xref: /netbsd-src/external/gpl3/gdb/dist/sim/frv/interrupts.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /* frv exception and interrupt support
2    Copyright (C) 1999-2014 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 3 of the License, or
10 (at your option) 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
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #define WANT_CPU frvbf
21 #define WANT_CPU_FRVBF
22 
23 #include "sim-main.h"
24 #include "bfd.h"
25 
26 /* FR-V Interrupt table.
27    Describes the interrupts supported by the FR-V.
28    This table *must* be maintained in order of interrupt priority as defined by
29    frv_interrupt_kind.  */
30 #define DEFERRED 1
31 #define PRECISE  1
32 #define ITABLE_ENTRY(name, class, deferral, precision, offset) \
33   {FRV_##name, FRV_EC_##name, class, deferral, precision, offset}
34 
35 struct frv_interrupt frv_interrupt_table[NUM_FRV_INTERRUPT_KINDS] =
36 {
37   /* External interrupts */
38   ITABLE_ENTRY(INTERRUPT_LEVEL_1,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x21),
39   ITABLE_ENTRY(INTERRUPT_LEVEL_2,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x22),
40   ITABLE_ENTRY(INTERRUPT_LEVEL_3,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x23),
41   ITABLE_ENTRY(INTERRUPT_LEVEL_4,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x24),
42   ITABLE_ENTRY(INTERRUPT_LEVEL_5,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x25),
43   ITABLE_ENTRY(INTERRUPT_LEVEL_6,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x26),
44   ITABLE_ENTRY(INTERRUPT_LEVEL_7,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x27),
45   ITABLE_ENTRY(INTERRUPT_LEVEL_8,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x28),
46   ITABLE_ENTRY(INTERRUPT_LEVEL_9,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x29),
47   ITABLE_ENTRY(INTERRUPT_LEVEL_10,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2a),
48   ITABLE_ENTRY(INTERRUPT_LEVEL_11,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2b),
49   ITABLE_ENTRY(INTERRUPT_LEVEL_12,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2c),
50   ITABLE_ENTRY(INTERRUPT_LEVEL_13,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2d),
51   ITABLE_ENTRY(INTERRUPT_LEVEL_14,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2e),
52   ITABLE_ENTRY(INTERRUPT_LEVEL_15,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2f),
53   /* Software interrupt */
54   ITABLE_ENTRY(TRAP_INSTRUCTION,             FRV_SOFTWARE_INTERRUPT, !DEFERRED, !PRECISE, 0x80),
55   /* Program interrupts */
56   ITABLE_ENTRY(COMMIT_EXCEPTION,             FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x19),
57   ITABLE_ENTRY(DIVISION_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x17),
58   ITABLE_ENTRY(DATA_STORE_ERROR,             FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x14),
59   ITABLE_ENTRY(DATA_ACCESS_EXCEPTION,        FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x13),
60   ITABLE_ENTRY(DATA_ACCESS_MMU_MISS,         FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x12),
61   ITABLE_ENTRY(DATA_ACCESS_ERROR,            FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x11),
62   ITABLE_ENTRY(MP_EXCEPTION,                 FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x0e),
63   ITABLE_ENTRY(FP_EXCEPTION,                 FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x0d),
64   ITABLE_ENTRY(MEM_ADDRESS_NOT_ALIGNED,      FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x10),
65   ITABLE_ENTRY(REGISTER_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x08),
66   ITABLE_ENTRY(MP_DISABLED,                  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x0b),
67   ITABLE_ENTRY(FP_DISABLED,                  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x0a),
68   ITABLE_ENTRY(PRIVILEGED_INSTRUCTION,       FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x06),
69   ITABLE_ENTRY(ILLEGAL_INSTRUCTION,          FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x07),
70   ITABLE_ENTRY(INSTRUCTION_ACCESS_EXCEPTION, FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x03),
71   ITABLE_ENTRY(INSTRUCTION_ACCESS_ERROR,     FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x02),
72   ITABLE_ENTRY(INSTRUCTION_ACCESS_MMU_MISS,  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x01),
73   ITABLE_ENTRY(COMPOUND_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x20),
74   /* Break interrupt */
75   ITABLE_ENTRY(BREAK_EXCEPTION,              FRV_BREAK_INTERRUPT,    !DEFERRED, !PRECISE, 0xff),
76   /* Reset interrupt */
77   ITABLE_ENTRY(RESET,                        FRV_RESET_INTERRUPT,    !DEFERRED, !PRECISE, 0x00)
78 };
79 
80 /* The current interrupt state.  */
81 struct frv_interrupt_state frv_interrupt_state;
82 
83 /* maintain the address of the start of the previous VLIW insn sequence.  */
84 IADDR previous_vliw_pc;
85 
86 /* Add a break interrupt to the interrupt queue.  */
87 struct frv_interrupt_queue_element *
88 frv_queue_break_interrupt (SIM_CPU *current_cpu)
89 {
90   return frv_queue_interrupt (current_cpu, FRV_BREAK_EXCEPTION);
91 }
92 
93 /* Add a software interrupt to the interrupt queue.  */
94 struct frv_interrupt_queue_element *
95 frv_queue_software_interrupt (SIM_CPU *current_cpu, SI offset)
96 {
97   struct frv_interrupt_queue_element *new_element
98     = frv_queue_interrupt (current_cpu, FRV_TRAP_INSTRUCTION);
99 
100   struct frv_interrupt *interrupt = & frv_interrupt_table[new_element->kind];
101   interrupt->handler_offset = offset;
102 
103   return new_element;
104 }
105 
106 /* Add a program interrupt to the interrupt queue.  */
107 struct frv_interrupt_queue_element *
108 frv_queue_program_interrupt (
109   SIM_CPU *current_cpu, enum frv_interrupt_kind kind
110 )
111 {
112   return frv_queue_interrupt (current_cpu, kind);
113 }
114 
115 /* Add an external interrupt to the interrupt queue.  */
116 struct frv_interrupt_queue_element *
117 frv_queue_external_interrupt (
118   SIM_CPU *current_cpu, enum frv_interrupt_kind kind
119 )
120 {
121   if (! GET_H_PSR_ET ()
122       || (kind != FRV_INTERRUPT_LEVEL_15 && kind < GET_H_PSR_PIL ()))
123     return NULL; /* Leave it for later.  */
124 
125   return frv_queue_interrupt (current_cpu, kind);
126 }
127 
128 /* Add any interrupt to the interrupt queue. It will be added in reverse
129    priority order.  This makes it easy to find the highest priority interrupt
130    at the end of the queue and to remove it after processing.  */
131 struct frv_interrupt_queue_element *
132 frv_queue_interrupt (SIM_CPU *current_cpu, enum frv_interrupt_kind kind)
133 {
134   int i;
135   int j;
136   int limit = frv_interrupt_state.queue_index;
137   struct frv_interrupt_queue_element *new_element;
138   enum frv_interrupt_class iclass;
139 
140   if (limit >= FRV_INTERRUPT_QUEUE_SIZE)
141     abort (); /* TODO: Make the queue dynamic */
142 
143   /* Find the right place in the queue.  */
144   for (i = 0; i < limit; ++i)
145     {
146       if (frv_interrupt_state.queue[i].kind >= kind)
147 	break;
148     }
149 
150   /* Don't queue two external interrupts of the same priority.  */
151   iclass = frv_interrupt_table[kind].iclass;
152   if (i < limit && iclass == FRV_EXTERNAL_INTERRUPT)
153     {
154       if (frv_interrupt_state.queue[i].kind == kind)
155 	return & frv_interrupt_state.queue[i];
156     }
157 
158   /* Make room for the new interrupt in this spot.  */
159   for (j = limit - 1; j >= i; --j)
160     frv_interrupt_state.queue[j + 1] = frv_interrupt_state.queue[j];
161 
162   /* Add the new interrupt.  */
163   frv_interrupt_state.queue_index++;
164   new_element = & frv_interrupt_state.queue[i];
165   new_element->kind = kind;
166   new_element->vpc = CPU_PC_GET (current_cpu);
167   new_element->u.data_written.length = 0;
168   frv_set_interrupt_queue_slot (current_cpu, new_element);
169 
170   return new_element;
171 }
172 
173 struct frv_interrupt_queue_element *
174 frv_queue_register_exception_interrupt (SIM_CPU *current_cpu, enum frv_rec rec)
175 {
176   struct frv_interrupt_queue_element *new_element =
177     frv_queue_program_interrupt (current_cpu, FRV_REGISTER_EXCEPTION);
178 
179   new_element->u.rec = rec;
180 
181   return new_element;
182 }
183 
184 struct frv_interrupt_queue_element *
185 frv_queue_mem_address_not_aligned_interrupt (SIM_CPU *current_cpu, USI addr)
186 {
187   struct frv_interrupt_queue_element *new_element;
188   USI isr = GET_ISR ();
189 
190   /* Make sure that this exception is not masked.  */
191   if (GET_ISR_EMAM (isr))
192     return NULL;
193 
194   /* Queue the interrupt.  */
195   new_element = frv_queue_program_interrupt (current_cpu,
196 					     FRV_MEM_ADDRESS_NOT_ALIGNED);
197   new_element->eaddress = addr;
198   new_element->u.data_written = frv_interrupt_state.data_written;
199   frv_interrupt_state.data_written.length = 0;
200 
201   return new_element;
202 }
203 
204 struct frv_interrupt_queue_element *
205 frv_queue_data_access_error_interrupt (SIM_CPU *current_cpu, USI addr)
206 {
207   struct frv_interrupt_queue_element *new_element;
208   new_element = frv_queue_program_interrupt (current_cpu,
209 					     FRV_DATA_ACCESS_ERROR);
210   new_element->eaddress = addr;
211   return new_element;
212 }
213 
214 struct frv_interrupt_queue_element *
215 frv_queue_data_access_exception_interrupt (SIM_CPU *current_cpu)
216 {
217   return frv_queue_program_interrupt (current_cpu, FRV_DATA_ACCESS_EXCEPTION);
218 }
219 
220 struct frv_interrupt_queue_element *
221 frv_queue_instruction_access_error_interrupt (SIM_CPU *current_cpu)
222 {
223   return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_ERROR);
224 }
225 
226 struct frv_interrupt_queue_element *
227 frv_queue_instruction_access_exception_interrupt (SIM_CPU *current_cpu)
228 {
229   return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_EXCEPTION);
230 }
231 
232 struct frv_interrupt_queue_element *
233 frv_queue_illegal_instruction_interrupt (
234   SIM_CPU *current_cpu, const CGEN_INSN *insn
235 )
236 {
237   SIM_DESC sd = CPU_STATE (current_cpu);
238   switch (STATE_ARCHITECTURE (sd)->mach)
239     {
240     case bfd_mach_fr400:
241     case bfd_mach_fr450:
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_fr450:
303     case bfd_mach_fr550:
304       break;
305     default:
306       /* Some machines generate fp_exception or mp_exception for this case.  */
307       if (frv_is_float_insn (insn))
308 	{
309 	  struct frv_fp_exception_info fp_info = {
310 	    FSR_NO_EXCEPTION, FTT_UNIMPLEMENTED_FPOP
311 	  };
312 	  return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
313 	}
314       if (frv_is_media_insn (insn))
315 	{
316 	  frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP,
317 					  0);
318 	  return NULL; /* no interrupt queued at this time.  */
319 	}
320       break;
321     }
322 
323   return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
324 }
325 
326 /* Queue the given fp_exception interrupt. Also update fp_info by removing
327    masked interrupts and updating the 'slot' flield.  */
328 struct frv_interrupt_queue_element *
329 frv_queue_fp_exception_interrupt (
330   SIM_CPU *current_cpu, struct frv_fp_exception_info *fp_info
331 )
332 {
333   SI fsr0 = GET_FSR (0);
334   int tem = GET_FSR_TEM (fsr0);
335   int aexc = GET_FSR_AEXC (fsr0);
336   struct frv_interrupt_queue_element *new_element = NULL;
337 
338   /* Update AEXC with the interrupts that are masked.  */
339   aexc |= fp_info->fsr_mask & ~tem;
340   SET_FSR_AEXC (fsr0, aexc);
341   SET_FSR (0, fsr0);
342 
343   /* update fsr_mask with the exceptions that are enabled.  */
344   fp_info->fsr_mask &= tem;
345 
346   /* If there is an unmasked interrupt then queue it, unless
347      this was a non-excepting insn, in which case simply set the NE
348      status registers.  */
349   if (frv_interrupt_state.ne_index != NE_NOFLAG
350       && fp_info->fsr_mask != FSR_NO_EXCEPTION)
351     {
352       SET_NE_FLAG (frv_interrupt_state.f_ne_flags,
353 		   frv_interrupt_state.ne_index);
354       /* TODO -- Set NESR for chips which support it.  */
355       new_element = NULL;
356     }
357   else if (fp_info->fsr_mask != FSR_NO_EXCEPTION
358 	   || fp_info->ftt == FTT_UNIMPLEMENTED_FPOP
359 	   || fp_info->ftt == FTT_SEQUENCE_ERROR
360 	   || fp_info->ftt == FTT_INVALID_FR)
361     {
362       new_element = frv_queue_program_interrupt (current_cpu, FRV_FP_EXCEPTION);
363       new_element->u.fp_info = *fp_info;
364     }
365 
366   return new_element;
367 }
368 
369 struct frv_interrupt_queue_element *
370 frv_queue_division_exception_interrupt (SIM_CPU *current_cpu, enum frv_dtt dtt)
371 {
372   struct frv_interrupt_queue_element *new_element =
373     frv_queue_program_interrupt (current_cpu, FRV_DIVISION_EXCEPTION);
374 
375   new_element->u.dtt = dtt;
376 
377   return new_element;
378 }
379 
380 /* Check for interrupts caused by illegal insn access.  These conditions are
381    checked in the order specified by the fr400 and fr500 LSI specs.  */
382 void
383 frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc)
384 {
385 
386   const CGEN_INSN *insn = sc->argbuf.idesc->idata;
387   SIM_DESC sd = CPU_STATE (current_cpu);
388   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
389 
390   /* Check for vliw constraints.  */
391   if (vliw->constraint_violation)
392     frv_queue_illegal_instruction_interrupt (current_cpu, insn);
393   /* Check for non-excepting insns.  */
394   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING)
395       && ! GET_H_PSR_NEM ())
396     frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
397   /* Check for conditional insns.  */
398   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL)
399       && ! GET_H_PSR_CM ())
400     frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
401   /* Make sure floating point support is enabled.  */
402   else if (! GET_H_PSR_EF ())
403     {
404       /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
405 	 off and the insns accesses a fp register.  */
406       if (frv_is_float_insn (insn)
407 	  || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)
408 	      && ! GET_H_PSR_EM ()))
409 	frv_queue_float_disabled_interrupt (current_cpu);
410     }
411   /* Make sure media support is enabled.  */
412   else if (! GET_H_PSR_EM ())
413     {
414       /* Generate mp_disabled if it is a media insn.  */
415       if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP)
416 	frv_queue_media_disabled_interrupt (current_cpu);
417     }
418   /* Check for privileged insns.  */
419   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) &&
420 	   ! GET_H_PSR_S ())
421     frv_queue_privileged_instruction_interrupt (current_cpu, insn);
422 #if 0 /* disable for now until we find out how FSR0.QNE gets reset.  */
423   else
424     {
425       /* Enter the halt state if FSR0.QNE is set and we are executing a
426 	 floating point insn, a media insn or an insn which access a FR
427 	 register.  */
428       SI fsr0 = GET_FSR (0);
429       if (GET_FSR_QNE (fsr0)
430 	  && (frv_is_float_insn (insn) || frv_is_media_insn (insn)
431 	      || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)))
432 	{
433 	  sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped,
434 			   SIM_SIGINT);
435 	}
436     }
437 #endif
438 }
439 
440 /* Record the current VLIW slot in the given interrupt queue element.  */
441 void
442 frv_set_interrupt_queue_slot (
443   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
444 )
445 {
446   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
447   int slot = vliw->next_slot - 1;
448   item->slot = (*vliw->current_vliw)[slot];
449 }
450 
451 /* Handle an individual interrupt.  */
452 static void
453 handle_interrupt (SIM_CPU *current_cpu, IADDR pc)
454 {
455   struct frv_interrupt *interrupt;
456   int writeback_done = 0;
457   while (1)
458     {
459       /* Interrupts are queued in priority order with the highest priority
460 	 last.  */
461       int index = frv_interrupt_state.queue_index - 1;
462       struct frv_interrupt_queue_element *item
463 	= & frv_interrupt_state.queue[index];
464       interrupt = & frv_interrupt_table[item->kind];
465 
466       switch (interrupt->iclass)
467 	{
468 	case FRV_EXTERNAL_INTERRUPT:
469 	  /* Perform writeback first. This may cause a higher priority
470 	     interrupt.  */
471 	  if (! writeback_done)
472 	    {
473 	      frvbf_perform_writeback (current_cpu);
474 	      writeback_done = 1;
475 	      continue;
476 	    }
477 	  frv_external_interrupt (current_cpu, item, pc);
478 	  return;
479 	case FRV_SOFTWARE_INTERRUPT:
480 	  frv_interrupt_state.queue_index = index;
481 	  frv_software_interrupt (current_cpu, item, pc);
482 	  return;
483 	case FRV_PROGRAM_INTERRUPT:
484 	  /* If the program interrupt is not strict (imprecise), then perform
485 	     writeback first. This may, in turn, cause a higher priority
486 	     interrupt.  */
487 	  if (! interrupt->precise && ! writeback_done)
488 	    {
489 	      frv_interrupt_state.imprecise_interrupt = item;
490 	      frvbf_perform_writeback (current_cpu);
491 	      writeback_done = 1;
492 	      continue;
493 	    }
494 	  frv_interrupt_state.queue_index = index;
495 	  frv_program_interrupt (current_cpu, item, pc);
496 	  return;
497 	case FRV_BREAK_INTERRUPT:
498 	  frv_interrupt_state.queue_index = index;
499 	  frv_break_interrupt (current_cpu, interrupt, pc);
500 	  return;
501 	case FRV_RESET_INTERRUPT:
502 	  break;
503 	default:
504 	  break;
505 	}
506       frv_interrupt_state.queue_index = index;
507       break; /* out of loop.  */
508     }
509 
510   /* We should never get here.  */
511   {
512     SIM_DESC sd = CPU_STATE (current_cpu);
513     sim_engine_abort (sd, current_cpu, pc,
514 		      "interrupt class not supported %d\n",
515 		      interrupt->iclass);
516   }
517 }
518 
519 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set.  If so, handle
520    the appropriate reset interrupt.  */
521 static int
522 check_reset (SIM_CPU *current_cpu, IADDR pc)
523 {
524   int hsr0;
525   int hr;
526   int sr;
527   SI rstr;
528   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
529   IADDR address = RSTR_ADDRESS;
530 
531   /* We don't want this to show up in the cache statistics, so read the
532      cache passively.  */
533   if (! frv_cache_read_passive_SI (cache, address, & rstr))
534     rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address);
535 
536   hr = GET_RSTR_HR (rstr);
537   sr = GET_RSTR_SR (rstr);
538 
539   if (! hr && ! sr)
540     return 0; /* no reset.  */
541 
542   /* Reinitialize the machine state.  */
543   if (hr)
544     frv_hardware_reset (current_cpu);
545   else
546     frv_software_reset (current_cpu);
547 
548   /* Branch to the reset address.  */
549   hsr0 = GET_HSR0 ();
550   if (GET_HSR0_SA (hsr0))
551     SET_H_PC (0xff000000);
552   else
553     SET_H_PC (0);
554 
555   return 1; /* reset */
556 }
557 
558 /* Process any pending interrupt(s) after a group of parallel insns.  */
559 void
560 frv_process_interrupts (SIM_CPU *current_cpu)
561 {
562   SI NE_flags[2];
563   /* Need to save the pc here because writeback may change it (due to a
564      branch).  */
565   IADDR pc = CPU_PC_GET (current_cpu);
566 
567   /* Check for a reset before anything else.  */
568   if (check_reset (current_cpu, pc))
569     return;
570 
571   /* First queue the writes for any accumulated NE flags.  */
572   if (frv_interrupt_state.f_ne_flags[0] != 0
573       || frv_interrupt_state.f_ne_flags[1] != 0)
574     {
575       GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
576       NE_flags[0] |= frv_interrupt_state.f_ne_flags[0];
577       NE_flags[1] |= frv_interrupt_state.f_ne_flags[1];
578       SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
579     }
580 
581   /* If there is no interrupt pending, then perform parallel writeback.  This
582      may cause an interrupt.  */
583   if (frv_interrupt_state.queue_index <= 0)
584     frvbf_perform_writeback (current_cpu);
585 
586   /* If there is an interrupt pending, then process it.  */
587   if (frv_interrupt_state.queue_index > 0)
588     handle_interrupt (current_cpu, pc);
589 }
590 
591 /* Find the next available ESR and return its index */
592 static int
593 esr_for_data_access_exception (
594   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
595 )
596 {
597   SIM_DESC sd = CPU_STATE (current_cpu);
598   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
599     return 8; /* Use ESR8, EPCR8.  */
600 
601   if (item->slot == UNIT_I0)
602     return 8; /* Use ESR8, EPCR8, EAR8, EDR8.  */
603 
604   return 9; /* Use ESR9, EPCR9, EAR9.  */
605 }
606 
607 /* Set the next available EDR register with the data which was to be stored
608    and return the index of the register.  */
609 static int
610 set_edr_register (
611   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index
612 )
613 {
614   /* EDR0, EDR4 and EDR8 are available as blocks of 4.
615        SI data uses EDR3, EDR7 and EDR11
616        DI data uses EDR2, EDR6 and EDR10
617        XI data uses EDR0, EDR4 and EDR8.  */
618   int i;
619   edr_index += 4 - item->u.data_written.length;
620   for (i = 0; i < item->u.data_written.length; ++i)
621     SET_EDR (edr_index + i, item->u.data_written.words[i]);
622 
623   return edr_index;
624 };
625 
626 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx.  */
627 static void
628 clear_exception_status_registers (SIM_CPU *current_cpu)
629 {
630   int i;
631   /* It is only necessary to clear the flag bits indicating which registers
632      are valid.  */
633   SET_ESFR (0, 0);
634   SET_ESFR (1, 0);
635 
636   for (i = 0; i <= 2; ++i)
637     {
638       SI esr = GET_ESR (i);
639       CLEAR_ESR_VALID (esr);
640       SET_ESR (i, esr);
641     }
642   for (i = 8; i <= 15; ++i)
643     {
644       SI esr = GET_ESR (i);
645       CLEAR_ESR_VALID (esr);
646       SET_ESR (i, esr);
647     }
648 }
649 
650 /* Record state for media exception.  */
651 void
652 frv_set_mp_exception_registers (
653   SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie
654 )
655 {
656   /* Record the interrupt factor in MSR0.  */
657   SI msr0 = GET_MSR (0);
658   if (GET_MSR_MTT (msr0) == MTT_NONE)
659     SET_MSR_MTT (msr0, mtt);
660 
661   /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF.  */
662   if (mtt == MTT_OVERFLOW)
663     {
664       FRV_VLIW *vliw = CPU_VLIW (current_cpu);
665       int slot = vliw->next_slot - 1;
666       SIM_DESC sd = CPU_STATE (current_cpu);
667 
668       /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE,
669 	 otherwise set MSR0.OVF and MSR0.SIE.  */
670       if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550 && (*vliw->current_vliw)[slot] == UNIT_FM1)
671 	{
672 	  SI msr = GET_MSR (1);
673 	  OR_MSR_SIE (msr, sie);
674 	  SET_MSR_OVF (msr);
675 	  SET_MSR (1, msr);
676 	}
677       else
678 	{
679 	  OR_MSR_SIE (msr0, sie);
680 	  SET_MSR_OVF (msr0);
681 	}
682 
683       /* Generate the interrupt now if MSR0.MPEM is set on fr550 */
684       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550 && GET_MSR_MPEM (msr0))
685 	frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION);
686       else
687 	{
688 	  /* Regardless of the slot, set MSR0.AOVF.  */
689 	  SET_MSR_AOVF (msr0);
690 	}
691     }
692 
693   SET_MSR (0, msr0);
694 }
695 
696 /* Determine the correct FQ register to use for the given exception.
697    Return -1 if a register is not available.  */
698 static int
699 fq_for_exception (
700   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
701 )
702 {
703   SI fq;
704   struct frv_fp_exception_info *fp_info = & item->u.fp_info;
705 
706   /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1.  */
707   if (fp_info->ftt == FTT_IEEE_754_EXCEPTION
708       && (fp_info->fsr_mask & (FSR_OVERFLOW | FSR_UNDERFLOW | FSR_INEXACT)))
709     {
710       fq = GET_FQ (0);
711       if (! GET_FQ_VALID (fq))
712 	return 0; /* FQ0 is available.  */
713       fq = GET_FQ (1);
714       if (! GET_FQ_VALID (fq))
715 	return 1; /* FQ1 is available.  */
716 
717       /* No FQ register is available */
718       {
719 	SIM_DESC sd = CPU_STATE (current_cpu);
720 	IADDR pc = CPU_PC_GET (current_cpu);
721 	sim_engine_abort (sd, current_cpu, pc, "No FQ register available\n");
722       }
723       return -1;
724     }
725   /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
726      otherwise.  */
727   if (item->slot == UNIT_FM0 || item->slot == UNIT_I0)
728     return 2;
729 
730   return 3;
731 }
732 
733 /* Set FSR0, FQ0-FQ9, depending on the interrupt.  */
734 static void
735 set_fp_exception_registers (
736   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
737 )
738 {
739   int fq_index;
740   SI fq;
741   SI insn;
742   SI fsr0;
743   IADDR pc;
744   struct frv_fp_exception_info *fp_info;
745   SIM_DESC sd = CPU_STATE (current_cpu);
746 
747   /* No FQ registers on fr550 */
748   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
749     {
750       /* Update the fsr.  */
751       fp_info = & item->u.fp_info;
752       fsr0 = GET_FSR (0);
753       SET_FSR_FTT (fsr0, fp_info->ftt);
754       SET_FSR (0, fsr0);
755       return;
756     }
757 
758   /* Select an FQ and update it with the exception information.  */
759   fq_index = fq_for_exception (current_cpu, item);
760   if (fq_index == -1)
761     return;
762 
763   fp_info = & item->u.fp_info;
764   fq = GET_FQ (fq_index);
765   SET_FQ_MIV (fq, MIV_FLOAT);
766   SET_FQ_SIE (fq, SIE_NIL);
767   SET_FQ_FTT (fq, fp_info->ftt);
768   SET_FQ_CEXC (fq, fp_info->fsr_mask);
769   SET_FQ_VALID (fq);
770   SET_FQ (fq_index, fq);
771 
772   /* Write the failing insn into FQx.OPC.  */
773   pc = item->vpc;
774   insn = GETMEMSI (current_cpu, pc, pc);
775   SET_FQ_OPC (fq_index, insn);
776 
777   /* Update the fsr.  */
778   fsr0 = GET_FSR (0);
779   SET_FSR_QNE (fsr0); /* FQ not empty */
780   SET_FSR_FTT (fsr0, fp_info->ftt);
781   SET_FSR (0, fsr0);
782 }
783 
784 /* Record the state of a division exception in the ISR.  */
785 static void
786 set_isr_exception_fields (
787   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
788 )
789 {
790   USI isr = GET_ISR ();
791   int dtt = GET_ISR_DTT (isr);
792   dtt |= item->u.dtt;
793   SET_ISR_DTT (isr, dtt);
794   SET_ISR (isr);
795 }
796 
797 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
798    interrupt.  */
799 static void
800 set_exception_status_registers (
801   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
802 )
803 {
804   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
805   int slot = (item->vpc - previous_vliw_pc) / 4;
806   int reg_index = -1;
807   int set_ear = 0;
808   int set_edr = 0;
809   int set_daec = 0;
810   int set_epcr = 0;
811   SI esr = 0;
812   SIM_DESC sd = CPU_STATE (current_cpu);
813 
814   /* If the interrupt is strict (precise) or the interrupt is on the insns
815      in the I0 pipe, then set the 0 registers.  */
816   if (interrupt->precise)
817     {
818       reg_index = 0;
819       if (interrupt->kind == FRV_REGISTER_EXCEPTION)
820 	SET_ESR_REC (esr, item->u.rec);
821       else if (interrupt->kind == FRV_INSTRUCTION_ACCESS_EXCEPTION)
822 	SET_ESR_IAEC (esr, item->u.iaec);
823       /* For fr550, don't set epcr for precise interrupts.  */
824       if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
825 	set_epcr = 1;
826     }
827   else
828     {
829       switch (interrupt->kind)
830 	{
831 	case FRV_DIVISION_EXCEPTION:
832 	  set_isr_exception_fields (current_cpu, item);
833 	  /* fall thru to set reg_index.  */
834 	case FRV_COMMIT_EXCEPTION:
835 	  /* For fr550, always use ESR0.  */
836 	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
837 	    reg_index = 0;
838 	  else if (item->slot == UNIT_I0)
839 	    reg_index = 0;
840 	  else if (item->slot == UNIT_I1)
841 	    reg_index = 1;
842 	  set_epcr = 1;
843 	  break;
844 	case FRV_DATA_STORE_ERROR:
845 	  reg_index = 14; /* Use ESR14.  */
846 	  break;
847 	case FRV_DATA_ACCESS_ERROR:
848 	  reg_index = 15; /* Use ESR15, EPCR15.  */
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 }
1413