2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of the GNU simulators.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #define WANT_CPU frvbf
22 #define WANT_CPU_FRVBF
28 /* Check for alignment and access restrictions. Return the corrected address.
31 fr400_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
33 /* Check access restrictions for double word loads only. */
36 if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
37 frv_queue_data_access_error_interrupt (current_cpu
, address
);
43 fr500_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
45 if (address
& align_mask
)
47 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
48 address
&= ~align_mask
;
51 if ((USI
)address
>= 0xfeff0600 && (USI
)address
<= 0xfeff7fff
52 || (USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff)
53 frv_queue_data_access_error_interrupt (current_cpu
, address
);
59 check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
61 SIM_DESC sd
= CPU_STATE (current_cpu
);
62 switch (STATE_ARCHITECTURE (sd
)->mach
)
65 address
= fr400_check_data_read_address (current_cpu
, address
,
68 case bfd_mach_frvtomcat
:
71 address
= fr500_check_data_read_address (current_cpu
, address
,
82 fr400_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
84 if (address
& align_mask
)
86 /* Make sure that this exception is not masked. */
88 if (! GET_ISR_EMAM (isr
))
90 /* Bad alignment causes a data_access_error on fr400. */
91 frv_queue_data_access_error_interrupt (current_cpu
, address
);
93 address
&= ~align_mask
;
95 /* Nothing to check. */
100 fr500_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
102 if ((USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe003fff
103 || (USI
)address
>= 0xfe004000 && (USI
)address
<= 0xfe3fffff
104 || (USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe403fff
105 || (USI
)address
>= 0xfe404000 && (USI
)address
<= 0xfe7fffff)
106 frv_queue_data_access_exception_interrupt (current_cpu
);
112 check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
114 SIM_DESC sd
= CPU_STATE (current_cpu
);
115 switch (STATE_ARCHITECTURE (sd
)->mach
)
118 address
= fr400_check_readwrite_address (current_cpu
, address
,
121 case bfd_mach_frvtomcat
:
124 address
= fr500_check_readwrite_address (current_cpu
, address
,
135 fr400_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
138 if (address
& align_mask
)
140 frv_queue_instruction_access_error_interrupt (current_cpu
);
141 address
&= ~align_mask
;
143 else if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
144 frv_queue_instruction_access_error_interrupt (current_cpu
);
150 fr500_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
153 if (address
& align_mask
)
155 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
156 address
&= ~align_mask
;
159 if ((USI
)address
>= 0xfeff0600 && (USI
)address
<= 0xfeff7fff
160 || (USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff)
161 frv_queue_instruction_access_error_interrupt (current_cpu
);
162 else if ((USI
)address
>= 0xfe004000 && (USI
)address
<= 0xfe3fffff
163 || (USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe403fff
164 || (USI
)address
>= 0xfe404000 && (USI
)address
<= 0xfe7fffff)
165 frv_queue_instruction_access_exception_interrupt (current_cpu
);
168 USI hsr0
= GET_HSR0 ();
169 if (! GET_HSR0_RME (hsr0
)
170 && (USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe003fff)
171 frv_queue_instruction_access_exception_interrupt (current_cpu
);
178 check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
, int align_mask
)
180 SIM_DESC sd
= CPU_STATE (current_cpu
);
181 switch (STATE_ARCHITECTURE (sd
)->mach
)
184 address
= fr400_check_insn_read_address (current_cpu
, address
,
187 case bfd_mach_frvtomcat
:
190 address
= fr500_check_insn_read_address (current_cpu
, address
,
202 frvbf_read_mem_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
204 USI hsr0
= GET_HSR0 ();
205 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
207 /* Check for access exceptions. */
208 address
= check_data_read_address (current_cpu
, address
, 0);
209 address
= check_readwrite_address (current_cpu
, address
, 0);
211 /* If we need to count cycles, then the cache operation will be
212 initiated from the model profiling functions.
213 See frvbf_model_.... */
216 CPU_LOAD_ADDRESS (current_cpu
) = address
;
217 CPU_LOAD_LENGTH (current_cpu
) = 1;
218 CPU_LOAD_SIGNED (current_cpu
) = 1;
219 return 0xb7; /* any random value */
222 if (GET_HSR0_DCE (hsr0
))
225 cycles
= frv_cache_read (cache
, 0, address
);
227 return CACHE_RETURN_DATA (cache
, 0, address
, QI
, 1);
230 return GETMEMQI (current_cpu
, pc
, address
);
234 frvbf_read_mem_UQI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
236 USI hsr0
= GET_HSR0 ();
237 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
239 /* Check for access exceptions. */
240 address
= check_data_read_address (current_cpu
, address
, 0);
241 address
= check_readwrite_address (current_cpu
, address
, 0);
243 /* If we need to count cycles, then the cache operation will be
244 initiated from the model profiling functions.
245 See frvbf_model_.... */
248 CPU_LOAD_ADDRESS (current_cpu
) = address
;
249 CPU_LOAD_LENGTH (current_cpu
) = 1;
250 CPU_LOAD_SIGNED (current_cpu
) = 0;
251 return 0xb7; /* any random value */
254 if (GET_HSR0_DCE (hsr0
))
257 cycles
= frv_cache_read (cache
, 0, address
);
259 return CACHE_RETURN_DATA (cache
, 0, address
, UQI
, 1);
262 return GETMEMUQI (current_cpu
, pc
, address
);
266 frvbf_read_mem_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
271 /* Check for access exceptions. */
272 address
= check_data_read_address (current_cpu
, address
, 1);
273 address
= check_readwrite_address (current_cpu
, address
, 1);
275 /* If we need to count cycles, then the cache operation will be
276 initiated from the model profiling functions.
277 See frvbf_model_.... */
279 cache
= CPU_DATA_CACHE (current_cpu
);
282 CPU_LOAD_ADDRESS (current_cpu
) = address
;
283 CPU_LOAD_LENGTH (current_cpu
) = 2;
284 CPU_LOAD_SIGNED (current_cpu
) = 1;
285 return 0xb711; /* any random value */
288 if (GET_HSR0_DCE (hsr0
))
291 cycles
= frv_cache_read (cache
, 0, address
);
293 return CACHE_RETURN_DATA (cache
, 0, address
, HI
, 2);
296 return GETMEMHI (current_cpu
, pc
, address
);
300 frvbf_read_mem_UHI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
305 /* Check for access exceptions. */
306 address
= check_data_read_address (current_cpu
, address
, 1);
307 address
= check_readwrite_address (current_cpu
, address
, 1);
309 /* If we need to count cycles, then the cache operation will be
310 initiated from the model profiling functions.
311 See frvbf_model_.... */
313 cache
= CPU_DATA_CACHE (current_cpu
);
316 CPU_LOAD_ADDRESS (current_cpu
) = address
;
317 CPU_LOAD_LENGTH (current_cpu
) = 2;
318 CPU_LOAD_SIGNED (current_cpu
) = 0;
319 return 0xb711; /* any random value */
322 if (GET_HSR0_DCE (hsr0
))
325 cycles
= frv_cache_read (cache
, 0, address
);
327 return CACHE_RETURN_DATA (cache
, 0, address
, UHI
, 2);
330 return GETMEMUHI (current_cpu
, pc
, address
);
334 frvbf_read_mem_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
339 /* Check for access exceptions. */
340 address
= check_data_read_address (current_cpu
, address
, 3);
341 address
= check_readwrite_address (current_cpu
, address
, 3);
344 cache
= CPU_DATA_CACHE (current_cpu
);
345 /* If we need to count cycles, then the cache operation will be
346 initiated from the model profiling functions.
347 See frvbf_model_.... */
350 CPU_LOAD_ADDRESS (current_cpu
) = address
;
351 CPU_LOAD_LENGTH (current_cpu
) = 4;
352 return 0x37111319; /* any random value */
355 if (GET_HSR0_DCE (hsr0
))
358 cycles
= frv_cache_read (cache
, 0, address
);
360 return CACHE_RETURN_DATA (cache
, 0, address
, SI
, 4);
363 return GETMEMSI (current_cpu
, pc
, address
);
367 frvbf_read_mem_WI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
369 return frvbf_read_mem_SI (current_cpu
, pc
, address
);
373 frvbf_read_mem_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
378 /* Check for access exceptions. */
379 address
= check_data_read_address (current_cpu
, address
, 7);
380 address
= check_readwrite_address (current_cpu
, address
, 7);
382 /* If we need to count cycles, then the cache operation will be
383 initiated from the model profiling functions.
384 See frvbf_model_.... */
386 cache
= CPU_DATA_CACHE (current_cpu
);
389 CPU_LOAD_ADDRESS (current_cpu
) = address
;
390 CPU_LOAD_LENGTH (current_cpu
) = 8;
391 return 0x37111319; /* any random value */
394 if (GET_HSR0_DCE (hsr0
))
397 cycles
= frv_cache_read (cache
, 0, address
);
399 return CACHE_RETURN_DATA (cache
, 0, address
, DI
, 8);
402 return GETMEMDI (current_cpu
, pc
, address
);
406 frvbf_read_mem_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
411 /* Check for access exceptions. */
412 address
= check_data_read_address (current_cpu
, address
, 7);
413 address
= check_readwrite_address (current_cpu
, address
, 7);
415 /* If we need to count cycles, then the cache operation will be
416 initiated from the model profiling functions.
417 See frvbf_model_.... */
419 cache
= CPU_DATA_CACHE (current_cpu
);
422 CPU_LOAD_ADDRESS (current_cpu
) = address
;
423 CPU_LOAD_LENGTH (current_cpu
) = 8;
424 return 0x37111319; /* any random value */
427 if (GET_HSR0_DCE (hsr0
))
430 cycles
= frv_cache_read (cache
, 0, address
);
432 return CACHE_RETURN_DATA (cache
, 0, address
, DF
, 8);
435 return GETMEMDF (current_cpu
, pc
, address
);
439 frvbf_read_imem_USI (SIM_CPU
*current_cpu
, PCADDR vpc
)
442 vpc
= check_insn_read_address (current_cpu
, vpc
, 3);
445 if (GET_HSR0_ICE (hsr0
))
450 /* We don't want this to show up in the cache statistics. That read
451 is done in frvbf_simulate_insn_prefetch. So read the cache or memory
453 cache
= CPU_INSN_CACHE (current_cpu
);
454 if (frv_cache_read_passive_SI (cache
, vpc
, &value
))
457 return sim_core_read_unaligned_4 (current_cpu
, vpc
, read_map
, vpc
);
461 fr400_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
463 if (address
& align_mask
)
465 /* On the fr400, this causes a data_access_error. */
466 /* Make sure that this exception is not masked. */
467 USI isr
= GET_ISR ();
468 if (! GET_ISR_EMAM (isr
))
470 /* Bad alignment causes a data_access_error on fr400. */
471 frv_queue_data_access_error_interrupt (current_cpu
, address
);
473 address
&= ~align_mask
;
476 && address
>= 0xfe800000 && address
<= 0xfeffffff)
477 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
483 fr500_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
485 if (address
& align_mask
)
487 struct frv_interrupt_queue_element
*item
=
488 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
489 /* Record the correct vliw slot with the interrupt. */
491 item
->slot
= frv_interrupt_state
.slot
;
492 address
&= ~align_mask
;
494 if (address
>= 0xfeff0600 && address
<= 0xfeff7fff
495 || address
>= 0xfe800000 && address
<= 0xfefeffff)
496 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
502 check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
504 SIM_DESC sd
= CPU_STATE (current_cpu
);
505 switch (STATE_ARCHITECTURE (sd
)->mach
)
508 address
= fr400_check_write_address (current_cpu
, address
, align_mask
);
510 case bfd_mach_frvtomcat
:
513 address
= fr500_check_write_address (current_cpu
, address
, align_mask
);
522 frvbf_write_mem_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, QI value
)
526 if (GET_HSR0_DCE (hsr0
))
527 sim_queue_fn_mem_qi_write (current_cpu
, frvbf_mem_set_QI
, address
, value
);
529 sim_queue_mem_qi_write (current_cpu
, address
, value
);
530 frv_set_write_queue_slot (current_cpu
);
534 frvbf_write_mem_UQI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, UQI value
)
536 frvbf_write_mem_QI (current_cpu
, pc
, address
, value
);
540 frvbf_write_mem_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
544 if (GET_HSR0_DCE (hsr0
))
545 sim_queue_fn_mem_hi_write (current_cpu
, frvbf_mem_set_HI
, address
, value
);
547 sim_queue_mem_hi_write (current_cpu
, address
, value
);
548 frv_set_write_queue_slot (current_cpu
);
552 frvbf_write_mem_UHI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, UHI value
)
554 frvbf_write_mem_HI (current_cpu
, pc
, address
, value
);
558 frvbf_write_mem_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
562 if (GET_HSR0_DCE (hsr0
))
563 sim_queue_fn_mem_si_write (current_cpu
, frvbf_mem_set_SI
, address
, value
);
565 sim_queue_mem_si_write (current_cpu
, address
, value
);
566 frv_set_write_queue_slot (current_cpu
);
570 frvbf_write_mem_WI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
572 frvbf_write_mem_SI (current_cpu
, pc
, address
, value
);
576 frvbf_write_mem_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
580 if (GET_HSR0_DCE (hsr0
))
581 sim_queue_fn_mem_di_write (current_cpu
, frvbf_mem_set_DI
, address
, value
);
583 sim_queue_mem_di_write (current_cpu
, address
, value
);
584 frv_set_write_queue_slot (current_cpu
);
588 frvbf_write_mem_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DF value
)
592 if (GET_HSR0_DCE (hsr0
))
593 sim_queue_fn_mem_df_write (current_cpu
, frvbf_mem_set_DF
, address
, value
);
595 sim_queue_mem_df_write (current_cpu
, address
, value
);
596 frv_set_write_queue_slot (current_cpu
);
599 /* Memory writes. These do the actual writing through the cache. */
601 frvbf_mem_set_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, QI value
)
603 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
605 /* Check for access errors. */
606 address
= check_write_address (current_cpu
, address
, 0);
607 address
= check_readwrite_address (current_cpu
, address
, 0);
609 /* If we need to count cycles, then submit the write request to the cache
610 and let it prioritize the request. Otherwise perform the write now. */
614 frv_cache_request_store (cache
, address
, slot
, (char *)&value
,
618 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
622 frvbf_mem_set_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
626 /* Check for access errors. */
627 address
= check_write_address (current_cpu
, address
, 1);
628 address
= check_readwrite_address (current_cpu
, address
, 1);
630 /* If we need to count cycles, then submit the write request to the cache
631 and let it prioritize the request. Otherwise perform the write now. */
632 value
= H2T_2 (value
);
633 cache
= CPU_DATA_CACHE (current_cpu
);
637 frv_cache_request_store (cache
, address
, slot
,
638 (char *)&value
, sizeof (value
));
641 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
645 frvbf_mem_set_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
649 /* Check for access errors. */
650 address
= check_write_address (current_cpu
, address
, 3);
651 address
= check_readwrite_address (current_cpu
, address
, 3);
653 /* If we need to count cycles, then submit the write request to the cache
654 and let it prioritize the request. Otherwise perform the write now. */
655 cache
= CPU_DATA_CACHE (current_cpu
);
656 value
= H2T_4 (value
);
660 frv_cache_request_store (cache
, address
, slot
,
661 (char *)&value
, sizeof (value
));
664 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
668 frvbf_mem_set_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
672 /* Check for access errors. */
673 address
= check_write_address (current_cpu
, address
, 7);
674 address
= check_readwrite_address (current_cpu
, address
, 7);
676 /* If we need to count cycles, then submit the write request to the cache
677 and let it prioritize the request. Otherwise perform the write now. */
678 value
= H2T_8 (value
);
679 cache
= CPU_DATA_CACHE (current_cpu
);
683 frv_cache_request_store (cache
, address
, slot
,
684 (char *)&value
, sizeof (value
));
687 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
691 frvbf_mem_set_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DF value
)
695 /* Check for access errors. */
696 address
= check_write_address (current_cpu
, address
, 7);
697 address
= check_readwrite_address (current_cpu
, address
, 7);
699 /* If we need to count cycles, then submit the write request to the cache
700 and let it prioritize the request. Otherwise perform the write now. */
701 value
= H2T_8 (value
);
702 cache
= CPU_DATA_CACHE (current_cpu
);
706 frv_cache_request_store (cache
, address
, slot
,
707 (char *)&value
, sizeof (value
));
710 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
714 frvbf_mem_set_XI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI
*value
)
719 /* Check for access errors. */
720 address
= check_write_address (current_cpu
, address
, 0xf);
721 address
= check_readwrite_address (current_cpu
, address
, 0xf);
723 /* TODO -- reverse word order as well? */
724 for (i
= 0; i
< 4; ++i
)
725 value
[i
] = H2T_4 (value
[i
]);
727 /* If we need to count cycles, then submit the write request to the cache
728 and let it prioritize the request. Otherwise perform the write now. */
729 cache
= CPU_DATA_CACHE (current_cpu
);
733 frv_cache_request_store (cache
, address
, slot
, (char*)value
, 16);
736 frv_cache_write (cache
, address
, (char*)value
, 16);
739 /* Record the current VLIW slot on the element at the top of the write queue.
742 frv_set_write_queue_slot (SIM_CPU
*current_cpu
)
744 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
745 int slot
= vliw
->next_slot
- 1;
746 CGEN_WRITE_QUEUE
*q
= CPU_WRITE_QUEUE (current_cpu
);
747 int ix
= CGEN_WRITE_QUEUE_INDEX (q
) - 1;
748 CGEN_WRITE_QUEUE_ELEMENT
*item
= CGEN_WRITE_QUEUE_ELEMENT (q
, ix
);
749 CGEN_WRITE_QUEUE_ELEMENT_PIPE (item
) = (*vliw
->current_vliw
)[slot
];