No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gdb6 / sim / frv / memory.c
blob2249904133c34e1b1ba1a3e41d5075338930cbc9
1 /* frv memory model.
2 Copyright (C) 1999, 2000, 2001, 2003 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)
10 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 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
24 #include "sim-main.h"
25 #include "cgen-mem.h"
26 #include "bfd.h"
28 /* Check for alignment and access restrictions. Return the corrected address.
30 static SI
31 fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
33 /* Check access restrictions for double word loads only. */
34 if (align_mask == 7)
36 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
37 frv_queue_data_access_error_interrupt (current_cpu, address);
39 return address;
42 static SI
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);
55 return address;
58 static SI
59 fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
61 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
62 || (align_mask > 0x3
63 && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
64 frv_queue_data_access_error_interrupt (current_cpu, address);
66 return address;
69 static SI
70 check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
72 SIM_DESC sd = CPU_STATE (current_cpu);
73 switch (STATE_ARCHITECTURE (sd)->mach)
75 case bfd_mach_fr400:
76 case bfd_mach_fr450:
77 address = fr400_check_data_read_address (current_cpu, address,
78 align_mask);
79 break;
80 case bfd_mach_frvtomcat:
81 case bfd_mach_fr500:
82 case bfd_mach_frv:
83 address = fr500_check_data_read_address (current_cpu, address,
84 align_mask);
85 break;
86 case bfd_mach_fr550:
87 address = fr550_check_data_read_address (current_cpu, address,
88 align_mask);
89 break;
90 default:
91 break;
94 return address;
97 static SI
98 fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
100 if (address & align_mask)
102 /* Make sure that this exception is not masked. */
103 USI isr = GET_ISR ();
104 if (! GET_ISR_EMAM (isr))
106 /* Bad alignment causes a data_access_error on fr400. */
107 frv_queue_data_access_error_interrupt (current_cpu, address);
109 address &= ~align_mask;
111 /* Nothing to check. */
112 return address;
115 static SI
116 fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
118 if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff
119 || (USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
120 || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
121 || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
122 frv_queue_data_access_exception_interrupt (current_cpu);
124 return address;
127 static SI
128 fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
130 /* No alignment restrictions on fr550 */
132 if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff
133 || (USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff)
134 frv_queue_data_access_exception_interrupt (current_cpu);
135 else
137 USI hsr0 = GET_HSR0 ();
138 if (! GET_HSR0_RME (hsr0)
139 && (USI)address >= 0xfe400000 && (USI)address <= 0xfe407fff)
140 frv_queue_data_access_exception_interrupt (current_cpu);
143 return address;
146 static SI
147 check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
149 SIM_DESC sd = CPU_STATE (current_cpu);
150 switch (STATE_ARCHITECTURE (sd)->mach)
152 case bfd_mach_fr400:
153 case bfd_mach_fr450:
154 address = fr400_check_readwrite_address (current_cpu, address,
155 align_mask);
156 break;
157 case bfd_mach_frvtomcat:
158 case bfd_mach_fr500:
159 case bfd_mach_frv:
160 address = fr500_check_readwrite_address (current_cpu, address,
161 align_mask);
162 break;
163 case bfd_mach_fr550:
164 address = fr550_check_readwrite_address (current_cpu, address,
165 align_mask);
166 break;
167 default:
168 break;
171 return address;
174 static PCADDR
175 fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
176 int align_mask)
178 if (address & align_mask)
180 frv_queue_instruction_access_error_interrupt (current_cpu);
181 address &= ~align_mask;
183 else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
184 frv_queue_instruction_access_error_interrupt (current_cpu);
186 return address;
189 static PCADDR
190 fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
191 int align_mask)
193 if (address & align_mask)
195 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
196 address &= ~align_mask;
199 if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
200 || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
201 frv_queue_instruction_access_error_interrupt (current_cpu);
202 else if ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
203 || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
204 || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
205 frv_queue_instruction_access_exception_interrupt (current_cpu);
206 else
208 USI hsr0 = GET_HSR0 ();
209 if (! GET_HSR0_RME (hsr0)
210 && (USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff)
211 frv_queue_instruction_access_exception_interrupt (current_cpu);
214 return address;
217 static PCADDR
218 fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
219 int align_mask)
221 address &= ~align_mask;
223 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
224 frv_queue_instruction_access_error_interrupt (current_cpu);
225 else if ((USI)address >= 0xfe008000 && (USI)address <= 0xfe7fffff)
226 frv_queue_instruction_access_exception_interrupt (current_cpu);
227 else
229 USI hsr0 = GET_HSR0 ();
230 if (! GET_HSR0_RME (hsr0)
231 && (USI)address >= 0xfe000000 && (USI)address <= 0xfe007fff)
232 frv_queue_instruction_access_exception_interrupt (current_cpu);
235 return address;
238 static PCADDR
239 check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
241 SIM_DESC sd = CPU_STATE (current_cpu);
242 switch (STATE_ARCHITECTURE (sd)->mach)
244 case bfd_mach_fr400:
245 case bfd_mach_fr450:
246 address = fr400_check_insn_read_address (current_cpu, address,
247 align_mask);
248 break;
249 case bfd_mach_frvtomcat:
250 case bfd_mach_fr500:
251 case bfd_mach_frv:
252 address = fr500_check_insn_read_address (current_cpu, address,
253 align_mask);
254 break;
255 case bfd_mach_fr550:
256 address = fr550_check_insn_read_address (current_cpu, address,
257 align_mask);
258 break;
259 default:
260 break;
263 return address;
266 /* Memory reads. */
268 frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
270 USI hsr0 = GET_HSR0 ();
271 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
273 /* Check for access exceptions. */
274 address = check_data_read_address (current_cpu, address, 0);
275 address = check_readwrite_address (current_cpu, address, 0);
277 /* If we need to count cycles, then the cache operation will be
278 initiated from the model profiling functions.
279 See frvbf_model_.... */
280 if (model_insn)
282 CPU_LOAD_ADDRESS (current_cpu) = address;
283 CPU_LOAD_LENGTH (current_cpu) = 1;
284 CPU_LOAD_SIGNED (current_cpu) = 1;
285 return 0xb7; /* any random value */
288 if (GET_HSR0_DCE (hsr0))
290 int cycles;
291 cycles = frv_cache_read (cache, 0, address);
292 if (cycles != 0)
293 return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
296 return GETMEMQI (current_cpu, pc, address);
300 frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
302 USI hsr0 = GET_HSR0 ();
303 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
305 /* Check for access exceptions. */
306 address = check_data_read_address (current_cpu, address, 0);
307 address = check_readwrite_address (current_cpu, address, 0);
309 /* If we need to count cycles, then the cache operation will be
310 initiated from the model profiling functions.
311 See frvbf_model_.... */
312 if (model_insn)
314 CPU_LOAD_ADDRESS (current_cpu) = address;
315 CPU_LOAD_LENGTH (current_cpu) = 1;
316 CPU_LOAD_SIGNED (current_cpu) = 0;
317 return 0xb7; /* any random value */
320 if (GET_HSR0_DCE (hsr0))
322 int cycles;
323 cycles = frv_cache_read (cache, 0, address);
324 if (cycles != 0)
325 return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
328 return GETMEMUQI (current_cpu, pc, address);
331 /* Read a HI which spans two cache lines */
332 static HI
333 read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
335 HI value = frvbf_read_mem_QI (current_cpu, pc, address);
336 value <<= 8;
337 value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1);
338 return T2H_2 (value);
342 frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
344 USI hsr0;
345 FRV_CACHE *cache;
347 /* Check for access exceptions. */
348 address = check_data_read_address (current_cpu, address, 1);
349 address = check_readwrite_address (current_cpu, address, 1);
351 /* If we need to count cycles, then the cache operation will be
352 initiated from the model profiling functions.
353 See frvbf_model_.... */
354 hsr0 = GET_HSR0 ();
355 cache = CPU_DATA_CACHE (current_cpu);
356 if (model_insn)
358 CPU_LOAD_ADDRESS (current_cpu) = address;
359 CPU_LOAD_LENGTH (current_cpu) = 2;
360 CPU_LOAD_SIGNED (current_cpu) = 1;
361 return 0xb711; /* any random value */
364 if (GET_HSR0_DCE (hsr0))
366 int cycles;
367 /* Handle access which crosses cache line boundary */
368 SIM_DESC sd = CPU_STATE (current_cpu);
369 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
371 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
372 return read_mem_unaligned_HI (current_cpu, pc, address);
374 cycles = frv_cache_read (cache, 0, address);
375 if (cycles != 0)
376 return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
379 return GETMEMHI (current_cpu, pc, address);
383 frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
385 USI hsr0;
386 FRV_CACHE *cache;
388 /* Check for access exceptions. */
389 address = check_data_read_address (current_cpu, address, 1);
390 address = check_readwrite_address (current_cpu, address, 1);
392 /* If we need to count cycles, then the cache operation will be
393 initiated from the model profiling functions.
394 See frvbf_model_.... */
395 hsr0 = GET_HSR0 ();
396 cache = CPU_DATA_CACHE (current_cpu);
397 if (model_insn)
399 CPU_LOAD_ADDRESS (current_cpu) = address;
400 CPU_LOAD_LENGTH (current_cpu) = 2;
401 CPU_LOAD_SIGNED (current_cpu) = 0;
402 return 0xb711; /* any random value */
405 if (GET_HSR0_DCE (hsr0))
407 int cycles;
408 /* Handle access which crosses cache line boundary */
409 SIM_DESC sd = CPU_STATE (current_cpu);
410 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
412 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
413 return read_mem_unaligned_HI (current_cpu, pc, address);
415 cycles = frv_cache_read (cache, 0, address);
416 if (cycles != 0)
417 return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
420 return GETMEMUHI (current_cpu, pc, address);
423 /* Read a SI which spans two cache lines */
424 static SI
425 read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
427 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
428 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
429 char valarray[4];
430 SI SIvalue;
431 HI HIvalue;
433 switch (hi_len)
435 case 1:
436 valarray[0] = frvbf_read_mem_QI (current_cpu, pc, address);
437 SIvalue = frvbf_read_mem_SI (current_cpu, pc, address + 1);
438 SIvalue = H2T_4 (SIvalue);
439 memcpy (valarray + 1, (char*)&SIvalue, 3);
440 break;
441 case 2:
442 HIvalue = frvbf_read_mem_HI (current_cpu, pc, address);
443 HIvalue = H2T_2 (HIvalue);
444 memcpy (valarray, (char*)&HIvalue, 2);
445 HIvalue = frvbf_read_mem_HI (current_cpu, pc, address + 2);
446 HIvalue = H2T_2 (HIvalue);
447 memcpy (valarray + 2, (char*)&HIvalue, 2);
448 break;
449 case 3:
450 SIvalue = frvbf_read_mem_SI (current_cpu, pc, address - 1);
451 SIvalue = H2T_4 (SIvalue);
452 memcpy (valarray, (char*)&SIvalue, 3);
453 valarray[3] = frvbf_read_mem_QI (current_cpu, pc, address + 3);
454 break;
455 default:
456 abort (); /* can't happen */
458 return T2H_4 (*(SI*)valarray);
462 frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
464 FRV_CACHE *cache;
465 USI hsr0;
467 /* Check for access exceptions. */
468 address = check_data_read_address (current_cpu, address, 3);
469 address = check_readwrite_address (current_cpu, address, 3);
471 hsr0 = GET_HSR0 ();
472 cache = CPU_DATA_CACHE (current_cpu);
473 /* If we need to count cycles, then the cache operation will be
474 initiated from the model profiling functions.
475 See frvbf_model_.... */
476 if (model_insn)
478 CPU_LOAD_ADDRESS (current_cpu) = address;
479 CPU_LOAD_LENGTH (current_cpu) = 4;
480 return 0x37111319; /* any random value */
483 if (GET_HSR0_DCE (hsr0))
485 int cycles;
486 /* Handle access which crosses cache line boundary */
487 SIM_DESC sd = CPU_STATE (current_cpu);
488 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
490 if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
491 return read_mem_unaligned_SI (current_cpu, pc, address);
493 cycles = frv_cache_read (cache, 0, address);
494 if (cycles != 0)
495 return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
498 return GETMEMSI (current_cpu, pc, address);
502 frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
504 return frvbf_read_mem_SI (current_cpu, pc, address);
507 /* Read a SI which spans two cache lines */
508 static DI
509 read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
511 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
512 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
513 DI value, value1;
515 switch (hi_len)
517 case 1:
518 value = frvbf_read_mem_QI (current_cpu, pc, address);
519 value <<= 56;
520 value1 = frvbf_read_mem_DI (current_cpu, pc, address + 1);
521 value1 = H2T_8 (value1);
522 value |= value1 & ((DI)0x00ffffff << 32);
523 value |= value1 & 0xffffffffu;
524 break;
525 case 2:
526 value = frvbf_read_mem_HI (current_cpu, pc, address);
527 value = H2T_2 (value);
528 value <<= 48;
529 value1 = frvbf_read_mem_DI (current_cpu, pc, address + 2);
530 value1 = H2T_8 (value1);
531 value |= value1 & ((DI)0x0000ffff << 32);
532 value |= value1 & 0xffffffffu;
533 break;
534 case 3:
535 value = frvbf_read_mem_SI (current_cpu, pc, address - 1);
536 value = H2T_4 (value);
537 value <<= 40;
538 value1 = frvbf_read_mem_DI (current_cpu, pc, address + 3);
539 value1 = H2T_8 (value1);
540 value |= value1 & ((DI)0x000000ff << 32);
541 value |= value1 & 0xffffffffu;
542 break;
543 case 4:
544 value = frvbf_read_mem_SI (current_cpu, pc, address);
545 value = H2T_4 (value);
546 value <<= 32;
547 value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4);
548 value1 = H2T_4 (value1);
549 value |= value1 & 0xffffffffu;
550 break;
551 case 5:
552 value = frvbf_read_mem_DI (current_cpu, pc, address - 3);
553 value = H2T_8 (value);
554 value <<= 24;
555 value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5);
556 value1 = H2T_4 (value1);
557 value |= value1 & 0x00ffffff;
558 break;
559 case 6:
560 value = frvbf_read_mem_DI (current_cpu, pc, address - 2);
561 value = H2T_8 (value);
562 value <<= 16;
563 value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6);
564 value1 = H2T_2 (value1);
565 value |= value1 & 0x0000ffff;
566 break;
567 case 7:
568 value = frvbf_read_mem_DI (current_cpu, pc, address - 1);
569 value = H2T_8 (value);
570 value <<= 8;
571 value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7);
572 value |= value1 & 0x000000ff;
573 break;
574 default:
575 abort (); /* can't happen */
577 return T2H_8 (value);
581 frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
583 USI hsr0;
584 FRV_CACHE *cache;
586 /* Check for access exceptions. */
587 address = check_data_read_address (current_cpu, address, 7);
588 address = check_readwrite_address (current_cpu, address, 7);
590 /* If we need to count cycles, then the cache operation will be
591 initiated from the model profiling functions.
592 See frvbf_model_.... */
593 hsr0 = GET_HSR0 ();
594 cache = CPU_DATA_CACHE (current_cpu);
595 if (model_insn)
597 CPU_LOAD_ADDRESS (current_cpu) = address;
598 CPU_LOAD_LENGTH (current_cpu) = 8;
599 return 0x37111319; /* any random value */
602 if (GET_HSR0_DCE (hsr0))
604 int cycles;
605 /* Handle access which crosses cache line boundary */
606 SIM_DESC sd = CPU_STATE (current_cpu);
607 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
609 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
610 return read_mem_unaligned_DI (current_cpu, pc, address);
612 cycles = frv_cache_read (cache, 0, address);
613 if (cycles != 0)
614 return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
617 return GETMEMDI (current_cpu, pc, address);
621 frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
623 USI hsr0;
624 FRV_CACHE *cache;
626 /* Check for access exceptions. */
627 address = check_data_read_address (current_cpu, address, 7);
628 address = check_readwrite_address (current_cpu, address, 7);
630 /* If we need to count cycles, then the cache operation will be
631 initiated from the model profiling functions.
632 See frvbf_model_.... */
633 hsr0 = GET_HSR0 ();
634 cache = CPU_DATA_CACHE (current_cpu);
635 if (model_insn)
637 CPU_LOAD_ADDRESS (current_cpu) = address;
638 CPU_LOAD_LENGTH (current_cpu) = 8;
639 return 0x37111319; /* any random value */
642 if (GET_HSR0_DCE (hsr0))
644 int cycles;
645 /* Handle access which crosses cache line boundary */
646 SIM_DESC sd = CPU_STATE (current_cpu);
647 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
649 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
650 return read_mem_unaligned_DI (current_cpu, pc, address);
652 cycles = frv_cache_read (cache, 0, address);
653 if (cycles != 0)
654 return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
657 return GETMEMDF (current_cpu, pc, address);
661 frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
663 USI hsr0;
664 vpc = check_insn_read_address (current_cpu, vpc, 3);
666 hsr0 = GET_HSR0 ();
667 if (GET_HSR0_ICE (hsr0))
669 FRV_CACHE *cache;
670 USI value;
672 /* We don't want this to show up in the cache statistics. That read
673 is done in frvbf_simulate_insn_prefetch. So read the cache or memory
674 passively here. */
675 cache = CPU_INSN_CACHE (current_cpu);
676 if (frv_cache_read_passive_SI (cache, vpc, &value))
677 return value;
679 return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
682 static SI
683 fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
685 if (align_mask == 7
686 && address >= 0xfe800000 && address <= 0xfeffffff)
687 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
689 return address;
692 static SI
693 fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
695 if (address & align_mask)
697 struct frv_interrupt_queue_element *item =
698 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
699 /* Record the correct vliw slot with the interrupt. */
700 if (item != NULL)
701 item->slot = frv_interrupt_state.slot;
702 address &= ~align_mask;
704 if (address >= 0xfeff0600 && address <= 0xfeff7fff
705 || address >= 0xfe800000 && address <= 0xfefeffff)
706 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
708 return address;
711 static SI
712 fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
714 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
715 || (align_mask > 0x3
716 && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
717 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
719 return address;
722 static SI
723 check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
725 SIM_DESC sd = CPU_STATE (current_cpu);
726 switch (STATE_ARCHITECTURE (sd)->mach)
728 case bfd_mach_fr400:
729 case bfd_mach_fr450:
730 address = fr400_check_write_address (current_cpu, address, align_mask);
731 break;
732 case bfd_mach_frvtomcat:
733 case bfd_mach_fr500:
734 case bfd_mach_frv:
735 address = fr500_check_write_address (current_cpu, address, align_mask);
736 break;
737 case bfd_mach_fr550:
738 address = fr550_check_write_address (current_cpu, address, align_mask);
739 break;
740 default:
741 break;
743 return address;
746 void
747 frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
749 USI hsr0;
750 hsr0 = GET_HSR0 ();
751 if (GET_HSR0_DCE (hsr0))
752 sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
753 else
754 sim_queue_mem_qi_write (current_cpu, address, value);
755 frv_set_write_queue_slot (current_cpu);
758 void
759 frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
761 frvbf_write_mem_QI (current_cpu, pc, address, value);
764 void
765 frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
767 USI hsr0;
768 hsr0 = GET_HSR0 ();
769 if (GET_HSR0_DCE (hsr0))
770 sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
771 else
772 sim_queue_mem_hi_write (current_cpu, address, value);
773 frv_set_write_queue_slot (current_cpu);
776 void
777 frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
779 frvbf_write_mem_HI (current_cpu, pc, address, value);
782 void
783 frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
785 USI hsr0;
786 hsr0 = GET_HSR0 ();
787 if (GET_HSR0_DCE (hsr0))
788 sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
789 else
790 sim_queue_mem_si_write (current_cpu, address, value);
791 frv_set_write_queue_slot (current_cpu);
794 void
795 frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
797 frvbf_write_mem_SI (current_cpu, pc, address, value);
800 void
801 frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
803 USI hsr0;
804 hsr0 = GET_HSR0 ();
805 if (GET_HSR0_DCE (hsr0))
806 sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
807 else
808 sim_queue_mem_di_write (current_cpu, address, value);
809 frv_set_write_queue_slot (current_cpu);
812 void
813 frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
815 USI hsr0;
816 hsr0 = GET_HSR0 ();
817 if (GET_HSR0_DCE (hsr0))
818 sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
819 else
820 sim_queue_mem_df_write (current_cpu, address, value);
821 frv_set_write_queue_slot (current_cpu);
824 /* Memory writes. These do the actual writing through the cache. */
825 void
826 frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
828 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
830 /* Check for access errors. */
831 address = check_write_address (current_cpu, address, 0);
832 address = check_readwrite_address (current_cpu, address, 0);
834 /* If we need to count cycles, then submit the write request to the cache
835 and let it prioritize the request. Otherwise perform the write now. */
836 if (model_insn)
838 int slot = UNIT_I0;
839 frv_cache_request_store (cache, address, slot, (char *)&value,
840 sizeof (value));
842 else
843 frv_cache_write (cache, address, (char *)&value, sizeof (value));
846 /* Write a HI which spans two cache lines */
847 static void
848 mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
850 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
851 /* value is already in target byte order */
852 frv_cache_write (cache, address, (char *)&value, 1);
853 frv_cache_write (cache, address + 1, ((char *)&value + 1), 1);
856 void
857 frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
859 FRV_CACHE *cache;
861 /* Check for access errors. */
862 address = check_write_address (current_cpu, address, 1);
863 address = check_readwrite_address (current_cpu, address, 1);
865 /* If we need to count cycles, then submit the write request to the cache
866 and let it prioritize the request. Otherwise perform the write now. */
867 value = H2T_2 (value);
868 cache = CPU_DATA_CACHE (current_cpu);
869 if (model_insn)
871 int slot = UNIT_I0;
872 frv_cache_request_store (cache, address, slot,
873 (char *)&value, sizeof (value));
875 else
877 /* Handle access which crosses cache line boundary */
878 SIM_DESC sd = CPU_STATE (current_cpu);
879 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
881 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
883 mem_set_unaligned_HI (current_cpu, pc, address, value);
884 return;
887 frv_cache_write (cache, address, (char *)&value, sizeof (value));
891 /* Write a SI which spans two cache lines */
892 static void
893 mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
895 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
896 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
897 /* value is already in target byte order */
898 frv_cache_write (cache, address, (char *)&value, hi_len);
899 frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 4 - hi_len);
902 void
903 frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
905 FRV_CACHE *cache;
907 /* Check for access errors. */
908 address = check_write_address (current_cpu, address, 3);
909 address = check_readwrite_address (current_cpu, address, 3);
911 /* If we need to count cycles, then submit the write request to the cache
912 and let it prioritize the request. Otherwise perform the write now. */
913 cache = CPU_DATA_CACHE (current_cpu);
914 value = H2T_4 (value);
915 if (model_insn)
917 int slot = UNIT_I0;
918 frv_cache_request_store (cache, address, slot,
919 (char *)&value, sizeof (value));
921 else
923 /* Handle access which crosses cache line boundary */
924 SIM_DESC sd = CPU_STATE (current_cpu);
925 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
927 if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
929 mem_set_unaligned_SI (current_cpu, pc, address, value);
930 return;
933 frv_cache_write (cache, address, (char *)&value, sizeof (value));
937 /* Write a DI which spans two cache lines */
938 static void
939 mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
941 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
942 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
943 /* value is already in target byte order */
944 frv_cache_write (cache, address, (char *)&value, hi_len);
945 frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 8 - hi_len);
948 void
949 frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
951 FRV_CACHE *cache;
953 /* Check for access errors. */
954 address = check_write_address (current_cpu, address, 7);
955 address = check_readwrite_address (current_cpu, address, 7);
957 /* If we need to count cycles, then submit the write request to the cache
958 and let it prioritize the request. Otherwise perform the write now. */
959 value = H2T_8 (value);
960 cache = CPU_DATA_CACHE (current_cpu);
961 if (model_insn)
963 int slot = UNIT_I0;
964 frv_cache_request_store (cache, address, slot,
965 (char *)&value, sizeof (value));
967 else
969 /* Handle access which crosses cache line boundary */
970 SIM_DESC sd = CPU_STATE (current_cpu);
971 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
973 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
975 mem_set_unaligned_DI (current_cpu, pc, address, value);
976 return;
979 frv_cache_write (cache, address, (char *)&value, sizeof (value));
983 void
984 frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
986 FRV_CACHE *cache;
988 /* Check for access errors. */
989 address = check_write_address (current_cpu, address, 7);
990 address = check_readwrite_address (current_cpu, address, 7);
992 /* If we need to count cycles, then submit the write request to the cache
993 and let it prioritize the request. Otherwise perform the write now. */
994 value = H2T_8 (value);
995 cache = CPU_DATA_CACHE (current_cpu);
996 if (model_insn)
998 int slot = UNIT_I0;
999 frv_cache_request_store (cache, address, slot,
1000 (char *)&value, sizeof (value));
1002 else
1004 /* Handle access which crosses cache line boundary */
1005 SIM_DESC sd = CPU_STATE (current_cpu);
1006 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
1008 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
1010 mem_set_unaligned_DI (current_cpu, pc, address, value);
1011 return;
1014 frv_cache_write (cache, address, (char *)&value, sizeof (value));
1018 void
1019 frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
1021 int i;
1022 FRV_CACHE *cache;
1024 /* Check for access errors. */
1025 address = check_write_address (current_cpu, address, 0xf);
1026 address = check_readwrite_address (current_cpu, address, 0xf);
1028 /* TODO -- reverse word order as well? */
1029 for (i = 0; i < 4; ++i)
1030 value[i] = H2T_4 (value[i]);
1032 /* If we need to count cycles, then submit the write request to the cache
1033 and let it prioritize the request. Otherwise perform the write now. */
1034 cache = CPU_DATA_CACHE (current_cpu);
1035 if (model_insn)
1037 int slot = UNIT_I0;
1038 frv_cache_request_store (cache, address, slot, (char*)value, 16);
1040 else
1041 frv_cache_write (cache, address, (char*)value, 16);
1044 /* Record the current VLIW slot on the element at the top of the write queue.
1046 void
1047 frv_set_write_queue_slot (SIM_CPU *current_cpu)
1049 FRV_VLIW *vliw = CPU_VLIW (current_cpu);
1050 int slot = vliw->next_slot - 1;
1051 CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
1052 int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1;
1053 CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix);
1054 CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot];