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 /* The fr400 does not have the fp_exception. */
239 SIM_DESC sd = CPU_STATE (current_cpu);
240 if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr400)
242 if (frv_is_float_insn (insn) || frv_is_media_insn (insn))
244 struct frv_fp_exception_info fp_info = {
245 FSR_NO_EXCEPTION, FTT_SEQUENCE_ERROR
247 return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
251 return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
254 struct frv_interrupt_queue_element *
255 frv_queue_non_implemented_instruction_interrupt (
256 SIM_CPU *current_cpu, const CGEN_INSN *insn
259 /* The fr400 does not have the fp_exception, nor does it generate mp_exception
261 SIM_DESC sd = CPU_STATE (current_cpu);
262 if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr400)
264 if (frv_is_float_insn (insn))
266 struct frv_fp_exception_info fp_info = {
267 FSR_NO_EXCEPTION, FTT_UNIMPLEMENTED_FPOP
269 return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
272 if (frv_is_media_insn (insn))
274 frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP,
276 return NULL; /* no interrupt queued at this time. */
281 return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
284 /* Queue the given fp_exception interrupt. Also update fp_info by removing
285 masked interrupts and updating the 'slot' flield. */
286 struct frv_interrupt_queue_element *
287 frv_queue_fp_exception_interrupt (
288 SIM_CPU *current_cpu, struct frv_fp_exception_info *fp_info
291 SI fsr0 = GET_FSR (0);
292 int tem = GET_FSR_TEM (fsr0);
293 int aexc = GET_FSR_AEXC (fsr0);
294 struct frv_interrupt_queue_element *new_element = NULL;
296 /* Update AEXC with the interrupts that are masked. */
297 aexc |= fp_info->fsr_mask & ~tem;
298 SET_FSR_AEXC (fsr0, aexc);
301 /* update fsr_mask with the exceptions that are enabled. */
302 fp_info->fsr_mask &= tem;
304 /* If there is an unmasked interrupt then queue it, unless
305 this was a non-excepting insn, in which case simply set the NE
307 if (frv_interrupt_state.ne_index != NE_NOFLAG
308 && fp_info->fsr_mask != FSR_NO_EXCEPTION)
310 SET_NE_FLAG (frv_interrupt_state.f_ne_flags,
311 frv_interrupt_state.ne_index);
312 /* TODO -- Set NESR for chips which support it. */
315 else if (fp_info->fsr_mask != FSR_NO_EXCEPTION
316 || fp_info->ftt == FTT_UNIMPLEMENTED_FPOP
317 || fp_info->ftt == FTT_SEQUENCE_ERROR
318 || fp_info->ftt == FTT_INVALID_FR)
320 new_element = frv_queue_program_interrupt (current_cpu, FRV_FP_EXCEPTION);
321 new_element->u.fp_info = *fp_info;
327 struct frv_interrupt_queue_element *
328 frv_queue_division_exception_interrupt (SIM_CPU *current_cpu, enum frv_dtt dtt)
330 struct frv_interrupt_queue_element *new_element =
331 frv_queue_program_interrupt (current_cpu, FRV_DIVISION_EXCEPTION);
333 new_element->u.dtt = dtt;
338 /* Check for interrupts caused by illegal insn access. These conditions are
339 checked in the order specified by the fr400 and fr500 LSI specs. */
341 frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc)
344 const CGEN_INSN *insn = sc->argbuf.idesc->idata;
345 SIM_DESC sd = CPU_STATE (current_cpu);
346 FRV_VLIW *vliw = CPU_VLIW (current_cpu);
348 /* Check for vliw constraints. */
349 if (vliw->constraint_violation)
350 frv_queue_illegal_instruction_interrupt (current_cpu, insn);
351 /* Check for non-excepting insns. */
352 else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING)
353 && ! GET_H_PSR_NEM ())
354 frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
355 /* Check for conditional insns. */
356 else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL)
357 && ! GET_H_PSR_CM ())
358 frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
359 /* Make sure floating point support is enabled. */
360 else if (! GET_H_PSR_EF ())
362 /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
363 off and the insns accesses a fp register. */
364 if (frv_is_float_insn (insn)
365 || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)
366 && ! GET_H_PSR_EM ()))
367 frv_queue_program_interrupt (current_cpu, FRV_FP_DISABLED);
369 /* Make sure media support is enabled. */
370 else if (! GET_H_PSR_EM ())
372 /* Generate mp_disabled if it is a media insn. */
373 if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP)
374 frv_queue_program_interrupt (current_cpu, FRV_MP_DISABLED);
376 /* Check for privileged insns. */
377 else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) &&
379 frv_queue_program_interrupt (current_cpu, FRV_PRIVILEGED_INSTRUCTION);
380 #if 0 /* disable for now until we find out how FSR0.QNE gets reset. */
383 /* Enter the halt state if FSR0.QNE is set and we are executing a
384 floating point insn, a media insn or an insn which access a FR
386 SI fsr0 = GET_FSR (0);
387 if (GET_FSR_QNE (fsr0)
388 && (frv_is_float_insn (insn) || frv_is_media_insn (insn)
389 || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)))
391 sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped,
398 /* Record the current VLIW slot in the given interrupt queue element. */
400 frv_set_interrupt_queue_slot (
401 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
404 FRV_VLIW *vliw = CPU_VLIW (current_cpu);
405 int slot = vliw->next_slot - 1;
406 item->slot = (*vliw->current_vliw)[slot];
409 /* Handle an individual interrupt. */
411 handle_interrupt (SIM_CPU *current_cpu, IADDR pc)
413 struct frv_interrupt *interrupt;
414 int writeback_done = 0;
417 /* Interrupts are queued in priority order with the highest priority
419 int index = frv_interrupt_state.queue_index - 1;
420 struct frv_interrupt_queue_element *item
421 = & frv_interrupt_state.queue[index];
422 interrupt = & frv_interrupt_table[item->kind];
424 switch (interrupt->iclass)
426 case FRV_EXTERNAL_INTERRUPT:
427 /* Perform writeback first. This may cause a higher priority
429 if (! writeback_done)
431 frvbf_perform_writeback (current_cpu);
435 frv_external_interrupt (current_cpu, item, pc);
437 case FRV_SOFTWARE_INTERRUPT:
438 frv_interrupt_state.queue_index = index;
439 frv_software_interrupt (current_cpu, item, pc);
441 case FRV_PROGRAM_INTERRUPT:
442 /* If the program interrupt is not strict (imprecise), then perform
443 writeback first. This may, in turn, cause a higher priority
445 if (! interrupt->precise && ! writeback_done)
447 frv_interrupt_state.imprecise_interrupt = item;
448 frvbf_perform_writeback (current_cpu);
452 frv_interrupt_state.queue_index = index;
453 frv_program_interrupt (current_cpu, item, pc);
455 case FRV_BREAK_INTERRUPT:
456 frv_interrupt_state.queue_index = index;
457 frv_break_interrupt (current_cpu, interrupt, pc);
459 case FRV_RESET_INTERRUPT:
464 frv_interrupt_state.queue_index = index;
465 break; /* out of loop. */
468 /* We should never get here. */
470 SIM_DESC sd = CPU_STATE (current_cpu);
471 sim_engine_abort (sd, current_cpu, pc,
472 "interrupt class not supported %d\n",
477 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set. If so, handle
478 the appropriate reset interrupt. */
480 check_reset (SIM_CPU *current_cpu, IADDR pc)
486 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
487 IADDR address = RSTR_ADDRESS;
489 /* We don't want this to show up in the cache statistics, so read the
491 if (! frv_cache_read_passive_SI (cache, address, & rstr))
492 rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address);
494 hr = GET_RSTR_HR (rstr);
495 sr = GET_RSTR_SR (rstr);
498 return 0; /* no reset. */
500 /* Reinitialize the machine state. */
502 frv_hardware_reset (current_cpu);
504 frv_software_reset (current_cpu);
506 /* Branch to the reset address. */
508 if (GET_HSR0_SA (hsr0))
509 SET_H_PC (0xff000000);
513 return 1; /* reset */
516 /* Process any pending interrupt(s) after a group of parallel insns. */
518 frv_process_interrupts (SIM_CPU *current_cpu)
521 /* Need to save the pc here because writeback may change it (due to a
523 IADDR pc = CPU_PC_GET (current_cpu);
525 /* Check for a reset before anything else. */
526 if (check_reset (current_cpu, pc))
529 /* First queue the writes for any accumulated NE flags. */
530 if (frv_interrupt_state.f_ne_flags[0] != 0
531 || frv_interrupt_state.f_ne_flags[1] != 0)
533 GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
534 NE_flags[0] |= frv_interrupt_state.f_ne_flags[0];
535 NE_flags[1] |= frv_interrupt_state.f_ne_flags[1];
536 SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
539 /* If there is no interrupt pending, then perform parallel writeback. This
540 may cause an interrupt. */
541 if (frv_interrupt_state.queue_index <= 0)
542 frvbf_perform_writeback (current_cpu);
544 /* If there is an interrupt pending, then process it. */
545 if (frv_interrupt_state.queue_index > 0)
546 handle_interrupt (current_cpu, pc);
549 /* Find the next available ESR and return its index */
551 esr_for_data_access_exception (
552 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
555 if (item->slot == UNIT_I0)
556 return 8; /* Use ESR8, EPCR8, EAR8, EDR8. */
558 return 9; /* Use ESR9, EPCR9, EAR9. */
561 /* Set the next available EDR register with the data which was to be stored
562 and return the index of the register. */
565 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index
568 /* EDR0, EDR4 and EDR8 are available as blocks of 4.
569 SI data uses EDR3, EDR7 and EDR11
570 DI data uses EDR2, EDR6 and EDR10
571 XI data uses EDR0, EDR4 and EDR8. */
573 edr_index += 4 - item->u.data_written.length;
574 for (i = 0; i < item->u.data_written.length; ++i)
575 SET_EDR (edr_index + i, item->u.data_written.words[i]);
580 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx. */
582 clear_exception_status_registers (SIM_CPU *current_cpu)
585 /* It is only necessary to clear the flag bits indicating which registers
590 for (i = 0; i <= 2; ++i)
592 SI esr = GET_ESR (i);
593 CLEAR_ESR_VALID (esr);
596 for (i = 8; i <= 13; ++i)
598 SI esr = GET_ESR (i);
599 CLEAR_ESR_VALID (esr);
604 /* Record state for media exception. */
606 frv_set_mp_exception_registers (
607 SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie
610 /* Record the interrupt factor in MSR0. */
611 SI msr0 = GET_MSR (0);
612 if (GET_MSR_MTT (msr0) == MTT_NONE)
613 SET_MSR_MTT (msr0, mtt);
615 /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF. */
616 if (mtt == MTT_OVERFLOW)
618 FRV_VLIW *vliw = CPU_VLIW (current_cpu);
619 int slot = vliw->next_slot - 1;
621 /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE,
622 otherwise set MSR0.OVF and MSR0.SIE. */
623 if ((*vliw->current_vliw)[slot] == UNIT_FM1)
625 SI msr = GET_MSR (1);
626 OR_MSR_SIE (msr, sie);
632 OR_MSR_SIE (msr0, sie);
636 /* Regardless of the slot, set MSR0.AOVF. */
643 /* Determine the correct FQ register to use for the given exception.
644 Return -1 if a register is not available. */
647 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
651 struct frv_fp_exception_info *fp_info = & item->u.fp_info;
653 /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1. */
654 if (fp_info->ftt == FTT_IEEE_754_EXCEPTION
655 && (fp_info->fsr_mask & (FSR_OVERFLOW | FSR_UNDERFLOW | FSR_INEXACT)))
658 if (! GET_FQ_VALID (fq))
659 return 0; /* FQ0 is available. */
661 if (! GET_FQ_VALID (fq))
662 return 1; /* FQ1 is available. */
664 /* No FQ register is available */
666 SIM_DESC sd = CPU_STATE (current_cpu);
667 IADDR pc = CPU_PC_GET (current_cpu);
668 sim_engine_abort (sd, current_cpu, pc, "No FQ register available\n");
672 /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
674 if (item->slot == UNIT_FM0 || item->slot == UNIT_I0)
680 /* Set FSR0, FQ0-FQ9, depending on the interrupt. */
682 set_fp_exception_registers (
683 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
691 struct frv_fp_exception_info *fp_info;
693 /* Select an FQ and update it with the exception information. */
694 fq_index = fq_for_exception (current_cpu, item);
698 fp_info = & item->u.fp_info;
699 fq = GET_FQ (fq_index);
700 SET_FQ_MIV (fq, MIV_FLOAT);
701 SET_FQ_SIE (fq, SIE_NIL);
702 SET_FQ_FTT (fq, fp_info->ftt);
703 SET_FQ_CEXC (fq, fp_info->fsr_mask);
705 SET_FQ (fq_index, fq);
707 /* Write the failing insn into FQx.OPC. */
709 insn = GETMEMSI (current_cpu, pc, pc);
710 SET_FQ_OPC (fq_index, insn);
712 /* Update the fsr. */
714 SET_FSR_QNE (fsr0); /* FQ not empty */
715 SET_FSR_FTT (fsr0, fp_info->ftt);
719 /* Record the state of a division exception in the ISR. */
721 set_isr_exception_fields (
722 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
725 USI isr = GET_ISR ();
726 int dtt = GET_ISR_DTT (isr);
728 SET_ISR_DTT (isr, dtt);
732 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
735 set_exception_status_registers (
736 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
739 struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
740 int slot = (item->vpc - previous_vliw_pc) / 4;
747 SIM_DESC sd = CPU_STATE (current_cpu);
749 /* If the interrupt is strict (precise) or the interrupt is on the insns
750 in the I0 pipe, then set the 0 registers. */
751 if (interrupt->precise)
754 if (interrupt->kind == FRV_REGISTER_EXCEPTION)
755 SET_ESR_REC (esr, item->u.rec);
756 else if (interrupt->kind == FRV_INSTRUCTION_ACCESS_EXCEPTION)
757 SET_ESR_IAEC (esr, item->u.iaec);
762 switch (interrupt->kind)
764 case FRV_DIVISION_EXCEPTION:
765 set_isr_exception_fields (current_cpu, item);
766 /* fall thru to set reg_index. */
767 case FRV_COMMIT_EXCEPTION:
768 if (item->slot == UNIT_I0)
770 else if (item->slot == UNIT_I1)
774 case FRV_DATA_STORE_ERROR:
775 reg_index = 14; /* Use ESR15, EPCR15. */
777 case FRV_DATA_ACCESS_ERROR:
778 reg_index = 15; /* Use ESR15, EPCR15. */
779 if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr400)
782 case FRV_DATA_ACCESS_EXCEPTION:
785 case FRV_DATA_ACCESS_MMU_MISS:
786 case FRV_MEM_ADDRESS_NOT_ALIGNED:
787 /* Get the appropriate ESR, EPCR, EAR and EDR.
788 EAR will be set. EDR will not be set if this is a store insn. */
790 if (item->u.data_written.length != 0)
792 reg_index = esr_for_data_access_exception (current_cpu, item);
795 case FRV_MP_EXCEPTION:
796 break; /* MSR0-1, FQ0-9 are already set. */
797 case FRV_FP_EXCEPTION:
798 set_fp_exception_registers (current_cpu, item);
802 SIM_DESC sd = CPU_STATE (current_cpu);
803 IADDR pc = CPU_PC_GET (current_cpu);
804 sim_engine_abort (sd, current_cpu, pc,
805 "invalid non-strict program interrupt kind: %d\n",
810 } /* non-strict (imprecise) interrupt */
812 /* Now fill in the selected exception status registers. */
815 /* Now set the exception status registers. */
816 SET_ESFR_FLAG (reg_index);
817 SET_ESR_EC (esr, interrupt->ec);
821 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
822 SET_EPCR (reg_index, previous_vliw_pc);
824 SET_EPCR (reg_index, item->vpc);
829 SET_EAR (reg_index, item->eaddress);
837 int edn = set_edr_register (current_cpu, item, 0/* EDR0-3 */);
838 SET_ESR_EDN (esr, edn);
845 SET_ESR_DAEC (esr, item->u.daec);
848 SET_ESR (reg_index, esr);
852 /* Check for compound interrupts.
853 Returns NULL if no interrupt is to be processed. */
854 static struct frv_interrupt *
855 check_for_compound_interrupt (
856 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
859 struct frv_interrupt *interrupt;
861 /* Set the exception status registers for the original interrupt. */
862 set_exception_status_registers (current_cpu, item);
863 interrupt = & frv_interrupt_table[item->kind];
865 if (! interrupt->precise)
871 mask = (1 << item->kind);
873 /* Look for more queued program interrupts which are non-deferred
874 (pending inhibit), imprecise (non-strict) different than an interrupt
875 already found and caused by a different insn. A bit mask is used
876 to keep track of interrupts which have already been detected. */
877 while (item != frv_interrupt_state.queue)
879 enum frv_interrupt_kind kind;
880 struct frv_interrupt *next_interrupt;
883 next_interrupt = & frv_interrupt_table[kind];
885 if (next_interrupt->iclass != FRV_PROGRAM_INTERRUPT)
886 break; /* no program interrupts left. */
888 if (item->vpc == vpc)
889 continue; /* caused by the same insn. */
892 if (! next_interrupt->precise && ! next_interrupt->deferred)
894 if (! (mask & (1 << kind)))
896 /* Set the exception status registers for the additional
898 set_exception_status_registers (current_cpu, item);
900 interrupt = & frv_interrupt_table[FRV_COMPOUND_EXCEPTION];
906 /* Return with either the original interrupt, a compound_exception,
911 /* Handle a program interrupt. */
913 frv_program_interrupt (
914 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
917 struct frv_interrupt *interrupt;
919 clear_exception_status_registers (current_cpu);
920 /* If two or more non-deferred imprecise (non-strict) interrupts occur
921 on two or more insns, then generate a compound_exception. */
922 interrupt = check_for_compound_interrupt (current_cpu, item);
923 if (interrupt != NULL)
925 frv_program_or_software_interrupt (current_cpu, interrupt, pc);
926 frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT,
927 FRV_PROGRAM_INTERRUPT);
931 /* Handle a software interrupt. */
933 frv_software_interrupt (
934 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
937 struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
938 frv_program_or_software_interrupt (current_cpu, interrupt, pc);
941 /* Handle a program interrupt or a software interrupt in non-operating mode. */
943 frv_non_operating_interrupt (
944 SIM_CPU *current_cpu, enum frv_interrupt_kind kind, IADDR pc
947 SIM_DESC sd = CPU_STATE (current_cpu);
950 case FRV_INTERRUPT_LEVEL_1:
951 case FRV_INTERRUPT_LEVEL_2:
952 case FRV_INTERRUPT_LEVEL_3:
953 case FRV_INTERRUPT_LEVEL_4:
954 case FRV_INTERRUPT_LEVEL_5:
955 case FRV_INTERRUPT_LEVEL_6:
956 case FRV_INTERRUPT_LEVEL_7:
957 case FRV_INTERRUPT_LEVEL_8:
958 case FRV_INTERRUPT_LEVEL_9:
959 case FRV_INTERRUPT_LEVEL_10:
960 case FRV_INTERRUPT_LEVEL_11:
961 case FRV_INTERRUPT_LEVEL_12:
962 case FRV_INTERRUPT_LEVEL_13:
963 case FRV_INTERRUPT_LEVEL_14:
964 case FRV_INTERRUPT_LEVEL_15:
965 sim_engine_abort (sd, current_cpu, pc,
966 "interrupt: external %d\n", kind + 1);
968 case FRV_TRAP_INSTRUCTION:
969 break; /* handle as in operating mode. */
970 case FRV_COMMIT_EXCEPTION:
971 sim_engine_abort (sd, current_cpu, pc,
972 "interrupt: commit_exception\n");
974 case FRV_DIVISION_EXCEPTION:
975 sim_engine_abort (sd, current_cpu, pc,
976 "interrupt: division_exception\n");
978 case FRV_DATA_STORE_ERROR:
979 sim_engine_abort (sd, current_cpu, pc,
980 "interrupt: data_store_error\n");
982 case FRV_DATA_ACCESS_EXCEPTION:
983 sim_engine_abort (sd, current_cpu, pc,
984 "interrupt: data_access_exception\n");
986 case FRV_DATA_ACCESS_MMU_MISS:
987 sim_engine_abort (sd, current_cpu, pc,
988 "interrupt: data_access_mmu_miss\n");
990 case FRV_DATA_ACCESS_ERROR:
991 sim_engine_abort (sd, current_cpu, pc,
992 "interrupt: data_access_error\n");
994 case FRV_MP_EXCEPTION:
995 sim_engine_abort (sd, current_cpu, pc,
996 "interrupt: mp_exception\n");
998 case FRV_FP_EXCEPTION:
999 sim_engine_abort (sd, current_cpu, pc,
1000 "interrupt: fp_exception\n");
1002 case FRV_MEM_ADDRESS_NOT_ALIGNED:
1003 sim_engine_abort (sd, current_cpu, pc,
1004 "interrupt: mem_address_not_aligned\n");
1006 case FRV_REGISTER_EXCEPTION:
1007 sim_engine_abort (sd, current_cpu, pc,
1008 "interrupt: register_exception\n");
1010 case FRV_MP_DISABLED:
1011 sim_engine_abort (sd, current_cpu, pc,
1012 "interrupt: mp_disabled\n");
1014 case FRV_FP_DISABLED:
1015 sim_engine_abort (sd, current_cpu, pc,
1016 "interrupt: fp_disabled\n");
1018 case FRV_PRIVILEGED_INSTRUCTION:
1019 sim_engine_abort (sd, current_cpu, pc,
1020 "interrupt: privileged_instruction\n");
1022 case FRV_ILLEGAL_INSTRUCTION:
1023 sim_engine_abort (sd, current_cpu, pc,
1024 "interrupt: illegal_instruction\n");
1026 case FRV_INSTRUCTION_ACCESS_EXCEPTION:
1027 sim_engine_abort (sd, current_cpu, pc,
1028 "interrupt: instruction_access_exception\n");
1030 case FRV_INSTRUCTION_ACCESS_MMU_MISS:
1031 sim_engine_abort (sd, current_cpu, pc,
1032 "interrupt: instruction_access_mmu_miss\n");
1034 case FRV_INSTRUCTION_ACCESS_ERROR:
1035 sim_engine_abort (sd, current_cpu, pc,
1036 "interrupt: insn_access_error\n");
1038 case FRV_COMPOUND_EXCEPTION:
1039 sim_engine_abort (sd, current_cpu, pc,
1040 "interrupt: compound_exception\n");
1042 case FRV_BREAK_EXCEPTION:
1043 sim_engine_abort (sd, current_cpu, pc,
1044 "interrupt: break_exception\n");
1047 sim_engine_abort (sd, current_cpu, pc,
1048 "interrupt: reset\n");
1051 sim_engine_abort (sd, current_cpu, pc,
1052 "unhandled interrupt kind: %d\n", kind);
1057 /* Handle a break interrupt. */
1059 frv_break_interrupt (
1060 SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1073 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1074 SET_H_BPSR_BS (GET_H_PSR_S ());
1075 SET_H_BPSR_BET (GET_H_PSR_ET ());
1078 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1079 SET_H_SPR (H_SPR_BPCSR, current_pc);
1081 /* Set the new PC in the TBR. */
1082 SET_H_TBR_TT (interrupt->handler_offset);
1083 new_pc = GET_H_SPR (H_SPR_TBR);
1086 CPU_DEBUG_STATE (current_cpu) = 1;
1089 /* Handle a program interrupt or a software interrupt. */
1091 frv_program_or_software_interrupt (
1092 SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1096 int original_psr_et;
1103 SR0 through SR3=GR4 through GR7
1104 TBR.TT=interrupt handler offset
1107 original_psr_et = GET_H_PSR_ET ();
1109 SET_H_PSR_PS (GET_H_PSR_S ());
1113 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1114 /* The PCSR depends on the precision of the interrupt. */
1115 if (interrupt->precise)
1116 SET_H_SPR (H_SPR_PCSR, previous_vliw_pc);
1118 SET_H_SPR (H_SPR_PCSR, current_pc);
1120 /* Set the new PC in the TBR. */
1121 SET_H_TBR_TT (interrupt->handler_offset);
1122 new_pc = GET_H_SPR (H_SPR_TBR);
1125 /* If PSR.ET was not originally set, then enter the stopped state. */
1126 if (! original_psr_et)
1128 SIM_DESC sd = CPU_STATE (current_cpu);
1129 frv_non_operating_interrupt (current_cpu, interrupt->kind, current_pc);
1130 sim_engine_halt (sd, current_cpu, NULL, new_pc, sim_stopped, SIM_SIGINT);
1134 /* Handle a program interrupt or a software interrupt. */
1136 frv_external_interrupt (
1137 SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1141 struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1143 /* Don't process the interrupt if PSR.ET is not set or if it is masked.
1144 Interrupt 15 is processed even if it appears to be masked. */
1145 if (! GET_H_PSR_ET ()
1146 || (interrupt->kind != FRV_INTERRUPT_LEVEL_15
1147 && interrupt->kind < GET_H_PSR_PIL ()))
1148 return; /* Leave it for later. */
1150 /* Remove the interrupt from the queue. */
1151 --frv_interrupt_state.queue_index;
1158 SR0 through SR3=GR4 through GR7
1159 TBR.TT=interrupt handler offset
1162 SET_H_PSR_PS (GET_H_PSR_S ());
1165 /* Must set PSR.S first to allow access to supervisor-only spr registers. */
1166 SET_H_SPR (H_SPR_PCSR, GET_H_PC ());
1168 /* Set the new PC in the TBR. */
1169 SET_H_TBR_TT (interrupt->handler_offset);
1170 new_pc = GET_H_SPR (H_SPR_TBR);
1174 /* Clear interrupts which fall within the range of classes given. */
1176 frv_clear_interrupt_classes (
1177 enum frv_interrupt_class low_class, enum frv_interrupt_class high_class
1182 int limit = frv_interrupt_state.queue_index;
1184 /* Find the lowest priority interrupt to be removed. */
1185 for (i = 0; i < limit; ++i)
1187 enum frv_interrupt_kind kind = frv_interrupt_state.queue[i].kind;
1188 struct frv_interrupt* interrupt = & frv_interrupt_table[kind];
1189 if (interrupt->iclass >= low_class)
1193 /* Find the highest priority interrupt to be removed. */
1194 for (j = limit - 1; j >= i; --j)
1196 enum frv_interrupt_kind kind = frv_interrupt_state.queue[j].kind;
1197 struct frv_interrupt* interrupt = & frv_interrupt_table[kind];
1198 if (interrupt->iclass <= high_class)
1202 /* Shuffle the remaining high priority interrupts down into the empty space
1203 left by the deleted interrupts. */
1206 for (++j; j < limit; ++j)
1207 frv_interrupt_state.queue[i++] = frv_interrupt_state.queue[j];
1208 frv_interrupt_state.queue_index -= (j - i);
1212 /* Save data written to memory into the interrupt state so that it can be
1213 copied to the appropriate EDR register, if necessary, in the event of an
1216 frv_save_data_written_for_interrupts (
1217 SIM_CPU *current_cpu, CGEN_WRITE_QUEUE_ELEMENT *item
1220 /* Record the slot containing the insn doing the write in the
1222 frv_interrupt_state.slot = CGEN_WRITE_QUEUE_ELEMENT_PIPE (item);
1224 /* Now record any data written to memory in the interrupt state. */
1225 switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item))
1232 case CGEN_FN_HI_WRITE:
1233 case CGEN_FN_SI_WRITE:
1234 case CGEN_FN_SF_WRITE:
1235 case CGEN_FN_DI_WRITE:
1236 case CGEN_FN_DF_WRITE:
1237 case CGEN_FN_XI_WRITE:
1238 case CGEN_FN_PC_WRITE:
1239 break; /* Ignore writes to registers. */
1240 case CGEN_MEM_QI_WRITE:
1241 frv_interrupt_state.data_written.length = 1;
1242 frv_interrupt_state.data_written.words[0]
1243 = item->kinds.mem_qi_write.value;
1245 case CGEN_MEM_HI_WRITE:
1246 frv_interrupt_state.data_written.length = 1;
1247 frv_interrupt_state.data_written.words[0]
1248 = item->kinds.mem_hi_write.value;
1250 case CGEN_MEM_SI_WRITE:
1251 frv_interrupt_state.data_written.length = 1;
1252 frv_interrupt_state.data_written.words[0]
1253 = item->kinds.mem_si_write.value;
1255 case CGEN_MEM_DI_WRITE:
1256 frv_interrupt_state.data_written.length = 2;
1257 frv_interrupt_state.data_written.words[0]
1258 = item->kinds.mem_di_write.value >> 32;
1259 frv_interrupt_state.data_written.words[1]
1260 = item->kinds.mem_di_write.value;
1262 case CGEN_MEM_DF_WRITE:
1263 frv_interrupt_state.data_written.length = 2;
1264 frv_interrupt_state.data_written.words[0]
1265 = item->kinds.mem_df_write.value >> 32;
1266 frv_interrupt_state.data_written.words[1]
1267 = item->kinds.mem_df_write.value;
1269 case CGEN_MEM_XI_WRITE:
1270 frv_interrupt_state.data_written.length = 4;
1271 frv_interrupt_state.data_written.words[0]
1272 = item->kinds.mem_xi_write.value[0];
1273 frv_interrupt_state.data_written.words[1]
1274 = item->kinds.mem_xi_write.value[1];
1275 frv_interrupt_state.data_written.words[2]
1276 = item->kinds.mem_xi_write.value[2];
1277 frv_interrupt_state.data_written.words[3]
1278 = item->kinds.mem_xi_write.value[3];
1280 case CGEN_FN_MEM_QI_WRITE:
1281 frv_interrupt_state.data_written.length = 1;
1282 frv_interrupt_state.data_written.words[0]
1283 = item->kinds.fn_mem_qi_write.value;
1285 case CGEN_FN_MEM_HI_WRITE:
1286 frv_interrupt_state.data_written.length = 1;
1287 frv_interrupt_state.data_written.words[0]
1288 = item->kinds.fn_mem_hi_write.value;
1290 case CGEN_FN_MEM_SI_WRITE:
1291 frv_interrupt_state.data_written.length = 1;
1292 frv_interrupt_state.data_written.words[0]
1293 = item->kinds.fn_mem_si_write.value;
1295 case CGEN_FN_MEM_DI_WRITE:
1296 frv_interrupt_state.data_written.length = 2;
1297 frv_interrupt_state.data_written.words[0]
1298 = item->kinds.fn_mem_di_write.value >> 32;
1299 frv_interrupt_state.data_written.words[1]
1300 = item->kinds.fn_mem_di_write.value;
1302 case CGEN_FN_MEM_DF_WRITE:
1303 frv_interrupt_state.data_written.length = 2;
1304 frv_interrupt_state.data_written.words[0]
1305 = item->kinds.fn_mem_df_write.value >> 32;
1306 frv_interrupt_state.data_written.words[1]
1307 = item->kinds.fn_mem_df_write.value;
1309 case CGEN_FN_MEM_XI_WRITE:
1310 frv_interrupt_state.data_written.length = 4;
1311 frv_interrupt_state.data_written.words[0]
1312 = item->kinds.fn_mem_xi_write.value[0];
1313 frv_interrupt_state.data_written.words[1]
1314 = item->kinds.fn_mem_xi_write.value[1];
1315 frv_interrupt_state.data_written.words[2]
1316 = item->kinds.fn_mem_xi_write.value[2];
1317 frv_interrupt_state.data_written.words[3]
1318 = item->kinds.fn_mem_xi_write.value[3];
1322 SIM_DESC sd = CPU_STATE (current_cpu);
1323 IADDR pc = CPU_PC_GET (current_cpu);
1324 sim_engine_abort (sd, current_cpu, pc,
1325 "unknown write kind during save for interrupt\n");