2 Copyright (C) 1999-2023 Free Software Foundation, Inc.
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 3 of the License, or
10 (at your option) any later version.
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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* This must come before any other includes. */
23 #define WANT_CPU frvbf
24 #define WANT_CPU_FRVBF
31 /* Check for alignment and access restrictions. Return the corrected address.
34 fr400_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
36 /* Check access restrictions for double word loads only. */
39 if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
40 frv_queue_data_access_error_interrupt (current_cpu
, address
);
46 fr500_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
48 if (address
& align_mask
)
50 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
51 address
&= ~align_mask
;
54 if (((USI
)address
>= 0xfeff0600 && (USI
)address
<= 0xfeff7fff)
55 || ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff))
56 frv_queue_data_access_error_interrupt (current_cpu
, address
);
62 fr550_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
64 if (((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff)
66 && ((USI
)address
>= 0xfeff0000 && (USI
)address
<= 0xfeffffff)))
67 frv_queue_data_access_error_interrupt (current_cpu
, address
);
73 check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
75 SIM_DESC sd
= CPU_STATE (current_cpu
);
76 switch (STATE_ARCHITECTURE (sd
)->mach
)
80 address
= fr400_check_data_read_address (current_cpu
, address
,
83 case bfd_mach_frvtomcat
:
86 address
= fr500_check_data_read_address (current_cpu
, address
,
90 address
= fr550_check_data_read_address (current_cpu
, address
,
101 fr400_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
103 if (address
& align_mask
)
105 /* Make sure that this exception is not masked. */
106 USI isr
= GET_ISR ();
107 if (! GET_ISR_EMAM (isr
))
109 /* Bad alignment causes a data_access_error on fr400. */
110 frv_queue_data_access_error_interrupt (current_cpu
, address
);
112 address
&= ~align_mask
;
114 /* Nothing to check. */
119 fr500_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
121 if (((USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe003fff)
122 || ((USI
)address
>= 0xfe004000 && (USI
)address
<= 0xfe3fffff)
123 || ((USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe403fff)
124 || ((USI
)address
>= 0xfe404000 && (USI
)address
<= 0xfe7fffff))
125 frv_queue_data_access_exception_interrupt (current_cpu
);
131 fr550_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
133 /* No alignment restrictions on fr550 */
135 if (((USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe3fffff)
136 || ((USI
)address
>= 0xfe408000 && (USI
)address
<= 0xfe7fffff))
137 frv_queue_data_access_exception_interrupt (current_cpu
);
140 USI hsr0
= GET_HSR0 ();
141 if (! GET_HSR0_RME (hsr0
)
142 && ((USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe407fff))
143 frv_queue_data_access_exception_interrupt (current_cpu
);
150 check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
152 SIM_DESC sd
= CPU_STATE (current_cpu
);
153 switch (STATE_ARCHITECTURE (sd
)->mach
)
157 address
= fr400_check_readwrite_address (current_cpu
, address
,
160 case bfd_mach_frvtomcat
:
163 address
= fr500_check_readwrite_address (current_cpu
, address
,
167 address
= fr550_check_readwrite_address (current_cpu
, address
,
178 fr400_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
181 if (address
& align_mask
)
183 frv_queue_instruction_access_error_interrupt (current_cpu
);
184 address
&= ~align_mask
;
186 else if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
187 frv_queue_instruction_access_error_interrupt (current_cpu
);
193 fr500_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
196 if (address
& align_mask
)
198 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
199 address
&= ~align_mask
;
202 if (((USI
)address
>= 0xfeff0600 && (USI
)address
<= 0xfeff7fff)
203 || ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff))
204 frv_queue_instruction_access_error_interrupt (current_cpu
);
205 else if (((USI
)address
>= 0xfe004000 && (USI
)address
<= 0xfe3fffff)
206 || ((USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe403fff)
207 || ((USI
)address
>= 0xfe404000 && (USI
)address
<= 0xfe7fffff))
208 frv_queue_instruction_access_exception_interrupt (current_cpu
);
211 USI hsr0
= GET_HSR0 ();
212 if (! GET_HSR0_RME (hsr0
)
213 && ((USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe003fff))
214 frv_queue_instruction_access_exception_interrupt (current_cpu
);
221 fr550_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
224 address
&= ~align_mask
;
226 if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
227 frv_queue_instruction_access_error_interrupt (current_cpu
);
228 else if ((USI
)address
>= 0xfe008000 && (USI
)address
<= 0xfe7fffff)
229 frv_queue_instruction_access_exception_interrupt (current_cpu
);
232 USI hsr0
= GET_HSR0 ();
233 if (! GET_HSR0_RME (hsr0
)
234 && (USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe007fff)
235 frv_queue_instruction_access_exception_interrupt (current_cpu
);
242 check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
, int align_mask
)
244 SIM_DESC sd
= CPU_STATE (current_cpu
);
245 switch (STATE_ARCHITECTURE (sd
)->mach
)
249 address
= fr400_check_insn_read_address (current_cpu
, address
,
252 case bfd_mach_frvtomcat
:
255 address
= fr500_check_insn_read_address (current_cpu
, address
,
259 address
= fr550_check_insn_read_address (current_cpu
, address
,
271 frvbf_read_mem_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
273 USI hsr0
= GET_HSR0 ();
274 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
276 /* Check for access exceptions. */
277 address
= check_data_read_address (current_cpu
, address
, 0);
278 address
= check_readwrite_address (current_cpu
, address
, 0);
280 /* If we need to count cycles, then the cache operation will be
281 initiated from the model profiling functions.
282 See frvbf_model_.... */
285 CPU_LOAD_ADDRESS (current_cpu
) = address
;
286 CPU_LOAD_LENGTH (current_cpu
) = 1;
287 CPU_LOAD_SIGNED (current_cpu
) = 1;
288 return 0xb7; /* any random value */
291 if (GET_HSR0_DCE (hsr0
))
294 cycles
= frv_cache_read (cache
, 0, address
);
296 return CACHE_RETURN_DATA (cache
, 0, address
, QI
, 1);
299 return GETMEMQI (current_cpu
, pc
, address
);
303 frvbf_read_mem_UQI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
305 USI hsr0
= GET_HSR0 ();
306 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
308 /* Check for access exceptions. */
309 address
= check_data_read_address (current_cpu
, address
, 0);
310 address
= check_readwrite_address (current_cpu
, address
, 0);
312 /* If we need to count cycles, then the cache operation will be
313 initiated from the model profiling functions.
314 See frvbf_model_.... */
317 CPU_LOAD_ADDRESS (current_cpu
) = address
;
318 CPU_LOAD_LENGTH (current_cpu
) = 1;
319 CPU_LOAD_SIGNED (current_cpu
) = 0;
320 return 0xb7; /* any random value */
323 if (GET_HSR0_DCE (hsr0
))
326 cycles
= frv_cache_read (cache
, 0, address
);
328 return CACHE_RETURN_DATA (cache
, 0, address
, UQI
, 1);
331 return GETMEMUQI (current_cpu
, pc
, address
);
334 /* Read a HI which spans two cache lines */
336 read_mem_unaligned_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
338 HI value
= frvbf_read_mem_QI (current_cpu
, pc
, address
);
340 value
|= frvbf_read_mem_UQI (current_cpu
, pc
, address
+ 1);
341 return T2H_2 (value
);
345 frvbf_read_mem_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
350 /* Check for access exceptions. */
351 address
= check_data_read_address (current_cpu
, address
, 1);
352 address
= check_readwrite_address (current_cpu
, address
, 1);
354 /* If we need to count cycles, then the cache operation will be
355 initiated from the model profiling functions.
356 See frvbf_model_.... */
358 cache
= CPU_DATA_CACHE (current_cpu
);
361 CPU_LOAD_ADDRESS (current_cpu
) = address
;
362 CPU_LOAD_LENGTH (current_cpu
) = 2;
363 CPU_LOAD_SIGNED (current_cpu
) = 1;
364 return 0xb711; /* any random value */
367 if (GET_HSR0_DCE (hsr0
))
370 /* Handle access which crosses cache line boundary */
371 SIM_DESC sd
= CPU_STATE (current_cpu
);
372 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
374 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 2))
375 return read_mem_unaligned_HI (current_cpu
, pc
, address
);
377 cycles
= frv_cache_read (cache
, 0, address
);
379 return CACHE_RETURN_DATA (cache
, 0, address
, HI
, 2);
382 return GETMEMHI (current_cpu
, pc
, address
);
386 frvbf_read_mem_UHI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
391 /* Check for access exceptions. */
392 address
= check_data_read_address (current_cpu
, address
, 1);
393 address
= check_readwrite_address (current_cpu
, address
, 1);
395 /* If we need to count cycles, then the cache operation will be
396 initiated from the model profiling functions.
397 See frvbf_model_.... */
399 cache
= CPU_DATA_CACHE (current_cpu
);
402 CPU_LOAD_ADDRESS (current_cpu
) = address
;
403 CPU_LOAD_LENGTH (current_cpu
) = 2;
404 CPU_LOAD_SIGNED (current_cpu
) = 0;
405 return 0xb711; /* any random value */
408 if (GET_HSR0_DCE (hsr0
))
411 /* Handle access which crosses cache line boundary */
412 SIM_DESC sd
= CPU_STATE (current_cpu
);
413 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
415 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 2))
416 return read_mem_unaligned_HI (current_cpu
, pc
, address
);
418 cycles
= frv_cache_read (cache
, 0, address
);
420 return CACHE_RETURN_DATA (cache
, 0, address
, UHI
, 2);
423 return GETMEMUHI (current_cpu
, pc
, address
);
426 /* Read a SI which spans two cache lines */
428 read_mem_unaligned_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
430 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
431 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
439 valarray
[0] = frvbf_read_mem_QI (current_cpu
, pc
, address
);
440 SIvalue
= frvbf_read_mem_SI (current_cpu
, pc
, address
+ 1);
441 SIvalue
= H2T_4 (SIvalue
);
442 memcpy (valarray
+ 1, (char*)&SIvalue
, 3);
445 HIvalue
= frvbf_read_mem_HI (current_cpu
, pc
, address
);
446 HIvalue
= H2T_2 (HIvalue
);
447 memcpy (valarray
, (char*)&HIvalue
, 2);
448 HIvalue
= frvbf_read_mem_HI (current_cpu
, pc
, address
+ 2);
449 HIvalue
= H2T_2 (HIvalue
);
450 memcpy (valarray
+ 2, (char*)&HIvalue
, 2);
453 SIvalue
= frvbf_read_mem_SI (current_cpu
, pc
, address
- 1);
454 SIvalue
= H2T_4 (SIvalue
);
455 memcpy (valarray
, (char*)&SIvalue
, 3);
456 valarray
[3] = frvbf_read_mem_QI (current_cpu
, pc
, address
+ 3);
459 abort (); /* can't happen */
461 return T2H_4 (*(SI
*)valarray
);
465 frvbf_read_mem_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
470 /* Check for access exceptions. */
471 address
= check_data_read_address (current_cpu
, address
, 3);
472 address
= check_readwrite_address (current_cpu
, address
, 3);
475 cache
= CPU_DATA_CACHE (current_cpu
);
476 /* If we need to count cycles, then the cache operation will be
477 initiated from the model profiling functions.
478 See frvbf_model_.... */
481 CPU_LOAD_ADDRESS (current_cpu
) = address
;
482 CPU_LOAD_LENGTH (current_cpu
) = 4;
483 return 0x37111319; /* any random value */
486 if (GET_HSR0_DCE (hsr0
))
489 /* Handle access which crosses cache line boundary */
490 SIM_DESC sd
= CPU_STATE (current_cpu
);
491 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
493 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 4))
494 return read_mem_unaligned_SI (current_cpu
, pc
, address
);
496 cycles
= frv_cache_read (cache
, 0, address
);
498 return CACHE_RETURN_DATA (cache
, 0, address
, SI
, 4);
501 return GETMEMSI (current_cpu
, pc
, address
);
505 frvbf_read_mem_WI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
507 return frvbf_read_mem_SI (current_cpu
, pc
, address
);
510 /* Read a SI which spans two cache lines */
512 read_mem_unaligned_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
514 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
515 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
521 value
= frvbf_read_mem_QI (current_cpu
, pc
, address
);
523 value1
= frvbf_read_mem_DI (current_cpu
, pc
, address
+ 1);
524 value1
= H2T_8 (value1
);
525 value
|= value1
& ((DI
)0x00ffffff << 32);
526 value
|= value1
& 0xffffffffu
;
529 value
= frvbf_read_mem_HI (current_cpu
, pc
, address
);
530 value
= H2T_2 (value
);
532 value1
= frvbf_read_mem_DI (current_cpu
, pc
, address
+ 2);
533 value1
= H2T_8 (value1
);
534 value
|= value1
& ((DI
)0x0000ffff << 32);
535 value
|= value1
& 0xffffffffu
;
538 value
= frvbf_read_mem_SI (current_cpu
, pc
, address
- 1);
539 value
= H2T_4 (value
);
541 value1
= frvbf_read_mem_DI (current_cpu
, pc
, address
+ 3);
542 value1
= H2T_8 (value1
);
543 value
|= value1
& ((DI
)0x000000ff << 32);
544 value
|= value1
& 0xffffffffu
;
547 value
= frvbf_read_mem_SI (current_cpu
, pc
, address
);
548 value
= H2T_4 (value
);
550 value1
= frvbf_read_mem_SI (current_cpu
, pc
, address
+ 4);
551 value1
= H2T_4 (value1
);
552 value
|= value1
& 0xffffffffu
;
555 value
= frvbf_read_mem_DI (current_cpu
, pc
, address
- 3);
556 value
= H2T_8 (value
);
558 value1
= frvbf_read_mem_SI (current_cpu
, pc
, address
+ 5);
559 value1
= H2T_4 (value1
);
560 value
|= value1
& 0x00ffffff;
563 value
= frvbf_read_mem_DI (current_cpu
, pc
, address
- 2);
564 value
= H2T_8 (value
);
566 value1
= frvbf_read_mem_HI (current_cpu
, pc
, address
+ 6);
567 value1
= H2T_2 (value1
);
568 value
|= value1
& 0x0000ffff;
571 value
= frvbf_read_mem_DI (current_cpu
, pc
, address
- 1);
572 value
= H2T_8 (value
);
574 value1
= frvbf_read_mem_QI (current_cpu
, pc
, address
+ 7);
575 value
|= value1
& 0x000000ff;
578 abort (); /* can't happen */
580 return T2H_8 (value
);
584 frvbf_read_mem_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
589 /* Check for access exceptions. */
590 address
= check_data_read_address (current_cpu
, address
, 7);
591 address
= check_readwrite_address (current_cpu
, address
, 7);
593 /* If we need to count cycles, then the cache operation will be
594 initiated from the model profiling functions.
595 See frvbf_model_.... */
597 cache
= CPU_DATA_CACHE (current_cpu
);
600 CPU_LOAD_ADDRESS (current_cpu
) = address
;
601 CPU_LOAD_LENGTH (current_cpu
) = 8;
602 return 0x37111319; /* any random value */
605 if (GET_HSR0_DCE (hsr0
))
608 /* Handle access which crosses cache line boundary */
609 SIM_DESC sd
= CPU_STATE (current_cpu
);
610 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
612 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
613 return read_mem_unaligned_DI (current_cpu
, pc
, address
);
615 cycles
= frv_cache_read (cache
, 0, address
);
617 return CACHE_RETURN_DATA (cache
, 0, address
, DI
, 8);
620 return GETMEMDI (current_cpu
, pc
, address
);
624 frvbf_read_mem_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
629 /* Check for access exceptions. */
630 address
= check_data_read_address (current_cpu
, address
, 7);
631 address
= check_readwrite_address (current_cpu
, address
, 7);
633 /* If we need to count cycles, then the cache operation will be
634 initiated from the model profiling functions.
635 See frvbf_model_.... */
637 cache
= CPU_DATA_CACHE (current_cpu
);
640 CPU_LOAD_ADDRESS (current_cpu
) = address
;
641 CPU_LOAD_LENGTH (current_cpu
) = 8;
642 return 0x37111319; /* any random value */
645 if (GET_HSR0_DCE (hsr0
))
648 /* Handle access which crosses cache line boundary */
649 SIM_DESC sd
= CPU_STATE (current_cpu
);
650 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
652 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
653 return read_mem_unaligned_DI (current_cpu
, pc
, address
);
655 cycles
= frv_cache_read (cache
, 0, address
);
657 return CACHE_RETURN_DATA (cache
, 0, address
, DF
, 8);
660 return GETMEMDF (current_cpu
, pc
, address
);
664 frvbf_read_imem_USI (SIM_CPU
*current_cpu
, PCADDR vpc
)
667 vpc
= check_insn_read_address (current_cpu
, vpc
, 3);
670 if (GET_HSR0_ICE (hsr0
))
675 /* We don't want this to show up in the cache statistics. That read
676 is done in frvbf_simulate_insn_prefetch. So read the cache or memory
678 cache
= CPU_INSN_CACHE (current_cpu
);
679 if (frv_cache_read_passive_SI (cache
, vpc
, &value
))
682 return sim_core_read_unaligned_4 (current_cpu
, vpc
, read_map
, vpc
);
686 fr400_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
689 && address
>= 0xfe800000 && address
<= 0xfeffffff)
690 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
696 fr500_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
698 if (address
& align_mask
)
700 struct frv_interrupt_queue_element
*item
=
701 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
702 /* Record the correct vliw slot with the interrupt. */
704 item
->slot
= frv_interrupt_state
.slot
;
705 address
&= ~align_mask
;
707 if ((address
>= 0xfeff0600 && address
<= 0xfeff7fff)
708 || (address
>= 0xfe800000 && address
<= 0xfefeffff))
709 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
715 fr550_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
717 if (((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff)
719 && ((USI
)address
>= 0xfeff0000 && (USI
)address
<= 0xfeffffff)))
720 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
726 check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
728 SIM_DESC sd
= CPU_STATE (current_cpu
);
729 switch (STATE_ARCHITECTURE (sd
)->mach
)
733 address
= fr400_check_write_address (current_cpu
, address
, align_mask
);
735 case bfd_mach_frvtomcat
:
738 address
= fr500_check_write_address (current_cpu
, address
, align_mask
);
741 address
= fr550_check_write_address (current_cpu
, address
, align_mask
);
750 frvbf_write_mem_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, QI value
)
754 if (GET_HSR0_DCE (hsr0
))
755 sim_queue_fn_mem_qi_write (current_cpu
, frvbf_mem_set_QI
, address
, value
);
757 sim_queue_mem_qi_write (current_cpu
, address
, value
);
758 frv_set_write_queue_slot (current_cpu
);
762 frvbf_write_mem_UQI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, UQI value
)
764 frvbf_write_mem_QI (current_cpu
, pc
, address
, value
);
768 frvbf_write_mem_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
772 if (GET_HSR0_DCE (hsr0
))
773 sim_queue_fn_mem_hi_write (current_cpu
, frvbf_mem_set_HI
, address
, value
);
775 sim_queue_mem_hi_write (current_cpu
, address
, value
);
776 frv_set_write_queue_slot (current_cpu
);
780 frvbf_write_mem_UHI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, UHI value
)
782 frvbf_write_mem_HI (current_cpu
, pc
, address
, value
);
786 frvbf_write_mem_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
790 if (GET_HSR0_DCE (hsr0
))
791 sim_queue_fn_mem_si_write (current_cpu
, frvbf_mem_set_SI
, address
, value
);
793 sim_queue_mem_si_write (current_cpu
, address
, value
);
794 frv_set_write_queue_slot (current_cpu
);
798 frvbf_write_mem_WI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
800 frvbf_write_mem_SI (current_cpu
, pc
, address
, value
);
804 frvbf_write_mem_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
808 if (GET_HSR0_DCE (hsr0
))
809 sim_queue_fn_mem_di_write (current_cpu
, frvbf_mem_set_DI
, address
, value
);
811 sim_queue_mem_di_write (current_cpu
, address
, value
);
812 frv_set_write_queue_slot (current_cpu
);
816 frvbf_write_mem_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DF value
)
820 if (GET_HSR0_DCE (hsr0
))
821 sim_queue_fn_mem_df_write (current_cpu
, frvbf_mem_set_DF
, address
, value
);
823 sim_queue_mem_df_write (current_cpu
, address
, value
);
824 frv_set_write_queue_slot (current_cpu
);
827 /* Memory writes. These do the actual writing through the cache. */
829 frvbf_mem_set_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, QI value
)
831 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
833 /* Check for access errors. */
834 address
= check_write_address (current_cpu
, address
, 0);
835 address
= check_readwrite_address (current_cpu
, address
, 0);
837 /* If we need to count cycles, then submit the write request to the cache
838 and let it prioritize the request. Otherwise perform the write now. */
842 frv_cache_request_store (cache
, address
, slot
, (char *)&value
,
846 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
849 /* Write a HI which spans two cache lines */
851 mem_set_unaligned_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
853 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
854 /* value is already in target byte order */
855 frv_cache_write (cache
, address
, (char *)&value
, 1);
856 frv_cache_write (cache
, address
+ 1, ((char *)&value
+ 1), 1);
860 frvbf_mem_set_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
864 /* Check for access errors. */
865 address
= check_write_address (current_cpu
, address
, 1);
866 address
= check_readwrite_address (current_cpu
, address
, 1);
868 /* If we need to count cycles, then submit the write request to the cache
869 and let it prioritize the request. Otherwise perform the write now. */
870 value
= H2T_2 (value
);
871 cache
= CPU_DATA_CACHE (current_cpu
);
875 frv_cache_request_store (cache
, address
, slot
,
876 (char *)&value
, sizeof (value
));
880 /* Handle access which crosses cache line boundary */
881 SIM_DESC sd
= CPU_STATE (current_cpu
);
882 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
884 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 2))
886 mem_set_unaligned_HI (current_cpu
, pc
, address
, value
);
890 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
894 /* Write a SI which spans two cache lines */
896 mem_set_unaligned_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
898 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
899 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
900 /* value is already in target byte order */
901 frv_cache_write (cache
, address
, (char *)&value
, hi_len
);
902 frv_cache_write (cache
, address
+ hi_len
, (char *)&value
+ hi_len
, 4 - hi_len
);
906 frvbf_mem_set_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
910 /* Check for access errors. */
911 address
= check_write_address (current_cpu
, address
, 3);
912 address
= check_readwrite_address (current_cpu
, address
, 3);
914 /* If we need to count cycles, then submit the write request to the cache
915 and let it prioritize the request. Otherwise perform the write now. */
916 cache
= CPU_DATA_CACHE (current_cpu
);
917 value
= H2T_4 (value
);
921 frv_cache_request_store (cache
, address
, slot
,
922 (char *)&value
, sizeof (value
));
926 /* Handle access which crosses cache line boundary */
927 SIM_DESC sd
= CPU_STATE (current_cpu
);
928 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
930 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 4))
932 mem_set_unaligned_SI (current_cpu
, pc
, address
, value
);
936 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
940 /* Write a DI which spans two cache lines */
942 mem_set_unaligned_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
944 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
945 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
946 /* value is already in target byte order */
947 frv_cache_write (cache
, address
, (char *)&value
, hi_len
);
948 frv_cache_write (cache
, address
+ hi_len
, (char *)&value
+ hi_len
, 8 - hi_len
);
952 frvbf_mem_set_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
956 /* Check for access errors. */
957 address
= check_write_address (current_cpu
, address
, 7);
958 address
= check_readwrite_address (current_cpu
, address
, 7);
960 /* If we need to count cycles, then submit the write request to the cache
961 and let it prioritize the request. Otherwise perform the write now. */
962 value
= H2T_8 (value
);
963 cache
= CPU_DATA_CACHE (current_cpu
);
967 frv_cache_request_store (cache
, address
, slot
,
968 (char *)&value
, sizeof (value
));
972 /* Handle access which crosses cache line boundary */
973 SIM_DESC sd
= CPU_STATE (current_cpu
);
974 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
976 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
978 mem_set_unaligned_DI (current_cpu
, pc
, address
, value
);
982 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
987 frvbf_mem_set_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DF value
)
991 /* Check for access errors. */
992 address
= check_write_address (current_cpu
, address
, 7);
993 address
= check_readwrite_address (current_cpu
, address
, 7);
995 /* If we need to count cycles, then submit the write request to the cache
996 and let it prioritize the request. Otherwise perform the write now. */
997 value
= H2T_8 (value
);
998 cache
= CPU_DATA_CACHE (current_cpu
);
1002 frv_cache_request_store (cache
, address
, slot
,
1003 (char *)&value
, sizeof (value
));
1007 /* Handle access which crosses cache line boundary */
1008 SIM_DESC sd
= CPU_STATE (current_cpu
);
1009 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
1011 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
1013 mem_set_unaligned_DI (current_cpu
, pc
, address
, value
);
1017 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
1022 frvbf_mem_set_XI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI
*value
)
1027 /* Check for access errors. */
1028 address
= check_write_address (current_cpu
, address
, 0xf);
1029 address
= check_readwrite_address (current_cpu
, address
, 0xf);
1031 /* TODO -- reverse word order as well? */
1032 for (i
= 0; i
< 4; ++i
)
1033 value
[i
] = H2T_4 (value
[i
]);
1035 /* If we need to count cycles, then submit the write request to the cache
1036 and let it prioritize the request. Otherwise perform the write now. */
1037 cache
= CPU_DATA_CACHE (current_cpu
);
1041 frv_cache_request_store (cache
, address
, slot
, (char*)value
, 16);
1044 frv_cache_write (cache
, address
, (char*)value
, 16);
1047 /* Record the current VLIW slot on the element at the top of the write queue.
1050 frv_set_write_queue_slot (SIM_CPU
*current_cpu
)
1052 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
1053 int slot
= vliw
->next_slot
- 1;
1054 CGEN_WRITE_QUEUE
*q
= CPU_WRITE_QUEUE (current_cpu
);
1055 int ix
= CGEN_WRITE_QUEUE_INDEX (q
) - 1;
1056 CGEN_WRITE_QUEUE_ELEMENT
*item
= CGEN_WRITE_QUEUE_ELEMENT (q
, ix
);
1057 CGEN_WRITE_QUEUE_ELEMENT_PIPE (item
) = (*vliw
->current_vliw
)[slot
];