]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/frv/memory.c
sim: switch config.h usage to defs.h
[thirdparty/binutils-gdb.git] / sim / frv / memory.c
1 /* frv memory model.
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 Contributed by Red Hat
4
5 This file is part of the GNU simulators.
6
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.
11
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.
16
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/>. */
19
20 /* This must come before any other includes. */
21 #include "defs.h"
22
23 #define WANT_CPU frvbf
24 #define WANT_CPU_FRVBF
25
26 #include "sim-main.h"
27 #include "cgen-mem.h"
28 #include "bfd.h"
29 #include <stdlib.h>
30
31 /* Check for alignment and access restrictions. Return the corrected address.
32 */
33 static SI
34 fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
35 {
36 /* Check access restrictions for double word loads only. */
37 if (align_mask == 7)
38 {
39 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
40 frv_queue_data_access_error_interrupt (current_cpu, address);
41 }
42 return address;
43 }
44
45 static SI
46 fr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
47 {
48 if (address & align_mask)
49 {
50 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
51 address &= ~align_mask;
52 }
53
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);
57
58 return address;
59 }
60
61 static SI
62 fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
63 {
64 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
65 || (align_mask > 0x3
66 && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
67 frv_queue_data_access_error_interrupt (current_cpu, address);
68
69 return address;
70 }
71
72 static SI
73 check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
74 {
75 SIM_DESC sd = CPU_STATE (current_cpu);
76 switch (STATE_ARCHITECTURE (sd)->mach)
77 {
78 case bfd_mach_fr400:
79 case bfd_mach_fr450:
80 address = fr400_check_data_read_address (current_cpu, address,
81 align_mask);
82 break;
83 case bfd_mach_frvtomcat:
84 case bfd_mach_fr500:
85 case bfd_mach_frv:
86 address = fr500_check_data_read_address (current_cpu, address,
87 align_mask);
88 break;
89 case bfd_mach_fr550:
90 address = fr550_check_data_read_address (current_cpu, address,
91 align_mask);
92 break;
93 default:
94 break;
95 }
96
97 return address;
98 }
99
100 static SI
101 fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
102 {
103 if (address & align_mask)
104 {
105 /* Make sure that this exception is not masked. */
106 USI isr = GET_ISR ();
107 if (! GET_ISR_EMAM (isr))
108 {
109 /* Bad alignment causes a data_access_error on fr400. */
110 frv_queue_data_access_error_interrupt (current_cpu, address);
111 }
112 address &= ~align_mask;
113 }
114 /* Nothing to check. */
115 return address;
116 }
117
118 static SI
119 fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
120 {
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);
126
127 return address;
128 }
129
130 static SI
131 fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
132 {
133 /* No alignment restrictions on fr550 */
134
135 if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff
136 || (USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff)
137 frv_queue_data_access_exception_interrupt (current_cpu);
138 else
139 {
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);
144 }
145
146 return address;
147 }
148
149 static SI
150 check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
151 {
152 SIM_DESC sd = CPU_STATE (current_cpu);
153 switch (STATE_ARCHITECTURE (sd)->mach)
154 {
155 case bfd_mach_fr400:
156 case bfd_mach_fr450:
157 address = fr400_check_readwrite_address (current_cpu, address,
158 align_mask);
159 break;
160 case bfd_mach_frvtomcat:
161 case bfd_mach_fr500:
162 case bfd_mach_frv:
163 address = fr500_check_readwrite_address (current_cpu, address,
164 align_mask);
165 break;
166 case bfd_mach_fr550:
167 address = fr550_check_readwrite_address (current_cpu, address,
168 align_mask);
169 break;
170 default:
171 break;
172 }
173
174 return address;
175 }
176
177 static PCADDR
178 fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
179 int align_mask)
180 {
181 if (address & align_mask)
182 {
183 frv_queue_instruction_access_error_interrupt (current_cpu);
184 address &= ~align_mask;
185 }
186 else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
187 frv_queue_instruction_access_error_interrupt (current_cpu);
188
189 return address;
190 }
191
192 static PCADDR
193 fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
194 int align_mask)
195 {
196 if (address & align_mask)
197 {
198 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
199 address &= ~align_mask;
200 }
201
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);
209 else
210 {
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);
215 }
216
217 return address;
218 }
219
220 static PCADDR
221 fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
222 int align_mask)
223 {
224 address &= ~align_mask;
225
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);
230 else
231 {
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);
236 }
237
238 return address;
239 }
240
241 static PCADDR
242 check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
243 {
244 SIM_DESC sd = CPU_STATE (current_cpu);
245 switch (STATE_ARCHITECTURE (sd)->mach)
246 {
247 case bfd_mach_fr400:
248 case bfd_mach_fr450:
249 address = fr400_check_insn_read_address (current_cpu, address,
250 align_mask);
251 break;
252 case bfd_mach_frvtomcat:
253 case bfd_mach_fr500:
254 case bfd_mach_frv:
255 address = fr500_check_insn_read_address (current_cpu, address,
256 align_mask);
257 break;
258 case bfd_mach_fr550:
259 address = fr550_check_insn_read_address (current_cpu, address,
260 align_mask);
261 break;
262 default:
263 break;
264 }
265
266 return address;
267 }
268
269 /* Memory reads. */
270 QI
271 frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
272 {
273 USI hsr0 = GET_HSR0 ();
274 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
275
276 /* Check for access exceptions. */
277 address = check_data_read_address (current_cpu, address, 0);
278 address = check_readwrite_address (current_cpu, address, 0);
279
280 /* If we need to count cycles, then the cache operation will be
281 initiated from the model profiling functions.
282 See frvbf_model_.... */
283 if (model_insn)
284 {
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 */
289 }
290
291 if (GET_HSR0_DCE (hsr0))
292 {
293 int cycles;
294 cycles = frv_cache_read (cache, 0, address);
295 if (cycles != 0)
296 return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
297 }
298
299 return GETMEMQI (current_cpu, pc, address);
300 }
301
302 UQI
303 frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
304 {
305 USI hsr0 = GET_HSR0 ();
306 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
307
308 /* Check for access exceptions. */
309 address = check_data_read_address (current_cpu, address, 0);
310 address = check_readwrite_address (current_cpu, address, 0);
311
312 /* If we need to count cycles, then the cache operation will be
313 initiated from the model profiling functions.
314 See frvbf_model_.... */
315 if (model_insn)
316 {
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 */
321 }
322
323 if (GET_HSR0_DCE (hsr0))
324 {
325 int cycles;
326 cycles = frv_cache_read (cache, 0, address);
327 if (cycles != 0)
328 return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
329 }
330
331 return GETMEMUQI (current_cpu, pc, address);
332 }
333
334 /* Read a HI which spans two cache lines */
335 static HI
336 read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
337 {
338 HI value = frvbf_read_mem_QI (current_cpu, pc, address);
339 value <<= 8;
340 value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1);
341 return T2H_2 (value);
342 }
343
344 HI
345 frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
346 {
347 USI hsr0;
348 FRV_CACHE *cache;
349
350 /* Check for access exceptions. */
351 address = check_data_read_address (current_cpu, address, 1);
352 address = check_readwrite_address (current_cpu, address, 1);
353
354 /* If we need to count cycles, then the cache operation will be
355 initiated from the model profiling functions.
356 See frvbf_model_.... */
357 hsr0 = GET_HSR0 ();
358 cache = CPU_DATA_CACHE (current_cpu);
359 if (model_insn)
360 {
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 */
365 }
366
367 if (GET_HSR0_DCE (hsr0))
368 {
369 int cycles;
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)
373 {
374 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
375 return read_mem_unaligned_HI (current_cpu, pc, address);
376 }
377 cycles = frv_cache_read (cache, 0, address);
378 if (cycles != 0)
379 return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
380 }
381
382 return GETMEMHI (current_cpu, pc, address);
383 }
384
385 UHI
386 frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
387 {
388 USI hsr0;
389 FRV_CACHE *cache;
390
391 /* Check for access exceptions. */
392 address = check_data_read_address (current_cpu, address, 1);
393 address = check_readwrite_address (current_cpu, address, 1);
394
395 /* If we need to count cycles, then the cache operation will be
396 initiated from the model profiling functions.
397 See frvbf_model_.... */
398 hsr0 = GET_HSR0 ();
399 cache = CPU_DATA_CACHE (current_cpu);
400 if (model_insn)
401 {
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 */
406 }
407
408 if (GET_HSR0_DCE (hsr0))
409 {
410 int cycles;
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)
414 {
415 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
416 return read_mem_unaligned_HI (current_cpu, pc, address);
417 }
418 cycles = frv_cache_read (cache, 0, address);
419 if (cycles != 0)
420 return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
421 }
422
423 return GETMEMUHI (current_cpu, pc, address);
424 }
425
426 /* Read a SI which spans two cache lines */
427 static SI
428 read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
429 {
430 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
431 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
432 char valarray[4];
433 SI SIvalue;
434 HI HIvalue;
435
436 switch (hi_len)
437 {
438 case 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);
443 break;
444 case 2:
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);
451 break;
452 case 3:
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);
457 break;
458 default:
459 abort (); /* can't happen */
460 }
461 return T2H_4 (*(SI*)valarray);
462 }
463
464 SI
465 frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
466 {
467 FRV_CACHE *cache;
468 USI hsr0;
469
470 /* Check for access exceptions. */
471 address = check_data_read_address (current_cpu, address, 3);
472 address = check_readwrite_address (current_cpu, address, 3);
473
474 hsr0 = GET_HSR0 ();
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_.... */
479 if (model_insn)
480 {
481 CPU_LOAD_ADDRESS (current_cpu) = address;
482 CPU_LOAD_LENGTH (current_cpu) = 4;
483 return 0x37111319; /* any random value */
484 }
485
486 if (GET_HSR0_DCE (hsr0))
487 {
488 int cycles;
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)
492 {
493 if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
494 return read_mem_unaligned_SI (current_cpu, pc, address);
495 }
496 cycles = frv_cache_read (cache, 0, address);
497 if (cycles != 0)
498 return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
499 }
500
501 return GETMEMSI (current_cpu, pc, address);
502 }
503
504 SI
505 frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
506 {
507 return frvbf_read_mem_SI (current_cpu, pc, address);
508 }
509
510 /* Read a SI which spans two cache lines */
511 static DI
512 read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
513 {
514 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
515 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
516 DI value, value1;
517
518 switch (hi_len)
519 {
520 case 1:
521 value = frvbf_read_mem_QI (current_cpu, pc, address);
522 value <<= 56;
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;
527 break;
528 case 2:
529 value = frvbf_read_mem_HI (current_cpu, pc, address);
530 value = H2T_2 (value);
531 value <<= 48;
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;
536 break;
537 case 3:
538 value = frvbf_read_mem_SI (current_cpu, pc, address - 1);
539 value = H2T_4 (value);
540 value <<= 40;
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;
545 break;
546 case 4:
547 value = frvbf_read_mem_SI (current_cpu, pc, address);
548 value = H2T_4 (value);
549 value <<= 32;
550 value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4);
551 value1 = H2T_4 (value1);
552 value |= value1 & 0xffffffffu;
553 break;
554 case 5:
555 value = frvbf_read_mem_DI (current_cpu, pc, address - 3);
556 value = H2T_8 (value);
557 value <<= 24;
558 value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5);
559 value1 = H2T_4 (value1);
560 value |= value1 & 0x00ffffff;
561 break;
562 case 6:
563 value = frvbf_read_mem_DI (current_cpu, pc, address - 2);
564 value = H2T_8 (value);
565 value <<= 16;
566 value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6);
567 value1 = H2T_2 (value1);
568 value |= value1 & 0x0000ffff;
569 break;
570 case 7:
571 value = frvbf_read_mem_DI (current_cpu, pc, address - 1);
572 value = H2T_8 (value);
573 value <<= 8;
574 value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7);
575 value |= value1 & 0x000000ff;
576 break;
577 default:
578 abort (); /* can't happen */
579 }
580 return T2H_8 (value);
581 }
582
583 DI
584 frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
585 {
586 USI hsr0;
587 FRV_CACHE *cache;
588
589 /* Check for access exceptions. */
590 address = check_data_read_address (current_cpu, address, 7);
591 address = check_readwrite_address (current_cpu, address, 7);
592
593 /* If we need to count cycles, then the cache operation will be
594 initiated from the model profiling functions.
595 See frvbf_model_.... */
596 hsr0 = GET_HSR0 ();
597 cache = CPU_DATA_CACHE (current_cpu);
598 if (model_insn)
599 {
600 CPU_LOAD_ADDRESS (current_cpu) = address;
601 CPU_LOAD_LENGTH (current_cpu) = 8;
602 return 0x37111319; /* any random value */
603 }
604
605 if (GET_HSR0_DCE (hsr0))
606 {
607 int cycles;
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)
611 {
612 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
613 return read_mem_unaligned_DI (current_cpu, pc, address);
614 }
615 cycles = frv_cache_read (cache, 0, address);
616 if (cycles != 0)
617 return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
618 }
619
620 return GETMEMDI (current_cpu, pc, address);
621 }
622
623 DF
624 frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
625 {
626 USI hsr0;
627 FRV_CACHE *cache;
628
629 /* Check for access exceptions. */
630 address = check_data_read_address (current_cpu, address, 7);
631 address = check_readwrite_address (current_cpu, address, 7);
632
633 /* If we need to count cycles, then the cache operation will be
634 initiated from the model profiling functions.
635 See frvbf_model_.... */
636 hsr0 = GET_HSR0 ();
637 cache = CPU_DATA_CACHE (current_cpu);
638 if (model_insn)
639 {
640 CPU_LOAD_ADDRESS (current_cpu) = address;
641 CPU_LOAD_LENGTH (current_cpu) = 8;
642 return 0x37111319; /* any random value */
643 }
644
645 if (GET_HSR0_DCE (hsr0))
646 {
647 int cycles;
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)
651 {
652 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
653 return read_mem_unaligned_DI (current_cpu, pc, address);
654 }
655 cycles = frv_cache_read (cache, 0, address);
656 if (cycles != 0)
657 return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
658 }
659
660 return GETMEMDF (current_cpu, pc, address);
661 }
662
663 USI
664 frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
665 {
666 USI hsr0;
667 vpc = check_insn_read_address (current_cpu, vpc, 3);
668
669 hsr0 = GET_HSR0 ();
670 if (GET_HSR0_ICE (hsr0))
671 {
672 FRV_CACHE *cache;
673 USI value;
674
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
677 passively here. */
678 cache = CPU_INSN_CACHE (current_cpu);
679 if (frv_cache_read_passive_SI (cache, vpc, &value))
680 return value;
681 }
682 return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
683 }
684
685 static SI
686 fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
687 {
688 if (align_mask == 7
689 && address >= 0xfe800000 && address <= 0xfeffffff)
690 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
691
692 return address;
693 }
694
695 static SI
696 fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
697 {
698 if (address & align_mask)
699 {
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. */
703 if (item != NULL)
704 item->slot = frv_interrupt_state.slot;
705 address &= ~align_mask;
706 }
707 if (address >= 0xfeff0600 && address <= 0xfeff7fff
708 || address >= 0xfe800000 && address <= 0xfefeffff)
709 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
710
711 return address;
712 }
713
714 static SI
715 fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
716 {
717 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
718 || (align_mask > 0x3
719 && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
720 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
721
722 return address;
723 }
724
725 static SI
726 check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
727 {
728 SIM_DESC sd = CPU_STATE (current_cpu);
729 switch (STATE_ARCHITECTURE (sd)->mach)
730 {
731 case bfd_mach_fr400:
732 case bfd_mach_fr450:
733 address = fr400_check_write_address (current_cpu, address, align_mask);
734 break;
735 case bfd_mach_frvtomcat:
736 case bfd_mach_fr500:
737 case bfd_mach_frv:
738 address = fr500_check_write_address (current_cpu, address, align_mask);
739 break;
740 case bfd_mach_fr550:
741 address = fr550_check_write_address (current_cpu, address, align_mask);
742 break;
743 default:
744 break;
745 }
746 return address;
747 }
748
749 void
750 frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
751 {
752 USI hsr0;
753 hsr0 = GET_HSR0 ();
754 if (GET_HSR0_DCE (hsr0))
755 sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
756 else
757 sim_queue_mem_qi_write (current_cpu, address, value);
758 frv_set_write_queue_slot (current_cpu);
759 }
760
761 void
762 frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
763 {
764 frvbf_write_mem_QI (current_cpu, pc, address, value);
765 }
766
767 void
768 frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
769 {
770 USI hsr0;
771 hsr0 = GET_HSR0 ();
772 if (GET_HSR0_DCE (hsr0))
773 sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
774 else
775 sim_queue_mem_hi_write (current_cpu, address, value);
776 frv_set_write_queue_slot (current_cpu);
777 }
778
779 void
780 frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
781 {
782 frvbf_write_mem_HI (current_cpu, pc, address, value);
783 }
784
785 void
786 frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
787 {
788 USI hsr0;
789 hsr0 = GET_HSR0 ();
790 if (GET_HSR0_DCE (hsr0))
791 sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
792 else
793 sim_queue_mem_si_write (current_cpu, address, value);
794 frv_set_write_queue_slot (current_cpu);
795 }
796
797 void
798 frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
799 {
800 frvbf_write_mem_SI (current_cpu, pc, address, value);
801 }
802
803 void
804 frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
805 {
806 USI hsr0;
807 hsr0 = GET_HSR0 ();
808 if (GET_HSR0_DCE (hsr0))
809 sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
810 else
811 sim_queue_mem_di_write (current_cpu, address, value);
812 frv_set_write_queue_slot (current_cpu);
813 }
814
815 void
816 frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
817 {
818 USI hsr0;
819 hsr0 = GET_HSR0 ();
820 if (GET_HSR0_DCE (hsr0))
821 sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
822 else
823 sim_queue_mem_df_write (current_cpu, address, value);
824 frv_set_write_queue_slot (current_cpu);
825 }
826
827 /* Memory writes. These do the actual writing through the cache. */
828 void
829 frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
830 {
831 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
832
833 /* Check for access errors. */
834 address = check_write_address (current_cpu, address, 0);
835 address = check_readwrite_address (current_cpu, address, 0);
836
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. */
839 if (model_insn)
840 {
841 int slot = UNIT_I0;
842 frv_cache_request_store (cache, address, slot, (char *)&value,
843 sizeof (value));
844 }
845 else
846 frv_cache_write (cache, address, (char *)&value, sizeof (value));
847 }
848
849 /* Write a HI which spans two cache lines */
850 static void
851 mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
852 {
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);
857 }
858
859 void
860 frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
861 {
862 FRV_CACHE *cache;
863
864 /* Check for access errors. */
865 address = check_write_address (current_cpu, address, 1);
866 address = check_readwrite_address (current_cpu, address, 1);
867
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);
872 if (model_insn)
873 {
874 int slot = UNIT_I0;
875 frv_cache_request_store (cache, address, slot,
876 (char *)&value, sizeof (value));
877 }
878 else
879 {
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)
883 {
884 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
885 {
886 mem_set_unaligned_HI (current_cpu, pc, address, value);
887 return;
888 }
889 }
890 frv_cache_write (cache, address, (char *)&value, sizeof (value));
891 }
892 }
893
894 /* Write a SI which spans two cache lines */
895 static void
896 mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
897 {
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);
903 }
904
905 void
906 frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
907 {
908 FRV_CACHE *cache;
909
910 /* Check for access errors. */
911 address = check_write_address (current_cpu, address, 3);
912 address = check_readwrite_address (current_cpu, address, 3);
913
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);
918 if (model_insn)
919 {
920 int slot = UNIT_I0;
921 frv_cache_request_store (cache, address, slot,
922 (char *)&value, sizeof (value));
923 }
924 else
925 {
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)
929 {
930 if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
931 {
932 mem_set_unaligned_SI (current_cpu, pc, address, value);
933 return;
934 }
935 }
936 frv_cache_write (cache, address, (char *)&value, sizeof (value));
937 }
938 }
939
940 /* Write a DI which spans two cache lines */
941 static void
942 mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
943 {
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);
949 }
950
951 void
952 frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
953 {
954 FRV_CACHE *cache;
955
956 /* Check for access errors. */
957 address = check_write_address (current_cpu, address, 7);
958 address = check_readwrite_address (current_cpu, address, 7);
959
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);
964 if (model_insn)
965 {
966 int slot = UNIT_I0;
967 frv_cache_request_store (cache, address, slot,
968 (char *)&value, sizeof (value));
969 }
970 else
971 {
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)
975 {
976 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
977 {
978 mem_set_unaligned_DI (current_cpu, pc, address, value);
979 return;
980 }
981 }
982 frv_cache_write (cache, address, (char *)&value, sizeof (value));
983 }
984 }
985
986 void
987 frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
988 {
989 FRV_CACHE *cache;
990
991 /* Check for access errors. */
992 address = check_write_address (current_cpu, address, 7);
993 address = check_readwrite_address (current_cpu, address, 7);
994
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);
999 if (model_insn)
1000 {
1001 int slot = UNIT_I0;
1002 frv_cache_request_store (cache, address, slot,
1003 (char *)&value, sizeof (value));
1004 }
1005 else
1006 {
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)
1010 {
1011 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
1012 {
1013 mem_set_unaligned_DI (current_cpu, pc, address, value);
1014 return;
1015 }
1016 }
1017 frv_cache_write (cache, address, (char *)&value, sizeof (value));
1018 }
1019 }
1020
1021 void
1022 frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
1023 {
1024 int i;
1025 FRV_CACHE *cache;
1026
1027 /* Check for access errors. */
1028 address = check_write_address (current_cpu, address, 0xf);
1029 address = check_readwrite_address (current_cpu, address, 0xf);
1030
1031 /* TODO -- reverse word order as well? */
1032 for (i = 0; i < 4; ++i)
1033 value[i] = H2T_4 (value[i]);
1034
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);
1038 if (model_insn)
1039 {
1040 int slot = UNIT_I0;
1041 frv_cache_request_store (cache, address, slot, (char*)value, 16);
1042 }
1043 else
1044 frv_cache_write (cache, address, (char*)value, 16);
1045 }
1046
1047 /* Record the current VLIW slot on the element at the top of the write queue.
1048 */
1049 void
1050 frv_set_write_queue_slot (SIM_CPU *current_cpu)
1051 {
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];
1058 }