2 Copyright (C) 1999-2019 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 #define WANT_CPU frvbf
21 #define WANT_CPU_FRVBF
27 /* Check for alignment and access restrictions. Return the corrected address.
30 fr400_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
32 /* Check access restrictions for double word loads only. */
35 if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
36 frv_queue_data_access_error_interrupt (current_cpu
, address
);
42 fr500_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
44 if (address
& align_mask
)
46 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
47 address
&= ~align_mask
;
50 if ((USI
)address
>= 0xfeff0600 && (USI
)address
<= 0xfeff7fff
51 || (USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff)
52 frv_queue_data_access_error_interrupt (current_cpu
, address
);
58 fr550_check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
60 if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff
62 && ((USI
)address
>= 0xfeff0000 && (USI
)address
<= 0xfeffffff)))
63 frv_queue_data_access_error_interrupt (current_cpu
, address
);
69 check_data_read_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
71 SIM_DESC sd
= CPU_STATE (current_cpu
);
72 switch (STATE_ARCHITECTURE (sd
)->mach
)
76 address
= fr400_check_data_read_address (current_cpu
, address
,
79 case bfd_mach_frvtomcat
:
82 address
= fr500_check_data_read_address (current_cpu
, address
,
86 address
= fr550_check_data_read_address (current_cpu
, address
,
97 fr400_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
99 if (address
& align_mask
)
101 /* Make sure that this exception is not masked. */
102 USI isr
= GET_ISR ();
103 if (! GET_ISR_EMAM (isr
))
105 /* Bad alignment causes a data_access_error on fr400. */
106 frv_queue_data_access_error_interrupt (current_cpu
, address
);
108 address
&= ~align_mask
;
110 /* Nothing to check. */
115 fr500_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
117 if ((USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe003fff
118 || (USI
)address
>= 0xfe004000 && (USI
)address
<= 0xfe3fffff
119 || (USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe403fff
120 || (USI
)address
>= 0xfe404000 && (USI
)address
<= 0xfe7fffff)
121 frv_queue_data_access_exception_interrupt (current_cpu
);
127 fr550_check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
129 /* No alignment restrictions on fr550 */
131 if ((USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe3fffff
132 || (USI
)address
>= 0xfe408000 && (USI
)address
<= 0xfe7fffff)
133 frv_queue_data_access_exception_interrupt (current_cpu
);
136 USI hsr0
= GET_HSR0 ();
137 if (! GET_HSR0_RME (hsr0
)
138 && (USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe407fff)
139 frv_queue_data_access_exception_interrupt (current_cpu
);
146 check_readwrite_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
148 SIM_DESC sd
= CPU_STATE (current_cpu
);
149 switch (STATE_ARCHITECTURE (sd
)->mach
)
153 address
= fr400_check_readwrite_address (current_cpu
, address
,
156 case bfd_mach_frvtomcat
:
159 address
= fr500_check_readwrite_address (current_cpu
, address
,
163 address
= fr550_check_readwrite_address (current_cpu
, address
,
174 fr400_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
177 if (address
& align_mask
)
179 frv_queue_instruction_access_error_interrupt (current_cpu
);
180 address
&= ~align_mask
;
182 else if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
183 frv_queue_instruction_access_error_interrupt (current_cpu
);
189 fr500_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
192 if (address
& align_mask
)
194 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
195 address
&= ~align_mask
;
198 if ((USI
)address
>= 0xfeff0600 && (USI
)address
<= 0xfeff7fff
199 || (USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff)
200 frv_queue_instruction_access_error_interrupt (current_cpu
);
201 else if ((USI
)address
>= 0xfe004000 && (USI
)address
<= 0xfe3fffff
202 || (USI
)address
>= 0xfe400000 && (USI
)address
<= 0xfe403fff
203 || (USI
)address
>= 0xfe404000 && (USI
)address
<= 0xfe7fffff)
204 frv_queue_instruction_access_exception_interrupt (current_cpu
);
207 USI hsr0
= GET_HSR0 ();
208 if (! GET_HSR0_RME (hsr0
)
209 && (USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe003fff)
210 frv_queue_instruction_access_exception_interrupt (current_cpu
);
217 fr550_check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
,
220 address
&= ~align_mask
;
222 if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfeffffff)
223 frv_queue_instruction_access_error_interrupt (current_cpu
);
224 else if ((USI
)address
>= 0xfe008000 && (USI
)address
<= 0xfe7fffff)
225 frv_queue_instruction_access_exception_interrupt (current_cpu
);
228 USI hsr0
= GET_HSR0 ();
229 if (! GET_HSR0_RME (hsr0
)
230 && (USI
)address
>= 0xfe000000 && (USI
)address
<= 0xfe007fff)
231 frv_queue_instruction_access_exception_interrupt (current_cpu
);
238 check_insn_read_address (SIM_CPU
*current_cpu
, PCADDR address
, int align_mask
)
240 SIM_DESC sd
= CPU_STATE (current_cpu
);
241 switch (STATE_ARCHITECTURE (sd
)->mach
)
245 address
= fr400_check_insn_read_address (current_cpu
, address
,
248 case bfd_mach_frvtomcat
:
251 address
= fr500_check_insn_read_address (current_cpu
, address
,
255 address
= fr550_check_insn_read_address (current_cpu
, address
,
267 frvbf_read_mem_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
269 USI hsr0
= GET_HSR0 ();
270 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
272 /* Check for access exceptions. */
273 address
= check_data_read_address (current_cpu
, address
, 0);
274 address
= check_readwrite_address (current_cpu
, address
, 0);
276 /* If we need to count cycles, then the cache operation will be
277 initiated from the model profiling functions.
278 See frvbf_model_.... */
281 CPU_LOAD_ADDRESS (current_cpu
) = address
;
282 CPU_LOAD_LENGTH (current_cpu
) = 1;
283 CPU_LOAD_SIGNED (current_cpu
) = 1;
284 return 0xb7; /* any random value */
287 if (GET_HSR0_DCE (hsr0
))
290 cycles
= frv_cache_read (cache
, 0, address
);
292 return CACHE_RETURN_DATA (cache
, 0, address
, QI
, 1);
295 return GETMEMQI (current_cpu
, pc
, address
);
299 frvbf_read_mem_UQI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
301 USI hsr0
= GET_HSR0 ();
302 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
304 /* Check for access exceptions. */
305 address
= check_data_read_address (current_cpu
, address
, 0);
306 address
= check_readwrite_address (current_cpu
, address
, 0);
308 /* If we need to count cycles, then the cache operation will be
309 initiated from the model profiling functions.
310 See frvbf_model_.... */
313 CPU_LOAD_ADDRESS (current_cpu
) = address
;
314 CPU_LOAD_LENGTH (current_cpu
) = 1;
315 CPU_LOAD_SIGNED (current_cpu
) = 0;
316 return 0xb7; /* any random value */
319 if (GET_HSR0_DCE (hsr0
))
322 cycles
= frv_cache_read (cache
, 0, address
);
324 return CACHE_RETURN_DATA (cache
, 0, address
, UQI
, 1);
327 return GETMEMUQI (current_cpu
, pc
, address
);
330 /* Read a HI which spans two cache lines */
332 read_mem_unaligned_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
334 HI value
= frvbf_read_mem_QI (current_cpu
, pc
, address
);
336 value
|= frvbf_read_mem_UQI (current_cpu
, pc
, address
+ 1);
337 return T2H_2 (value
);
341 frvbf_read_mem_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
346 /* Check for access exceptions. */
347 address
= check_data_read_address (current_cpu
, address
, 1);
348 address
= check_readwrite_address (current_cpu
, address
, 1);
350 /* If we need to count cycles, then the cache operation will be
351 initiated from the model profiling functions.
352 See frvbf_model_.... */
354 cache
= CPU_DATA_CACHE (current_cpu
);
357 CPU_LOAD_ADDRESS (current_cpu
) = address
;
358 CPU_LOAD_LENGTH (current_cpu
) = 2;
359 CPU_LOAD_SIGNED (current_cpu
) = 1;
360 return 0xb711; /* any random value */
363 if (GET_HSR0_DCE (hsr0
))
366 /* Handle access which crosses cache line boundary */
367 SIM_DESC sd
= CPU_STATE (current_cpu
);
368 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
370 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 2))
371 return read_mem_unaligned_HI (current_cpu
, pc
, address
);
373 cycles
= frv_cache_read (cache
, 0, address
);
375 return CACHE_RETURN_DATA (cache
, 0, address
, HI
, 2);
378 return GETMEMHI (current_cpu
, pc
, address
);
382 frvbf_read_mem_UHI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
387 /* Check for access exceptions. */
388 address
= check_data_read_address (current_cpu
, address
, 1);
389 address
= check_readwrite_address (current_cpu
, address
, 1);
391 /* If we need to count cycles, then the cache operation will be
392 initiated from the model profiling functions.
393 See frvbf_model_.... */
395 cache
= CPU_DATA_CACHE (current_cpu
);
398 CPU_LOAD_ADDRESS (current_cpu
) = address
;
399 CPU_LOAD_LENGTH (current_cpu
) = 2;
400 CPU_LOAD_SIGNED (current_cpu
) = 0;
401 return 0xb711; /* any random value */
404 if (GET_HSR0_DCE (hsr0
))
407 /* Handle access which crosses cache line boundary */
408 SIM_DESC sd
= CPU_STATE (current_cpu
);
409 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
411 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 2))
412 return read_mem_unaligned_HI (current_cpu
, pc
, address
);
414 cycles
= frv_cache_read (cache
, 0, address
);
416 return CACHE_RETURN_DATA (cache
, 0, address
, UHI
, 2);
419 return GETMEMUHI (current_cpu
, pc
, address
);
422 /* Read a SI which spans two cache lines */
424 read_mem_unaligned_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
426 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
427 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
435 valarray
[0] = frvbf_read_mem_QI (current_cpu
, pc
, address
);
436 SIvalue
= frvbf_read_mem_SI (current_cpu
, pc
, address
+ 1);
437 SIvalue
= H2T_4 (SIvalue
);
438 memcpy (valarray
+ 1, (char*)&SIvalue
, 3);
441 HIvalue
= frvbf_read_mem_HI (current_cpu
, pc
, address
);
442 HIvalue
= H2T_2 (HIvalue
);
443 memcpy (valarray
, (char*)&HIvalue
, 2);
444 HIvalue
= frvbf_read_mem_HI (current_cpu
, pc
, address
+ 2);
445 HIvalue
= H2T_2 (HIvalue
);
446 memcpy (valarray
+ 2, (char*)&HIvalue
, 2);
449 SIvalue
= frvbf_read_mem_SI (current_cpu
, pc
, address
- 1);
450 SIvalue
= H2T_4 (SIvalue
);
451 memcpy (valarray
, (char*)&SIvalue
, 3);
452 valarray
[3] = frvbf_read_mem_QI (current_cpu
, pc
, address
+ 3);
455 abort (); /* can't happen */
457 return T2H_4 (*(SI
*)valarray
);
461 frvbf_read_mem_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
466 /* Check for access exceptions. */
467 address
= check_data_read_address (current_cpu
, address
, 3);
468 address
= check_readwrite_address (current_cpu
, address
, 3);
471 cache
= CPU_DATA_CACHE (current_cpu
);
472 /* If we need to count cycles, then the cache operation will be
473 initiated from the model profiling functions.
474 See frvbf_model_.... */
477 CPU_LOAD_ADDRESS (current_cpu
) = address
;
478 CPU_LOAD_LENGTH (current_cpu
) = 4;
479 return 0x37111319; /* any random value */
482 if (GET_HSR0_DCE (hsr0
))
485 /* Handle access which crosses cache line boundary */
486 SIM_DESC sd
= CPU_STATE (current_cpu
);
487 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
489 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 4))
490 return read_mem_unaligned_SI (current_cpu
, pc
, address
);
492 cycles
= frv_cache_read (cache
, 0, address
);
494 return CACHE_RETURN_DATA (cache
, 0, address
, SI
, 4);
497 return GETMEMSI (current_cpu
, pc
, address
);
501 frvbf_read_mem_WI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
503 return frvbf_read_mem_SI (current_cpu
, pc
, address
);
506 /* Read a SI which spans two cache lines */
508 read_mem_unaligned_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
510 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
511 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
517 value
= frvbf_read_mem_QI (current_cpu
, pc
, address
);
519 value1
= frvbf_read_mem_DI (current_cpu
, pc
, address
+ 1);
520 value1
= H2T_8 (value1
);
521 value
|= value1
& ((DI
)0x00ffffff << 32);
522 value
|= value1
& 0xffffffffu
;
525 value
= frvbf_read_mem_HI (current_cpu
, pc
, address
);
526 value
= H2T_2 (value
);
528 value1
= frvbf_read_mem_DI (current_cpu
, pc
, address
+ 2);
529 value1
= H2T_8 (value1
);
530 value
|= value1
& ((DI
)0x0000ffff << 32);
531 value
|= value1
& 0xffffffffu
;
534 value
= frvbf_read_mem_SI (current_cpu
, pc
, address
- 1);
535 value
= H2T_4 (value
);
537 value1
= frvbf_read_mem_DI (current_cpu
, pc
, address
+ 3);
538 value1
= H2T_8 (value1
);
539 value
|= value1
& ((DI
)0x000000ff << 32);
540 value
|= value1
& 0xffffffffu
;
543 value
= frvbf_read_mem_SI (current_cpu
, pc
, address
);
544 value
= H2T_4 (value
);
546 value1
= frvbf_read_mem_SI (current_cpu
, pc
, address
+ 4);
547 value1
= H2T_4 (value1
);
548 value
|= value1
& 0xffffffffu
;
551 value
= frvbf_read_mem_DI (current_cpu
, pc
, address
- 3);
552 value
= H2T_8 (value
);
554 value1
= frvbf_read_mem_SI (current_cpu
, pc
, address
+ 5);
555 value1
= H2T_4 (value1
);
556 value
|= value1
& 0x00ffffff;
559 value
= frvbf_read_mem_DI (current_cpu
, pc
, address
- 2);
560 value
= H2T_8 (value
);
562 value1
= frvbf_read_mem_HI (current_cpu
, pc
, address
+ 6);
563 value1
= H2T_2 (value1
);
564 value
|= value1
& 0x0000ffff;
567 value
= frvbf_read_mem_DI (current_cpu
, pc
, address
- 1);
568 value
= H2T_8 (value
);
570 value1
= frvbf_read_mem_QI (current_cpu
, pc
, address
+ 7);
571 value
|= value1
& 0x000000ff;
574 abort (); /* can't happen */
576 return T2H_8 (value
);
580 frvbf_read_mem_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
585 /* Check for access exceptions. */
586 address
= check_data_read_address (current_cpu
, address
, 7);
587 address
= check_readwrite_address (current_cpu
, address
, 7);
589 /* If we need to count cycles, then the cache operation will be
590 initiated from the model profiling functions.
591 See frvbf_model_.... */
593 cache
= CPU_DATA_CACHE (current_cpu
);
596 CPU_LOAD_ADDRESS (current_cpu
) = address
;
597 CPU_LOAD_LENGTH (current_cpu
) = 8;
598 return 0x37111319; /* any random value */
601 if (GET_HSR0_DCE (hsr0
))
604 /* Handle access which crosses cache line boundary */
605 SIM_DESC sd
= CPU_STATE (current_cpu
);
606 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
608 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
609 return read_mem_unaligned_DI (current_cpu
, pc
, address
);
611 cycles
= frv_cache_read (cache
, 0, address
);
613 return CACHE_RETURN_DATA (cache
, 0, address
, DI
, 8);
616 return GETMEMDI (current_cpu
, pc
, address
);
620 frvbf_read_mem_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
)
625 /* Check for access exceptions. */
626 address
= check_data_read_address (current_cpu
, address
, 7);
627 address
= check_readwrite_address (current_cpu
, address
, 7);
629 /* If we need to count cycles, then the cache operation will be
630 initiated from the model profiling functions.
631 See frvbf_model_.... */
633 cache
= CPU_DATA_CACHE (current_cpu
);
636 CPU_LOAD_ADDRESS (current_cpu
) = address
;
637 CPU_LOAD_LENGTH (current_cpu
) = 8;
638 return 0x37111319; /* any random value */
641 if (GET_HSR0_DCE (hsr0
))
644 /* Handle access which crosses cache line boundary */
645 SIM_DESC sd
= CPU_STATE (current_cpu
);
646 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
648 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
649 return read_mem_unaligned_DI (current_cpu
, pc
, address
);
651 cycles
= frv_cache_read (cache
, 0, address
);
653 return CACHE_RETURN_DATA (cache
, 0, address
, DF
, 8);
656 return GETMEMDF (current_cpu
, pc
, address
);
660 frvbf_read_imem_USI (SIM_CPU
*current_cpu
, PCADDR vpc
)
663 vpc
= check_insn_read_address (current_cpu
, vpc
, 3);
666 if (GET_HSR0_ICE (hsr0
))
671 /* We don't want this to show up in the cache statistics. That read
672 is done in frvbf_simulate_insn_prefetch. So read the cache or memory
674 cache
= CPU_INSN_CACHE (current_cpu
);
675 if (frv_cache_read_passive_SI (cache
, vpc
, &value
))
678 return sim_core_read_unaligned_4 (current_cpu
, vpc
, read_map
, vpc
);
682 fr400_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
685 && address
>= 0xfe800000 && address
<= 0xfeffffff)
686 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
692 fr500_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
694 if (address
& align_mask
)
696 struct frv_interrupt_queue_element
*item
=
697 frv_queue_mem_address_not_aligned_interrupt (current_cpu
, address
);
698 /* Record the correct vliw slot with the interrupt. */
700 item
->slot
= frv_interrupt_state
.slot
;
701 address
&= ~align_mask
;
703 if (address
>= 0xfeff0600 && address
<= 0xfeff7fff
704 || address
>= 0xfe800000 && address
<= 0xfefeffff)
705 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
711 fr550_check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
713 if ((USI
)address
>= 0xfe800000 && (USI
)address
<= 0xfefeffff
715 && ((USI
)address
>= 0xfeff0000 && (USI
)address
<= 0xfeffffff)))
716 frv_queue_program_interrupt (current_cpu
, FRV_DATA_STORE_ERROR
);
722 check_write_address (SIM_CPU
*current_cpu
, SI address
, int align_mask
)
724 SIM_DESC sd
= CPU_STATE (current_cpu
);
725 switch (STATE_ARCHITECTURE (sd
)->mach
)
729 address
= fr400_check_write_address (current_cpu
, address
, align_mask
);
731 case bfd_mach_frvtomcat
:
734 address
= fr500_check_write_address (current_cpu
, address
, align_mask
);
737 address
= fr550_check_write_address (current_cpu
, address
, align_mask
);
746 frvbf_write_mem_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, QI value
)
750 if (GET_HSR0_DCE (hsr0
))
751 sim_queue_fn_mem_qi_write (current_cpu
, frvbf_mem_set_QI
, address
, value
);
753 sim_queue_mem_qi_write (current_cpu
, address
, value
);
754 frv_set_write_queue_slot (current_cpu
);
758 frvbf_write_mem_UQI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, UQI value
)
760 frvbf_write_mem_QI (current_cpu
, pc
, address
, value
);
764 frvbf_write_mem_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
768 if (GET_HSR0_DCE (hsr0
))
769 sim_queue_fn_mem_hi_write (current_cpu
, frvbf_mem_set_HI
, address
, value
);
771 sim_queue_mem_hi_write (current_cpu
, address
, value
);
772 frv_set_write_queue_slot (current_cpu
);
776 frvbf_write_mem_UHI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, UHI value
)
778 frvbf_write_mem_HI (current_cpu
, pc
, address
, value
);
782 frvbf_write_mem_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
786 if (GET_HSR0_DCE (hsr0
))
787 sim_queue_fn_mem_si_write (current_cpu
, frvbf_mem_set_SI
, address
, value
);
789 sim_queue_mem_si_write (current_cpu
, address
, value
);
790 frv_set_write_queue_slot (current_cpu
);
794 frvbf_write_mem_WI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
796 frvbf_write_mem_SI (current_cpu
, pc
, address
, value
);
800 frvbf_write_mem_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
804 if (GET_HSR0_DCE (hsr0
))
805 sim_queue_fn_mem_di_write (current_cpu
, frvbf_mem_set_DI
, address
, value
);
807 sim_queue_mem_di_write (current_cpu
, address
, value
);
808 frv_set_write_queue_slot (current_cpu
);
812 frvbf_write_mem_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DF value
)
816 if (GET_HSR0_DCE (hsr0
))
817 sim_queue_fn_mem_df_write (current_cpu
, frvbf_mem_set_DF
, address
, value
);
819 sim_queue_mem_df_write (current_cpu
, address
, value
);
820 frv_set_write_queue_slot (current_cpu
);
823 /* Memory writes. These do the actual writing through the cache. */
825 frvbf_mem_set_QI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, QI value
)
827 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
829 /* Check for access errors. */
830 address
= check_write_address (current_cpu
, address
, 0);
831 address
= check_readwrite_address (current_cpu
, address
, 0);
833 /* If we need to count cycles, then submit the write request to the cache
834 and let it prioritize the request. Otherwise perform the write now. */
838 frv_cache_request_store (cache
, address
, slot
, (char *)&value
,
842 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
845 /* Write a HI which spans two cache lines */
847 mem_set_unaligned_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
849 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
850 /* value is already in target byte order */
851 frv_cache_write (cache
, address
, (char *)&value
, 1);
852 frv_cache_write (cache
, address
+ 1, ((char *)&value
+ 1), 1);
856 frvbf_mem_set_HI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, HI value
)
860 /* Check for access errors. */
861 address
= check_write_address (current_cpu
, address
, 1);
862 address
= check_readwrite_address (current_cpu
, address
, 1);
864 /* If we need to count cycles, then submit the write request to the cache
865 and let it prioritize the request. Otherwise perform the write now. */
866 value
= H2T_2 (value
);
867 cache
= CPU_DATA_CACHE (current_cpu
);
871 frv_cache_request_store (cache
, address
, slot
,
872 (char *)&value
, sizeof (value
));
876 /* Handle access which crosses cache line boundary */
877 SIM_DESC sd
= CPU_STATE (current_cpu
);
878 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
880 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 2))
882 mem_set_unaligned_HI (current_cpu
, pc
, address
, value
);
886 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
890 /* Write a SI which spans two cache lines */
892 mem_set_unaligned_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
894 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
895 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
896 /* value is already in target byte order */
897 frv_cache_write (cache
, address
, (char *)&value
, hi_len
);
898 frv_cache_write (cache
, address
+ hi_len
, (char *)&value
+ hi_len
, 4 - hi_len
);
902 frvbf_mem_set_SI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI value
)
906 /* Check for access errors. */
907 address
= check_write_address (current_cpu
, address
, 3);
908 address
= check_readwrite_address (current_cpu
, address
, 3);
910 /* If we need to count cycles, then submit the write request to the cache
911 and let it prioritize the request. Otherwise perform the write now. */
912 cache
= CPU_DATA_CACHE (current_cpu
);
913 value
= H2T_4 (value
);
917 frv_cache_request_store (cache
, address
, slot
,
918 (char *)&value
, sizeof (value
));
922 /* Handle access which crosses cache line boundary */
923 SIM_DESC sd
= CPU_STATE (current_cpu
);
924 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
926 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 4))
928 mem_set_unaligned_SI (current_cpu
, pc
, address
, value
);
932 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
936 /* Write a DI which spans two cache lines */
938 mem_set_unaligned_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
940 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
941 unsigned hi_len
= cache
->line_size
- (address
& (cache
->line_size
- 1));
942 /* value is already in target byte order */
943 frv_cache_write (cache
, address
, (char *)&value
, hi_len
);
944 frv_cache_write (cache
, address
+ hi_len
, (char *)&value
+ hi_len
, 8 - hi_len
);
948 frvbf_mem_set_DI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DI value
)
952 /* Check for access errors. */
953 address
= check_write_address (current_cpu
, address
, 7);
954 address
= check_readwrite_address (current_cpu
, address
, 7);
956 /* If we need to count cycles, then submit the write request to the cache
957 and let it prioritize the request. Otherwise perform the write now. */
958 value
= H2T_8 (value
);
959 cache
= CPU_DATA_CACHE (current_cpu
);
963 frv_cache_request_store (cache
, address
, slot
,
964 (char *)&value
, sizeof (value
));
968 /* Handle access which crosses cache line boundary */
969 SIM_DESC sd
= CPU_STATE (current_cpu
);
970 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
972 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
974 mem_set_unaligned_DI (current_cpu
, pc
, address
, value
);
978 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
983 frvbf_mem_set_DF (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, DF value
)
987 /* Check for access errors. */
988 address
= check_write_address (current_cpu
, address
, 7);
989 address
= check_readwrite_address (current_cpu
, address
, 7);
991 /* If we need to count cycles, then submit the write request to the cache
992 and let it prioritize the request. Otherwise perform the write now. */
993 value
= H2T_8 (value
);
994 cache
= CPU_DATA_CACHE (current_cpu
);
998 frv_cache_request_store (cache
, address
, slot
,
999 (char *)&value
, sizeof (value
));
1003 /* Handle access which crosses cache line boundary */
1004 SIM_DESC sd
= CPU_STATE (current_cpu
);
1005 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
1007 if (DATA_CROSSES_CACHE_LINE (cache
, address
, 8))
1009 mem_set_unaligned_DI (current_cpu
, pc
, address
, value
);
1013 frv_cache_write (cache
, address
, (char *)&value
, sizeof (value
));
1018 frvbf_mem_set_XI (SIM_CPU
*current_cpu
, IADDR pc
, SI address
, SI
*value
)
1023 /* Check for access errors. */
1024 address
= check_write_address (current_cpu
, address
, 0xf);
1025 address
= check_readwrite_address (current_cpu
, address
, 0xf);
1027 /* TODO -- reverse word order as well? */
1028 for (i
= 0; i
< 4; ++i
)
1029 value
[i
] = H2T_4 (value
[i
]);
1031 /* If we need to count cycles, then submit the write request to the cache
1032 and let it prioritize the request. Otherwise perform the write now. */
1033 cache
= CPU_DATA_CACHE (current_cpu
);
1037 frv_cache_request_store (cache
, address
, slot
, (char*)value
, 16);
1040 frv_cache_write (cache
, address
, (char*)value
, 16);
1043 /* Record the current VLIW slot on the element at the top of the write queue.
1046 frv_set_write_queue_slot (SIM_CPU
*current_cpu
)
1048 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
1049 int slot
= vliw
->next_slot
- 1;
1050 CGEN_WRITE_QUEUE
*q
= CPU_WRITE_QUEUE (current_cpu
);
1051 int ix
= CGEN_WRITE_QUEUE_INDEX (q
) - 1;
1052 CGEN_WRITE_QUEUE_ELEMENT
*item
= CGEN_WRITE_QUEUE_ELEMENT (q
, ix
);
1053 CGEN_WRITE_QUEUE_ELEMENT_PIPE (item
) = (*vliw
->current_vliw
)[slot
];