1 /* frv exception and interrupt support
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
27 /* FR-V Interrupt table.
28 Describes the interrupts supported by the FR-V.
29 This table *must* be maintained in order of interrupt priority as defined by
30 frv_interrupt_kind. */
33 #define ITABLE_ENTRY(name, class, deferral, precision, offset) \
34 {FRV_##name, FRV_EC_##name, class, deferral, precision, offset}
36 struct frv_interrupt frv_interrupt_table
[NUM_FRV_INTERRUPT_KINDS
] =
38 /* External interrupts */
39 ITABLE_ENTRY(INTERRUPT_LEVEL_1
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x21),
40 ITABLE_ENTRY(INTERRUPT_LEVEL_2
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x22),
41 ITABLE_ENTRY(INTERRUPT_LEVEL_3
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x23),
42 ITABLE_ENTRY(INTERRUPT_LEVEL_4
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x24),
43 ITABLE_ENTRY(INTERRUPT_LEVEL_5
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x25),
44 ITABLE_ENTRY(INTERRUPT_LEVEL_6
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x26),
45 ITABLE_ENTRY(INTERRUPT_LEVEL_7
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x27),
46 ITABLE_ENTRY(INTERRUPT_LEVEL_8
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x28),
47 ITABLE_ENTRY(INTERRUPT_LEVEL_9
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x29),
48 ITABLE_ENTRY(INTERRUPT_LEVEL_10
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2a),
49 ITABLE_ENTRY(INTERRUPT_LEVEL_11
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2b),
50 ITABLE_ENTRY(INTERRUPT_LEVEL_12
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2c),
51 ITABLE_ENTRY(INTERRUPT_LEVEL_13
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2d),
52 ITABLE_ENTRY(INTERRUPT_LEVEL_14
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2e),
53 ITABLE_ENTRY(INTERRUPT_LEVEL_15
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2f),
54 /* Software interrupt */
55 ITABLE_ENTRY(TRAP_INSTRUCTION
, FRV_SOFTWARE_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x80),
56 /* Program interrupts */
57 ITABLE_ENTRY(COMMIT_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x19),
58 ITABLE_ENTRY(DIVISION_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x17),
59 ITABLE_ENTRY(DATA_STORE_ERROR
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x14),
60 ITABLE_ENTRY(DATA_ACCESS_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x13),
61 ITABLE_ENTRY(DATA_ACCESS_MMU_MISS
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x12),
62 ITABLE_ENTRY(DATA_ACCESS_ERROR
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x11),
63 ITABLE_ENTRY(MP_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x0e),
64 ITABLE_ENTRY(FP_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x0d),
65 ITABLE_ENTRY(MEM_ADDRESS_NOT_ALIGNED
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x10),
66 ITABLE_ENTRY(REGISTER_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x08),
67 ITABLE_ENTRY(MP_DISABLED
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x0b),
68 ITABLE_ENTRY(FP_DISABLED
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x0a),
69 ITABLE_ENTRY(PRIVILEGED_INSTRUCTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x06),
70 ITABLE_ENTRY(ILLEGAL_INSTRUCTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x07),
71 ITABLE_ENTRY(INSTRUCTION_ACCESS_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x03),
72 ITABLE_ENTRY(INSTRUCTION_ACCESS_ERROR
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x02),
73 ITABLE_ENTRY(INSTRUCTION_ACCESS_MMU_MISS
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x01),
74 ITABLE_ENTRY(COMPOUND_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x20),
76 ITABLE_ENTRY(BREAK_EXCEPTION
, FRV_BREAK_INTERRUPT
, !DEFERRED
, !PRECISE
, 0xff),
78 ITABLE_ENTRY(RESET
, FRV_RESET_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x00)
81 /* The current interrupt state. */
82 struct frv_interrupt_state frv_interrupt_state
;
84 /* maintain the address of the start of the previous VLIW insn sequence. */
85 IADDR previous_vliw_pc
;
87 /* Add a break interrupt to the interrupt queue. */
88 struct frv_interrupt_queue_element
*
89 frv_queue_break_interrupt (SIM_CPU
*current_cpu
)
91 return frv_queue_interrupt (current_cpu
, FRV_BREAK_EXCEPTION
);
94 /* Add a software interrupt to the interrupt queue. */
95 struct frv_interrupt_queue_element
*
96 frv_queue_software_interrupt (SIM_CPU
*current_cpu
, SI offset
)
98 struct frv_interrupt_queue_element
*new_element
99 = frv_queue_interrupt (current_cpu
, FRV_TRAP_INSTRUCTION
);
101 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[new_element
->kind
];
102 interrupt
->handler_offset
= offset
;
107 /* Add a program interrupt to the interrupt queue. */
108 struct frv_interrupt_queue_element
*
109 frv_queue_program_interrupt (
110 SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
113 return frv_queue_interrupt (current_cpu
, kind
);
116 /* Add an external interrupt to the interrupt queue. */
117 struct frv_interrupt_queue_element
*
118 frv_queue_external_interrupt (
119 SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
122 if (! GET_H_PSR_ET ()
123 || (kind
!= FRV_INTERRUPT_LEVEL_15
&& kind
< GET_H_PSR_PIL ()))
124 return NULL
; /* Leave it for later. */
126 return frv_queue_interrupt (current_cpu
, kind
);
129 /* Add any interrupt to the interrupt queue. It will be added in reverse
130 priority order. This makes it easy to find the highest priority interrupt
131 at the end of the queue and to remove it after processing. */
132 struct frv_interrupt_queue_element
*
133 frv_queue_interrupt (SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
)
137 int limit
= frv_interrupt_state
.queue_index
;
138 struct frv_interrupt_queue_element
*new_element
;
139 enum frv_interrupt_class iclass
;
141 if (limit
>= FRV_INTERRUPT_QUEUE_SIZE
)
142 abort (); /* TODO: Make the queue dynamic */
144 /* Find the right place in the queue. */
145 for (i
= 0; i
< limit
; ++i
)
147 if (frv_interrupt_state
.queue
[i
].kind
>= kind
)
151 /* Don't queue two external interrupts of the same priority. */
152 iclass
= frv_interrupt_table
[kind
].iclass
;
153 if (i
< limit
&& iclass
== FRV_EXTERNAL_INTERRUPT
)
155 if (frv_interrupt_state
.queue
[i
].kind
== kind
)
156 return & frv_interrupt_state
.queue
[i
];
159 /* Make room for the new interrupt in this spot. */
160 for (j
= limit
- 1; j
>= i
; --j
)
161 frv_interrupt_state
.queue
[j
+ 1] = frv_interrupt_state
.queue
[j
];
163 /* Add the new interrupt. */
164 frv_interrupt_state
.queue_index
++;
165 new_element
= & frv_interrupt_state
.queue
[i
];
166 new_element
->kind
= kind
;
167 new_element
->vpc
= CPU_PC_GET (current_cpu
);
168 new_element
->u
.data_written
.length
= 0;
169 frv_set_interrupt_queue_slot (current_cpu
, new_element
);
174 struct frv_interrupt_queue_element
*
175 frv_queue_register_exception_interrupt (SIM_CPU
*current_cpu
, enum frv_rec rec
)
177 struct frv_interrupt_queue_element
*new_element
=
178 frv_queue_program_interrupt (current_cpu
, FRV_REGISTER_EXCEPTION
);
180 new_element
->u
.rec
= rec
;
185 struct frv_interrupt_queue_element
*
186 frv_queue_mem_address_not_aligned_interrupt (SIM_CPU
*current_cpu
, USI addr
)
188 struct frv_interrupt_queue_element
*new_element
;
189 USI isr
= GET_ISR ();
191 /* Make sure that this exception is not masked. */
192 if (GET_ISR_EMAM (isr
))
195 /* Queue the interrupt. */
196 new_element
= frv_queue_program_interrupt (current_cpu
,
197 FRV_MEM_ADDRESS_NOT_ALIGNED
);
198 new_element
->eaddress
= addr
;
199 new_element
->u
.data_written
= frv_interrupt_state
.data_written
;
200 frv_interrupt_state
.data_written
.length
= 0;
205 struct frv_interrupt_queue_element
*
206 frv_queue_data_access_error_interrupt (SIM_CPU
*current_cpu
, USI addr
)
208 struct frv_interrupt_queue_element
*new_element
;
209 new_element
= frv_queue_program_interrupt (current_cpu
,
210 FRV_DATA_ACCESS_ERROR
);
211 new_element
->eaddress
= addr
;
215 struct frv_interrupt_queue_element
*
216 frv_queue_data_access_exception_interrupt (SIM_CPU
*current_cpu
)
218 return frv_queue_program_interrupt (current_cpu
, FRV_DATA_ACCESS_EXCEPTION
);
221 struct frv_interrupt_queue_element
*
222 frv_queue_instruction_access_error_interrupt (SIM_CPU
*current_cpu
)
224 return frv_queue_program_interrupt (current_cpu
, FRV_INSTRUCTION_ACCESS_ERROR
);
227 struct frv_interrupt_queue_element
*
228 frv_queue_instruction_access_exception_interrupt (SIM_CPU
*current_cpu
)
230 return frv_queue_program_interrupt (current_cpu
, FRV_INSTRUCTION_ACCESS_EXCEPTION
);
233 struct frv_interrupt_queue_element
*
234 frv_queue_illegal_instruction_interrupt (
235 SIM_CPU
*current_cpu
, const CGEN_INSN
*insn
238 SIM_DESC sd
= CPU_STATE (current_cpu
);
239 switch (STATE_ARCHITECTURE (sd
)->mach
)
246 /* Some machines generate fp_exception for this case. */
247 if (frv_is_float_insn (insn
) || frv_is_media_insn (insn
))
249 struct frv_fp_exception_info fp_info
= {
250 FSR_NO_EXCEPTION
, FTT_SEQUENCE_ERROR
252 return frv_queue_fp_exception_interrupt (current_cpu
, & fp_info
);
257 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
260 struct frv_interrupt_queue_element
*
261 frv_queue_privileged_instruction_interrupt (SIM_CPU
*current_cpu
, const CGEN_INSN
*insn
)
263 /* The fr550 has no privileged instruction interrupt. It uses
264 illegal_instruction. */
265 SIM_DESC sd
= CPU_STATE (current_cpu
);
266 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
267 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
269 return frv_queue_program_interrupt (current_cpu
, FRV_PRIVILEGED_INSTRUCTION
);
272 struct frv_interrupt_queue_element
*
273 frv_queue_float_disabled_interrupt (SIM_CPU
*current_cpu
)
275 /* The fr550 has no fp_disabled interrupt. It uses illegal_instruction. */
276 SIM_DESC sd
= CPU_STATE (current_cpu
);
277 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
278 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
280 return frv_queue_program_interrupt (current_cpu
, FRV_FP_DISABLED
);
283 struct frv_interrupt_queue_element
*
284 frv_queue_media_disabled_interrupt (SIM_CPU
*current_cpu
)
286 /* The fr550 has no mp_disabled interrupt. It uses illegal_instruction. */
287 SIM_DESC sd
= CPU_STATE (current_cpu
);
288 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
289 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
291 return frv_queue_program_interrupt (current_cpu
, FRV_MP_DISABLED
);
294 struct frv_interrupt_queue_element
*
295 frv_queue_non_implemented_instruction_interrupt (
296 SIM_CPU
*current_cpu
, const CGEN_INSN
*insn
299 SIM_DESC sd
= CPU_STATE (current_cpu
);
300 switch (STATE_ARCHITECTURE (sd
)->mach
)
307 /* Some machines generate fp_exception or mp_exception for this case. */
308 if (frv_is_float_insn (insn
))
310 struct frv_fp_exception_info fp_info
= {
311 FSR_NO_EXCEPTION
, FTT_UNIMPLEMENTED_FPOP
313 return frv_queue_fp_exception_interrupt (current_cpu
, & fp_info
);
315 if (frv_is_media_insn (insn
))
317 frv_set_mp_exception_registers (current_cpu
, MTT_UNIMPLEMENTED_MPOP
,
319 return NULL
; /* no interrupt queued at this time. */
324 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
327 /* Queue the given fp_exception interrupt. Also update fp_info by removing
328 masked interrupts and updating the 'slot' flield. */
329 struct frv_interrupt_queue_element
*
330 frv_queue_fp_exception_interrupt (
331 SIM_CPU
*current_cpu
, struct frv_fp_exception_info
*fp_info
334 SI fsr0
= GET_FSR (0);
335 int tem
= GET_FSR_TEM (fsr0
);
336 int aexc
= GET_FSR_AEXC (fsr0
);
337 struct frv_interrupt_queue_element
*new_element
= NULL
;
339 /* Update AEXC with the interrupts that are masked. */
340 aexc
|= fp_info
->fsr_mask
& ~tem
;
341 SET_FSR_AEXC (fsr0
, aexc
);
344 /* update fsr_mask with the exceptions that are enabled. */
345 fp_info
->fsr_mask
&= tem
;
347 /* If there is an unmasked interrupt then queue it, unless
348 this was a non-excepting insn, in which case simply set the NE
350 if (frv_interrupt_state
.ne_index
!= NE_NOFLAG
351 && fp_info
->fsr_mask
!= FSR_NO_EXCEPTION
)
353 SET_NE_FLAG (frv_interrupt_state
.f_ne_flags
,
354 frv_interrupt_state
.ne_index
);
355 /* TODO -- Set NESR for chips which support it. */
358 else if (fp_info
->fsr_mask
!= FSR_NO_EXCEPTION
359 || fp_info
->ftt
== FTT_UNIMPLEMENTED_FPOP
360 || fp_info
->ftt
== FTT_SEQUENCE_ERROR
361 || fp_info
->ftt
== FTT_INVALID_FR
)
363 new_element
= frv_queue_program_interrupt (current_cpu
, FRV_FP_EXCEPTION
);
364 new_element
->u
.fp_info
= *fp_info
;
370 struct frv_interrupt_queue_element
*
371 frv_queue_division_exception_interrupt (SIM_CPU
*current_cpu
, enum frv_dtt dtt
)
373 struct frv_interrupt_queue_element
*new_element
=
374 frv_queue_program_interrupt (current_cpu
, FRV_DIVISION_EXCEPTION
);
376 new_element
->u
.dtt
= dtt
;
381 /* Check for interrupts caused by illegal insn access. These conditions are
382 checked in the order specified by the fr400 and fr500 LSI specs. */
384 frv_detect_insn_access_interrupts (SIM_CPU
*current_cpu
, SCACHE
*sc
)
387 const CGEN_INSN
*insn
= sc
->argbuf
.idesc
->idata
;
388 SIM_DESC sd
= CPU_STATE (current_cpu
);
389 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
391 /* Check for vliw constraints. */
392 if (vliw
->constraint_violation
)
393 frv_queue_illegal_instruction_interrupt (current_cpu
, insn
);
394 /* Check for non-excepting insns. */
395 else if (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_NON_EXCEPTING
)
396 && ! GET_H_PSR_NEM ())
397 frv_queue_non_implemented_instruction_interrupt (current_cpu
, insn
);
398 /* Check for conditional insns. */
399 else if (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_CONDITIONAL
)
400 && ! GET_H_PSR_CM ())
401 frv_queue_non_implemented_instruction_interrupt (current_cpu
, insn
);
402 /* Make sure floating point support is enabled. */
403 else if (! GET_H_PSR_EF ())
405 /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
406 off and the insns accesses a fp register. */
407 if (frv_is_float_insn (insn
)
408 || (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_FR_ACCESS
)
409 && ! GET_H_PSR_EM ()))
410 frv_queue_float_disabled_interrupt (current_cpu
);
412 /* Make sure media support is enabled. */
413 else if (! GET_H_PSR_EM ())
415 /* Generate mp_disabled if it is a media insn. */
416 if (frv_is_media_insn (insn
) || CGEN_INSN_NUM (insn
) == FRV_INSN_MTRAP
)
417 frv_queue_media_disabled_interrupt (current_cpu
);
419 /* Check for privileged insns. */
420 else if (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_PRIVILEGED
) &&
422 frv_queue_privileged_instruction_interrupt (current_cpu
, insn
);
423 #if 0 /* disable for now until we find out how FSR0.QNE gets reset. */
426 /* Enter the halt state if FSR0.QNE is set and we are executing a
427 floating point insn, a media insn or an insn which access a FR
429 SI fsr0
= GET_FSR (0);
430 if (GET_FSR_QNE (fsr0
)
431 && (frv_is_float_insn (insn
) || frv_is_media_insn (insn
)
432 || CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_FR_ACCESS
)))
434 sim_engine_halt (sd
, current_cpu
, NULL
, GET_H_PC (), sim_stopped
,
441 /* Record the current VLIW slot in the given interrupt queue element. */
443 frv_set_interrupt_queue_slot (
444 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
447 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
448 int slot
= vliw
->next_slot
- 1;
449 item
->slot
= (*vliw
->current_vliw
)[slot
];
452 /* Handle an individual interrupt. */
454 handle_interrupt (SIM_CPU
*current_cpu
, IADDR pc
)
456 struct frv_interrupt
*interrupt
;
457 int writeback_done
= 0;
460 /* Interrupts are queued in priority order with the highest priority
462 int index
= frv_interrupt_state
.queue_index
- 1;
463 struct frv_interrupt_queue_element
*item
464 = & frv_interrupt_state
.queue
[index
];
465 interrupt
= & frv_interrupt_table
[item
->kind
];
467 switch (interrupt
->iclass
)
469 case FRV_EXTERNAL_INTERRUPT
:
470 /* Perform writeback first. This may cause a higher priority
472 if (! writeback_done
)
474 frvbf_perform_writeback (current_cpu
);
478 frv_external_interrupt (current_cpu
, item
, pc
);
480 case FRV_SOFTWARE_INTERRUPT
:
481 frv_interrupt_state
.queue_index
= index
;
482 frv_software_interrupt (current_cpu
, item
, pc
);
484 case FRV_PROGRAM_INTERRUPT
:
485 /* If the program interrupt is not strict (imprecise), then perform
486 writeback first. This may, in turn, cause a higher priority
488 if (! interrupt
->precise
&& ! writeback_done
)
490 frv_interrupt_state
.imprecise_interrupt
= item
;
491 frvbf_perform_writeback (current_cpu
);
495 frv_interrupt_state
.queue_index
= index
;
496 frv_program_interrupt (current_cpu
, item
, pc
);
498 case FRV_BREAK_INTERRUPT
:
499 frv_interrupt_state
.queue_index
= index
;
500 frv_break_interrupt (current_cpu
, interrupt
, pc
);
502 case FRV_RESET_INTERRUPT
:
507 frv_interrupt_state
.queue_index
= index
;
508 break; /* out of loop. */
511 /* We should never get here. */
513 SIM_DESC sd
= CPU_STATE (current_cpu
);
514 sim_engine_abort (sd
, current_cpu
, pc
,
515 "interrupt class not supported %d\n",
520 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set. If so, handle
521 the appropriate reset interrupt. */
523 check_reset (SIM_CPU
*current_cpu
, IADDR pc
)
529 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
530 IADDR address
= RSTR_ADDRESS
;
532 /* We don't want this to show up in the cache statistics, so read the
534 if (! frv_cache_read_passive_SI (cache
, address
, & rstr
))
535 rstr
= sim_core_read_unaligned_4 (current_cpu
, pc
, read_map
, address
);
537 hr
= GET_RSTR_HR (rstr
);
538 sr
= GET_RSTR_SR (rstr
);
541 return 0; /* no reset. */
543 /* Reinitialize the machine state. */
545 frv_hardware_reset (current_cpu
);
547 frv_software_reset (current_cpu
);
549 /* Branch to the reset address. */
551 if (GET_HSR0_SA (hsr0
))
552 SET_H_PC (0xff000000);
556 return 1; /* reset */
559 /* Process any pending interrupt(s) after a group of parallel insns. */
561 frv_process_interrupts (SIM_CPU
*current_cpu
)
564 /* Need to save the pc here because writeback may change it (due to a
566 IADDR pc
= CPU_PC_GET (current_cpu
);
568 /* Check for a reset before anything else. */
569 if (check_reset (current_cpu
, pc
))
572 /* First queue the writes for any accumulated NE flags. */
573 if (frv_interrupt_state
.f_ne_flags
[0] != 0
574 || frv_interrupt_state
.f_ne_flags
[1] != 0)
576 GET_NE_FLAGS (NE_flags
, H_SPR_FNER0
);
577 NE_flags
[0] |= frv_interrupt_state
.f_ne_flags
[0];
578 NE_flags
[1] |= frv_interrupt_state
.f_ne_flags
[1];
579 SET_NE_FLAGS (H_SPR_FNER0
, NE_flags
);
582 /* If there is no interrupt pending, then perform parallel writeback. This
583 may cause an interrupt. */
584 if (frv_interrupt_state
.queue_index
<= 0)
585 frvbf_perform_writeback (current_cpu
);
587 /* If there is an interrupt pending, then process it. */
588 if (frv_interrupt_state
.queue_index
> 0)
589 handle_interrupt (current_cpu
, pc
);
592 /* Find the next available ESR and return its index */
594 esr_for_data_access_exception (
595 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
598 SIM_DESC sd
= CPU_STATE (current_cpu
);
599 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
600 return 8; /* Use ESR8, EPCR8. */
602 if (item
->slot
== UNIT_I0
)
603 return 8; /* Use ESR8, EPCR8, EAR8, EDR8. */
605 return 9; /* Use ESR9, EPCR9, EAR9. */
608 /* Set the next available EDR register with the data which was to be stored
609 and return the index of the register. */
612 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, int edr_index
615 /* EDR0, EDR4 and EDR8 are available as blocks of 4.
616 SI data uses EDR3, EDR7 and EDR11
617 DI data uses EDR2, EDR6 and EDR10
618 XI data uses EDR0, EDR4 and EDR8. */
620 edr_index
+= 4 - item
->u
.data_written
.length
;
621 for (i
= 0; i
< item
->u
.data_written
.length
; ++i
)
622 SET_EDR (edr_index
+ i
, item
->u
.data_written
.words
[i
]);
627 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx. */
629 clear_exception_status_registers (SIM_CPU
*current_cpu
)
632 /* It is only necessary to clear the flag bits indicating which registers
637 for (i
= 0; i
<= 2; ++i
)
639 SI esr
= GET_ESR (i
);
640 CLEAR_ESR_VALID (esr
);
643 for (i
= 8; i
<= 15; ++i
)
645 SI esr
= GET_ESR (i
);
646 CLEAR_ESR_VALID (esr
);
651 /* Record state for media exception. */
653 frv_set_mp_exception_registers (
654 SIM_CPU
*current_cpu
, enum frv_msr_mtt mtt
, int sie
657 /* Record the interrupt factor in MSR0. */
658 SI msr0
= GET_MSR (0);
659 if (GET_MSR_MTT (msr0
) == MTT_NONE
)
660 SET_MSR_MTT (msr0
, mtt
);
662 /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF. */
663 if (mtt
== MTT_OVERFLOW
)
665 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
666 int slot
= vliw
->next_slot
- 1;
667 SIM_DESC sd
= CPU_STATE (current_cpu
);
669 /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE,
670 otherwise set MSR0.OVF and MSR0.SIE. */
671 if (STATE_ARCHITECTURE (sd
)->mach
!= bfd_mach_fr550
&& (*vliw
->current_vliw
)[slot
] == UNIT_FM1
)
673 SI msr
= GET_MSR (1);
674 OR_MSR_SIE (msr
, sie
);
680 OR_MSR_SIE (msr0
, sie
);
684 /* Generate the interrupt now if MSR0.MPEM is set on fr550 */
685 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
&& GET_MSR_MPEM (msr0
))
686 frv_queue_program_interrupt (current_cpu
, FRV_MP_EXCEPTION
);
689 /* Regardless of the slot, set MSR0.AOVF. */
697 /* Determine the correct FQ register to use for the given exception.
698 Return -1 if a register is not available. */
701 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
705 struct frv_fp_exception_info
*fp_info
= & item
->u
.fp_info
;
707 /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1. */
708 if (fp_info
->ftt
== FTT_IEEE_754_EXCEPTION
709 && (fp_info
->fsr_mask
& (FSR_OVERFLOW
| FSR_UNDERFLOW
| FSR_INEXACT
)))
712 if (! GET_FQ_VALID (fq
))
713 return 0; /* FQ0 is available. */
715 if (! GET_FQ_VALID (fq
))
716 return 1; /* FQ1 is available. */
718 /* No FQ register is available */
720 SIM_DESC sd
= CPU_STATE (current_cpu
);
721 IADDR pc
= CPU_PC_GET (current_cpu
);
722 sim_engine_abort (sd
, current_cpu
, pc
, "No FQ register available\n");
726 /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
728 if (item
->slot
== UNIT_FM0
|| item
->slot
== UNIT_I0
)
734 /* Set FSR0, FQ0-FQ9, depending on the interrupt. */
736 set_fp_exception_registers (
737 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
745 struct frv_fp_exception_info
*fp_info
;
746 SIM_DESC sd
= CPU_STATE (current_cpu
);
748 /* No FQ registers on fr550 */
749 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
751 /* Update the fsr. */
752 fp_info
= & item
->u
.fp_info
;
754 SET_FSR_FTT (fsr0
, fp_info
->ftt
);
759 /* Select an FQ and update it with the exception information. */
760 fq_index
= fq_for_exception (current_cpu
, item
);
764 fp_info
= & item
->u
.fp_info
;
765 fq
= GET_FQ (fq_index
);
766 SET_FQ_MIV (fq
, MIV_FLOAT
);
767 SET_FQ_SIE (fq
, SIE_NIL
);
768 SET_FQ_FTT (fq
, fp_info
->ftt
);
769 SET_FQ_CEXC (fq
, fp_info
->fsr_mask
);
771 SET_FQ (fq_index
, fq
);
773 /* Write the failing insn into FQx.OPC. */
775 insn
= GETMEMSI (current_cpu
, pc
, pc
);
776 SET_FQ_OPC (fq_index
, insn
);
778 /* Update the fsr. */
780 SET_FSR_QNE (fsr0
); /* FQ not empty */
781 SET_FSR_FTT (fsr0
, fp_info
->ftt
);
785 /* Record the state of a division exception in the ISR. */
787 set_isr_exception_fields (
788 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
791 USI isr
= GET_ISR ();
792 int dtt
= GET_ISR_DTT (isr
);
794 SET_ISR_DTT (isr
, dtt
);
798 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
801 set_exception_status_registers (
802 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
805 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[item
->kind
];
806 int slot
= (item
->vpc
- previous_vliw_pc
) / 4;
813 SIM_DESC sd
= CPU_STATE (current_cpu
);
815 /* If the interrupt is strict (precise) or the interrupt is on the insns
816 in the I0 pipe, then set the 0 registers. */
817 if (interrupt
->precise
)
820 if (interrupt
->kind
== FRV_REGISTER_EXCEPTION
)
821 SET_ESR_REC (esr
, item
->u
.rec
);
822 else if (interrupt
->kind
== FRV_INSTRUCTION_ACCESS_EXCEPTION
)
823 SET_ESR_IAEC (esr
, item
->u
.iaec
);
824 /* For fr550, don't set epcr for precise interrupts. */
825 if (STATE_ARCHITECTURE (sd
)->mach
!= bfd_mach_fr550
)
830 switch (interrupt
->kind
)
832 case FRV_DIVISION_EXCEPTION
:
833 set_isr_exception_fields (current_cpu
, item
);
834 /* fall thru to set reg_index. */
835 case FRV_COMMIT_EXCEPTION
:
836 /* For fr550, always use ESR0. */
837 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
839 else if (item
->slot
== UNIT_I0
)
841 else if (item
->slot
== UNIT_I1
)
845 case FRV_DATA_STORE_ERROR
:
846 reg_index
= 14; /* Use ESR14. */
848 case FRV_DATA_ACCESS_ERROR
:
849 reg_index
= 15; /* Use ESR15, EPCR15. */
852 case FRV_DATA_ACCESS_EXCEPTION
:
855 case FRV_DATA_ACCESS_MMU_MISS
:
856 case FRV_MEM_ADDRESS_NOT_ALIGNED
:
857 /* Get the appropriate ESR, EPCR, EAR and EDR.
858 EAR will be set. EDR will not be set if this is a store insn. */
860 /* For fr550, never use EDRx. */
861 if (STATE_ARCHITECTURE (sd
)->mach
!= bfd_mach_fr550
)
862 if (item
->u
.data_written
.length
!= 0)
864 reg_index
= esr_for_data_access_exception (current_cpu
, item
);
867 case FRV_MP_EXCEPTION
:
868 /* For fr550, use EPCR2 and ESR2. */
869 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
874 break; /* MSR0-1, FQ0-9 are already set. */
875 case FRV_FP_EXCEPTION
:
876 set_fp_exception_registers (current_cpu
, item
);
877 /* For fr550, use EPCR2 and ESR2. */
878 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
886 SIM_DESC sd
= CPU_STATE (current_cpu
);
887 IADDR pc
= CPU_PC_GET (current_cpu
);
888 sim_engine_abort (sd
, current_cpu
, pc
,
889 "invalid non-strict program interrupt kind: %d\n",
894 } /* non-strict (imprecise) interrupt */
896 /* Now fill in the selected exception status registers. */
899 /* Now set the exception status registers. */
900 SET_ESFR_FLAG (reg_index
);
901 SET_ESR_EC (esr
, interrupt
->ec
);
905 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr400
)
906 SET_EPCR (reg_index
, previous_vliw_pc
);
908 SET_EPCR (reg_index
, item
->vpc
);
913 SET_EAR (reg_index
, item
->eaddress
);
921 int edn
= set_edr_register (current_cpu
, item
, 0/* EDR0-3 */);
922 SET_ESR_EDN (esr
, edn
);
929 SET_ESR_DAEC (esr
, item
->u
.daec
);
932 SET_ESR (reg_index
, esr
);
936 /* Check for compound interrupts.
937 Returns NULL if no interrupt is to be processed. */
938 static struct frv_interrupt
*
939 check_for_compound_interrupt (
940 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
943 struct frv_interrupt
*interrupt
;
945 /* Set the exception status registers for the original interrupt. */
946 set_exception_status_registers (current_cpu
, item
);
947 interrupt
= & frv_interrupt_table
[item
->kind
];
949 if (! interrupt
->precise
)
955 mask
= (1 << item
->kind
);
957 /* Look for more queued program interrupts which are non-deferred
958 (pending inhibit), imprecise (non-strict) different than an interrupt
959 already found and caused by a different insn. A bit mask is used
960 to keep track of interrupts which have already been detected. */
961 while (item
!= frv_interrupt_state
.queue
)
963 enum frv_interrupt_kind kind
;
964 struct frv_interrupt
*next_interrupt
;
967 next_interrupt
= & frv_interrupt_table
[kind
];
969 if (next_interrupt
->iclass
!= FRV_PROGRAM_INTERRUPT
)
970 break; /* no program interrupts left. */
972 if (item
->vpc
== vpc
)
973 continue; /* caused by the same insn. */
976 if (! next_interrupt
->precise
&& ! next_interrupt
->deferred
)
978 if (! (mask
& (1 << kind
)))
980 /* Set the exception status registers for the additional
982 set_exception_status_registers (current_cpu
, item
);
984 interrupt
= & frv_interrupt_table
[FRV_COMPOUND_EXCEPTION
];
990 /* Return with either the original interrupt, a compound_exception,
995 /* Handle a program interrupt. */
997 frv_program_interrupt (
998 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, IADDR pc
1001 struct frv_interrupt
*interrupt
;
1003 clear_exception_status_registers (current_cpu
);
1004 /* If two or more non-deferred imprecise (non-strict) interrupts occur
1005 on two or more insns, then generate a compound_exception. */
1006 interrupt
= check_for_compound_interrupt (current_cpu
, item
);
1007 if (interrupt
!= NULL
)
1009 frv_program_or_software_interrupt (current_cpu
, interrupt
, pc
);
1010 frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT
,
1011 FRV_PROGRAM_INTERRUPT
);
1015 /* Handle a software interrupt. */
1017 frv_software_interrupt (
1018 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, IADDR pc
1021 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[item
->kind
];
1022 frv_program_or_software_interrupt (current_cpu
, interrupt
, pc
);
1025 /* Handle a program interrupt or a software interrupt in non-operating mode. */
1027 frv_non_operating_interrupt (
1028 SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
, IADDR pc
1031 SIM_DESC sd
= CPU_STATE (current_cpu
);
1034 case FRV_INTERRUPT_LEVEL_1
:
1035 case FRV_INTERRUPT_LEVEL_2
:
1036 case FRV_INTERRUPT_LEVEL_3
:
1037 case FRV_INTERRUPT_LEVEL_4
:
1038 case FRV_INTERRUPT_LEVEL_5
:
1039 case FRV_INTERRUPT_LEVEL_6
:
1040 case FRV_INTERRUPT_LEVEL_7
:
1041 case FRV_INTERRUPT_LEVEL_8
:
1042 case FRV_INTERRUPT_LEVEL_9
:
1043 case FRV_INTERRUPT_LEVEL_10
:
1044 case FRV_INTERRUPT_LEVEL_11
:
1045 case FRV_INTERRUPT_LEVEL_12
:
1046 case FRV_INTERRUPT_LEVEL_13
:
1047 case FRV_INTERRUPT_LEVEL_14
:
1048 case FRV_INTERRUPT_LEVEL_15
:
1049 sim_engine_abort (sd
, current_cpu
, pc
,
1050 "interrupt: external %d\n", kind
+ 1);
1052 case FRV_TRAP_INSTRUCTION
:
1053 break; /* handle as in operating mode. */
1054 case FRV_COMMIT_EXCEPTION
:
1055 sim_engine_abort (sd
, current_cpu
, pc
,
1056 "interrupt: commit_exception\n");
1058 case FRV_DIVISION_EXCEPTION
:
1059 sim_engine_abort (sd
, current_cpu
, pc
,
1060 "interrupt: division_exception\n");
1062 case FRV_DATA_STORE_ERROR
:
1063 sim_engine_abort (sd
, current_cpu
, pc
,
1064 "interrupt: data_store_error\n");
1066 case FRV_DATA_ACCESS_EXCEPTION
:
1067 sim_engine_abort (sd
, current_cpu
, pc
,
1068 "interrupt: data_access_exception\n");
1070 case FRV_DATA_ACCESS_MMU_MISS
:
1071 sim_engine_abort (sd
, current_cpu
, pc
,
1072 "interrupt: data_access_mmu_miss\n");
1074 case FRV_DATA_ACCESS_ERROR
:
1075 sim_engine_abort (sd
, current_cpu
, pc
,
1076 "interrupt: data_access_error\n");
1078 case FRV_MP_EXCEPTION
:
1079 sim_engine_abort (sd
, current_cpu
, pc
,
1080 "interrupt: mp_exception\n");
1082 case FRV_FP_EXCEPTION
:
1083 sim_engine_abort (sd
, current_cpu
, pc
,
1084 "interrupt: fp_exception\n");
1086 case FRV_MEM_ADDRESS_NOT_ALIGNED
:
1087 sim_engine_abort (sd
, current_cpu
, pc
,
1088 "interrupt: mem_address_not_aligned\n");
1090 case FRV_REGISTER_EXCEPTION
:
1091 sim_engine_abort (sd
, current_cpu
, pc
,
1092 "interrupt: register_exception\n");
1094 case FRV_MP_DISABLED
:
1095 sim_engine_abort (sd
, current_cpu
, pc
,
1096 "interrupt: mp_disabled\n");
1098 case FRV_FP_DISABLED
:
1099 sim_engine_abort (sd
, current_cpu
, pc
,
1100 "interrupt: fp_disabled\n");
1102 case FRV_PRIVILEGED_INSTRUCTION
:
1103 sim_engine_abort (sd
, current_cpu
, pc
,
1104 "interrupt: privileged_instruction\n");
1106 case FRV_ILLEGAL_INSTRUCTION
:
1107 sim_engine_abort (sd
, current_cpu
, pc
,
1108 "interrupt: illegal_instruction\n");
1110 case FRV_INSTRUCTION_ACCESS_EXCEPTION
:
1111 sim_engine_abort (sd
, current_cpu
, pc
,
1112 "interrupt: instruction_access_exception\n");
1114 case FRV_INSTRUCTION_ACCESS_MMU_MISS
:
1115 sim_engine_abort (sd
, current_cpu
, pc
,
1116 "interrupt: instruction_access_mmu_miss\n");
1118 case FRV_INSTRUCTION_ACCESS_ERROR
:
1119 sim_engine_abort (sd
, current_cpu
, pc
,
1120 "interrupt: insn_access_error\n");
1122 case FRV_COMPOUND_EXCEPTION
:
1123 sim_engine_abort (sd
, current_cpu
, pc
,
1124 "interrupt: compound_exception\n");
1126 case FRV_BREAK_EXCEPTION
:
1127 sim_engine_abort (sd
, current_cpu
, pc
,
1128 "interrupt: break_exception\n");
1131 sim_engine_abort (sd
, current_cpu
, pc
,
1132 "interrupt: reset\n");
1135 sim_engine_abort (sd
, current_cpu
, pc
,
1136 "unhandled interrupt kind: %d\n", kind
);
1141 /* Handle a break interrupt. */
1143 frv_break_interrupt (
1144 SIM_CPU
*current_cpu
, struct frv_interrupt
*interrupt
, IADDR current_pc
1157 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1158 SET_H_BPSR_BS (GET_H_PSR_S ());
1159 SET_H_BPSR_BET (GET_H_PSR_ET ());
1162 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1163 SET_H_SPR (H_SPR_BPCSR
, current_pc
);
1165 /* Set the new PC in the TBR. */
1166 SET_H_TBR_TT (interrupt
->handler_offset
);
1167 new_pc
= GET_H_SPR (H_SPR_TBR
);
1170 CPU_DEBUG_STATE (current_cpu
) = 1;
1173 /* Handle a program interrupt or a software interrupt. */
1175 frv_program_or_software_interrupt (
1176 SIM_CPU
*current_cpu
, struct frv_interrupt
*interrupt
, IADDR current_pc
1180 int original_psr_et
;
1187 SR0 through SR3=GR4 through GR7
1188 TBR.TT=interrupt handler offset
1191 original_psr_et
= GET_H_PSR_ET ();
1193 SET_H_PSR_PS (GET_H_PSR_S ());
1197 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1198 /* The PCSR depends on the precision of the interrupt. */
1199 if (interrupt
->precise
)
1200 SET_H_SPR (H_SPR_PCSR
, previous_vliw_pc
);
1202 SET_H_SPR (H_SPR_PCSR
, current_pc
);
1204 /* Set the new PC in the TBR. */
1205 SET_H_TBR_TT (interrupt
->handler_offset
);
1206 new_pc
= GET_H_SPR (H_SPR_TBR
);
1209 /* If PSR.ET was not originally set, then enter the stopped state. */
1210 if (! original_psr_et
)
1212 SIM_DESC sd
= CPU_STATE (current_cpu
);
1213 frv_non_operating_interrupt (current_cpu
, interrupt
->kind
, current_pc
);
1214 sim_engine_halt (sd
, current_cpu
, NULL
, new_pc
, sim_stopped
, SIM_SIGINT
);
1218 /* Handle a program interrupt or a software interrupt. */
1220 frv_external_interrupt (
1221 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, IADDR pc
1225 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[item
->kind
];
1227 /* Don't process the interrupt if PSR.ET is not set or if it is masked.
1228 Interrupt 15 is processed even if it appears to be masked. */
1229 if (! GET_H_PSR_ET ()
1230 || (interrupt
->kind
!= FRV_INTERRUPT_LEVEL_15
1231 && interrupt
->kind
< GET_H_PSR_PIL ()))
1232 return; /* Leave it for later. */
1234 /* Remove the interrupt from the queue. */
1235 --frv_interrupt_state
.queue_index
;
1242 SR0 through SR3=GR4 through GR7
1243 TBR.TT=interrupt handler offset
1246 SET_H_PSR_PS (GET_H_PSR_S ());
1249 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1250 SET_H_SPR (H_SPR_PCSR
, GET_H_PC ());
1252 /* Set the new PC in the TBR. */
1253 SET_H_TBR_TT (interrupt
->handler_offset
);
1254 new_pc
= GET_H_SPR (H_SPR_TBR
);
1258 /* Clear interrupts which fall within the range of classes given. */
1260 frv_clear_interrupt_classes (
1261 enum frv_interrupt_class low_class
, enum frv_interrupt_class high_class
1266 int limit
= frv_interrupt_state
.queue_index
;
1268 /* Find the lowest priority interrupt to be removed. */
1269 for (i
= 0; i
< limit
; ++i
)
1271 enum frv_interrupt_kind kind
= frv_interrupt_state
.queue
[i
].kind
;
1272 struct frv_interrupt
* interrupt
= & frv_interrupt_table
[kind
];
1273 if (interrupt
->iclass
>= low_class
)
1277 /* Find the highest priority interrupt to be removed. */
1278 for (j
= limit
- 1; j
>= i
; --j
)
1280 enum frv_interrupt_kind kind
= frv_interrupt_state
.queue
[j
].kind
;
1281 struct frv_interrupt
* interrupt
= & frv_interrupt_table
[kind
];
1282 if (interrupt
->iclass
<= high_class
)
1286 /* Shuffle the remaining high priority interrupts down into the empty space
1287 left by the deleted interrupts. */
1290 for (++j
; j
< limit
; ++j
)
1291 frv_interrupt_state
.queue
[i
++] = frv_interrupt_state
.queue
[j
];
1292 frv_interrupt_state
.queue_index
-= (j
- i
);
1296 /* Save data written to memory into the interrupt state so that it can be
1297 copied to the appropriate EDR register, if necessary, in the event of an
1300 frv_save_data_written_for_interrupts (
1301 SIM_CPU
*current_cpu
, CGEN_WRITE_QUEUE_ELEMENT
*item
1304 /* Record the slot containing the insn doing the write in the
1306 frv_interrupt_state
.slot
= CGEN_WRITE_QUEUE_ELEMENT_PIPE (item
);
1308 /* Now record any data written to memory in the interrupt state. */
1309 switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item
))
1316 case CGEN_FN_HI_WRITE
:
1317 case CGEN_FN_SI_WRITE
:
1318 case CGEN_FN_SF_WRITE
:
1319 case CGEN_FN_DI_WRITE
:
1320 case CGEN_FN_DF_WRITE
:
1321 case CGEN_FN_XI_WRITE
:
1322 case CGEN_FN_PC_WRITE
:
1323 break; /* Ignore writes to registers. */
1324 case CGEN_MEM_QI_WRITE
:
1325 frv_interrupt_state
.data_written
.length
= 1;
1326 frv_interrupt_state
.data_written
.words
[0]
1327 = item
->kinds
.mem_qi_write
.value
;
1329 case CGEN_MEM_HI_WRITE
:
1330 frv_interrupt_state
.data_written
.length
= 1;
1331 frv_interrupt_state
.data_written
.words
[0]
1332 = item
->kinds
.mem_hi_write
.value
;
1334 case CGEN_MEM_SI_WRITE
:
1335 frv_interrupt_state
.data_written
.length
= 1;
1336 frv_interrupt_state
.data_written
.words
[0]
1337 = item
->kinds
.mem_si_write
.value
;
1339 case CGEN_MEM_DI_WRITE
:
1340 frv_interrupt_state
.data_written
.length
= 2;
1341 frv_interrupt_state
.data_written
.words
[0]
1342 = item
->kinds
.mem_di_write
.value
>> 32;
1343 frv_interrupt_state
.data_written
.words
[1]
1344 = item
->kinds
.mem_di_write
.value
;
1346 case CGEN_MEM_DF_WRITE
:
1347 frv_interrupt_state
.data_written
.length
= 2;
1348 frv_interrupt_state
.data_written
.words
[0]
1349 = item
->kinds
.mem_df_write
.value
>> 32;
1350 frv_interrupt_state
.data_written
.words
[1]
1351 = item
->kinds
.mem_df_write
.value
;
1353 case CGEN_MEM_XI_WRITE
:
1354 frv_interrupt_state
.data_written
.length
= 4;
1355 frv_interrupt_state
.data_written
.words
[0]
1356 = item
->kinds
.mem_xi_write
.value
[0];
1357 frv_interrupt_state
.data_written
.words
[1]
1358 = item
->kinds
.mem_xi_write
.value
[1];
1359 frv_interrupt_state
.data_written
.words
[2]
1360 = item
->kinds
.mem_xi_write
.value
[2];
1361 frv_interrupt_state
.data_written
.words
[3]
1362 = item
->kinds
.mem_xi_write
.value
[3];
1364 case CGEN_FN_MEM_QI_WRITE
:
1365 frv_interrupt_state
.data_written
.length
= 1;
1366 frv_interrupt_state
.data_written
.words
[0]
1367 = item
->kinds
.fn_mem_qi_write
.value
;
1369 case CGEN_FN_MEM_HI_WRITE
:
1370 frv_interrupt_state
.data_written
.length
= 1;
1371 frv_interrupt_state
.data_written
.words
[0]
1372 = item
->kinds
.fn_mem_hi_write
.value
;
1374 case CGEN_FN_MEM_SI_WRITE
:
1375 frv_interrupt_state
.data_written
.length
= 1;
1376 frv_interrupt_state
.data_written
.words
[0]
1377 = item
->kinds
.fn_mem_si_write
.value
;
1379 case CGEN_FN_MEM_DI_WRITE
:
1380 frv_interrupt_state
.data_written
.length
= 2;
1381 frv_interrupt_state
.data_written
.words
[0]
1382 = item
->kinds
.fn_mem_di_write
.value
>> 32;
1383 frv_interrupt_state
.data_written
.words
[1]
1384 = item
->kinds
.fn_mem_di_write
.value
;
1386 case CGEN_FN_MEM_DF_WRITE
:
1387 frv_interrupt_state
.data_written
.length
= 2;
1388 frv_interrupt_state
.data_written
.words
[0]
1389 = item
->kinds
.fn_mem_df_write
.value
>> 32;
1390 frv_interrupt_state
.data_written
.words
[1]
1391 = item
->kinds
.fn_mem_df_write
.value
;
1393 case CGEN_FN_MEM_XI_WRITE
:
1394 frv_interrupt_state
.data_written
.length
= 4;
1395 frv_interrupt_state
.data_written
.words
[0]
1396 = item
->kinds
.fn_mem_xi_write
.value
[0];
1397 frv_interrupt_state
.data_written
.words
[1]
1398 = item
->kinds
.fn_mem_xi_write
.value
[1];
1399 frv_interrupt_state
.data_written
.words
[2]
1400 = item
->kinds
.fn_mem_xi_write
.value
[2];
1401 frv_interrupt_state
.data_written
.words
[3]
1402 = item
->kinds
.fn_mem_xi_write
.value
[3];
1406 SIM_DESC sd
= CPU_STATE (current_cpu
);
1407 IADDR pc
= CPU_PC_GET (current_cpu
);
1408 sim_engine_abort (sd
, current_cpu
, pc
,
1409 "unknown write kind during save for interrupt\n");