]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/frv/memory.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / frv / memory.c
1 /* frv memory model.
2 Copyright (C) 1999-2013 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 #define WANT_CPU frvbf
21 #define WANT_CPU_FRVBF
22
23 #include "sim-main.h"
24 #include "cgen-mem.h"
25 #include "bfd.h"
26
27 /* Check for alignment and access restrictions. Return the corrected address.
28 */
29 static SI
30 fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
31 {
32 /* Check access restrictions for double word loads only. */
33 if (align_mask == 7)
34 {
35 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
36 frv_queue_data_access_error_interrupt (current_cpu, address);
37 }
38 return address;
39 }
40
41 static SI
42 fr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
43 {
44 if (address & align_mask)
45 {
46 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
47 address &= ~align_mask;
48 }
49
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);
53
54 return address;
55 }
56
57 static SI
58 fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
59 {
60 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
61 || (align_mask > 0x3
62 && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
63 frv_queue_data_access_error_interrupt (current_cpu, address);
64
65 return address;
66 }
67
68 static SI
69 check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
70 {
71 SIM_DESC sd = CPU_STATE (current_cpu);
72 switch (STATE_ARCHITECTURE (sd)->mach)
73 {
74 case bfd_mach_fr400:
75 case bfd_mach_fr450:
76 address = fr400_check_data_read_address (current_cpu, address,
77 align_mask);
78 break;
79 case bfd_mach_frvtomcat:
80 case bfd_mach_fr500:
81 case bfd_mach_frv:
82 address = fr500_check_data_read_address (current_cpu, address,
83 align_mask);
84 break;
85 case bfd_mach_fr550:
86 address = fr550_check_data_read_address (current_cpu, address,
87 align_mask);
88 break;
89 default:
90 break;
91 }
92
93 return address;
94 }
95
96 static SI
97 fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
98 {
99 if (address & align_mask)
100 {
101 /* Make sure that this exception is not masked. */
102 USI isr = GET_ISR ();
103 if (! GET_ISR_EMAM (isr))
104 {
105 /* Bad alignment causes a data_access_error on fr400. */
106 frv_queue_data_access_error_interrupt (current_cpu, address);
107 }
108 address &= ~align_mask;
109 }
110 /* Nothing to check. */
111 return address;
112 }
113
114 static SI
115 fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
116 {
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);
122
123 return address;
124 }
125
126 static SI
127 fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
128 {
129 /* No alignment restrictions on fr550 */
130
131 if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff
132 || (USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff)
133 frv_queue_data_access_exception_interrupt (current_cpu);
134 else
135 {
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);
140 }
141
142 return address;
143 }
144
145 static SI
146 check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
147 {
148 SIM_DESC sd = CPU_STATE (current_cpu);
149 switch (STATE_ARCHITECTURE (sd)->mach)
150 {
151 case bfd_mach_fr400:
152 case bfd_mach_fr450:
153 address = fr400_check_readwrite_address (current_cpu, address,
154 align_mask);
155 break;
156 case bfd_mach_frvtomcat:
157 case bfd_mach_fr500:
158 case bfd_mach_frv:
159 address = fr500_check_readwrite_address (current_cpu, address,
160 align_mask);
161 break;
162 case bfd_mach_fr550:
163 address = fr550_check_readwrite_address (current_cpu, address,
164 align_mask);
165 break;
166 default:
167 break;
168 }
169
170 return address;
171 }
172
173 static PCADDR
174 fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
175 int align_mask)
176 {
177 if (address & align_mask)
178 {
179 frv_queue_instruction_access_error_interrupt (current_cpu);
180 address &= ~align_mask;
181 }
182 else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
183 frv_queue_instruction_access_error_interrupt (current_cpu);
184
185 return address;
186 }
187
188 static PCADDR
189 fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
190 int align_mask)
191 {
192 if (address & align_mask)
193 {
194 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
195 address &= ~align_mask;
196 }
197
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);
205 else
206 {
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);
211 }
212
213 return address;
214 }
215
216 static PCADDR
217 fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
218 int align_mask)
219 {
220 address &= ~align_mask;
221
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);
226 else
227 {
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);
232 }
233
234 return address;
235 }
236
237 static PCADDR
238 check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
239 {
240 SIM_DESC sd = CPU_STATE (current_cpu);
241 switch (STATE_ARCHITECTURE (sd)->mach)
242 {
243 case bfd_mach_fr400:
244 case bfd_mach_fr450:
245 address = fr400_check_insn_read_address (current_cpu, address,
246 align_mask);
247 break;
248 case bfd_mach_frvtomcat:
249 case bfd_mach_fr500:
250 case bfd_mach_frv:
251 address = fr500_check_insn_read_address (current_cpu, address,
252 align_mask);
253 break;
254 case bfd_mach_fr550:
255 address = fr550_check_insn_read_address (current_cpu, address,
256 align_mask);
257 break;
258 default:
259 break;
260 }
261
262 return address;
263 }
264
265 /* Memory reads. */
266 QI
267 frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
268 {
269 USI hsr0 = GET_HSR0 ();
270 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
271
272 /* Check for access exceptions. */
273 address = check_data_read_address (current_cpu, address, 0);
274 address = check_readwrite_address (current_cpu, address, 0);
275
276 /* If we need to count cycles, then the cache operation will be
277 initiated from the model profiling functions.
278 See frvbf_model_.... */
279 if (model_insn)
280 {
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 */
285 }
286
287 if (GET_HSR0_DCE (hsr0))
288 {
289 int cycles;
290 cycles = frv_cache_read (cache, 0, address);
291 if (cycles != 0)
292 return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
293 }
294
295 return GETMEMQI (current_cpu, pc, address);
296 }
297
298 UQI
299 frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
300 {
301 USI hsr0 = GET_HSR0 ();
302 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
303
304 /* Check for access exceptions. */
305 address = check_data_read_address (current_cpu, address, 0);
306 address = check_readwrite_address (current_cpu, address, 0);
307
308 /* If we need to count cycles, then the cache operation will be
309 initiated from the model profiling functions.
310 See frvbf_model_.... */
311 if (model_insn)
312 {
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 */
317 }
318
319 if (GET_HSR0_DCE (hsr0))
320 {
321 int cycles;
322 cycles = frv_cache_read (cache, 0, address);
323 if (cycles != 0)
324 return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
325 }
326
327 return GETMEMUQI (current_cpu, pc, address);
328 }
329
330 /* Read a HI which spans two cache lines */
331 static HI
332 read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
333 {
334 HI value = frvbf_read_mem_QI (current_cpu, pc, address);
335 value <<= 8;
336 value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1);
337 return T2H_2 (value);
338 }
339
340 HI
341 frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
342 {
343 USI hsr0;
344 FRV_CACHE *cache;
345
346 /* Check for access exceptions. */
347 address = check_data_read_address (current_cpu, address, 1);
348 address = check_readwrite_address (current_cpu, address, 1);
349
350 /* If we need to count cycles, then the cache operation will be
351 initiated from the model profiling functions.
352 See frvbf_model_.... */
353 hsr0 = GET_HSR0 ();
354 cache = CPU_DATA_CACHE (current_cpu);
355 if (model_insn)
356 {
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 */
361 }
362
363 if (GET_HSR0_DCE (hsr0))
364 {
365 int cycles;
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)
369 {
370 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
371 return read_mem_unaligned_HI (current_cpu, pc, address);
372 }
373 cycles = frv_cache_read (cache, 0, address);
374 if (cycles != 0)
375 return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
376 }
377
378 return GETMEMHI (current_cpu, pc, address);
379 }
380
381 UHI
382 frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
383 {
384 USI hsr0;
385 FRV_CACHE *cache;
386
387 /* Check for access exceptions. */
388 address = check_data_read_address (current_cpu, address, 1);
389 address = check_readwrite_address (current_cpu, address, 1);
390
391 /* If we need to count cycles, then the cache operation will be
392 initiated from the model profiling functions.
393 See frvbf_model_.... */
394 hsr0 = GET_HSR0 ();
395 cache = CPU_DATA_CACHE (current_cpu);
396 if (model_insn)
397 {
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 */
402 }
403
404 if (GET_HSR0_DCE (hsr0))
405 {
406 int cycles;
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)
410 {
411 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
412 return read_mem_unaligned_HI (current_cpu, pc, address);
413 }
414 cycles = frv_cache_read (cache, 0, address);
415 if (cycles != 0)
416 return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
417 }
418
419 return GETMEMUHI (current_cpu, pc, address);
420 }
421
422 /* Read a SI which spans two cache lines */
423 static SI
424 read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
425 {
426 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
427 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
428 char valarray[4];
429 SI SIvalue;
430 HI HIvalue;
431
432 switch (hi_len)
433 {
434 case 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);
439 break;
440 case 2:
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);
447 break;
448 case 3:
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);
453 break;
454 default:
455 abort (); /* can't happen */
456 }
457 return T2H_4 (*(SI*)valarray);
458 }
459
460 SI
461 frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
462 {
463 FRV_CACHE *cache;
464 USI hsr0;
465
466 /* Check for access exceptions. */
467 address = check_data_read_address (current_cpu, address, 3);
468 address = check_readwrite_address (current_cpu, address, 3);
469
470 hsr0 = GET_HSR0 ();
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_.... */
475 if (model_insn)
476 {
477 CPU_LOAD_ADDRESS (current_cpu) = address;
478 CPU_LOAD_LENGTH (current_cpu) = 4;
479 return 0x37111319; /* any random value */
480 }
481
482 if (GET_HSR0_DCE (hsr0))
483 {
484 int cycles;
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)
488 {
489 if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
490 return read_mem_unaligned_SI (current_cpu, pc, address);
491 }
492 cycles = frv_cache_read (cache, 0, address);
493 if (cycles != 0)
494 return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
495 }
496
497 return GETMEMSI (current_cpu, pc, address);
498 }
499
500 SI
501 frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
502 {
503 return frvbf_read_mem_SI (current_cpu, pc, address);
504 }
505
506 /* Read a SI which spans two cache lines */
507 static DI
508 read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
509 {
510 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
511 unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
512 DI value, value1;
513
514 switch (hi_len)
515 {
516 case 1:
517 value = frvbf_read_mem_QI (current_cpu, pc, address);
518 value <<= 56;
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;
523 break;
524 case 2:
525 value = frvbf_read_mem_HI (current_cpu, pc, address);
526 value = H2T_2 (value);
527 value <<= 48;
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;
532 break;
533 case 3:
534 value = frvbf_read_mem_SI (current_cpu, pc, address - 1);
535 value = H2T_4 (value);
536 value <<= 40;
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;
541 break;
542 case 4:
543 value = frvbf_read_mem_SI (current_cpu, pc, address);
544 value = H2T_4 (value);
545 value <<= 32;
546 value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4);
547 value1 = H2T_4 (value1);
548 value |= value1 & 0xffffffffu;
549 break;
550 case 5:
551 value = frvbf_read_mem_DI (current_cpu, pc, address - 3);
552 value = H2T_8 (value);
553 value <<= 24;
554 value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5);
555 value1 = H2T_4 (value1);
556 value |= value1 & 0x00ffffff;
557 break;
558 case 6:
559 value = frvbf_read_mem_DI (current_cpu, pc, address - 2);
560 value = H2T_8 (value);
561 value <<= 16;
562 value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6);
563 value1 = H2T_2 (value1);
564 value |= value1 & 0x0000ffff;
565 break;
566 case 7:
567 value = frvbf_read_mem_DI (current_cpu, pc, address - 1);
568 value = H2T_8 (value);
569 value <<= 8;
570 value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7);
571 value |= value1 & 0x000000ff;
572 break;
573 default:
574 abort (); /* can't happen */
575 }
576 return T2H_8 (value);
577 }
578
579 DI
580 frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
581 {
582 USI hsr0;
583 FRV_CACHE *cache;
584
585 /* Check for access exceptions. */
586 address = check_data_read_address (current_cpu, address, 7);
587 address = check_readwrite_address (current_cpu, address, 7);
588
589 /* If we need to count cycles, then the cache operation will be
590 initiated from the model profiling functions.
591 See frvbf_model_.... */
592 hsr0 = GET_HSR0 ();
593 cache = CPU_DATA_CACHE (current_cpu);
594 if (model_insn)
595 {
596 CPU_LOAD_ADDRESS (current_cpu) = address;
597 CPU_LOAD_LENGTH (current_cpu) = 8;
598 return 0x37111319; /* any random value */
599 }
600
601 if (GET_HSR0_DCE (hsr0))
602 {
603 int cycles;
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)
607 {
608 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
609 return read_mem_unaligned_DI (current_cpu, pc, address);
610 }
611 cycles = frv_cache_read (cache, 0, address);
612 if (cycles != 0)
613 return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
614 }
615
616 return GETMEMDI (current_cpu, pc, address);
617 }
618
619 DF
620 frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
621 {
622 USI hsr0;
623 FRV_CACHE *cache;
624
625 /* Check for access exceptions. */
626 address = check_data_read_address (current_cpu, address, 7);
627 address = check_readwrite_address (current_cpu, address, 7);
628
629 /* If we need to count cycles, then the cache operation will be
630 initiated from the model profiling functions.
631 See frvbf_model_.... */
632 hsr0 = GET_HSR0 ();
633 cache = CPU_DATA_CACHE (current_cpu);
634 if (model_insn)
635 {
636 CPU_LOAD_ADDRESS (current_cpu) = address;
637 CPU_LOAD_LENGTH (current_cpu) = 8;
638 return 0x37111319; /* any random value */
639 }
640
641 if (GET_HSR0_DCE (hsr0))
642 {
643 int cycles;
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)
647 {
648 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
649 return read_mem_unaligned_DI (current_cpu, pc, address);
650 }
651 cycles = frv_cache_read (cache, 0, address);
652 if (cycles != 0)
653 return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
654 }
655
656 return GETMEMDF (current_cpu, pc, address);
657 }
658
659 USI
660 frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
661 {
662 USI hsr0;
663 vpc = check_insn_read_address (current_cpu, vpc, 3);
664
665 hsr0 = GET_HSR0 ();
666 if (GET_HSR0_ICE (hsr0))
667 {
668 FRV_CACHE *cache;
669 USI value;
670
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
673 passively here. */
674 cache = CPU_INSN_CACHE (current_cpu);
675 if (frv_cache_read_passive_SI (cache, vpc, &value))
676 return value;
677 }
678 return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
679 }
680
681 static SI
682 fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
683 {
684 if (align_mask == 7
685 && address >= 0xfe800000 && address <= 0xfeffffff)
686 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
687
688 return address;
689 }
690
691 static SI
692 fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
693 {
694 if (address & align_mask)
695 {
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. */
699 if (item != NULL)
700 item->slot = frv_interrupt_state.slot;
701 address &= ~align_mask;
702 }
703 if (address >= 0xfeff0600 && address <= 0xfeff7fff
704 || address >= 0xfe800000 && address <= 0xfefeffff)
705 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
706
707 return address;
708 }
709
710 static SI
711 fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
712 {
713 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
714 || (align_mask > 0x3
715 && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
716 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
717
718 return address;
719 }
720
721 static SI
722 check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
723 {
724 SIM_DESC sd = CPU_STATE (current_cpu);
725 switch (STATE_ARCHITECTURE (sd)->mach)
726 {
727 case bfd_mach_fr400:
728 case bfd_mach_fr450:
729 address = fr400_check_write_address (current_cpu, address, align_mask);
730 break;
731 case bfd_mach_frvtomcat:
732 case bfd_mach_fr500:
733 case bfd_mach_frv:
734 address = fr500_check_write_address (current_cpu, address, align_mask);
735 break;
736 case bfd_mach_fr550:
737 address = fr550_check_write_address (current_cpu, address, align_mask);
738 break;
739 default:
740 break;
741 }
742 return address;
743 }
744
745 void
746 frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
747 {
748 USI hsr0;
749 hsr0 = GET_HSR0 ();
750 if (GET_HSR0_DCE (hsr0))
751 sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
752 else
753 sim_queue_mem_qi_write (current_cpu, address, value);
754 frv_set_write_queue_slot (current_cpu);
755 }
756
757 void
758 frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
759 {
760 frvbf_write_mem_QI (current_cpu, pc, address, value);
761 }
762
763 void
764 frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
765 {
766 USI hsr0;
767 hsr0 = GET_HSR0 ();
768 if (GET_HSR0_DCE (hsr0))
769 sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
770 else
771 sim_queue_mem_hi_write (current_cpu, address, value);
772 frv_set_write_queue_slot (current_cpu);
773 }
774
775 void
776 frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
777 {
778 frvbf_write_mem_HI (current_cpu, pc, address, value);
779 }
780
781 void
782 frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
783 {
784 USI hsr0;
785 hsr0 = GET_HSR0 ();
786 if (GET_HSR0_DCE (hsr0))
787 sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
788 else
789 sim_queue_mem_si_write (current_cpu, address, value);
790 frv_set_write_queue_slot (current_cpu);
791 }
792
793 void
794 frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
795 {
796 frvbf_write_mem_SI (current_cpu, pc, address, value);
797 }
798
799 void
800 frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
801 {
802 USI hsr0;
803 hsr0 = GET_HSR0 ();
804 if (GET_HSR0_DCE (hsr0))
805 sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
806 else
807 sim_queue_mem_di_write (current_cpu, address, value);
808 frv_set_write_queue_slot (current_cpu);
809 }
810
811 void
812 frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
813 {
814 USI hsr0;
815 hsr0 = GET_HSR0 ();
816 if (GET_HSR0_DCE (hsr0))
817 sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
818 else
819 sim_queue_mem_df_write (current_cpu, address, value);
820 frv_set_write_queue_slot (current_cpu);
821 }
822
823 /* Memory writes. These do the actual writing through the cache. */
824 void
825 frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
826 {
827 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
828
829 /* Check for access errors. */
830 address = check_write_address (current_cpu, address, 0);
831 address = check_readwrite_address (current_cpu, address, 0);
832
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. */
835 if (model_insn)
836 {
837 int slot = UNIT_I0;
838 frv_cache_request_store (cache, address, slot, (char *)&value,
839 sizeof (value));
840 }
841 else
842 frv_cache_write (cache, address, (char *)&value, sizeof (value));
843 }
844
845 /* Write a HI which spans two cache lines */
846 static void
847 mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
848 {
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);
853 }
854
855 void
856 frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
857 {
858 FRV_CACHE *cache;
859
860 /* Check for access errors. */
861 address = check_write_address (current_cpu, address, 1);
862 address = check_readwrite_address (current_cpu, address, 1);
863
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);
868 if (model_insn)
869 {
870 int slot = UNIT_I0;
871 frv_cache_request_store (cache, address, slot,
872 (char *)&value, sizeof (value));
873 }
874 else
875 {
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)
879 {
880 if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
881 {
882 mem_set_unaligned_HI (current_cpu, pc, address, value);
883 return;
884 }
885 }
886 frv_cache_write (cache, address, (char *)&value, sizeof (value));
887 }
888 }
889
890 /* Write a SI which spans two cache lines */
891 static void
892 mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
893 {
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);
899 }
900
901 void
902 frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
903 {
904 FRV_CACHE *cache;
905
906 /* Check for access errors. */
907 address = check_write_address (current_cpu, address, 3);
908 address = check_readwrite_address (current_cpu, address, 3);
909
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);
914 if (model_insn)
915 {
916 int slot = UNIT_I0;
917 frv_cache_request_store (cache, address, slot,
918 (char *)&value, sizeof (value));
919 }
920 else
921 {
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)
925 {
926 if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
927 {
928 mem_set_unaligned_SI (current_cpu, pc, address, value);
929 return;
930 }
931 }
932 frv_cache_write (cache, address, (char *)&value, sizeof (value));
933 }
934 }
935
936 /* Write a DI which spans two cache lines */
937 static void
938 mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
939 {
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);
945 }
946
947 void
948 frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
949 {
950 FRV_CACHE *cache;
951
952 /* Check for access errors. */
953 address = check_write_address (current_cpu, address, 7);
954 address = check_readwrite_address (current_cpu, address, 7);
955
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);
960 if (model_insn)
961 {
962 int slot = UNIT_I0;
963 frv_cache_request_store (cache, address, slot,
964 (char *)&value, sizeof (value));
965 }
966 else
967 {
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)
971 {
972 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
973 {
974 mem_set_unaligned_DI (current_cpu, pc, address, value);
975 return;
976 }
977 }
978 frv_cache_write (cache, address, (char *)&value, sizeof (value));
979 }
980 }
981
982 void
983 frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
984 {
985 FRV_CACHE *cache;
986
987 /* Check for access errors. */
988 address = check_write_address (current_cpu, address, 7);
989 address = check_readwrite_address (current_cpu, address, 7);
990
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);
995 if (model_insn)
996 {
997 int slot = UNIT_I0;
998 frv_cache_request_store (cache, address, slot,
999 (char *)&value, sizeof (value));
1000 }
1001 else
1002 {
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)
1006 {
1007 if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
1008 {
1009 mem_set_unaligned_DI (current_cpu, pc, address, value);
1010 return;
1011 }
1012 }
1013 frv_cache_write (cache, address, (char *)&value, sizeof (value));
1014 }
1015 }
1016
1017 void
1018 frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
1019 {
1020 int i;
1021 FRV_CACHE *cache;
1022
1023 /* Check for access errors. */
1024 address = check_write_address (current_cpu, address, 0xf);
1025 address = check_readwrite_address (current_cpu, address, 0xf);
1026
1027 /* TODO -- reverse word order as well? */
1028 for (i = 0; i < 4; ++i)
1029 value[i] = H2T_4 (value[i]);
1030
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);
1034 if (model_insn)
1035 {
1036 int slot = UNIT_I0;
1037 frv_cache_request_store (cache, address, slot, (char*)value, 16);
1038 }
1039 else
1040 frv_cache_write (cache, address, (char*)value, 16);
1041 }
1042
1043 /* Record the current VLIW slot on the element at the top of the write queue.
1044 */
1045 void
1046 frv_set_write_queue_slot (SIM_CPU *current_cpu)
1047 {
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];
1054 }