540ee06e28d6630d45989115d33e46776c3d927b
[external/binutils.git] / sim / frv / interrupts.c
1 /* frv exception and interrupt support
2    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3    Contributed by Red Hat.
4
5 This file is part of the GNU simulators.
6
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)
10 any later version.
11
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.
16
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.  */
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_fr550:
243       break;
244     default:
245       /* Some machines generate fp_exception for this case.  */
246       if (frv_is_float_insn (insn) || frv_is_media_insn (insn))
247         {
248           struct frv_fp_exception_info fp_info = {
249             FSR_NO_EXCEPTION, FTT_SEQUENCE_ERROR
250           };
251           return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
252         }
253       break;
254     }
255
256   return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
257 }
258
259 struct frv_interrupt_queue_element *
260 frv_queue_privileged_instruction_interrupt (SIM_CPU *current_cpu, const CGEN_INSN *insn)
261 {
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);
267
268   return frv_queue_program_interrupt (current_cpu, FRV_PRIVILEGED_INSTRUCTION);
269 }
270
271 struct frv_interrupt_queue_element *
272 frv_queue_float_disabled_interrupt (SIM_CPU *current_cpu)
273 {
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);
278   
279   return frv_queue_program_interrupt (current_cpu, FRV_FP_DISABLED);
280 }
281
282 struct frv_interrupt_queue_element *
283 frv_queue_media_disabled_interrupt (SIM_CPU *current_cpu)
284 {
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);
289   
290   return frv_queue_program_interrupt (current_cpu, FRV_MP_DISABLED);
291 }
292
293 struct frv_interrupt_queue_element *
294 frv_queue_non_implemented_instruction_interrupt (
295   SIM_CPU *current_cpu, const CGEN_INSN *insn
296 )
297 {
298   SIM_DESC sd = CPU_STATE (current_cpu);
299   switch (STATE_ARCHITECTURE (sd)->mach)
300     {
301     case bfd_mach_fr400:
302     case bfd_mach_fr550:
303       break;
304     default:
305       /* Some machines generate fp_exception or mp_exception for this case.  */
306       if (frv_is_float_insn (insn))
307         {
308           struct frv_fp_exception_info fp_info = {
309             FSR_NO_EXCEPTION, FTT_UNIMPLEMENTED_FPOP
310           };
311           return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
312         }
313       if (frv_is_media_insn (insn))
314         {
315           frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP,
316                                           0);
317           return NULL; /* no interrupt queued at this time.  */
318         }
319       break;
320     }
321
322   return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
323 }
324
325 /* Queue the given fp_exception interrupt. Also update fp_info by removing
326    masked interrupts and updating the 'slot' flield.  */
327 struct frv_interrupt_queue_element *
328 frv_queue_fp_exception_interrupt (
329   SIM_CPU *current_cpu, struct frv_fp_exception_info *fp_info
330 )
331 {
332   SI fsr0 = GET_FSR (0);
333   int tem = GET_FSR_TEM (fsr0);
334   int aexc = GET_FSR_AEXC (fsr0);
335   struct frv_interrupt_queue_element *new_element = NULL;
336
337   /* Update AEXC with the interrupts that are masked.  */
338   aexc |= fp_info->fsr_mask & ~tem;
339   SET_FSR_AEXC (fsr0, aexc);
340   SET_FSR (0, fsr0);
341
342   /* update fsr_mask with the exceptions that are enabled.  */
343   fp_info->fsr_mask &= tem;
344
345   /* If there is an unmasked interrupt then queue it, unless
346      this was a non-excepting insn, in which case simply set the NE
347      status registers.  */
348   if (frv_interrupt_state.ne_index != NE_NOFLAG
349       && fp_info->fsr_mask != FSR_NO_EXCEPTION)
350     {
351       SET_NE_FLAG (frv_interrupt_state.f_ne_flags, 
352                    frv_interrupt_state.ne_index);
353       /* TODO -- Set NESR for chips which support it.  */
354       new_element = NULL;
355     }
356   else if (fp_info->fsr_mask != FSR_NO_EXCEPTION
357            || fp_info->ftt == FTT_UNIMPLEMENTED_FPOP
358            || fp_info->ftt == FTT_SEQUENCE_ERROR
359            || fp_info->ftt == FTT_INVALID_FR)
360     {
361       new_element = frv_queue_program_interrupt (current_cpu, FRV_FP_EXCEPTION);
362       new_element->u.fp_info = *fp_info;
363     }
364
365   return new_element;
366 }
367
368 struct frv_interrupt_queue_element *
369 frv_queue_division_exception_interrupt (SIM_CPU *current_cpu, enum frv_dtt dtt)
370 {
371   struct frv_interrupt_queue_element *new_element =
372     frv_queue_program_interrupt (current_cpu, FRV_DIVISION_EXCEPTION);
373
374   new_element->u.dtt = dtt;
375
376   return new_element;
377 }
378
379 /* Check for interrupts caused by illegal insn access.  These conditions are
380    checked in the order specified by the fr400 and fr500 LSI specs.  */
381 void
382 frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc)
383 {
384
385   const CGEN_INSN *insn = sc->argbuf.idesc->idata;
386   SIM_DESC sd = CPU_STATE (current_cpu);
387   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
388
389   /* Check for vliw constraints.  */
390   if (vliw->constraint_violation)
391     frv_queue_illegal_instruction_interrupt (current_cpu, insn);
392   /* Check for non-excepting insns.  */
393   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING)
394       && ! GET_H_PSR_NEM ())
395     frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
396   /* Check for conditional insns.  */
397   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL)
398       && ! GET_H_PSR_CM ())
399     frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
400   /* Make sure floating point support is enabled.  */
401   else if (! GET_H_PSR_EF ())
402     {
403       /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
404          off and the insns accesses a fp register.  */
405       if (frv_is_float_insn (insn)
406           || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)
407               && ! GET_H_PSR_EM ()))
408         frv_queue_float_disabled_interrupt (current_cpu);
409     }
410   /* Make sure media support is enabled.  */
411   else if (! GET_H_PSR_EM ())
412     {
413       /* Generate mp_disabled if it is a media insn.  */
414       if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP)
415         frv_queue_media_disabled_interrupt (current_cpu);
416     }
417   /* Check for privileged insns.  */
418   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) &&
419            ! GET_H_PSR_S ())
420     frv_queue_privileged_instruction_interrupt (current_cpu, insn);
421 #if 0 /* disable for now until we find out how FSR0.QNE gets reset.  */
422   else
423     {
424       /* Enter the halt state if FSR0.QNE is set and we are executing a
425          floating point insn, a media insn or an insn which access a FR
426          register.  */
427       SI fsr0 = GET_FSR (0);
428       if (GET_FSR_QNE (fsr0)
429           && (frv_is_float_insn (insn) || frv_is_media_insn (insn)
430               || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)))
431         {
432           sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped,
433                            SIM_SIGINT);
434         }
435     }
436 #endif
437 }
438
439 /* Record the current VLIW slot in the given interrupt queue element.  */
440 void
441 frv_set_interrupt_queue_slot (
442   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
443 )
444 {
445   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
446   int slot = vliw->next_slot - 1;
447   item->slot = (*vliw->current_vliw)[slot];
448 }
449
450 /* Handle an individual interrupt.  */
451 static void
452 handle_interrupt (SIM_CPU *current_cpu, IADDR pc)
453 {
454   struct frv_interrupt *interrupt;
455   int writeback_done = 0;
456   while (1)
457     {
458       /* Interrupts are queued in priority order with the highest priority
459          last.  */
460       int index = frv_interrupt_state.queue_index - 1;
461       struct frv_interrupt_queue_element *item
462         = & frv_interrupt_state.queue[index];
463       interrupt = & frv_interrupt_table[item->kind];
464
465       switch (interrupt->iclass)
466         {
467         case FRV_EXTERNAL_INTERRUPT:
468           /* Perform writeback first. This may cause a higher priority
469              interrupt.  */
470           if (! writeback_done)
471             {
472               frvbf_perform_writeback (current_cpu);
473               writeback_done = 1;
474               continue;
475             }
476           frv_external_interrupt (current_cpu, item, pc);
477           return;
478         case FRV_SOFTWARE_INTERRUPT:
479           frv_interrupt_state.queue_index = index;
480           frv_software_interrupt (current_cpu, item, pc);
481           return;
482         case FRV_PROGRAM_INTERRUPT:
483           /* If the program interrupt is not strict (imprecise), then perform
484              writeback first. This may, in turn, cause a higher priority
485              interrupt.  */
486           if (! interrupt->precise && ! writeback_done)
487             {
488               frv_interrupt_state.imprecise_interrupt = item;
489               frvbf_perform_writeback (current_cpu);
490               writeback_done = 1;
491               continue;
492             }
493           frv_interrupt_state.queue_index = index;
494           frv_program_interrupt (current_cpu, item, pc);
495           return;
496         case FRV_BREAK_INTERRUPT:
497           frv_interrupt_state.queue_index = index;
498           frv_break_interrupt (current_cpu, interrupt, pc);
499           return;
500         case FRV_RESET_INTERRUPT:
501           break;
502         default:
503           break;
504         }
505       frv_interrupt_state.queue_index = index;
506       break; /* out of loop.  */
507     }
508
509   /* We should never get here.  */
510   {
511     SIM_DESC sd = CPU_STATE (current_cpu);
512     sim_engine_abort (sd, current_cpu, pc,
513                       "interrupt class not supported %d\n",
514                       interrupt->iclass);
515   }
516 }
517
518 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set.  If so, handle
519    the appropriate reset interrupt.  */
520 static int
521 check_reset (SIM_CPU *current_cpu, IADDR pc)
522 {
523   int hsr0;
524   int hr;
525   int sr;
526   SI rstr;
527   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
528   IADDR address = RSTR_ADDRESS;
529
530   /* We don't want this to show up in the cache statistics, so read the
531      cache passively.  */
532   if (! frv_cache_read_passive_SI (cache, address, & rstr))
533     rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address);
534
535   hr = GET_RSTR_HR (rstr);
536   sr = GET_RSTR_SR (rstr);
537
538   if (! hr && ! sr)
539     return 0; /* no reset.  */
540
541   /* Reinitialize the machine state.  */
542   if (hr)
543     frv_hardware_reset (current_cpu);
544   else
545     frv_software_reset (current_cpu);
546
547   /* Branch to the reset address.  */
548   hsr0 = GET_HSR0 ();
549   if (GET_HSR0_SA (hsr0))
550     SET_H_PC (0xff000000);
551   else
552     SET_H_PC (0);
553
554   return 1; /* reset */
555 }
556
557 /* Process any pending interrupt(s) after a group of parallel insns.  */
558 void
559 frv_process_interrupts (SIM_CPU *current_cpu)
560 {
561   SI NE_flags[2];
562   /* Need to save the pc here because writeback may change it (due to a
563      branch).  */
564   IADDR pc = CPU_PC_GET (current_cpu);
565
566   /* Check for a reset before anything else.  */
567   if (check_reset (current_cpu, pc))
568     return;
569
570   /* First queue the writes for any accumulated NE flags.  */
571   if (frv_interrupt_state.f_ne_flags[0] != 0
572       || frv_interrupt_state.f_ne_flags[1] != 0)
573     {
574       GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
575       NE_flags[0] |= frv_interrupt_state.f_ne_flags[0];
576       NE_flags[1] |= frv_interrupt_state.f_ne_flags[1];
577       SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
578     }
579
580   /* If there is no interrupt pending, then perform parallel writeback.  This
581      may cause an interrupt.  */
582   if (frv_interrupt_state.queue_index <= 0)
583     frvbf_perform_writeback (current_cpu);
584
585   /* If there is an interrupt pending, then process it.  */
586   if (frv_interrupt_state.queue_index > 0)
587     handle_interrupt (current_cpu, pc);
588 }
589
590 /* Find the next available ESR and return its index */
591 static int
592 esr_for_data_access_exception (
593   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
594 )
595 {
596   SIM_DESC sd = CPU_STATE (current_cpu);
597   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
598     return 8; /* Use ESR8, EPCR8.  */
599
600   if (item->slot == UNIT_I0)
601     return 8; /* Use ESR8, EPCR8, EAR8, EDR8.  */
602
603   return 9; /* Use ESR9, EPCR9, EAR9.  */
604 }
605
606 /* Set the next available EDR register with the data which was to be stored
607    and return the index of the register.  */
608 static int
609 set_edr_register (
610   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index
611 )
612 {
613   /* EDR0, EDR4 and EDR8 are available as blocks of 4.
614        SI data uses EDR3, EDR7 and EDR11
615        DI data uses EDR2, EDR6 and EDR10
616        XI data uses EDR0, EDR4 and EDR8.  */
617   int i;
618   edr_index += 4 - item->u.data_written.length;
619   for (i = 0; i < item->u.data_written.length; ++i)
620     SET_EDR (edr_index + i, item->u.data_written.words[i]);
621
622   return edr_index;
623 };
624
625 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx.  */
626 static void
627 clear_exception_status_registers (SIM_CPU *current_cpu)
628 {
629   int i;
630   /* It is only necessary to clear the flag bits indicating which registers
631      are valid.  */
632   SET_ESFR (0, 0);
633   SET_ESFR (1, 0);
634
635   for (i = 0; i <= 2; ++i)
636     {
637       SI esr = GET_ESR (i);
638       CLEAR_ESR_VALID (esr);
639       SET_ESR (i, esr);
640     }
641   for (i = 8; i <= 15; ++i)
642     {
643       SI esr = GET_ESR (i);
644       CLEAR_ESR_VALID (esr);
645       SET_ESR (i, esr);
646     }
647 }
648
649 /* Record state for media exception.  */
650 void
651 frv_set_mp_exception_registers (
652   SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie
653 )
654 {
655   /* Record the interrupt factor in MSR0.  */
656   SI msr0 = GET_MSR (0);
657   if (GET_MSR_MTT (msr0) == MTT_NONE)
658     SET_MSR_MTT (msr0, mtt);
659
660   /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF.  */
661   if (mtt == MTT_OVERFLOW)
662     {
663       FRV_VLIW *vliw = CPU_VLIW (current_cpu);
664       int slot = vliw->next_slot - 1;
665       SIM_DESC sd = CPU_STATE (current_cpu);
666
667       /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE,
668          otherwise set MSR0.OVF and MSR0.SIE.  */
669       if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550 && (*vliw->current_vliw)[slot] == UNIT_FM1)
670         {
671           SI msr = GET_MSR (1);
672           OR_MSR_SIE (msr, sie);
673           SET_MSR_OVF (msr);
674           SET_MSR (1, msr);
675         }
676       else
677         {
678           OR_MSR_SIE (msr0, sie);
679           SET_MSR_OVF (msr0);
680         }
681
682       /* Generate the interrupt now if MSR0.MPEM is set on fr550 */
683       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550 && GET_MSR_MPEM (msr0))
684         frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION);
685       else
686         {
687           /* Regardless of the slot, set MSR0.AOVF.  */
688           SET_MSR_AOVF (msr0);
689         }
690     }
691
692   SET_MSR (0, msr0);
693 }
694
695 /* Determine the correct FQ register to use for the given exception.
696    Return -1 if a register is not available.  */
697 static int
698 fq_for_exception (
699   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
700 )
701 {
702   SI fq;
703   struct frv_fp_exception_info *fp_info = & item->u.fp_info;
704
705   /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1.  */
706   if (fp_info->ftt == FTT_IEEE_754_EXCEPTION
707       && (fp_info->fsr_mask & (FSR_OVERFLOW | FSR_UNDERFLOW | FSR_INEXACT)))
708     {
709       fq = GET_FQ (0);
710       if (! GET_FQ_VALID (fq))
711         return 0; /* FQ0 is available.  */
712       fq = GET_FQ (1);
713       if (! GET_FQ_VALID (fq))
714         return 1; /* FQ1 is available.  */
715
716       /* No FQ register is available */
717       {
718         SIM_DESC sd = CPU_STATE (current_cpu);
719         IADDR pc = CPU_PC_GET (current_cpu);
720         sim_engine_abort (sd, current_cpu, pc, "No FQ register available\n");
721       }
722       return -1;
723     }
724   /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
725      otherwise.  */
726   if (item->slot == UNIT_FM0 || item->slot == UNIT_I0)
727     return 2;
728
729   return 3;
730 }
731
732 /* Set FSR0, FQ0-FQ9, depending on the interrupt.  */
733 static void
734 set_fp_exception_registers (
735   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
736 )
737 {
738   int fq_index;
739   SI fq;
740   SI insn;
741   SI fsr0;
742   IADDR pc;
743   struct frv_fp_exception_info *fp_info;
744   SIM_DESC sd = CPU_STATE (current_cpu);
745
746   /* No FQ registers on fr550 */
747   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
748     {
749       /* Update the fsr.  */
750       fp_info = & item->u.fp_info;
751       fsr0 = GET_FSR (0);
752       SET_FSR_FTT (fsr0, fp_info->ftt);
753       SET_FSR (0, fsr0);
754       return;
755     }
756
757   /* Select an FQ and update it with the exception information.  */
758   fq_index = fq_for_exception (current_cpu, item);
759   if (fq_index == -1)
760     return;
761
762   fp_info = & item->u.fp_info;
763   fq = GET_FQ (fq_index);
764   SET_FQ_MIV (fq, MIV_FLOAT);
765   SET_FQ_SIE (fq, SIE_NIL);
766   SET_FQ_FTT (fq, fp_info->ftt);
767   SET_FQ_CEXC (fq, fp_info->fsr_mask);
768   SET_FQ_VALID (fq);
769   SET_FQ (fq_index, fq);
770
771   /* Write the failing insn into FQx.OPC.  */
772   pc = item->vpc;
773   insn = GETMEMSI (current_cpu, pc, pc);
774   SET_FQ_OPC (fq_index, insn);
775
776   /* Update the fsr.  */
777   fsr0 = GET_FSR (0);
778   SET_FSR_QNE (fsr0); /* FQ not empty */
779   SET_FSR_FTT (fsr0, fp_info->ftt);
780   SET_FSR (0, fsr0);
781 }
782
783 /* Record the state of a division exception in the ISR.  */
784 static void
785 set_isr_exception_fields (
786   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
787 )
788 {
789   USI isr = GET_ISR ();
790   int dtt = GET_ISR_DTT (isr);
791   dtt |= item->u.dtt;
792   SET_ISR_DTT (isr, dtt);
793   SET_ISR (isr);
794 }
795
796 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
797    interrupt.  */
798 static void
799 set_exception_status_registers (
800   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
801 )
802 {
803   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
804   int slot = (item->vpc - previous_vliw_pc) / 4;
805   int reg_index = -1;
806   int set_ear = 0;
807   int set_edr = 0;
808   int set_daec = 0;
809   int set_epcr = 0;
810   SI esr = 0;
811   SIM_DESC sd = CPU_STATE (current_cpu);
812
813   /* If the interrupt is strict (precise) or the interrupt is on the insns
814      in the I0 pipe, then set the 0 registers.  */
815   if (interrupt->precise)
816     {
817       reg_index = 0;
818       if (interrupt->kind == FRV_REGISTER_EXCEPTION)
819         SET_ESR_REC (esr, item->u.rec);
820       else if (interrupt->kind == FRV_INSTRUCTION_ACCESS_EXCEPTION)
821         SET_ESR_IAEC (esr, item->u.iaec);
822       /* For fr550, don't set epcr for precise interrupts.  */
823       if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
824         set_epcr = 1;
825     }
826   else
827     {
828       switch (interrupt->kind)
829         {
830         case FRV_DIVISION_EXCEPTION:
831           set_isr_exception_fields (current_cpu, item);
832           /* fall thru to set reg_index.  */
833         case FRV_COMMIT_EXCEPTION:
834           /* For fr550, always use ESR0.  */
835           if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
836             reg_index = 0;
837           else if (item->slot == UNIT_I0)
838             reg_index = 0;
839           else if (item->slot == UNIT_I1)
840             reg_index = 1;
841           set_epcr = 1;
842           break;
843         case FRV_DATA_STORE_ERROR:
844           reg_index = 14; /* Use ESR14.  */
845           break;
846         case FRV_DATA_ACCESS_ERROR:
847           reg_index = 15; /* Use ESR15, EPCR15.  */
848           if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr400)
849             set_ear = 1;
850           break;
851         case FRV_DATA_ACCESS_EXCEPTION:
852           set_daec = 1;
853           /* fall through */
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.  */
858           set_ear = 1;
859           /* For fr550, never use EDRx.  */
860           if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
861             if (item->u.data_written.length != 0)
862               set_edr = 1;
863           reg_index = esr_for_data_access_exception (current_cpu, item);
864           set_epcr = 1;
865           break;
866         case FRV_MP_EXCEPTION:
867           /* For fr550, use EPCR2 and ESR2.  */
868           if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
869             {
870               reg_index = 2;
871               set_epcr = 1;
872             }
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)
878             {
879               reg_index = 2;
880               set_epcr = 1;
881             }
882           break;
883         default:
884           {
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",
889                               interrupt->kind);
890             break;
891           }
892         }
893     } /* non-strict (imprecise) interrupt */
894
895   /* Now fill in the selected exception status registers.  */
896   if (reg_index != -1)
897     {
898       /* Now set the exception status registers.  */
899       SET_ESFR_FLAG (reg_index);
900       SET_ESR_EC (esr, interrupt->ec);
901
902       if (set_epcr)
903         {
904           if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
905             SET_EPCR (reg_index, previous_vliw_pc);
906           else
907             SET_EPCR (reg_index, item->vpc);
908         }
909
910       if (set_ear)
911         {
912           SET_EAR (reg_index, item->eaddress);
913           SET_ESR_EAV (esr);
914         }
915       else
916         CLEAR_ESR_EAV (esr);
917
918       if (set_edr)
919         {
920           int edn = set_edr_register (current_cpu, item, 0/* EDR0-3 */);
921           SET_ESR_EDN (esr, edn);
922           SET_ESR_EDV (esr);
923         }
924       else
925         CLEAR_ESR_EDV (esr);
926
927       if (set_daec)
928         SET_ESR_DAEC (esr, item->u.daec);
929
930       SET_ESR_VALID (esr);
931       SET_ESR (reg_index, esr);
932     }
933 }
934
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
940 )
941 {
942   struct frv_interrupt *interrupt;
943
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];
947
948   if (! interrupt->precise)
949     {
950       IADDR vpc = 0;
951       int mask = 0;
952
953       vpc = item->vpc;
954       mask = (1 << item->kind);
955
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)
961         {
962           enum frv_interrupt_kind kind;
963           struct frv_interrupt *next_interrupt;
964           --item;
965           kind = item->kind;
966           next_interrupt = & frv_interrupt_table[kind];
967
968           if (next_interrupt->iclass != FRV_PROGRAM_INTERRUPT)
969             break; /* no program interrupts left.  */
970
971           if (item->vpc == vpc)
972             continue; /* caused by the same insn.  */
973
974           vpc = item->vpc;
975           if (! next_interrupt->precise && ! next_interrupt->deferred)
976             {
977               if (! (mask & (1 << kind)))
978                 {
979                   /* Set the exception status registers for the additional
980                      interrupt.  */
981                   set_exception_status_registers (current_cpu, item);
982                   mask |= (1 << kind);
983                   interrupt = & frv_interrupt_table[FRV_COMPOUND_EXCEPTION];
984                 }
985             }
986         }
987     }
988
989   /* Return with either the original interrupt, a compound_exception,
990      or no exception.  */
991   return interrupt;
992 }
993
994 /* Handle a program interrupt.  */
995 void
996 frv_program_interrupt (
997   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
998 )
999 {
1000   struct frv_interrupt *interrupt;
1001
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)
1007     {
1008       frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1009       frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT,
1010                                    FRV_PROGRAM_INTERRUPT);
1011     }
1012 }
1013
1014 /* Handle a software interrupt.  */
1015 void
1016 frv_software_interrupt (
1017   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1018 )
1019 {
1020   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1021   frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1022 }
1023
1024 /* Handle a program interrupt or a software interrupt in non-operating mode.  */
1025 void
1026 frv_non_operating_interrupt (
1027   SIM_CPU *current_cpu, enum frv_interrupt_kind kind, IADDR pc
1028 )
1029 {
1030   SIM_DESC sd = CPU_STATE (current_cpu);
1031   switch (kind)
1032     {
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);
1050       break;
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");
1056       break;
1057     case FRV_DIVISION_EXCEPTION:
1058       sim_engine_abort (sd, current_cpu, pc,
1059                         "interrupt: division_exception\n");
1060       break;
1061     case FRV_DATA_STORE_ERROR:
1062       sim_engine_abort (sd, current_cpu, pc,
1063                         "interrupt: data_store_error\n");
1064       break;
1065     case FRV_DATA_ACCESS_EXCEPTION:
1066       sim_engine_abort (sd, current_cpu, pc,
1067                         "interrupt: data_access_exception\n");
1068       break;
1069     case FRV_DATA_ACCESS_MMU_MISS:
1070       sim_engine_abort (sd, current_cpu, pc,
1071                         "interrupt: data_access_mmu_miss\n");
1072       break;
1073     case FRV_DATA_ACCESS_ERROR:
1074       sim_engine_abort (sd, current_cpu, pc,
1075                         "interrupt: data_access_error\n");
1076       break;
1077     case FRV_MP_EXCEPTION:
1078       sim_engine_abort (sd, current_cpu, pc,
1079                         "interrupt: mp_exception\n");
1080       break;
1081     case FRV_FP_EXCEPTION:
1082       sim_engine_abort (sd, current_cpu, pc,
1083                         "interrupt: fp_exception\n");
1084       break;
1085     case FRV_MEM_ADDRESS_NOT_ALIGNED:
1086       sim_engine_abort (sd, current_cpu, pc,
1087                         "interrupt: mem_address_not_aligned\n");
1088       break;
1089     case FRV_REGISTER_EXCEPTION:
1090       sim_engine_abort (sd, current_cpu, pc,
1091                         "interrupt: register_exception\n");
1092       break;
1093     case FRV_MP_DISABLED:
1094       sim_engine_abort (sd, current_cpu, pc,
1095                         "interrupt: mp_disabled\n");
1096       break;
1097     case FRV_FP_DISABLED:
1098       sim_engine_abort (sd, current_cpu, pc,
1099                         "interrupt: fp_disabled\n");
1100       break;
1101     case FRV_PRIVILEGED_INSTRUCTION:
1102       sim_engine_abort (sd, current_cpu, pc,
1103                         "interrupt: privileged_instruction\n");
1104       break;
1105     case FRV_ILLEGAL_INSTRUCTION:
1106       sim_engine_abort (sd, current_cpu, pc,
1107                         "interrupt: illegal_instruction\n");
1108       break;
1109     case FRV_INSTRUCTION_ACCESS_EXCEPTION:
1110       sim_engine_abort (sd, current_cpu, pc,
1111                         "interrupt: instruction_access_exception\n");
1112       break;
1113     case FRV_INSTRUCTION_ACCESS_MMU_MISS:
1114       sim_engine_abort (sd, current_cpu, pc,
1115                         "interrupt: instruction_access_mmu_miss\n");
1116       break;
1117     case FRV_INSTRUCTION_ACCESS_ERROR:
1118       sim_engine_abort (sd, current_cpu, pc,
1119                         "interrupt: insn_access_error\n");
1120       break;
1121     case FRV_COMPOUND_EXCEPTION:
1122       sim_engine_abort (sd, current_cpu, pc,
1123                         "interrupt: compound_exception\n");
1124       break;
1125     case FRV_BREAK_EXCEPTION:
1126       sim_engine_abort (sd, current_cpu, pc,
1127                         "interrupt: break_exception\n");
1128       break;
1129     case FRV_RESET:
1130       sim_engine_abort (sd, current_cpu, pc,
1131                         "interrupt: reset\n");
1132       break;
1133     default:
1134       sim_engine_abort (sd, current_cpu, pc,
1135                         "unhandled interrupt kind: %d\n", kind);
1136       break;
1137     }
1138 }
1139
1140 /* Handle a break interrupt.  */
1141 void
1142 frv_break_interrupt (
1143   SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1144 )
1145 {
1146   IADDR new_pc;
1147
1148   /* BPCSR=PC
1149      BPSR.BS=PSR.S
1150      BPSR.BET=PSR.ET
1151      PSR.S=1
1152      PSR.ET=0
1153      TBR.TT=0xff
1154      PC=TBR
1155   */
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 ());
1159   SET_H_PSR_S (1);
1160   SET_H_PSR_ET (0);
1161   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1162   SET_H_SPR (H_SPR_BPCSR, current_pc);
1163
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);
1167   SET_H_PC (new_pc);
1168
1169   CPU_DEBUG_STATE (current_cpu) = 1;
1170 }
1171
1172 /* Handle a program interrupt or a software interrupt.  */
1173 void
1174 frv_program_or_software_interrupt (
1175   SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1176 )
1177 {
1178   USI new_pc;
1179   int original_psr_et;
1180
1181   /* PCSR=PC
1182      PSR.PS=PSR.S
1183      PSR.ET=0
1184      PSR.S=1
1185      if PSR.ESR==1
1186        SR0 through SR3=GR4 through GR7
1187        TBR.TT=interrupt handler offset
1188        PC=TBR
1189   */
1190   original_psr_et = GET_H_PSR_ET ();
1191
1192   SET_H_PSR_PS (GET_H_PSR_S ());
1193   SET_H_PSR_ET (0);
1194   SET_H_PSR_S (1);
1195
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);
1200   else
1201     SET_H_SPR (H_SPR_PCSR, current_pc);
1202
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);
1206   SET_H_PC (new_pc);
1207
1208   /* If PSR.ET was not originally set, then enter the stopped state.  */
1209   if (! original_psr_et)
1210     {
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);
1214     }
1215 }
1216
1217 /* Handle a program interrupt or a software interrupt.  */
1218 void
1219 frv_external_interrupt (
1220   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1221 )
1222 {
1223   USI new_pc;
1224   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1225
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.  */
1232
1233   /* Remove the interrupt from the queue.  */
1234   --frv_interrupt_state.queue_index;
1235
1236   /* PCSR=PC
1237      PSR.PS=PSR.S
1238      PSR.ET=0
1239      PSR.S=1
1240      if PSR.ESR==1
1241        SR0 through SR3=GR4 through GR7
1242        TBR.TT=interrupt handler offset
1243        PC=TBR
1244   */
1245   SET_H_PSR_PS (GET_H_PSR_S ());
1246   SET_H_PSR_ET (0);
1247   SET_H_PSR_S (1);
1248   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1249   SET_H_SPR (H_SPR_PCSR, GET_H_PC ());
1250
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);
1254   SET_H_PC (new_pc);
1255 }
1256
1257 /* Clear interrupts which fall within the range of classes given.  */
1258 void
1259 frv_clear_interrupt_classes (
1260   enum frv_interrupt_class low_class, enum frv_interrupt_class high_class
1261 )
1262 {
1263   int i;
1264   int j;
1265   int limit = frv_interrupt_state.queue_index;
1266
1267   /* Find the lowest priority interrupt to be removed.  */
1268   for (i = 0; i < limit; ++i)
1269     {
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)
1273         break;
1274     }
1275
1276   /* Find the highest priority interrupt to be removed.  */
1277   for (j = limit - 1; j >= i; --j)
1278     {
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)
1282         break;
1283     }
1284
1285   /* Shuffle the remaining high priority interrupts down into the empty space
1286      left by the deleted interrupts.  */
1287   if (j >= i)
1288     {
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);
1292     }
1293 }
1294
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
1297    interrupt.  */
1298 void
1299 frv_save_data_written_for_interrupts (
1300   SIM_CPU *current_cpu, CGEN_WRITE_QUEUE_ELEMENT *item
1301 )
1302 {
1303   /* Record the slot containing the insn doing the write in the
1304      interrupt state.  */
1305   frv_interrupt_state.slot = CGEN_WRITE_QUEUE_ELEMENT_PIPE (item);
1306
1307   /* Now record any data written to memory in the interrupt state.  */
1308   switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item))
1309     {
1310     case CGEN_BI_WRITE:
1311     case CGEN_QI_WRITE:
1312     case CGEN_SI_WRITE:
1313     case CGEN_SF_WRITE:
1314     case CGEN_PC_WRITE:
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;
1327       break;
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;
1332       break;
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;
1337       break;
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;
1344       break;
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;
1351       break;
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];
1362       break;
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;
1367       break;
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;
1372       break;
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;
1377       break;
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;
1384       break;
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;
1391       break;
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];
1402       break;
1403     default:
1404       {
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");
1409       }
1410       break;
1411     }
1412 }