1 /* frv exception and interrupt support
2 Copyright (C) 1999-2019 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 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #define WANT_CPU frvbf
21 #define WANT_CPU_FRVBF
26 /* FR-V Interrupt table.
27 Describes the interrupts supported by the FR-V.
28 This table *must* be maintained in order of interrupt priority as defined by
29 frv_interrupt_kind. */
32 #define ITABLE_ENTRY(name, class, deferral, precision, offset) \
33 {FRV_##name, FRV_EC_##name, class, deferral, precision, offset}
35 struct frv_interrupt frv_interrupt_table
[NUM_FRV_INTERRUPT_KINDS
] =
37 /* External interrupts */
38 ITABLE_ENTRY(INTERRUPT_LEVEL_1
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x21),
39 ITABLE_ENTRY(INTERRUPT_LEVEL_2
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x22),
40 ITABLE_ENTRY(INTERRUPT_LEVEL_3
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x23),
41 ITABLE_ENTRY(INTERRUPT_LEVEL_4
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x24),
42 ITABLE_ENTRY(INTERRUPT_LEVEL_5
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x25),
43 ITABLE_ENTRY(INTERRUPT_LEVEL_6
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x26),
44 ITABLE_ENTRY(INTERRUPT_LEVEL_7
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x27),
45 ITABLE_ENTRY(INTERRUPT_LEVEL_8
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x28),
46 ITABLE_ENTRY(INTERRUPT_LEVEL_9
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x29),
47 ITABLE_ENTRY(INTERRUPT_LEVEL_10
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2a),
48 ITABLE_ENTRY(INTERRUPT_LEVEL_11
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2b),
49 ITABLE_ENTRY(INTERRUPT_LEVEL_12
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2c),
50 ITABLE_ENTRY(INTERRUPT_LEVEL_13
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2d),
51 ITABLE_ENTRY(INTERRUPT_LEVEL_14
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2e),
52 ITABLE_ENTRY(INTERRUPT_LEVEL_15
, FRV_EXTERNAL_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x2f),
53 /* Software interrupt */
54 ITABLE_ENTRY(TRAP_INSTRUCTION
, FRV_SOFTWARE_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x80),
55 /* Program interrupts */
56 ITABLE_ENTRY(COMMIT_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x19),
57 ITABLE_ENTRY(DIVISION_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x17),
58 ITABLE_ENTRY(DATA_STORE_ERROR
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x14),
59 ITABLE_ENTRY(DATA_ACCESS_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x13),
60 ITABLE_ENTRY(DATA_ACCESS_MMU_MISS
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x12),
61 ITABLE_ENTRY(DATA_ACCESS_ERROR
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x11),
62 ITABLE_ENTRY(MP_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x0e),
63 ITABLE_ENTRY(FP_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x0d),
64 ITABLE_ENTRY(MEM_ADDRESS_NOT_ALIGNED
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x10),
65 ITABLE_ENTRY(REGISTER_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x08),
66 ITABLE_ENTRY(MP_DISABLED
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x0b),
67 ITABLE_ENTRY(FP_DISABLED
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x0a),
68 ITABLE_ENTRY(PRIVILEGED_INSTRUCTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x06),
69 ITABLE_ENTRY(ILLEGAL_INSTRUCTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x07),
70 ITABLE_ENTRY(INSTRUCTION_ACCESS_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x03),
71 ITABLE_ENTRY(INSTRUCTION_ACCESS_ERROR
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x02),
72 ITABLE_ENTRY(INSTRUCTION_ACCESS_MMU_MISS
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, PRECISE
, 0x01),
73 ITABLE_ENTRY(COMPOUND_EXCEPTION
, FRV_PROGRAM_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x20),
75 ITABLE_ENTRY(BREAK_EXCEPTION
, FRV_BREAK_INTERRUPT
, !DEFERRED
, !PRECISE
, 0xff),
77 ITABLE_ENTRY(RESET
, FRV_RESET_INTERRUPT
, !DEFERRED
, !PRECISE
, 0x00)
80 /* The current interrupt state. */
81 struct frv_interrupt_state frv_interrupt_state
;
83 /* maintain the address of the start of the previous VLIW insn sequence. */
84 IADDR previous_vliw_pc
;
86 /* Add a break interrupt to the interrupt queue. */
87 struct frv_interrupt_queue_element
*
88 frv_queue_break_interrupt (SIM_CPU
*current_cpu
)
90 return frv_queue_interrupt (current_cpu
, FRV_BREAK_EXCEPTION
);
93 /* Add a software interrupt to the interrupt queue. */
94 struct frv_interrupt_queue_element
*
95 frv_queue_software_interrupt (SIM_CPU
*current_cpu
, SI offset
)
97 struct frv_interrupt_queue_element
*new_element
98 = frv_queue_interrupt (current_cpu
, FRV_TRAP_INSTRUCTION
);
100 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[new_element
->kind
];
101 interrupt
->handler_offset
= offset
;
106 /* Add a program interrupt to the interrupt queue. */
107 struct frv_interrupt_queue_element
*
108 frv_queue_program_interrupt (
109 SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
112 return frv_queue_interrupt (current_cpu
, kind
);
115 /* Add an external interrupt to the interrupt queue. */
116 struct frv_interrupt_queue_element
*
117 frv_queue_external_interrupt (
118 SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
121 if (! GET_H_PSR_ET ()
122 || (kind
!= FRV_INTERRUPT_LEVEL_15
&& kind
< GET_H_PSR_PIL ()))
123 return NULL
; /* Leave it for later. */
125 return frv_queue_interrupt (current_cpu
, kind
);
128 /* Add any interrupt to the interrupt queue. It will be added in reverse
129 priority order. This makes it easy to find the highest priority interrupt
130 at the end of the queue and to remove it after processing. */
131 struct frv_interrupt_queue_element
*
132 frv_queue_interrupt (SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
)
136 int limit
= frv_interrupt_state
.queue_index
;
137 struct frv_interrupt_queue_element
*new_element
;
138 enum frv_interrupt_class iclass
;
140 if (limit
>= FRV_INTERRUPT_QUEUE_SIZE
)
141 abort (); /* TODO: Make the queue dynamic */
143 /* Find the right place in the queue. */
144 for (i
= 0; i
< limit
; ++i
)
146 if (frv_interrupt_state
.queue
[i
].kind
>= kind
)
150 /* Don't queue two external interrupts of the same priority. */
151 iclass
= frv_interrupt_table
[kind
].iclass
;
152 if (i
< limit
&& iclass
== FRV_EXTERNAL_INTERRUPT
)
154 if (frv_interrupt_state
.queue
[i
].kind
== kind
)
155 return & frv_interrupt_state
.queue
[i
];
158 /* Make room for the new interrupt in this spot. */
159 for (j
= limit
- 1; j
>= i
; --j
)
160 frv_interrupt_state
.queue
[j
+ 1] = frv_interrupt_state
.queue
[j
];
162 /* Add the new interrupt. */
163 frv_interrupt_state
.queue_index
++;
164 new_element
= & frv_interrupt_state
.queue
[i
];
165 new_element
->kind
= kind
;
166 new_element
->vpc
= CPU_PC_GET (current_cpu
);
167 new_element
->u
.data_written
.length
= 0;
168 frv_set_interrupt_queue_slot (current_cpu
, new_element
);
173 struct frv_interrupt_queue_element
*
174 frv_queue_register_exception_interrupt (SIM_CPU
*current_cpu
, enum frv_rec rec
)
176 struct frv_interrupt_queue_element
*new_element
=
177 frv_queue_program_interrupt (current_cpu
, FRV_REGISTER_EXCEPTION
);
179 new_element
->u
.rec
= rec
;
184 struct frv_interrupt_queue_element
*
185 frv_queue_mem_address_not_aligned_interrupt (SIM_CPU
*current_cpu
, USI addr
)
187 struct frv_interrupt_queue_element
*new_element
;
188 USI isr
= GET_ISR ();
190 /* Make sure that this exception is not masked. */
191 if (GET_ISR_EMAM (isr
))
194 /* Queue the interrupt. */
195 new_element
= frv_queue_program_interrupt (current_cpu
,
196 FRV_MEM_ADDRESS_NOT_ALIGNED
);
197 new_element
->eaddress
= addr
;
198 new_element
->u
.data_written
= frv_interrupt_state
.data_written
;
199 frv_interrupt_state
.data_written
.length
= 0;
204 struct frv_interrupt_queue_element
*
205 frv_queue_data_access_error_interrupt (SIM_CPU
*current_cpu
, USI addr
)
207 struct frv_interrupt_queue_element
*new_element
;
208 new_element
= frv_queue_program_interrupt (current_cpu
,
209 FRV_DATA_ACCESS_ERROR
);
210 new_element
->eaddress
= addr
;
214 struct frv_interrupt_queue_element
*
215 frv_queue_data_access_exception_interrupt (SIM_CPU
*current_cpu
)
217 return frv_queue_program_interrupt (current_cpu
, FRV_DATA_ACCESS_EXCEPTION
);
220 struct frv_interrupt_queue_element
*
221 frv_queue_instruction_access_error_interrupt (SIM_CPU
*current_cpu
)
223 return frv_queue_program_interrupt (current_cpu
, FRV_INSTRUCTION_ACCESS_ERROR
);
226 struct frv_interrupt_queue_element
*
227 frv_queue_instruction_access_exception_interrupt (SIM_CPU
*current_cpu
)
229 return frv_queue_program_interrupt (current_cpu
, FRV_INSTRUCTION_ACCESS_EXCEPTION
);
232 struct frv_interrupt_queue_element
*
233 frv_queue_illegal_instruction_interrupt (
234 SIM_CPU
*current_cpu
, const CGEN_INSN
*insn
237 SIM_DESC sd
= CPU_STATE (current_cpu
);
238 switch (STATE_ARCHITECTURE (sd
)->mach
)
245 /* Some machines generate fp_exception for this case. */
246 if (frv_is_float_insn (insn
) || frv_is_media_insn (insn
))
248 struct frv_fp_exception_info fp_info
= {
249 FSR_NO_EXCEPTION
, FTT_SEQUENCE_ERROR
251 return frv_queue_fp_exception_interrupt (current_cpu
, & fp_info
);
256 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
259 struct frv_interrupt_queue_element
*
260 frv_queue_privileged_instruction_interrupt (SIM_CPU
*current_cpu
, const CGEN_INSN
*insn
)
262 /* The fr550 has no privileged instruction interrupt. It uses
263 illegal_instruction. */
264 SIM_DESC sd
= CPU_STATE (current_cpu
);
265 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
266 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
268 return frv_queue_program_interrupt (current_cpu
, FRV_PRIVILEGED_INSTRUCTION
);
271 struct frv_interrupt_queue_element
*
272 frv_queue_float_disabled_interrupt (SIM_CPU
*current_cpu
)
274 /* The fr550 has no fp_disabled interrupt. It uses illegal_instruction. */
275 SIM_DESC sd
= CPU_STATE (current_cpu
);
276 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
277 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
279 return frv_queue_program_interrupt (current_cpu
, FRV_FP_DISABLED
);
282 struct frv_interrupt_queue_element
*
283 frv_queue_media_disabled_interrupt (SIM_CPU
*current_cpu
)
285 /* The fr550 has no mp_disabled interrupt. It uses illegal_instruction. */
286 SIM_DESC sd
= CPU_STATE (current_cpu
);
287 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
288 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
290 return frv_queue_program_interrupt (current_cpu
, FRV_MP_DISABLED
);
293 struct frv_interrupt_queue_element
*
294 frv_queue_non_implemented_instruction_interrupt (
295 SIM_CPU
*current_cpu
, const CGEN_INSN
*insn
298 SIM_DESC sd
= CPU_STATE (current_cpu
);
299 switch (STATE_ARCHITECTURE (sd
)->mach
)
306 /* Some machines generate fp_exception or mp_exception for this case. */
307 if (frv_is_float_insn (insn
))
309 struct frv_fp_exception_info fp_info
= {
310 FSR_NO_EXCEPTION
, FTT_UNIMPLEMENTED_FPOP
312 return frv_queue_fp_exception_interrupt (current_cpu
, & fp_info
);
314 if (frv_is_media_insn (insn
))
316 frv_set_mp_exception_registers (current_cpu
, MTT_UNIMPLEMENTED_MPOP
,
318 return NULL
; /* no interrupt queued at this time. */
323 return frv_queue_program_interrupt (current_cpu
, FRV_ILLEGAL_INSTRUCTION
);
326 /* Queue the given fp_exception interrupt. Also update fp_info by removing
327 masked interrupts and updating the 'slot' flield. */
328 struct frv_interrupt_queue_element
*
329 frv_queue_fp_exception_interrupt (
330 SIM_CPU
*current_cpu
, struct frv_fp_exception_info
*fp_info
333 SI fsr0
= GET_FSR (0);
334 int tem
= GET_FSR_TEM (fsr0
);
335 int aexc
= GET_FSR_AEXC (fsr0
);
336 struct frv_interrupt_queue_element
*new_element
= NULL
;
338 /* Update AEXC with the interrupts that are masked. */
339 aexc
|= fp_info
->fsr_mask
& ~tem
;
340 SET_FSR_AEXC (fsr0
, aexc
);
343 /* update fsr_mask with the exceptions that are enabled. */
344 fp_info
->fsr_mask
&= tem
;
346 /* If there is an unmasked interrupt then queue it, unless
347 this was a non-excepting insn, in which case simply set the NE
349 if (frv_interrupt_state
.ne_index
!= NE_NOFLAG
350 && fp_info
->fsr_mask
!= FSR_NO_EXCEPTION
)
352 SET_NE_FLAG (frv_interrupt_state
.f_ne_flags
,
353 frv_interrupt_state
.ne_index
);
354 /* TODO -- Set NESR for chips which support it. */
357 else if (fp_info
->fsr_mask
!= FSR_NO_EXCEPTION
358 || fp_info
->ftt
== FTT_UNIMPLEMENTED_FPOP
359 || fp_info
->ftt
== FTT_SEQUENCE_ERROR
360 || fp_info
->ftt
== FTT_INVALID_FR
)
362 new_element
= frv_queue_program_interrupt (current_cpu
, FRV_FP_EXCEPTION
);
363 new_element
->u
.fp_info
= *fp_info
;
369 struct frv_interrupt_queue_element
*
370 frv_queue_division_exception_interrupt (SIM_CPU
*current_cpu
, enum frv_dtt dtt
)
372 struct frv_interrupt_queue_element
*new_element
=
373 frv_queue_program_interrupt (current_cpu
, FRV_DIVISION_EXCEPTION
);
375 new_element
->u
.dtt
= dtt
;
380 /* Check for interrupts caused by illegal insn access. These conditions are
381 checked in the order specified by the fr400 and fr500 LSI specs. */
383 frv_detect_insn_access_interrupts (SIM_CPU
*current_cpu
, SCACHE
*sc
)
386 const CGEN_INSN
*insn
= sc
->argbuf
.idesc
->idata
;
387 SIM_DESC sd
= CPU_STATE (current_cpu
);
388 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
390 /* Check for vliw constraints. */
391 if (vliw
->constraint_violation
)
392 frv_queue_illegal_instruction_interrupt (current_cpu
, insn
);
393 /* Check for non-excepting insns. */
394 else if (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_NON_EXCEPTING
)
395 && ! GET_H_PSR_NEM ())
396 frv_queue_non_implemented_instruction_interrupt (current_cpu
, insn
);
397 /* Check for conditional insns. */
398 else if (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_CONDITIONAL
)
399 && ! GET_H_PSR_CM ())
400 frv_queue_non_implemented_instruction_interrupt (current_cpu
, insn
);
401 /* Make sure floating point support is enabled. */
402 else if (! GET_H_PSR_EF ())
404 /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
405 off and the insns accesses a fp register. */
406 if (frv_is_float_insn (insn
)
407 || (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_FR_ACCESS
)
408 && ! GET_H_PSR_EM ()))
409 frv_queue_float_disabled_interrupt (current_cpu
);
411 /* Make sure media support is enabled. */
412 else if (! GET_H_PSR_EM ())
414 /* Generate mp_disabled if it is a media insn. */
415 if (frv_is_media_insn (insn
) || CGEN_INSN_NUM (insn
) == FRV_INSN_MTRAP
)
416 frv_queue_media_disabled_interrupt (current_cpu
);
418 /* Check for privileged insns. */
419 else if (CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_PRIVILEGED
) &&
421 frv_queue_privileged_instruction_interrupt (current_cpu
, insn
);
422 #if 0 /* disable for now until we find out how FSR0.QNE gets reset. */
425 /* Enter the halt state if FSR0.QNE is set and we are executing a
426 floating point insn, a media insn or an insn which access a FR
428 SI fsr0
= GET_FSR (0);
429 if (GET_FSR_QNE (fsr0
)
430 && (frv_is_float_insn (insn
) || frv_is_media_insn (insn
)
431 || CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_FR_ACCESS
)))
433 sim_engine_halt (sd
, current_cpu
, NULL
, GET_H_PC (), sim_stopped
,
440 /* Record the current VLIW slot in the given interrupt queue element. */
442 frv_set_interrupt_queue_slot (
443 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
446 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
447 int slot
= vliw
->next_slot
- 1;
448 item
->slot
= (*vliw
->current_vliw
)[slot
];
451 /* Handle an individual interrupt. */
453 handle_interrupt (SIM_CPU
*current_cpu
, IADDR pc
)
455 struct frv_interrupt
*interrupt
;
456 int writeback_done
= 0;
459 /* Interrupts are queued in priority order with the highest priority
461 int index
= frv_interrupt_state
.queue_index
- 1;
462 struct frv_interrupt_queue_element
*item
463 = & frv_interrupt_state
.queue
[index
];
464 interrupt
= & frv_interrupt_table
[item
->kind
];
466 switch (interrupt
->iclass
)
468 case FRV_EXTERNAL_INTERRUPT
:
469 /* Perform writeback first. This may cause a higher priority
471 if (! writeback_done
)
473 frvbf_perform_writeback (current_cpu
);
477 frv_external_interrupt (current_cpu
, item
, pc
);
479 case FRV_SOFTWARE_INTERRUPT
:
480 frv_interrupt_state
.queue_index
= index
;
481 frv_software_interrupt (current_cpu
, item
, pc
);
483 case FRV_PROGRAM_INTERRUPT
:
484 /* If the program interrupt is not strict (imprecise), then perform
485 writeback first. This may, in turn, cause a higher priority
487 if (! interrupt
->precise
&& ! writeback_done
)
489 frv_interrupt_state
.imprecise_interrupt
= item
;
490 frvbf_perform_writeback (current_cpu
);
494 frv_interrupt_state
.queue_index
= index
;
495 frv_program_interrupt (current_cpu
, item
, pc
);
497 case FRV_BREAK_INTERRUPT
:
498 frv_interrupt_state
.queue_index
= index
;
499 frv_break_interrupt (current_cpu
, interrupt
, pc
);
501 case FRV_RESET_INTERRUPT
:
506 frv_interrupt_state
.queue_index
= index
;
507 break; /* out of loop. */
510 /* We should never get here. */
512 SIM_DESC sd
= CPU_STATE (current_cpu
);
513 sim_engine_abort (sd
, current_cpu
, pc
,
514 "interrupt class not supported %d\n",
519 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set. If so, handle
520 the appropriate reset interrupt. */
522 check_reset (SIM_CPU
*current_cpu
, IADDR pc
)
528 FRV_CACHE
*cache
= CPU_DATA_CACHE (current_cpu
);
529 IADDR address
= RSTR_ADDRESS
;
531 /* We don't want this to show up in the cache statistics, so read the
533 if (! frv_cache_read_passive_SI (cache
, address
, & rstr
))
534 rstr
= sim_core_read_unaligned_4 (current_cpu
, pc
, read_map
, address
);
536 hr
= GET_RSTR_HR (rstr
);
537 sr
= GET_RSTR_SR (rstr
);
540 return 0; /* no reset. */
542 /* Reinitialize the machine state. */
544 frv_hardware_reset (current_cpu
);
546 frv_software_reset (current_cpu
);
548 /* Branch to the reset address. */
550 if (GET_HSR0_SA (hsr0
))
551 SET_H_PC (0xff000000);
555 return 1; /* reset */
558 /* Process any pending interrupt(s) after a group of parallel insns. */
560 frv_process_interrupts (SIM_CPU
*current_cpu
)
563 /* Need to save the pc here because writeback may change it (due to a
565 IADDR pc
= CPU_PC_GET (current_cpu
);
567 /* Check for a reset before anything else. */
568 if (check_reset (current_cpu
, pc
))
571 /* First queue the writes for any accumulated NE flags. */
572 if (frv_interrupt_state
.f_ne_flags
[0] != 0
573 || frv_interrupt_state
.f_ne_flags
[1] != 0)
575 GET_NE_FLAGS (NE_flags
, H_SPR_FNER0
);
576 NE_flags
[0] |= frv_interrupt_state
.f_ne_flags
[0];
577 NE_flags
[1] |= frv_interrupt_state
.f_ne_flags
[1];
578 SET_NE_FLAGS (H_SPR_FNER0
, NE_flags
);
581 /* If there is no interrupt pending, then perform parallel writeback. This
582 may cause an interrupt. */
583 if (frv_interrupt_state
.queue_index
<= 0)
584 frvbf_perform_writeback (current_cpu
);
586 /* If there is an interrupt pending, then process it. */
587 if (frv_interrupt_state
.queue_index
> 0)
588 handle_interrupt (current_cpu
, pc
);
591 /* Find the next available ESR and return its index */
593 esr_for_data_access_exception (
594 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
597 SIM_DESC sd
= CPU_STATE (current_cpu
);
598 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
599 return 8; /* Use ESR8, EPCR8. */
601 if (item
->slot
== UNIT_I0
)
602 return 8; /* Use ESR8, EPCR8, EAR8, EDR8. */
604 return 9; /* Use ESR9, EPCR9, EAR9. */
607 /* Set the next available EDR register with the data which was to be stored
608 and return the index of the register. */
611 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, int edr_index
614 /* EDR0, EDR4 and EDR8 are available as blocks of 4.
615 SI data uses EDR3, EDR7 and EDR11
616 DI data uses EDR2, EDR6 and EDR10
617 XI data uses EDR0, EDR4 and EDR8. */
619 edr_index
+= 4 - item
->u
.data_written
.length
;
620 for (i
= 0; i
< item
->u
.data_written
.length
; ++i
)
621 SET_EDR (edr_index
+ i
, item
->u
.data_written
.words
[i
]);
626 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx. */
628 clear_exception_status_registers (SIM_CPU
*current_cpu
)
631 /* It is only necessary to clear the flag bits indicating which registers
636 for (i
= 0; i
<= 2; ++i
)
638 SI esr
= GET_ESR (i
);
639 CLEAR_ESR_VALID (esr
);
642 for (i
= 8; i
<= 15; ++i
)
644 SI esr
= GET_ESR (i
);
645 CLEAR_ESR_VALID (esr
);
650 /* Record state for media exception. */
652 frv_set_mp_exception_registers (
653 SIM_CPU
*current_cpu
, enum frv_msr_mtt mtt
, int sie
656 /* Record the interrupt factor in MSR0. */
657 SI msr0
= GET_MSR (0);
658 if (GET_MSR_MTT (msr0
) == MTT_NONE
)
659 SET_MSR_MTT (msr0
, mtt
);
661 /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF. */
662 if (mtt
== MTT_OVERFLOW
)
664 FRV_VLIW
*vliw
= CPU_VLIW (current_cpu
);
665 int slot
= vliw
->next_slot
- 1;
666 SIM_DESC sd
= CPU_STATE (current_cpu
);
668 /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE,
669 otherwise set MSR0.OVF and MSR0.SIE. */
670 if (STATE_ARCHITECTURE (sd
)->mach
!= bfd_mach_fr550
&& (*vliw
->current_vliw
)[slot
] == UNIT_FM1
)
672 SI msr
= GET_MSR (1);
673 OR_MSR_SIE (msr
, sie
);
679 OR_MSR_SIE (msr0
, sie
);
683 /* Generate the interrupt now if MSR0.MPEM is set on fr550 */
684 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
&& GET_MSR_MPEM (msr0
))
685 frv_queue_program_interrupt (current_cpu
, FRV_MP_EXCEPTION
);
688 /* Regardless of the slot, set MSR0.AOVF. */
696 /* Determine the correct FQ register to use for the given exception.
697 Return -1 if a register is not available. */
700 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
704 struct frv_fp_exception_info
*fp_info
= & item
->u
.fp_info
;
706 /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1. */
707 if (fp_info
->ftt
== FTT_IEEE_754_EXCEPTION
708 && (fp_info
->fsr_mask
& (FSR_OVERFLOW
| FSR_UNDERFLOW
| FSR_INEXACT
)))
711 if (! GET_FQ_VALID (fq
))
712 return 0; /* FQ0 is available. */
714 if (! GET_FQ_VALID (fq
))
715 return 1; /* FQ1 is available. */
717 /* No FQ register is available */
719 SIM_DESC sd
= CPU_STATE (current_cpu
);
720 IADDR pc
= CPU_PC_GET (current_cpu
);
721 sim_engine_abort (sd
, current_cpu
, pc
, "No FQ register available\n");
725 /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
727 if (item
->slot
== UNIT_FM0
|| item
->slot
== UNIT_I0
)
733 /* Set FSR0, FQ0-FQ9, depending on the interrupt. */
735 set_fp_exception_registers (
736 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
744 struct frv_fp_exception_info
*fp_info
;
745 SIM_DESC sd
= CPU_STATE (current_cpu
);
747 /* No FQ registers on fr550 */
748 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
750 /* Update the fsr. */
751 fp_info
= & item
->u
.fp_info
;
753 SET_FSR_FTT (fsr0
, fp_info
->ftt
);
758 /* Select an FQ and update it with the exception information. */
759 fq_index
= fq_for_exception (current_cpu
, item
);
763 fp_info
= & item
->u
.fp_info
;
764 fq
= GET_FQ (fq_index
);
765 SET_FQ_MIV (fq
, MIV_FLOAT
);
766 SET_FQ_SIE (fq
, SIE_NIL
);
767 SET_FQ_FTT (fq
, fp_info
->ftt
);
768 SET_FQ_CEXC (fq
, fp_info
->fsr_mask
);
770 SET_FQ (fq_index
, fq
);
772 /* Write the failing insn into FQx.OPC. */
774 insn
= GETMEMSI (current_cpu
, pc
, pc
);
775 SET_FQ_OPC (fq_index
, insn
);
777 /* Update the fsr. */
779 SET_FSR_QNE (fsr0
); /* FQ not empty */
780 SET_FSR_FTT (fsr0
, fp_info
->ftt
);
784 /* Record the state of a division exception in the ISR. */
786 set_isr_exception_fields (
787 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
790 USI isr
= GET_ISR ();
791 int dtt
= GET_ISR_DTT (isr
);
793 SET_ISR_DTT (isr
, dtt
);
797 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
800 set_exception_status_registers (
801 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
804 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[item
->kind
];
805 int slot
= (item
->vpc
- previous_vliw_pc
) / 4;
812 SIM_DESC sd
= CPU_STATE (current_cpu
);
814 /* If the interrupt is strict (precise) or the interrupt is on the insns
815 in the I0 pipe, then set the 0 registers. */
816 if (interrupt
->precise
)
819 if (interrupt
->kind
== FRV_REGISTER_EXCEPTION
)
820 SET_ESR_REC (esr
, item
->u
.rec
);
821 else if (interrupt
->kind
== FRV_INSTRUCTION_ACCESS_EXCEPTION
)
822 SET_ESR_IAEC (esr
, item
->u
.iaec
);
823 /* For fr550, don't set epcr for precise interrupts. */
824 if (STATE_ARCHITECTURE (sd
)->mach
!= bfd_mach_fr550
)
829 switch (interrupt
->kind
)
831 case FRV_DIVISION_EXCEPTION
:
832 set_isr_exception_fields (current_cpu
, item
);
833 /* fall thru to set reg_index. */
834 case FRV_COMMIT_EXCEPTION
:
835 /* For fr550, always use ESR0. */
836 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
838 else if (item
->slot
== UNIT_I0
)
840 else if (item
->slot
== UNIT_I1
)
844 case FRV_DATA_STORE_ERROR
:
845 reg_index
= 14; /* Use ESR14. */
847 case FRV_DATA_ACCESS_ERROR
:
848 reg_index
= 15; /* Use ESR15, EPCR15. */
851 case FRV_DATA_ACCESS_EXCEPTION
:
854 case FRV_DATA_ACCESS_MMU_MISS
:
855 case FRV_MEM_ADDRESS_NOT_ALIGNED
:
856 /* Get the appropriate ESR, EPCR, EAR and EDR.
857 EAR will be set. EDR will not be set if this is a store insn. */
859 /* For fr550, never use EDRx. */
860 if (STATE_ARCHITECTURE (sd
)->mach
!= bfd_mach_fr550
)
861 if (item
->u
.data_written
.length
!= 0)
863 reg_index
= esr_for_data_access_exception (current_cpu
, item
);
866 case FRV_MP_EXCEPTION
:
867 /* For fr550, use EPCR2 and ESR2. */
868 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
873 break; /* MSR0-1, FQ0-9 are already set. */
874 case FRV_FP_EXCEPTION
:
875 set_fp_exception_registers (current_cpu
, item
);
876 /* For fr550, use EPCR2 and ESR2. */
877 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr550
)
885 SIM_DESC sd
= CPU_STATE (current_cpu
);
886 IADDR pc
= CPU_PC_GET (current_cpu
);
887 sim_engine_abort (sd
, current_cpu
, pc
,
888 "invalid non-strict program interrupt kind: %d\n",
893 } /* non-strict (imprecise) interrupt */
895 /* Now fill in the selected exception status registers. */
898 /* Now set the exception status registers. */
899 SET_ESFR_FLAG (reg_index
);
900 SET_ESR_EC (esr
, interrupt
->ec
);
904 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_fr400
)
905 SET_EPCR (reg_index
, previous_vliw_pc
);
907 SET_EPCR (reg_index
, item
->vpc
);
912 SET_EAR (reg_index
, item
->eaddress
);
920 int edn
= set_edr_register (current_cpu
, item
, 0/* EDR0-3 */);
921 SET_ESR_EDN (esr
, edn
);
928 SET_ESR_DAEC (esr
, item
->u
.daec
);
931 SET_ESR (reg_index
, esr
);
935 /* Check for compound interrupts.
936 Returns NULL if no interrupt is to be processed. */
937 static struct frv_interrupt
*
938 check_for_compound_interrupt (
939 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
942 struct frv_interrupt
*interrupt
;
944 /* Set the exception status registers for the original interrupt. */
945 set_exception_status_registers (current_cpu
, item
);
946 interrupt
= & frv_interrupt_table
[item
->kind
];
948 if (! interrupt
->precise
)
954 mask
= (1 << item
->kind
);
956 /* Look for more queued program interrupts which are non-deferred
957 (pending inhibit), imprecise (non-strict) different than an interrupt
958 already found and caused by a different insn. A bit mask is used
959 to keep track of interrupts which have already been detected. */
960 while (item
!= frv_interrupt_state
.queue
)
962 enum frv_interrupt_kind kind
;
963 struct frv_interrupt
*next_interrupt
;
966 next_interrupt
= & frv_interrupt_table
[kind
];
968 if (next_interrupt
->iclass
!= FRV_PROGRAM_INTERRUPT
)
969 break; /* no program interrupts left. */
971 if (item
->vpc
== vpc
)
972 continue; /* caused by the same insn. */
975 if (! next_interrupt
->precise
&& ! next_interrupt
->deferred
)
977 if (! (mask
& (1 << kind
)))
979 /* Set the exception status registers for the additional
981 set_exception_status_registers (current_cpu
, item
);
983 interrupt
= & frv_interrupt_table
[FRV_COMPOUND_EXCEPTION
];
989 /* Return with either the original interrupt, a compound_exception,
994 /* Handle a program interrupt. */
996 frv_program_interrupt (
997 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, IADDR pc
1000 struct frv_interrupt
*interrupt
;
1002 clear_exception_status_registers (current_cpu
);
1003 /* If two or more non-deferred imprecise (non-strict) interrupts occur
1004 on two or more insns, then generate a compound_exception. */
1005 interrupt
= check_for_compound_interrupt (current_cpu
, item
);
1006 if (interrupt
!= NULL
)
1008 frv_program_or_software_interrupt (current_cpu
, interrupt
, pc
);
1009 frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT
,
1010 FRV_PROGRAM_INTERRUPT
);
1014 /* Handle a software interrupt. */
1016 frv_software_interrupt (
1017 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, IADDR pc
1020 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[item
->kind
];
1021 frv_program_or_software_interrupt (current_cpu
, interrupt
, pc
);
1024 /* Handle a program interrupt or a software interrupt in non-operating mode. */
1026 frv_non_operating_interrupt (
1027 SIM_CPU
*current_cpu
, enum frv_interrupt_kind kind
, IADDR pc
1030 SIM_DESC sd
= CPU_STATE (current_cpu
);
1033 case FRV_INTERRUPT_LEVEL_1
:
1034 case FRV_INTERRUPT_LEVEL_2
:
1035 case FRV_INTERRUPT_LEVEL_3
:
1036 case FRV_INTERRUPT_LEVEL_4
:
1037 case FRV_INTERRUPT_LEVEL_5
:
1038 case FRV_INTERRUPT_LEVEL_6
:
1039 case FRV_INTERRUPT_LEVEL_7
:
1040 case FRV_INTERRUPT_LEVEL_8
:
1041 case FRV_INTERRUPT_LEVEL_9
:
1042 case FRV_INTERRUPT_LEVEL_10
:
1043 case FRV_INTERRUPT_LEVEL_11
:
1044 case FRV_INTERRUPT_LEVEL_12
:
1045 case FRV_INTERRUPT_LEVEL_13
:
1046 case FRV_INTERRUPT_LEVEL_14
:
1047 case FRV_INTERRUPT_LEVEL_15
:
1048 sim_engine_abort (sd
, current_cpu
, pc
,
1049 "interrupt: external %d\n", kind
+ 1);
1051 case FRV_TRAP_INSTRUCTION
:
1052 break; /* handle as in operating mode. */
1053 case FRV_COMMIT_EXCEPTION
:
1054 sim_engine_abort (sd
, current_cpu
, pc
,
1055 "interrupt: commit_exception\n");
1057 case FRV_DIVISION_EXCEPTION
:
1058 sim_engine_abort (sd
, current_cpu
, pc
,
1059 "interrupt: division_exception\n");
1061 case FRV_DATA_STORE_ERROR
:
1062 sim_engine_abort (sd
, current_cpu
, pc
,
1063 "interrupt: data_store_error\n");
1065 case FRV_DATA_ACCESS_EXCEPTION
:
1066 sim_engine_abort (sd
, current_cpu
, pc
,
1067 "interrupt: data_access_exception\n");
1069 case FRV_DATA_ACCESS_MMU_MISS
:
1070 sim_engine_abort (sd
, current_cpu
, pc
,
1071 "interrupt: data_access_mmu_miss\n");
1073 case FRV_DATA_ACCESS_ERROR
:
1074 sim_engine_abort (sd
, current_cpu
, pc
,
1075 "interrupt: data_access_error\n");
1077 case FRV_MP_EXCEPTION
:
1078 sim_engine_abort (sd
, current_cpu
, pc
,
1079 "interrupt: mp_exception\n");
1081 case FRV_FP_EXCEPTION
:
1082 sim_engine_abort (sd
, current_cpu
, pc
,
1083 "interrupt: fp_exception\n");
1085 case FRV_MEM_ADDRESS_NOT_ALIGNED
:
1086 sim_engine_abort (sd
, current_cpu
, pc
,
1087 "interrupt: mem_address_not_aligned\n");
1089 case FRV_REGISTER_EXCEPTION
:
1090 sim_engine_abort (sd
, current_cpu
, pc
,
1091 "interrupt: register_exception\n");
1093 case FRV_MP_DISABLED
:
1094 sim_engine_abort (sd
, current_cpu
, pc
,
1095 "interrupt: mp_disabled\n");
1097 case FRV_FP_DISABLED
:
1098 sim_engine_abort (sd
, current_cpu
, pc
,
1099 "interrupt: fp_disabled\n");
1101 case FRV_PRIVILEGED_INSTRUCTION
:
1102 sim_engine_abort (sd
, current_cpu
, pc
,
1103 "interrupt: privileged_instruction\n");
1105 case FRV_ILLEGAL_INSTRUCTION
:
1106 sim_engine_abort (sd
, current_cpu
, pc
,
1107 "interrupt: illegal_instruction\n");
1109 case FRV_INSTRUCTION_ACCESS_EXCEPTION
:
1110 sim_engine_abort (sd
, current_cpu
, pc
,
1111 "interrupt: instruction_access_exception\n");
1113 case FRV_INSTRUCTION_ACCESS_MMU_MISS
:
1114 sim_engine_abort (sd
, current_cpu
, pc
,
1115 "interrupt: instruction_access_mmu_miss\n");
1117 case FRV_INSTRUCTION_ACCESS_ERROR
:
1118 sim_engine_abort (sd
, current_cpu
, pc
,
1119 "interrupt: insn_access_error\n");
1121 case FRV_COMPOUND_EXCEPTION
:
1122 sim_engine_abort (sd
, current_cpu
, pc
,
1123 "interrupt: compound_exception\n");
1125 case FRV_BREAK_EXCEPTION
:
1126 sim_engine_abort (sd
, current_cpu
, pc
,
1127 "interrupt: break_exception\n");
1130 sim_engine_abort (sd
, current_cpu
, pc
,
1131 "interrupt: reset\n");
1134 sim_engine_abort (sd
, current_cpu
, pc
,
1135 "unhandled interrupt kind: %d\n", kind
);
1140 /* Handle a break interrupt. */
1142 frv_break_interrupt (
1143 SIM_CPU
*current_cpu
, struct frv_interrupt
*interrupt
, IADDR current_pc
1156 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1157 SET_H_BPSR_BS (GET_H_PSR_S ());
1158 SET_H_BPSR_BET (GET_H_PSR_ET ());
1161 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1162 SET_H_SPR (H_SPR_BPCSR
, current_pc
);
1164 /* Set the new PC in the TBR. */
1165 SET_H_TBR_TT (interrupt
->handler_offset
);
1166 new_pc
= GET_H_SPR (H_SPR_TBR
);
1169 CPU_DEBUG_STATE (current_cpu
) = 1;
1172 /* Handle a program interrupt or a software interrupt. */
1174 frv_program_or_software_interrupt (
1175 SIM_CPU
*current_cpu
, struct frv_interrupt
*interrupt
, IADDR current_pc
1179 int original_psr_et
;
1186 SR0 through SR3=GR4 through GR7
1187 TBR.TT=interrupt handler offset
1190 original_psr_et
= GET_H_PSR_ET ();
1192 SET_H_PSR_PS (GET_H_PSR_S ());
1196 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1197 /* The PCSR depends on the precision of the interrupt. */
1198 if (interrupt
->precise
)
1199 SET_H_SPR (H_SPR_PCSR
, previous_vliw_pc
);
1201 SET_H_SPR (H_SPR_PCSR
, current_pc
);
1203 /* Set the new PC in the TBR. */
1204 SET_H_TBR_TT (interrupt
->handler_offset
);
1205 new_pc
= GET_H_SPR (H_SPR_TBR
);
1208 /* If PSR.ET was not originally set, then enter the stopped state. */
1209 if (! original_psr_et
)
1211 SIM_DESC sd
= CPU_STATE (current_cpu
);
1212 frv_non_operating_interrupt (current_cpu
, interrupt
->kind
, current_pc
);
1213 sim_engine_halt (sd
, current_cpu
, NULL
, new_pc
, sim_stopped
, SIM_SIGINT
);
1217 /* Handle a program interrupt or a software interrupt. */
1219 frv_external_interrupt (
1220 SIM_CPU
*current_cpu
, struct frv_interrupt_queue_element
*item
, IADDR pc
1224 struct frv_interrupt
*interrupt
= & frv_interrupt_table
[item
->kind
];
1226 /* Don't process the interrupt if PSR.ET is not set or if it is masked.
1227 Interrupt 15 is processed even if it appears to be masked. */
1228 if (! GET_H_PSR_ET ()
1229 || (interrupt
->kind
!= FRV_INTERRUPT_LEVEL_15
1230 && interrupt
->kind
< GET_H_PSR_PIL ()))
1231 return; /* Leave it for later. */
1233 /* Remove the interrupt from the queue. */
1234 --frv_interrupt_state
.queue_index
;
1241 SR0 through SR3=GR4 through GR7
1242 TBR.TT=interrupt handler offset
1245 SET_H_PSR_PS (GET_H_PSR_S ());
1248 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1249 SET_H_SPR (H_SPR_PCSR
, GET_H_PC ());
1251 /* Set the new PC in the TBR. */
1252 SET_H_TBR_TT (interrupt
->handler_offset
);
1253 new_pc
= GET_H_SPR (H_SPR_TBR
);
1257 /* Clear interrupts which fall within the range of classes given. */
1259 frv_clear_interrupt_classes (
1260 enum frv_interrupt_class low_class
, enum frv_interrupt_class high_class
1265 int limit
= frv_interrupt_state
.queue_index
;
1267 /* Find the lowest priority interrupt to be removed. */
1268 for (i
= 0; i
< limit
; ++i
)
1270 enum frv_interrupt_kind kind
= frv_interrupt_state
.queue
[i
].kind
;
1271 struct frv_interrupt
* interrupt
= & frv_interrupt_table
[kind
];
1272 if (interrupt
->iclass
>= low_class
)
1276 /* Find the highest priority interrupt to be removed. */
1277 for (j
= limit
- 1; j
>= i
; --j
)
1279 enum frv_interrupt_kind kind
= frv_interrupt_state
.queue
[j
].kind
;
1280 struct frv_interrupt
* interrupt
= & frv_interrupt_table
[kind
];
1281 if (interrupt
->iclass
<= high_class
)
1285 /* Shuffle the remaining high priority interrupts down into the empty space
1286 left by the deleted interrupts. */
1289 for (++j
; j
< limit
; ++j
)
1290 frv_interrupt_state
.queue
[i
++] = frv_interrupt_state
.queue
[j
];
1291 frv_interrupt_state
.queue_index
-= (j
- i
);
1295 /* Save data written to memory into the interrupt state so that it can be
1296 copied to the appropriate EDR register, if necessary, in the event of an
1299 frv_save_data_written_for_interrupts (
1300 SIM_CPU
*current_cpu
, CGEN_WRITE_QUEUE_ELEMENT
*item
1303 /* Record the slot containing the insn doing the write in the
1305 frv_interrupt_state
.slot
= CGEN_WRITE_QUEUE_ELEMENT_PIPE (item
);
1307 /* Now record any data written to memory in the interrupt state. */
1308 switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item
))
1315 case CGEN_FN_HI_WRITE
:
1316 case CGEN_FN_SI_WRITE
:
1317 case CGEN_FN_SF_WRITE
:
1318 case CGEN_FN_DI_WRITE
:
1319 case CGEN_FN_DF_WRITE
:
1320 case CGEN_FN_XI_WRITE
:
1321 case CGEN_FN_PC_WRITE
:
1322 break; /* Ignore writes to registers. */
1323 case CGEN_MEM_QI_WRITE
:
1324 frv_interrupt_state
.data_written
.length
= 1;
1325 frv_interrupt_state
.data_written
.words
[0]
1326 = item
->kinds
.mem_qi_write
.value
;
1328 case CGEN_MEM_HI_WRITE
:
1329 frv_interrupt_state
.data_written
.length
= 1;
1330 frv_interrupt_state
.data_written
.words
[0]
1331 = item
->kinds
.mem_hi_write
.value
;
1333 case CGEN_MEM_SI_WRITE
:
1334 frv_interrupt_state
.data_written
.length
= 1;
1335 frv_interrupt_state
.data_written
.words
[0]
1336 = item
->kinds
.mem_si_write
.value
;
1338 case CGEN_MEM_DI_WRITE
:
1339 frv_interrupt_state
.data_written
.length
= 2;
1340 frv_interrupt_state
.data_written
.words
[0]
1341 = item
->kinds
.mem_di_write
.value
>> 32;
1342 frv_interrupt_state
.data_written
.words
[1]
1343 = item
->kinds
.mem_di_write
.value
;
1345 case CGEN_MEM_DF_WRITE
:
1346 frv_interrupt_state
.data_written
.length
= 2;
1347 frv_interrupt_state
.data_written
.words
[0]
1348 = item
->kinds
.mem_df_write
.value
>> 32;
1349 frv_interrupt_state
.data_written
.words
[1]
1350 = item
->kinds
.mem_df_write
.value
;
1352 case CGEN_MEM_XI_WRITE
:
1353 frv_interrupt_state
.data_written
.length
= 4;
1354 frv_interrupt_state
.data_written
.words
[0]
1355 = item
->kinds
.mem_xi_write
.value
[0];
1356 frv_interrupt_state
.data_written
.words
[1]
1357 = item
->kinds
.mem_xi_write
.value
[1];
1358 frv_interrupt_state
.data_written
.words
[2]
1359 = item
->kinds
.mem_xi_write
.value
[2];
1360 frv_interrupt_state
.data_written
.words
[3]
1361 = item
->kinds
.mem_xi_write
.value
[3];
1363 case CGEN_FN_MEM_QI_WRITE
:
1364 frv_interrupt_state
.data_written
.length
= 1;
1365 frv_interrupt_state
.data_written
.words
[0]
1366 = item
->kinds
.fn_mem_qi_write
.value
;
1368 case CGEN_FN_MEM_HI_WRITE
:
1369 frv_interrupt_state
.data_written
.length
= 1;
1370 frv_interrupt_state
.data_written
.words
[0]
1371 = item
->kinds
.fn_mem_hi_write
.value
;
1373 case CGEN_FN_MEM_SI_WRITE
:
1374 frv_interrupt_state
.data_written
.length
= 1;
1375 frv_interrupt_state
.data_written
.words
[0]
1376 = item
->kinds
.fn_mem_si_write
.value
;
1378 case CGEN_FN_MEM_DI_WRITE
:
1379 frv_interrupt_state
.data_written
.length
= 2;
1380 frv_interrupt_state
.data_written
.words
[0]
1381 = item
->kinds
.fn_mem_di_write
.value
>> 32;
1382 frv_interrupt_state
.data_written
.words
[1]
1383 = item
->kinds
.fn_mem_di_write
.value
;
1385 case CGEN_FN_MEM_DF_WRITE
:
1386 frv_interrupt_state
.data_written
.length
= 2;
1387 frv_interrupt_state
.data_written
.words
[0]
1388 = item
->kinds
.fn_mem_df_write
.value
>> 32;
1389 frv_interrupt_state
.data_written
.words
[1]
1390 = item
->kinds
.fn_mem_df_write
.value
;
1392 case CGEN_FN_MEM_XI_WRITE
:
1393 frv_interrupt_state
.data_written
.length
= 4;
1394 frv_interrupt_state
.data_written
.words
[0]
1395 = item
->kinds
.fn_mem_xi_write
.value
[0];
1396 frv_interrupt_state
.data_written
.words
[1]
1397 = item
->kinds
.fn_mem_xi_write
.value
[1];
1398 frv_interrupt_state
.data_written
.words
[2]
1399 = item
->kinds
.fn_mem_xi_write
.value
[2];
1400 frv_interrupt_state
.data_written
.words
[3]
1401 = item
->kinds
.fn_mem_xi_write
.value
[3];
1405 SIM_DESC sd
= CPU_STATE (current_cpu
);
1406 IADDR pc
= CPU_PC_GET (current_cpu
);
1407 sim_engine_abort (sd
, current_cpu
, pc
,
1408 "unknown write kind during save for interrupt\n");