OSDN Git Service

sim: gpio: update mask a/b signals better
[pf3gnuchains/pf3gnuchains4x.git] / sim / frv / interrupts.c
1 /* frv exception and interrupt support
2    Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4    Contributed by Red Hat.
5
6 This file is part of the GNU simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #define WANT_CPU frvbf
22 #define WANT_CPU_FRVBF
23
24 #include "sim-main.h"
25 #include "bfd.h"
26
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.  */
31 #define DEFERRED 1
32 #define PRECISE  1
33 #define ITABLE_ENTRY(name, class, deferral, precision, offset) \
34   {FRV_##name, FRV_EC_##name, class, deferral, precision, offset}
35
36 struct frv_interrupt frv_interrupt_table[NUM_FRV_INTERRUPT_KINDS] =
37 {
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),
75   /* Break interrupt */
76   ITABLE_ENTRY(BREAK_EXCEPTION,              FRV_BREAK_INTERRUPT,    !DEFERRED, !PRECISE, 0xff),
77   /* Reset interrupt */
78   ITABLE_ENTRY(RESET,                        FRV_RESET_INTERRUPT,    !DEFERRED, !PRECISE, 0x00)
79 };
80
81 /* The current interrupt state.  */
82 struct frv_interrupt_state frv_interrupt_state;
83
84 /* maintain the address of the start of the previous VLIW insn sequence.  */
85 IADDR previous_vliw_pc;
86
87 /* Add a break interrupt to the interrupt queue.  */
88 struct frv_interrupt_queue_element *
89 frv_queue_break_interrupt (SIM_CPU *current_cpu)
90 {
91   return frv_queue_interrupt (current_cpu, FRV_BREAK_EXCEPTION);
92 }
93
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)
97 {
98   struct frv_interrupt_queue_element *new_element
99     = frv_queue_interrupt (current_cpu, FRV_TRAP_INSTRUCTION);
100
101   struct frv_interrupt *interrupt = & frv_interrupt_table[new_element->kind];
102   interrupt->handler_offset = offset;
103
104   return new_element;
105 }
106
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
111 )
112 {
113   return frv_queue_interrupt (current_cpu, kind);
114 }
115
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
120 )
121 {
122   if (! GET_H_PSR_ET ()
123       || (kind != FRV_INTERRUPT_LEVEL_15 && kind < GET_H_PSR_PIL ()))
124     return NULL; /* Leave it for later.  */
125
126   return frv_queue_interrupt (current_cpu, kind);
127 }
128
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)
134 {
135   int i;
136   int j;
137   int limit = frv_interrupt_state.queue_index;
138   struct frv_interrupt_queue_element *new_element;
139   enum frv_interrupt_class iclass;
140
141   if (limit >= FRV_INTERRUPT_QUEUE_SIZE)
142     abort (); /* TODO: Make the queue dynamic */
143
144   /* Find the right place in the queue.  */
145   for (i = 0; i < limit; ++i)
146     {
147       if (frv_interrupt_state.queue[i].kind >= kind)
148         break;
149     }
150
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)
154     {
155       if (frv_interrupt_state.queue[i].kind == kind)
156         return & frv_interrupt_state.queue[i];
157     }
158
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];
162
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);
170
171   return new_element;
172 }
173
174 struct frv_interrupt_queue_element *
175 frv_queue_register_exception_interrupt (SIM_CPU *current_cpu, enum frv_rec rec)
176 {
177   struct frv_interrupt_queue_element *new_element =
178     frv_queue_program_interrupt (current_cpu, FRV_REGISTER_EXCEPTION);
179
180   new_element->u.rec = rec;
181
182   return new_element;
183 }
184
185 struct frv_interrupt_queue_element *
186 frv_queue_mem_address_not_aligned_interrupt (SIM_CPU *current_cpu, USI addr)
187 {
188   struct frv_interrupt_queue_element *new_element;
189   USI isr = GET_ISR ();
190
191   /* Make sure that this exception is not masked.  */
192   if (GET_ISR_EMAM (isr))
193     return NULL;
194
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;
201
202   return new_element;
203 }
204
205 struct frv_interrupt_queue_element *
206 frv_queue_data_access_error_interrupt (SIM_CPU *current_cpu, USI addr)
207 {
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;
212   return new_element;
213 }
214
215 struct frv_interrupt_queue_element *
216 frv_queue_data_access_exception_interrupt (SIM_CPU *current_cpu)
217 {
218   return frv_queue_program_interrupt (current_cpu, FRV_DATA_ACCESS_EXCEPTION);
219 }
220
221 struct frv_interrupt_queue_element *
222 frv_queue_instruction_access_error_interrupt (SIM_CPU *current_cpu)
223 {
224   return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_ERROR);
225 }
226
227 struct frv_interrupt_queue_element *
228 frv_queue_instruction_access_exception_interrupt (SIM_CPU *current_cpu)
229 {
230   return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_EXCEPTION);
231 }
232
233 struct frv_interrupt_queue_element *
234 frv_queue_illegal_instruction_interrupt (
235   SIM_CPU *current_cpu, const CGEN_INSN *insn
236 )
237 {
238   SIM_DESC sd = CPU_STATE (current_cpu);
239   switch (STATE_ARCHITECTURE (sd)->mach)
240     {
241     case bfd_mach_fr400:
242     case bfd_mach_fr450:
243     case bfd_mach_fr550:
244       break;
245     default:
246       /* Some machines generate fp_exception for this case.  */
247       if (frv_is_float_insn (insn) || frv_is_media_insn (insn))
248         {
249           struct frv_fp_exception_info fp_info = {
250             FSR_NO_EXCEPTION, FTT_SEQUENCE_ERROR
251           };
252           return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
253         }
254       break;
255     }
256
257   return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
258 }
259
260 struct frv_interrupt_queue_element *
261 frv_queue_privileged_instruction_interrupt (SIM_CPU *current_cpu, const CGEN_INSN *insn)
262 {
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);
268
269   return frv_queue_program_interrupt (current_cpu, FRV_PRIVILEGED_INSTRUCTION);
270 }
271
272 struct frv_interrupt_queue_element *
273 frv_queue_float_disabled_interrupt (SIM_CPU *current_cpu)
274 {
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);
279   
280   return frv_queue_program_interrupt (current_cpu, FRV_FP_DISABLED);
281 }
282
283 struct frv_interrupt_queue_element *
284 frv_queue_media_disabled_interrupt (SIM_CPU *current_cpu)
285 {
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);
290   
291   return frv_queue_program_interrupt (current_cpu, FRV_MP_DISABLED);
292 }
293
294 struct frv_interrupt_queue_element *
295 frv_queue_non_implemented_instruction_interrupt (
296   SIM_CPU *current_cpu, const CGEN_INSN *insn
297 )
298 {
299   SIM_DESC sd = CPU_STATE (current_cpu);
300   switch (STATE_ARCHITECTURE (sd)->mach)
301     {
302     case bfd_mach_fr400:
303     case bfd_mach_fr450:
304     case bfd_mach_fr550:
305       break;
306     default:
307       /* Some machines generate fp_exception or mp_exception for this case.  */
308       if (frv_is_float_insn (insn))
309         {
310           struct frv_fp_exception_info fp_info = {
311             FSR_NO_EXCEPTION, FTT_UNIMPLEMENTED_FPOP
312           };
313           return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
314         }
315       if (frv_is_media_insn (insn))
316         {
317           frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP,
318                                           0);
319           return NULL; /* no interrupt queued at this time.  */
320         }
321       break;
322     }
323
324   return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
325 }
326
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
332 )
333 {
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;
338
339   /* Update AEXC with the interrupts that are masked.  */
340   aexc |= fp_info->fsr_mask & ~tem;
341   SET_FSR_AEXC (fsr0, aexc);
342   SET_FSR (0, fsr0);
343
344   /* update fsr_mask with the exceptions that are enabled.  */
345   fp_info->fsr_mask &= tem;
346
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
349      status registers.  */
350   if (frv_interrupt_state.ne_index != NE_NOFLAG
351       && fp_info->fsr_mask != FSR_NO_EXCEPTION)
352     {
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.  */
356       new_element = NULL;
357     }
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)
362     {
363       new_element = frv_queue_program_interrupt (current_cpu, FRV_FP_EXCEPTION);
364       new_element->u.fp_info = *fp_info;
365     }
366
367   return new_element;
368 }
369
370 struct frv_interrupt_queue_element *
371 frv_queue_division_exception_interrupt (SIM_CPU *current_cpu, enum frv_dtt dtt)
372 {
373   struct frv_interrupt_queue_element *new_element =
374     frv_queue_program_interrupt (current_cpu, FRV_DIVISION_EXCEPTION);
375
376   new_element->u.dtt = dtt;
377
378   return new_element;
379 }
380
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.  */
383 void
384 frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc)
385 {
386
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);
390
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 ())
404     {
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);
411     }
412   /* Make sure media support is enabled.  */
413   else if (! GET_H_PSR_EM ())
414     {
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);
418     }
419   /* Check for privileged insns.  */
420   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) &&
421            ! GET_H_PSR_S ())
422     frv_queue_privileged_instruction_interrupt (current_cpu, insn);
423 #if 0 /* disable for now until we find out how FSR0.QNE gets reset.  */
424   else
425     {
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
428          register.  */
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)))
433         {
434           sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped,
435                            SIM_SIGINT);
436         }
437     }
438 #endif
439 }
440
441 /* Record the current VLIW slot in the given interrupt queue element.  */
442 void
443 frv_set_interrupt_queue_slot (
444   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
445 )
446 {
447   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
448   int slot = vliw->next_slot - 1;
449   item->slot = (*vliw->current_vliw)[slot];
450 }
451
452 /* Handle an individual interrupt.  */
453 static void
454 handle_interrupt (SIM_CPU *current_cpu, IADDR pc)
455 {
456   struct frv_interrupt *interrupt;
457   int writeback_done = 0;
458   while (1)
459     {
460       /* Interrupts are queued in priority order with the highest priority
461          last.  */
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];
466
467       switch (interrupt->iclass)
468         {
469         case FRV_EXTERNAL_INTERRUPT:
470           /* Perform writeback first. This may cause a higher priority
471              interrupt.  */
472           if (! writeback_done)
473             {
474               frvbf_perform_writeback (current_cpu);
475               writeback_done = 1;
476               continue;
477             }
478           frv_external_interrupt (current_cpu, item, pc);
479           return;
480         case FRV_SOFTWARE_INTERRUPT:
481           frv_interrupt_state.queue_index = index;
482           frv_software_interrupt (current_cpu, item, pc);
483           return;
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
487              interrupt.  */
488           if (! interrupt->precise && ! writeback_done)
489             {
490               frv_interrupt_state.imprecise_interrupt = item;
491               frvbf_perform_writeback (current_cpu);
492               writeback_done = 1;
493               continue;
494             }
495           frv_interrupt_state.queue_index = index;
496           frv_program_interrupt (current_cpu, item, pc);
497           return;
498         case FRV_BREAK_INTERRUPT:
499           frv_interrupt_state.queue_index = index;
500           frv_break_interrupt (current_cpu, interrupt, pc);
501           return;
502         case FRV_RESET_INTERRUPT:
503           break;
504         default:
505           break;
506         }
507       frv_interrupt_state.queue_index = index;
508       break; /* out of loop.  */
509     }
510
511   /* We should never get here.  */
512   {
513     SIM_DESC sd = CPU_STATE (current_cpu);
514     sim_engine_abort (sd, current_cpu, pc,
515                       "interrupt class not supported %d\n",
516                       interrupt->iclass);
517   }
518 }
519
520 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set.  If so, handle
521    the appropriate reset interrupt.  */
522 static int
523 check_reset (SIM_CPU *current_cpu, IADDR pc)
524 {
525   int hsr0;
526   int hr;
527   int sr;
528   SI rstr;
529   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
530   IADDR address = RSTR_ADDRESS;
531
532   /* We don't want this to show up in the cache statistics, so read the
533      cache passively.  */
534   if (! frv_cache_read_passive_SI (cache, address, & rstr))
535     rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address);
536
537   hr = GET_RSTR_HR (rstr);
538   sr = GET_RSTR_SR (rstr);
539
540   if (! hr && ! sr)
541     return 0; /* no reset.  */
542
543   /* Reinitialize the machine state.  */
544   if (hr)
545     frv_hardware_reset (current_cpu);
546   else
547     frv_software_reset (current_cpu);
548
549   /* Branch to the reset address.  */
550   hsr0 = GET_HSR0 ();
551   if (GET_HSR0_SA (hsr0))
552     SET_H_PC (0xff000000);
553   else
554     SET_H_PC (0);
555
556   return 1; /* reset */
557 }
558
559 /* Process any pending interrupt(s) after a group of parallel insns.  */
560 void
561 frv_process_interrupts (SIM_CPU *current_cpu)
562 {
563   SI NE_flags[2];
564   /* Need to save the pc here because writeback may change it (due to a
565      branch).  */
566   IADDR pc = CPU_PC_GET (current_cpu);
567
568   /* Check for a reset before anything else.  */
569   if (check_reset (current_cpu, pc))
570     return;
571
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)
575     {
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);
580     }
581
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);
586
587   /* If there is an interrupt pending, then process it.  */
588   if (frv_interrupt_state.queue_index > 0)
589     handle_interrupt (current_cpu, pc);
590 }
591
592 /* Find the next available ESR and return its index */
593 static int
594 esr_for_data_access_exception (
595   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
596 )
597 {
598   SIM_DESC sd = CPU_STATE (current_cpu);
599   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
600     return 8; /* Use ESR8, EPCR8.  */
601
602   if (item->slot == UNIT_I0)
603     return 8; /* Use ESR8, EPCR8, EAR8, EDR8.  */
604
605   return 9; /* Use ESR9, EPCR9, EAR9.  */
606 }
607
608 /* Set the next available EDR register with the data which was to be stored
609    and return the index of the register.  */
610 static int
611 set_edr_register (
612   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index
613 )
614 {
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.  */
619   int i;
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]);
623
624   return edr_index;
625 };
626
627 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx.  */
628 static void
629 clear_exception_status_registers (SIM_CPU *current_cpu)
630 {
631   int i;
632   /* It is only necessary to clear the flag bits indicating which registers
633      are valid.  */
634   SET_ESFR (0, 0);
635   SET_ESFR (1, 0);
636
637   for (i = 0; i <= 2; ++i)
638     {
639       SI esr = GET_ESR (i);
640       CLEAR_ESR_VALID (esr);
641       SET_ESR (i, esr);
642     }
643   for (i = 8; i <= 15; ++i)
644     {
645       SI esr = GET_ESR (i);
646       CLEAR_ESR_VALID (esr);
647       SET_ESR (i, esr);
648     }
649 }
650
651 /* Record state for media exception.  */
652 void
653 frv_set_mp_exception_registers (
654   SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie
655 )
656 {
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);
661
662   /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF.  */
663   if (mtt == MTT_OVERFLOW)
664     {
665       FRV_VLIW *vliw = CPU_VLIW (current_cpu);
666       int slot = vliw->next_slot - 1;
667       SIM_DESC sd = CPU_STATE (current_cpu);
668
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)
672         {
673           SI msr = GET_MSR (1);
674           OR_MSR_SIE (msr, sie);
675           SET_MSR_OVF (msr);
676           SET_MSR (1, msr);
677         }
678       else
679         {
680           OR_MSR_SIE (msr0, sie);
681           SET_MSR_OVF (msr0);
682         }
683
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);
687       else
688         {
689           /* Regardless of the slot, set MSR0.AOVF.  */
690           SET_MSR_AOVF (msr0);
691         }
692     }
693
694   SET_MSR (0, msr0);
695 }
696
697 /* Determine the correct FQ register to use for the given exception.
698    Return -1 if a register is not available.  */
699 static int
700 fq_for_exception (
701   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
702 )
703 {
704   SI fq;
705   struct frv_fp_exception_info *fp_info = & item->u.fp_info;
706
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)))
710     {
711       fq = GET_FQ (0);
712       if (! GET_FQ_VALID (fq))
713         return 0; /* FQ0 is available.  */
714       fq = GET_FQ (1);
715       if (! GET_FQ_VALID (fq))
716         return 1; /* FQ1 is available.  */
717
718       /* No FQ register is available */
719       {
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");
723       }
724       return -1;
725     }
726   /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
727      otherwise.  */
728   if (item->slot == UNIT_FM0 || item->slot == UNIT_I0)
729     return 2;
730
731   return 3;
732 }
733
734 /* Set FSR0, FQ0-FQ9, depending on the interrupt.  */
735 static void
736 set_fp_exception_registers (
737   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
738 )
739 {
740   int fq_index;
741   SI fq;
742   SI insn;
743   SI fsr0;
744   IADDR pc;
745   struct frv_fp_exception_info *fp_info;
746   SIM_DESC sd = CPU_STATE (current_cpu);
747
748   /* No FQ registers on fr550 */
749   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
750     {
751       /* Update the fsr.  */
752       fp_info = & item->u.fp_info;
753       fsr0 = GET_FSR (0);
754       SET_FSR_FTT (fsr0, fp_info->ftt);
755       SET_FSR (0, fsr0);
756       return;
757     }
758
759   /* Select an FQ and update it with the exception information.  */
760   fq_index = fq_for_exception (current_cpu, item);
761   if (fq_index == -1)
762     return;
763
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);
770   SET_FQ_VALID (fq);
771   SET_FQ (fq_index, fq);
772
773   /* Write the failing insn into FQx.OPC.  */
774   pc = item->vpc;
775   insn = GETMEMSI (current_cpu, pc, pc);
776   SET_FQ_OPC (fq_index, insn);
777
778   /* Update the fsr.  */
779   fsr0 = GET_FSR (0);
780   SET_FSR_QNE (fsr0); /* FQ not empty */
781   SET_FSR_FTT (fsr0, fp_info->ftt);
782   SET_FSR (0, fsr0);
783 }
784
785 /* Record the state of a division exception in the ISR.  */
786 static void
787 set_isr_exception_fields (
788   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
789 )
790 {
791   USI isr = GET_ISR ();
792   int dtt = GET_ISR_DTT (isr);
793   dtt |= item->u.dtt;
794   SET_ISR_DTT (isr, dtt);
795   SET_ISR (isr);
796 }
797
798 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
799    interrupt.  */
800 static void
801 set_exception_status_registers (
802   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
803 )
804 {
805   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
806   int slot = (item->vpc - previous_vliw_pc) / 4;
807   int reg_index = -1;
808   int set_ear = 0;
809   int set_edr = 0;
810   int set_daec = 0;
811   int set_epcr = 0;
812   SI esr = 0;
813   SIM_DESC sd = CPU_STATE (current_cpu);
814
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)
818     {
819       reg_index = 0;
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)
826         set_epcr = 1;
827     }
828   else
829     {
830       switch (interrupt->kind)
831         {
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)
838             reg_index = 0;
839           else if (item->slot == UNIT_I0)
840             reg_index = 0;
841           else if (item->slot == UNIT_I1)
842             reg_index = 1;
843           set_epcr = 1;
844           break;
845         case FRV_DATA_STORE_ERROR:
846           reg_index = 14; /* Use ESR14.  */
847           break;
848         case FRV_DATA_ACCESS_ERROR:
849           reg_index = 15; /* Use ESR15, EPCR15.  */
850           set_ear = 1;
851           break;
852         case FRV_DATA_ACCESS_EXCEPTION:
853           set_daec = 1;
854           /* fall through */
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.  */
859           set_ear = 1;
860           /* For fr550, never use EDRx.  */
861           if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
862             if (item->u.data_written.length != 0)
863               set_edr = 1;
864           reg_index = esr_for_data_access_exception (current_cpu, item);
865           set_epcr = 1;
866           break;
867         case FRV_MP_EXCEPTION:
868           /* For fr550, use EPCR2 and ESR2.  */
869           if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
870             {
871               reg_index = 2;
872               set_epcr = 1;
873             }
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)
879             {
880               reg_index = 2;
881               set_epcr = 1;
882             }
883           break;
884         default:
885           {
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",
890                               interrupt->kind);
891             break;
892           }
893         }
894     } /* non-strict (imprecise) interrupt */
895
896   /* Now fill in the selected exception status registers.  */
897   if (reg_index != -1)
898     {
899       /* Now set the exception status registers.  */
900       SET_ESFR_FLAG (reg_index);
901       SET_ESR_EC (esr, interrupt->ec);
902
903       if (set_epcr)
904         {
905           if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
906             SET_EPCR (reg_index, previous_vliw_pc);
907           else
908             SET_EPCR (reg_index, item->vpc);
909         }
910
911       if (set_ear)
912         {
913           SET_EAR (reg_index, item->eaddress);
914           SET_ESR_EAV (esr);
915         }
916       else
917         CLEAR_ESR_EAV (esr);
918
919       if (set_edr)
920         {
921           int edn = set_edr_register (current_cpu, item, 0/* EDR0-3 */);
922           SET_ESR_EDN (esr, edn);
923           SET_ESR_EDV (esr);
924         }
925       else
926         CLEAR_ESR_EDV (esr);
927
928       if (set_daec)
929         SET_ESR_DAEC (esr, item->u.daec);
930
931       SET_ESR_VALID (esr);
932       SET_ESR (reg_index, esr);
933     }
934 }
935
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
941 )
942 {
943   struct frv_interrupt *interrupt;
944
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];
948
949   if (! interrupt->precise)
950     {
951       IADDR vpc = 0;
952       int mask = 0;
953
954       vpc = item->vpc;
955       mask = (1 << item->kind);
956
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)
962         {
963           enum frv_interrupt_kind kind;
964           struct frv_interrupt *next_interrupt;
965           --item;
966           kind = item->kind;
967           next_interrupt = & frv_interrupt_table[kind];
968
969           if (next_interrupt->iclass != FRV_PROGRAM_INTERRUPT)
970             break; /* no program interrupts left.  */
971
972           if (item->vpc == vpc)
973             continue; /* caused by the same insn.  */
974
975           vpc = item->vpc;
976           if (! next_interrupt->precise && ! next_interrupt->deferred)
977             {
978               if (! (mask & (1 << kind)))
979                 {
980                   /* Set the exception status registers for the additional
981                      interrupt.  */
982                   set_exception_status_registers (current_cpu, item);
983                   mask |= (1 << kind);
984                   interrupt = & frv_interrupt_table[FRV_COMPOUND_EXCEPTION];
985                 }
986             }
987         }
988     }
989
990   /* Return with either the original interrupt, a compound_exception,
991      or no exception.  */
992   return interrupt;
993 }
994
995 /* Handle a program interrupt.  */
996 void
997 frv_program_interrupt (
998   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
999 )
1000 {
1001   struct frv_interrupt *interrupt;
1002
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)
1008     {
1009       frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1010       frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT,
1011                                    FRV_PROGRAM_INTERRUPT);
1012     }
1013 }
1014
1015 /* Handle a software interrupt.  */
1016 void
1017 frv_software_interrupt (
1018   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1019 )
1020 {
1021   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1022   frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1023 }
1024
1025 /* Handle a program interrupt or a software interrupt in non-operating mode.  */
1026 void
1027 frv_non_operating_interrupt (
1028   SIM_CPU *current_cpu, enum frv_interrupt_kind kind, IADDR pc
1029 )
1030 {
1031   SIM_DESC sd = CPU_STATE (current_cpu);
1032   switch (kind)
1033     {
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);
1051       break;
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");
1057       break;
1058     case FRV_DIVISION_EXCEPTION:
1059       sim_engine_abort (sd, current_cpu, pc,
1060                         "interrupt: division_exception\n");
1061       break;
1062     case FRV_DATA_STORE_ERROR:
1063       sim_engine_abort (sd, current_cpu, pc,
1064                         "interrupt: data_store_error\n");
1065       break;
1066     case FRV_DATA_ACCESS_EXCEPTION:
1067       sim_engine_abort (sd, current_cpu, pc,
1068                         "interrupt: data_access_exception\n");
1069       break;
1070     case FRV_DATA_ACCESS_MMU_MISS:
1071       sim_engine_abort (sd, current_cpu, pc,
1072                         "interrupt: data_access_mmu_miss\n");
1073       break;
1074     case FRV_DATA_ACCESS_ERROR:
1075       sim_engine_abort (sd, current_cpu, pc,
1076                         "interrupt: data_access_error\n");
1077       break;
1078     case FRV_MP_EXCEPTION:
1079       sim_engine_abort (sd, current_cpu, pc,
1080                         "interrupt: mp_exception\n");
1081       break;
1082     case FRV_FP_EXCEPTION:
1083       sim_engine_abort (sd, current_cpu, pc,
1084                         "interrupt: fp_exception\n");
1085       break;
1086     case FRV_MEM_ADDRESS_NOT_ALIGNED:
1087       sim_engine_abort (sd, current_cpu, pc,
1088                         "interrupt: mem_address_not_aligned\n");
1089       break;
1090     case FRV_REGISTER_EXCEPTION:
1091       sim_engine_abort (sd, current_cpu, pc,
1092                         "interrupt: register_exception\n");
1093       break;
1094     case FRV_MP_DISABLED:
1095       sim_engine_abort (sd, current_cpu, pc,
1096                         "interrupt: mp_disabled\n");
1097       break;
1098     case FRV_FP_DISABLED:
1099       sim_engine_abort (sd, current_cpu, pc,
1100                         "interrupt: fp_disabled\n");
1101       break;
1102     case FRV_PRIVILEGED_INSTRUCTION:
1103       sim_engine_abort (sd, current_cpu, pc,
1104                         "interrupt: privileged_instruction\n");
1105       break;
1106     case FRV_ILLEGAL_INSTRUCTION:
1107       sim_engine_abort (sd, current_cpu, pc,
1108                         "interrupt: illegal_instruction\n");
1109       break;
1110     case FRV_INSTRUCTION_ACCESS_EXCEPTION:
1111       sim_engine_abort (sd, current_cpu, pc,
1112                         "interrupt: instruction_access_exception\n");
1113       break;
1114     case FRV_INSTRUCTION_ACCESS_MMU_MISS:
1115       sim_engine_abort (sd, current_cpu, pc,
1116                         "interrupt: instruction_access_mmu_miss\n");
1117       break;
1118     case FRV_INSTRUCTION_ACCESS_ERROR:
1119       sim_engine_abort (sd, current_cpu, pc,
1120                         "interrupt: insn_access_error\n");
1121       break;
1122     case FRV_COMPOUND_EXCEPTION:
1123       sim_engine_abort (sd, current_cpu, pc,
1124                         "interrupt: compound_exception\n");
1125       break;
1126     case FRV_BREAK_EXCEPTION:
1127       sim_engine_abort (sd, current_cpu, pc,
1128                         "interrupt: break_exception\n");
1129       break;
1130     case FRV_RESET:
1131       sim_engine_abort (sd, current_cpu, pc,
1132                         "interrupt: reset\n");
1133       break;
1134     default:
1135       sim_engine_abort (sd, current_cpu, pc,
1136                         "unhandled interrupt kind: %d\n", kind);
1137       break;
1138     }
1139 }
1140
1141 /* Handle a break interrupt.  */
1142 void
1143 frv_break_interrupt (
1144   SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1145 )
1146 {
1147   IADDR new_pc;
1148
1149   /* BPCSR=PC
1150      BPSR.BS=PSR.S
1151      BPSR.BET=PSR.ET
1152      PSR.S=1
1153      PSR.ET=0
1154      TBR.TT=0xff
1155      PC=TBR
1156   */
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 ());
1160   SET_H_PSR_S (1);
1161   SET_H_PSR_ET (0);
1162   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1163   SET_H_SPR (H_SPR_BPCSR, current_pc);
1164
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);
1168   SET_H_PC (new_pc);
1169
1170   CPU_DEBUG_STATE (current_cpu) = 1;
1171 }
1172
1173 /* Handle a program interrupt or a software interrupt.  */
1174 void
1175 frv_program_or_software_interrupt (
1176   SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1177 )
1178 {
1179   USI new_pc;
1180   int original_psr_et;
1181
1182   /* PCSR=PC
1183      PSR.PS=PSR.S
1184      PSR.ET=0
1185      PSR.S=1
1186      if PSR.ESR==1
1187        SR0 through SR3=GR4 through GR7
1188        TBR.TT=interrupt handler offset
1189        PC=TBR
1190   */
1191   original_psr_et = GET_H_PSR_ET ();
1192
1193   SET_H_PSR_PS (GET_H_PSR_S ());
1194   SET_H_PSR_ET (0);
1195   SET_H_PSR_S (1);
1196
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);
1201   else
1202     SET_H_SPR (H_SPR_PCSR, current_pc);
1203
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);
1207   SET_H_PC (new_pc);
1208
1209   /* If PSR.ET was not originally set, then enter the stopped state.  */
1210   if (! original_psr_et)
1211     {
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);
1215     }
1216 }
1217
1218 /* Handle a program interrupt or a software interrupt.  */
1219 void
1220 frv_external_interrupt (
1221   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1222 )
1223 {
1224   USI new_pc;
1225   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1226
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.  */
1233
1234   /* Remove the interrupt from the queue.  */
1235   --frv_interrupt_state.queue_index;
1236
1237   /* PCSR=PC
1238      PSR.PS=PSR.S
1239      PSR.ET=0
1240      PSR.S=1
1241      if PSR.ESR==1
1242        SR0 through SR3=GR4 through GR7
1243        TBR.TT=interrupt handler offset
1244        PC=TBR
1245   */
1246   SET_H_PSR_PS (GET_H_PSR_S ());
1247   SET_H_PSR_ET (0);
1248   SET_H_PSR_S (1);
1249   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1250   SET_H_SPR (H_SPR_PCSR, GET_H_PC ());
1251
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);
1255   SET_H_PC (new_pc);
1256 }
1257
1258 /* Clear interrupts which fall within the range of classes given.  */
1259 void
1260 frv_clear_interrupt_classes (
1261   enum frv_interrupt_class low_class, enum frv_interrupt_class high_class
1262 )
1263 {
1264   int i;
1265   int j;
1266   int limit = frv_interrupt_state.queue_index;
1267
1268   /* Find the lowest priority interrupt to be removed.  */
1269   for (i = 0; i < limit; ++i)
1270     {
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)
1274         break;
1275     }
1276
1277   /* Find the highest priority interrupt to be removed.  */
1278   for (j = limit - 1; j >= i; --j)
1279     {
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)
1283         break;
1284     }
1285
1286   /* Shuffle the remaining high priority interrupts down into the empty space
1287      left by the deleted interrupts.  */
1288   if (j >= i)
1289     {
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);
1293     }
1294 }
1295
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
1298    interrupt.  */
1299 void
1300 frv_save_data_written_for_interrupts (
1301   SIM_CPU *current_cpu, CGEN_WRITE_QUEUE_ELEMENT *item
1302 )
1303 {
1304   /* Record the slot containing the insn doing the write in the
1305      interrupt state.  */
1306   frv_interrupt_state.slot = CGEN_WRITE_QUEUE_ELEMENT_PIPE (item);
1307
1308   /* Now record any data written to memory in the interrupt state.  */
1309   switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item))
1310     {
1311     case CGEN_BI_WRITE:
1312     case CGEN_QI_WRITE:
1313     case CGEN_SI_WRITE:
1314     case CGEN_SF_WRITE:
1315     case CGEN_PC_WRITE:
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;
1328       break;
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;
1333       break;
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;
1338       break;
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;
1345       break;
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;
1352       break;
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];
1363       break;
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;
1368       break;
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;
1373       break;
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;
1378       break;
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;
1385       break;
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;
1392       break;
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];
1403       break;
1404     default:
1405       {
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");
1410       }
1411       break;
1412     }
1413 }