2 Copyright (C) 1999, 2000, 2001 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)
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
28 /* Check for alignment and access restrictions. Return the corrected address.
31 fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
33 /* Check access restrictions for double word loads only. */
36 if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
37 frv_queue_data_access_error_interrupt (current_cpu, address);
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);
59 check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
61 SIM_DESC sd = CPU_STATE (current_cpu);
62 switch (STATE_ARCHITECTURE (sd)->mach)
65 address = fr400_check_data_read_address (current_cpu, address,
68 case bfd_mach_frvtomcat:
71 address = fr500_check_data_read_address (current_cpu, address,
82 fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
84 if (address & align_mask)
86 /* Make sure that this exception is not masked. */
88 if (! GET_ISR_EMAM (isr))
90 /* Bad alignment causes a data_access_error on fr400. */
91 frv_queue_data_access_error_interrupt (current_cpu, address);
93 address &= ~align_mask;
95 /* Nothing to check. */
100 fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
102 if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff
103 || (USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
104 || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
105 || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
106 frv_queue_data_access_exception_interrupt (current_cpu);
112 check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
114 SIM_DESC sd = CPU_STATE (current_cpu);
115 switch (STATE_ARCHITECTURE (sd)->mach)
118 address = fr400_check_readwrite_address (current_cpu, address,
121 case bfd_mach_frvtomcat:
124 address = fr500_check_readwrite_address (current_cpu, address,
135 fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
138 if (address & align_mask)
140 frv_queue_instruction_access_error_interrupt (current_cpu);
141 address &= ~align_mask;
143 else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
144 frv_queue_instruction_access_error_interrupt (current_cpu);
150 fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
153 if (address & align_mask)
155 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
156 address &= ~align_mask;
159 if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
160 || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
161 frv_queue_instruction_access_error_interrupt (current_cpu);
162 else if ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
163 || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
164 || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
165 frv_queue_instruction_access_exception_interrupt (current_cpu);
168 USI hsr0 = GET_HSR0 ();
169 if (! GET_HSR0_RME (hsr0)
170 && (USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff)
171 frv_queue_instruction_access_exception_interrupt (current_cpu);
178 check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
180 SIM_DESC sd = CPU_STATE (current_cpu);
181 switch (STATE_ARCHITECTURE (sd)->mach)
184 address = fr400_check_insn_read_address (current_cpu, address,
187 case bfd_mach_frvtomcat:
190 address = fr500_check_insn_read_address (current_cpu, address,
202 frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
204 USI hsr0 = GET_HSR0 ();
205 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
207 /* Check for access exceptions. */
208 address = check_data_read_address (current_cpu, address, 0);
209 address = check_readwrite_address (current_cpu, address, 0);
211 /* If we need to count cycles, then the cache operation will be
212 initiated from the model profiling functions.
213 See frvbf_model_.... */
216 CPU_LOAD_ADDRESS (current_cpu) = address;
217 CPU_LOAD_LENGTH (current_cpu) = 1;
218 CPU_LOAD_SIGNED (current_cpu) = 1;
219 return 0xb7; /* any random value */
222 if (GET_HSR0_DCE (hsr0))
225 cycles = frv_cache_read (cache, 0, address);
227 return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
230 return GETMEMQI (current_cpu, pc, address);
234 frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
236 USI hsr0 = GET_HSR0 ();
237 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
239 /* Check for access exceptions. */
240 address = check_data_read_address (current_cpu, address, 0);
241 address = check_readwrite_address (current_cpu, address, 0);
243 /* If we need to count cycles, then the cache operation will be
244 initiated from the model profiling functions.
245 See frvbf_model_.... */
248 CPU_LOAD_ADDRESS (current_cpu) = address;
249 CPU_LOAD_LENGTH (current_cpu) = 1;
250 CPU_LOAD_SIGNED (current_cpu) = 0;
251 return 0xb7; /* any random value */
254 if (GET_HSR0_DCE (hsr0))
257 cycles = frv_cache_read (cache, 0, address);
259 return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
262 return GETMEMUQI (current_cpu, pc, address);
266 frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
271 /* Check for access exceptions. */
272 address = check_data_read_address (current_cpu, address, 1);
273 address = check_readwrite_address (current_cpu, address, 1);
275 /* If we need to count cycles, then the cache operation will be
276 initiated from the model profiling functions.
277 See frvbf_model_.... */
279 cache = CPU_DATA_CACHE (current_cpu);
282 CPU_LOAD_ADDRESS (current_cpu) = address;
283 CPU_LOAD_LENGTH (current_cpu) = 2;
284 CPU_LOAD_SIGNED (current_cpu) = 1;
285 return 0xb711; /* any random value */
288 if (GET_HSR0_DCE (hsr0))
291 cycles = frv_cache_read (cache, 0, address);
293 return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
296 return GETMEMHI (current_cpu, pc, address);
300 frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
305 /* Check for access exceptions. */
306 address = check_data_read_address (current_cpu, address, 1);
307 address = check_readwrite_address (current_cpu, address, 1);
309 /* If we need to count cycles, then the cache operation will be
310 initiated from the model profiling functions.
311 See frvbf_model_.... */
313 cache = CPU_DATA_CACHE (current_cpu);
316 CPU_LOAD_ADDRESS (current_cpu) = address;
317 CPU_LOAD_LENGTH (current_cpu) = 2;
318 CPU_LOAD_SIGNED (current_cpu) = 0;
319 return 0xb711; /* any random value */
322 if (GET_HSR0_DCE (hsr0))
325 cycles = frv_cache_read (cache, 0, address);
327 return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
330 return GETMEMUHI (current_cpu, pc, address);
334 frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
339 /* Check for access exceptions. */
340 address = check_data_read_address (current_cpu, address, 3);
341 address = check_readwrite_address (current_cpu, address, 3);
344 cache = CPU_DATA_CACHE (current_cpu);
345 /* If we need to count cycles, then the cache operation will be
346 initiated from the model profiling functions.
347 See frvbf_model_.... */
350 CPU_LOAD_ADDRESS (current_cpu) = address;
351 CPU_LOAD_LENGTH (current_cpu) = 4;
352 return 0x37111319; /* any random value */
355 if (GET_HSR0_DCE (hsr0))
358 cycles = frv_cache_read (cache, 0, address);
360 return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
363 return GETMEMSI (current_cpu, pc, address);
367 frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
369 return frvbf_read_mem_SI (current_cpu, pc, address);
373 frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
378 /* Check for access exceptions. */
379 address = check_data_read_address (current_cpu, address, 7);
380 address = check_readwrite_address (current_cpu, address, 7);
382 /* If we need to count cycles, then the cache operation will be
383 initiated from the model profiling functions.
384 See frvbf_model_.... */
386 cache = CPU_DATA_CACHE (current_cpu);
389 CPU_LOAD_ADDRESS (current_cpu) = address;
390 CPU_LOAD_LENGTH (current_cpu) = 8;
391 return 0x37111319; /* any random value */
394 if (GET_HSR0_DCE (hsr0))
397 cycles = frv_cache_read (cache, 0, address);
399 return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
402 return GETMEMDI (current_cpu, pc, address);
406 frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
411 /* Check for access exceptions. */
412 address = check_data_read_address (current_cpu, address, 7);
413 address = check_readwrite_address (current_cpu, address, 7);
415 /* If we need to count cycles, then the cache operation will be
416 initiated from the model profiling functions.
417 See frvbf_model_.... */
419 cache = CPU_DATA_CACHE (current_cpu);
422 CPU_LOAD_ADDRESS (current_cpu) = address;
423 CPU_LOAD_LENGTH (current_cpu) = 8;
424 return 0x37111319; /* any random value */
427 if (GET_HSR0_DCE (hsr0))
430 cycles = frv_cache_read (cache, 0, address);
432 return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
435 return GETMEMDF (current_cpu, pc, address);
439 frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
442 vpc = check_insn_read_address (current_cpu, vpc, 3);
445 if (GET_HSR0_ICE (hsr0))
450 /* We don't want this to show up in the cache statistics. That read
451 is done in frvbf_simulate_insn_prefetch. So read the cache or memory
453 cache = CPU_INSN_CACHE (current_cpu);
454 if (frv_cache_read_passive_SI (cache, vpc, &value))
457 return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
461 fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
463 if (address & align_mask)
465 /* On the fr400, this causes a data_access_error. */
466 /* Make sure that this exception is not masked. */
467 USI isr = GET_ISR ();
468 if (! GET_ISR_EMAM (isr))
470 /* Bad alignment causes a data_access_error on fr400. */
471 frv_queue_data_access_error_interrupt (current_cpu, address);
473 address &= ~align_mask;
476 && address >= 0xfe800000 && address <= 0xfeffffff)
477 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
483 fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
485 if (address & align_mask)
487 struct frv_interrupt_queue_element *item =
488 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
489 /* Record the correct vliw slot with the interrupt. */
491 item->slot = frv_interrupt_state.slot;
492 address &= ~align_mask;
494 if (address >= 0xfeff0600 && address <= 0xfeff7fff
495 || address >= 0xfe800000 && address <= 0xfefeffff)
496 frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
502 check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
504 SIM_DESC sd = CPU_STATE (current_cpu);
505 switch (STATE_ARCHITECTURE (sd)->mach)
508 address = fr400_check_write_address (current_cpu, address, align_mask);
510 case bfd_mach_frvtomcat:
513 address = fr500_check_write_address (current_cpu, address, align_mask);
522 frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
526 if (GET_HSR0_DCE (hsr0))
527 sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
529 sim_queue_mem_qi_write (current_cpu, address, value);
530 frv_set_write_queue_slot (current_cpu);
534 frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
536 frvbf_write_mem_QI (current_cpu, pc, address, value);
540 frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
544 if (GET_HSR0_DCE (hsr0))
545 sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
547 sim_queue_mem_hi_write (current_cpu, address, value);
548 frv_set_write_queue_slot (current_cpu);
552 frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
554 frvbf_write_mem_HI (current_cpu, pc, address, value);
558 frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
562 if (GET_HSR0_DCE (hsr0))
563 sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
565 sim_queue_mem_si_write (current_cpu, address, value);
566 frv_set_write_queue_slot (current_cpu);
570 frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
572 frvbf_write_mem_SI (current_cpu, pc, address, value);
576 frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
580 if (GET_HSR0_DCE (hsr0))
581 sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
583 sim_queue_mem_di_write (current_cpu, address, value);
584 frv_set_write_queue_slot (current_cpu);
588 frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
592 if (GET_HSR0_DCE (hsr0))
593 sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
595 sim_queue_mem_df_write (current_cpu, address, value);
596 frv_set_write_queue_slot (current_cpu);
599 /* Memory writes. These do the actual writing through the cache. */
601 frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
603 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
605 /* Check for access errors. */
606 address = check_write_address (current_cpu, address, 0);
607 address = check_readwrite_address (current_cpu, address, 0);
609 /* If we need to count cycles, then submit the write request to the cache
610 and let it prioritize the request. Otherwise perform the write now. */
614 frv_cache_request_store (cache, address, slot, (char *)&value,
618 frv_cache_write (cache, address, (char *)&value, sizeof (value));
622 frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
626 /* Check for access errors. */
627 address = check_write_address (current_cpu, address, 1);
628 address = check_readwrite_address (current_cpu, address, 1);
630 /* If we need to count cycles, then submit the write request to the cache
631 and let it prioritize the request. Otherwise perform the write now. */
632 value = H2T_2 (value);
633 cache = CPU_DATA_CACHE (current_cpu);
637 frv_cache_request_store (cache, address, slot,
638 (char *)&value, sizeof (value));
641 frv_cache_write (cache, address, (char *)&value, sizeof (value));
645 frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
649 /* Check for access errors. */
650 address = check_write_address (current_cpu, address, 3);
651 address = check_readwrite_address (current_cpu, address, 3);
653 /* If we need to count cycles, then submit the write request to the cache
654 and let it prioritize the request. Otherwise perform the write now. */
655 cache = CPU_DATA_CACHE (current_cpu);
656 value = H2T_4 (value);
660 frv_cache_request_store (cache, address, slot,
661 (char *)&value, sizeof (value));
664 frv_cache_write (cache, address, (char *)&value, sizeof (value));
668 frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
672 /* Check for access errors. */
673 address = check_write_address (current_cpu, address, 7);
674 address = check_readwrite_address (current_cpu, address, 7);
676 /* If we need to count cycles, then submit the write request to the cache
677 and let it prioritize the request. Otherwise perform the write now. */
678 value = H2T_8 (value);
679 cache = CPU_DATA_CACHE (current_cpu);
683 frv_cache_request_store (cache, address, slot,
684 (char *)&value, sizeof (value));
687 frv_cache_write (cache, address, (char *)&value, sizeof (value));
691 frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
695 /* Check for access errors. */
696 address = check_write_address (current_cpu, address, 7);
697 address = check_readwrite_address (current_cpu, address, 7);
699 /* If we need to count cycles, then submit the write request to the cache
700 and let it prioritize the request. Otherwise perform the write now. */
701 value = H2T_8 (value);
702 cache = CPU_DATA_CACHE (current_cpu);
706 frv_cache_request_store (cache, address, slot,
707 (char *)&value, sizeof (value));
710 frv_cache_write (cache, address, (char *)&value, sizeof (value));
714 frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
719 /* Check for access errors. */
720 address = check_write_address (current_cpu, address, 0xf);
721 address = check_readwrite_address (current_cpu, address, 0xf);
723 /* TODO -- reverse word order as well? */
724 for (i = 0; i < 4; ++i)
725 value[i] = H2T_4 (value[i]);
727 /* If we need to count cycles, then submit the write request to the cache
728 and let it prioritize the request. Otherwise perform the write now. */
729 cache = CPU_DATA_CACHE (current_cpu);
733 frv_cache_request_store (cache, address, slot, (char*)value, 16);
736 frv_cache_write (cache, address, (char*)value, 16);
739 /* Record the current VLIW slot on the element at the top of the write queue.
742 frv_set_write_queue_slot (SIM_CPU *current_cpu)
744 FRV_VLIW *vliw = CPU_VLIW (current_cpu);
745 int slot = vliw->next_slot - 1;
746 CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
747 int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1;
748 CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix);
749 CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot];