xref: /netbsd-src/external/gpl3/gdb/dist/sim/frv/interrupts.c (revision 854b025f2fdbc2b8be5b6915e0337cc556c8c54d)
1 /* frv exception and interrupt support
2    Copyright (C) 1999-2024 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 /* This must come before any other includes.  */
21 #include "defs.h"
22 
23 #define WANT_CPU frvbf
24 #define WANT_CPU_FRVBF
25 
26 #include "sim-main.h"
27 #include "sim-signal.h"
28 #include "bfd.h"
29 #include <stdlib.h>
30 #include "cgen-mem.h"
31 
32 /* FR-V Interrupt table.
33    Describes the interrupts supported by the FR-V.
34    This table *must* be maintained in order of interrupt priority as defined by
35    frv_interrupt_kind.  */
36 #define DEFERRED 1
37 #define PRECISE  1
38 #define ITABLE_ENTRY(name, class, deferral, precision, offset) \
39   {FRV_##name, FRV_EC_##name, class, deferral, precision, offset}
40 
41 struct frv_interrupt frv_interrupt_table[NUM_FRV_INTERRUPT_KINDS] =
42 {
43   /* External interrupts */
44   ITABLE_ENTRY(INTERRUPT_LEVEL_1,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x21),
45   ITABLE_ENTRY(INTERRUPT_LEVEL_2,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x22),
46   ITABLE_ENTRY(INTERRUPT_LEVEL_3,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x23),
47   ITABLE_ENTRY(INTERRUPT_LEVEL_4,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x24),
48   ITABLE_ENTRY(INTERRUPT_LEVEL_5,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x25),
49   ITABLE_ENTRY(INTERRUPT_LEVEL_6,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x26),
50   ITABLE_ENTRY(INTERRUPT_LEVEL_7,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x27),
51   ITABLE_ENTRY(INTERRUPT_LEVEL_8,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x28),
52   ITABLE_ENTRY(INTERRUPT_LEVEL_9,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x29),
53   ITABLE_ENTRY(INTERRUPT_LEVEL_10,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2a),
54   ITABLE_ENTRY(INTERRUPT_LEVEL_11,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2b),
55   ITABLE_ENTRY(INTERRUPT_LEVEL_12,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2c),
56   ITABLE_ENTRY(INTERRUPT_LEVEL_13,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2d),
57   ITABLE_ENTRY(INTERRUPT_LEVEL_14,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2e),
58   ITABLE_ENTRY(INTERRUPT_LEVEL_15,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2f),
59   /* Software interrupt */
60   ITABLE_ENTRY(TRAP_INSTRUCTION,             FRV_SOFTWARE_INTERRUPT, !DEFERRED, !PRECISE, 0x80),
61   /* Program interrupts */
62   ITABLE_ENTRY(COMMIT_EXCEPTION,             FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x19),
63   ITABLE_ENTRY(DIVISION_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x17),
64   ITABLE_ENTRY(DATA_STORE_ERROR,             FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x14),
65   ITABLE_ENTRY(DATA_ACCESS_EXCEPTION,        FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x13),
66   ITABLE_ENTRY(DATA_ACCESS_MMU_MISS,         FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x12),
67   ITABLE_ENTRY(DATA_ACCESS_ERROR,            FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x11),
68   ITABLE_ENTRY(MP_EXCEPTION,                 FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x0e),
69   ITABLE_ENTRY(FP_EXCEPTION,                 FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x0d),
70   ITABLE_ENTRY(MEM_ADDRESS_NOT_ALIGNED,      FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x10),
71   ITABLE_ENTRY(REGISTER_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x08),
72   ITABLE_ENTRY(MP_DISABLED,                  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x0b),
73   ITABLE_ENTRY(FP_DISABLED,                  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x0a),
74   ITABLE_ENTRY(PRIVILEGED_INSTRUCTION,       FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x06),
75   ITABLE_ENTRY(ILLEGAL_INSTRUCTION,          FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x07),
76   ITABLE_ENTRY(INSTRUCTION_ACCESS_EXCEPTION, FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x03),
77   ITABLE_ENTRY(INSTRUCTION_ACCESS_ERROR,     FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x02),
78   ITABLE_ENTRY(INSTRUCTION_ACCESS_MMU_MISS,  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x01),
79   ITABLE_ENTRY(COMPOUND_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x20),
80   /* Break interrupt */
81   ITABLE_ENTRY(BREAK_EXCEPTION,              FRV_BREAK_INTERRUPT,    !DEFERRED, !PRECISE, 0xff),
82   /* Reset interrupt */
83   ITABLE_ENTRY(RESET,                        FRV_RESET_INTERRUPT,    !DEFERRED, !PRECISE, 0x00)
84 };
85 
86 /* The current interrupt state.  */
87 struct frv_interrupt_state frv_interrupt_state;
88 
89 /* maintain the address of the start of the previous VLIW insn sequence.  */
90 IADDR previous_vliw_pc;
91 
92 /* Add a break interrupt to the interrupt queue.  */
93 struct frv_interrupt_queue_element *
94 frv_queue_break_interrupt (SIM_CPU *current_cpu)
95 {
96   return frv_queue_interrupt (current_cpu, FRV_BREAK_EXCEPTION);
97 }
98 
99 /* Add a software interrupt to the interrupt queue.  */
100 struct frv_interrupt_queue_element *
101 frv_queue_software_interrupt (SIM_CPU *current_cpu, SI offset)
102 {
103   struct frv_interrupt_queue_element *new_element
104     = frv_queue_interrupt (current_cpu, FRV_TRAP_INSTRUCTION);
105 
106   struct frv_interrupt *interrupt = & frv_interrupt_table[new_element->kind];
107   interrupt->handler_offset = offset;
108 
109   return new_element;
110 }
111 
112 /* Add a program interrupt to the interrupt queue.  */
113 struct frv_interrupt_queue_element *
114 frv_queue_program_interrupt (
115   SIM_CPU *current_cpu, enum frv_interrupt_kind kind
116 )
117 {
118   return frv_queue_interrupt (current_cpu, kind);
119 }
120 
121 /* Add an external interrupt to the interrupt queue.  */
122 struct frv_interrupt_queue_element *
123 frv_queue_external_interrupt (
124   SIM_CPU *current_cpu, enum frv_interrupt_kind kind
125 )
126 {
127   if (! GET_H_PSR_ET ()
128       || (kind != FRV_INTERRUPT_LEVEL_15 && kind < GET_H_PSR_PIL ()))
129     return NULL; /* Leave it for later.  */
130 
131   return frv_queue_interrupt (current_cpu, kind);
132 }
133 
134 /* Add any interrupt to the interrupt queue. It will be added in reverse
135    priority order.  This makes it easy to find the highest priority interrupt
136    at the end of the queue and to remove it after processing.  */
137 struct frv_interrupt_queue_element *
138 frv_queue_interrupt (SIM_CPU *current_cpu, enum frv_interrupt_kind kind)
139 {
140   int i;
141   int j;
142   int limit = frv_interrupt_state.queue_index;
143   struct frv_interrupt_queue_element *new_element;
144   enum frv_interrupt_class iclass;
145 
146   if (limit >= FRV_INTERRUPT_QUEUE_SIZE)
147     abort (); /* TODO: Make the queue dynamic */
148 
149   /* Find the right place in the queue.  */
150   for (i = 0; i < limit; ++i)
151     {
152       if (frv_interrupt_state.queue[i].kind >= kind)
153 	break;
154     }
155 
156   /* Don't queue two external interrupts of the same priority.  */
157   iclass = frv_interrupt_table[kind].iclass;
158   if (i < limit && iclass == FRV_EXTERNAL_INTERRUPT)
159     {
160       if (frv_interrupt_state.queue[i].kind == kind)
161 	return & frv_interrupt_state.queue[i];
162     }
163 
164   /* Make room for the new interrupt in this spot.  */
165   for (j = limit - 1; j >= i; --j)
166     frv_interrupt_state.queue[j + 1] = frv_interrupt_state.queue[j];
167 
168   /* Add the new interrupt.  */
169   frv_interrupt_state.queue_index++;
170   new_element = & frv_interrupt_state.queue[i];
171   new_element->kind = kind;
172   new_element->vpc = CPU_PC_GET (current_cpu);
173   new_element->u.data_written.length = 0;
174   frv_set_interrupt_queue_slot (current_cpu, new_element);
175 
176   return new_element;
177 }
178 
179 struct frv_interrupt_queue_element *
180 frv_queue_register_exception_interrupt (SIM_CPU *current_cpu, enum frv_rec rec)
181 {
182   struct frv_interrupt_queue_element *new_element =
183     frv_queue_program_interrupt (current_cpu, FRV_REGISTER_EXCEPTION);
184 
185   new_element->u.rec = rec;
186 
187   return new_element;
188 }
189 
190 struct frv_interrupt_queue_element *
191 frv_queue_mem_address_not_aligned_interrupt (SIM_CPU *current_cpu, USI addr)
192 {
193   struct frv_interrupt_queue_element *new_element;
194   USI isr = GET_ISR ();
195 
196   /* Make sure that this exception is not masked.  */
197   if (GET_ISR_EMAM (isr))
198     return NULL;
199 
200   /* Queue the interrupt.  */
201   new_element = frv_queue_program_interrupt (current_cpu,
202 					     FRV_MEM_ADDRESS_NOT_ALIGNED);
203   new_element->eaddress = addr;
204   new_element->u.data_written = frv_interrupt_state.data_written;
205   frv_interrupt_state.data_written.length = 0;
206 
207   return new_element;
208 }
209 
210 struct frv_interrupt_queue_element *
211 frv_queue_data_access_error_interrupt (SIM_CPU *current_cpu, USI addr)
212 {
213   struct frv_interrupt_queue_element *new_element;
214   new_element = frv_queue_program_interrupt (current_cpu,
215 					     FRV_DATA_ACCESS_ERROR);
216   new_element->eaddress = addr;
217   return new_element;
218 }
219 
220 struct frv_interrupt_queue_element *
221 frv_queue_data_access_exception_interrupt (SIM_CPU *current_cpu)
222 {
223   return frv_queue_program_interrupt (current_cpu, FRV_DATA_ACCESS_EXCEPTION);
224 }
225 
226 struct frv_interrupt_queue_element *
227 frv_queue_instruction_access_error_interrupt (SIM_CPU *current_cpu)
228 {
229   return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_ERROR);
230 }
231 
232 struct frv_interrupt_queue_element *
233 frv_queue_instruction_access_exception_interrupt (SIM_CPU *current_cpu)
234 {
235   return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_EXCEPTION);
236 }
237 
238 struct frv_interrupt_queue_element *
239 frv_queue_illegal_instruction_interrupt (
240   SIM_CPU *current_cpu, const CGEN_INSN *insn
241 )
242 {
243   SIM_DESC sd = CPU_STATE (current_cpu);
244   switch (STATE_ARCHITECTURE (sd)->mach)
245     {
246     case bfd_mach_fr400:
247     case bfd_mach_fr450:
248     case bfd_mach_fr550:
249       break;
250     default:
251       /* Some machines generate fp_exception for this case.  */
252       if (frv_is_float_insn (insn) || frv_is_media_insn (insn))
253 	{
254 	  struct frv_fp_exception_info fp_info = {
255 	    FSR_NO_EXCEPTION, FTT_SEQUENCE_ERROR
256 	  };
257 	  return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
258 	}
259       break;
260     }
261 
262   return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
263 }
264 
265 struct frv_interrupt_queue_element *
266 frv_queue_privileged_instruction_interrupt (SIM_CPU *current_cpu, const CGEN_INSN *insn)
267 {
268   /* The fr550 has no privileged instruction interrupt. It uses
269      illegal_instruction.  */
270   SIM_DESC sd = CPU_STATE (current_cpu);
271   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
272     return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
273 
274   return frv_queue_program_interrupt (current_cpu, FRV_PRIVILEGED_INSTRUCTION);
275 }
276 
277 struct frv_interrupt_queue_element *
278 frv_queue_float_disabled_interrupt (SIM_CPU *current_cpu)
279 {
280   /* The fr550 has no fp_disabled interrupt. It uses illegal_instruction.  */
281   SIM_DESC sd = CPU_STATE (current_cpu);
282   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
283     return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
284 
285   return frv_queue_program_interrupt (current_cpu, FRV_FP_DISABLED);
286 }
287 
288 struct frv_interrupt_queue_element *
289 frv_queue_media_disabled_interrupt (SIM_CPU *current_cpu)
290 {
291   /* The fr550 has no mp_disabled interrupt. It uses illegal_instruction.  */
292   SIM_DESC sd = CPU_STATE (current_cpu);
293   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
294     return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
295 
296   return frv_queue_program_interrupt (current_cpu, FRV_MP_DISABLED);
297 }
298 
299 struct frv_interrupt_queue_element *
300 frv_queue_non_implemented_instruction_interrupt (
301   SIM_CPU *current_cpu, const CGEN_INSN *insn
302 )
303 {
304   SIM_DESC sd = CPU_STATE (current_cpu);
305   switch (STATE_ARCHITECTURE (sd)->mach)
306     {
307     case bfd_mach_fr400:
308     case bfd_mach_fr450:
309     case bfd_mach_fr550:
310       break;
311     default:
312       /* Some machines generate fp_exception or mp_exception for this case.  */
313       if (frv_is_float_insn (insn))
314 	{
315 	  struct frv_fp_exception_info fp_info = {
316 	    FSR_NO_EXCEPTION, FTT_UNIMPLEMENTED_FPOP
317 	  };
318 	  return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
319 	}
320       if (frv_is_media_insn (insn))
321 	{
322 	  frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP,
323 					  0);
324 	  return NULL; /* no interrupt queued at this time.  */
325 	}
326       break;
327     }
328 
329   return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
330 }
331 
332 /* Queue the given fp_exception interrupt. Also update fp_info by removing
333    masked interrupts and updating the 'slot' flield.  */
334 struct frv_interrupt_queue_element *
335 frv_queue_fp_exception_interrupt (
336   SIM_CPU *current_cpu, struct frv_fp_exception_info *fp_info
337 )
338 {
339   SI fsr0 = GET_FSR (0);
340   int tem = GET_FSR_TEM (fsr0);
341   int aexc = GET_FSR_AEXC (fsr0);
342   struct frv_interrupt_queue_element *new_element = NULL;
343 
344   /* Update AEXC with the interrupts that are masked.  */
345   aexc |= fp_info->fsr_mask & ~tem;
346   SET_FSR_AEXC (fsr0, aexc);
347   SET_FSR (0, fsr0);
348 
349   /* update fsr_mask with the exceptions that are enabled.  */
350   fp_info->fsr_mask &= tem;
351 
352   /* If there is an unmasked interrupt then queue it, unless
353      this was a non-excepting insn, in which case simply set the NE
354      status registers.  */
355   if (frv_interrupt_state.ne_index != NE_NOFLAG
356       && fp_info->fsr_mask != FSR_NO_EXCEPTION)
357     {
358       SET_NE_FLAG (frv_interrupt_state.f_ne_flags,
359 		   frv_interrupt_state.ne_index);
360       /* TODO -- Set NESR for chips which support it.  */
361       new_element = NULL;
362     }
363   else if (fp_info->fsr_mask != FSR_NO_EXCEPTION
364 	   || fp_info->ftt == FTT_UNIMPLEMENTED_FPOP
365 	   || fp_info->ftt == FTT_SEQUENCE_ERROR
366 	   || fp_info->ftt == FTT_INVALID_FR)
367     {
368       new_element = frv_queue_program_interrupt (current_cpu, FRV_FP_EXCEPTION);
369       new_element->u.fp_info = *fp_info;
370     }
371 
372   return new_element;
373 }
374 
375 struct frv_interrupt_queue_element *
376 frv_queue_division_exception_interrupt (SIM_CPU *current_cpu, enum frv_dtt dtt)
377 {
378   struct frv_interrupt_queue_element *new_element =
379     frv_queue_program_interrupt (current_cpu, FRV_DIVISION_EXCEPTION);
380 
381   new_element->u.dtt = dtt;
382 
383   return new_element;
384 }
385 
386 /* Check for interrupts caused by illegal insn access.  These conditions are
387    checked in the order specified by the fr400 and fr500 LSI specs.  */
388 void
389 frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc)
390 {
391 
392   const CGEN_INSN *insn = sc->argbuf.idesc->idata;
393   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
394 
395   /* Check for vliw constraints.  */
396   if (vliw->constraint_violation)
397     frv_queue_illegal_instruction_interrupt (current_cpu, insn);
398   /* Check for non-excepting insns.  */
399   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING)
400       && ! GET_H_PSR_NEM ())
401     frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
402   /* Check for conditional insns.  */
403   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL)
404       && ! GET_H_PSR_CM ())
405     frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
406   /* Make sure floating point support is enabled.  */
407   else if (! GET_H_PSR_EF ())
408     {
409       /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
410 	 off and the insns accesses a fp register.  */
411       if (frv_is_float_insn (insn)
412 	  || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)
413 	      && ! GET_H_PSR_EM ()))
414 	frv_queue_float_disabled_interrupt (current_cpu);
415     }
416   /* Make sure media support is enabled.  */
417   else if (! GET_H_PSR_EM ())
418     {
419       /* Generate mp_disabled if it is a media insn.  */
420       if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP)
421 	frv_queue_media_disabled_interrupt (current_cpu);
422     }
423   /* Check for privileged insns.  */
424   else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) &&
425 	   ! GET_H_PSR_S ())
426     frv_queue_privileged_instruction_interrupt (current_cpu, insn);
427 #if 0 /* disable for now until we find out how FSR0.QNE gets reset.  */
428   else
429     {
430       /* Enter the halt state if FSR0.QNE is set and we are executing a
431 	 floating point insn, a media insn or an insn which access a FR
432 	 register.  */
433       SIM_DESC sd = CPU_STATE (current_cpu);
434       SI fsr0 = GET_FSR (0);
435       if (GET_FSR_QNE (fsr0)
436 	  && (frv_is_float_insn (insn) || frv_is_media_insn (insn)
437 	      || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)))
438 	{
439 	  sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped,
440 			   SIM_SIGINT);
441 	}
442     }
443 #endif
444 }
445 
446 /* Record the current VLIW slot in the given interrupt queue element.  */
447 void
448 frv_set_interrupt_queue_slot (
449   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
450 )
451 {
452   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
453   int slot = vliw->next_slot - 1;
454   item->slot = (*vliw->current_vliw)[slot];
455 }
456 
457 /* Handle an individual interrupt.  */
458 static void
459 handle_interrupt (SIM_CPU *current_cpu, IADDR pc)
460 {
461   struct frv_interrupt *interrupt;
462   int writeback_done = 0;
463   while (1)
464     {
465       /* Interrupts are queued in priority order with the highest priority
466 	 last.  */
467       int index = frv_interrupt_state.queue_index - 1;
468       struct frv_interrupt_queue_element *item
469 	= & frv_interrupt_state.queue[index];
470       interrupt = & frv_interrupt_table[item->kind];
471 
472       switch (interrupt->iclass)
473 	{
474 	case FRV_EXTERNAL_INTERRUPT:
475 	  /* Perform writeback first. This may cause a higher priority
476 	     interrupt.  */
477 	  if (! writeback_done)
478 	    {
479 	      frvbf_perform_writeback (current_cpu);
480 	      writeback_done = 1;
481 	      continue;
482 	    }
483 	  frv_external_interrupt (current_cpu, item, pc);
484 	  return;
485 	case FRV_SOFTWARE_INTERRUPT:
486 	  frv_interrupt_state.queue_index = index;
487 	  frv_software_interrupt (current_cpu, item, pc);
488 	  return;
489 	case FRV_PROGRAM_INTERRUPT:
490 	  /* If the program interrupt is not strict (imprecise), then perform
491 	     writeback first. This may, in turn, cause a higher priority
492 	     interrupt.  */
493 	  if (! interrupt->precise && ! writeback_done)
494 	    {
495 	      frv_interrupt_state.imprecise_interrupt = item;
496 	      frvbf_perform_writeback (current_cpu);
497 	      writeback_done = 1;
498 	      continue;
499 	    }
500 	  frv_interrupt_state.queue_index = index;
501 	  frv_program_interrupt (current_cpu, item, pc);
502 	  return;
503 	case FRV_BREAK_INTERRUPT:
504 	  frv_interrupt_state.queue_index = index;
505 	  frv_break_interrupt (current_cpu, interrupt, pc);
506 	  return;
507 	case FRV_RESET_INTERRUPT:
508 	  break;
509 	default:
510 	  break;
511 	}
512       frv_interrupt_state.queue_index = index;
513       break; /* out of loop.  */
514     }
515 
516   /* We should never get here.  */
517   {
518     SIM_DESC sd = CPU_STATE (current_cpu);
519     sim_engine_abort (sd, current_cpu, pc,
520 		      "interrupt class not supported %d\n",
521 		      interrupt->iclass);
522   }
523 }
524 
525 /* Check to see the if the RSTR.HR or RSTR.SR bits have been set.  If so, handle
526    the appropriate reset interrupt.  */
527 static int
528 check_reset (SIM_CPU *current_cpu, IADDR pc)
529 {
530   int hsr0;
531   int hr;
532   int sr;
533   SI rstr;
534   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
535   IADDR address = RSTR_ADDRESS;
536 
537   /* We don't want this to show up in the cache statistics, so read the
538      cache passively.  */
539   if (! frv_cache_read_passive_SI (cache, address, & rstr))
540     rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address);
541 
542   hr = GET_RSTR_HR (rstr);
543   sr = GET_RSTR_SR (rstr);
544 
545   if (! hr && ! sr)
546     return 0; /* no reset.  */
547 
548   /* Reinitialize the machine state.  */
549   if (hr)
550     frv_hardware_reset (current_cpu);
551   else
552     frv_software_reset (current_cpu);
553 
554   /* Branch to the reset address.  */
555   hsr0 = GET_HSR0 ();
556   if (GET_HSR0_SA (hsr0))
557     SET_H_PC (0xff000000);
558   else
559     SET_H_PC (0);
560 
561   return 1; /* reset */
562 }
563 
564 /* Process any pending interrupt(s) after a group of parallel insns.  */
565 void
566 frv_process_interrupts (SIM_CPU *current_cpu)
567 {
568   SI NE_flags[2];
569   /* Need to save the pc here because writeback may change it (due to a
570      branch).  */
571   IADDR pc = CPU_PC_GET (current_cpu);
572 
573   /* Check for a reset before anything else.  */
574   if (check_reset (current_cpu, pc))
575     return;
576 
577   /* First queue the writes for any accumulated NE flags.  */
578   if (frv_interrupt_state.f_ne_flags[0] != 0
579       || frv_interrupt_state.f_ne_flags[1] != 0)
580     {
581       GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
582       NE_flags[0] |= frv_interrupt_state.f_ne_flags[0];
583       NE_flags[1] |= frv_interrupt_state.f_ne_flags[1];
584       SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
585     }
586 
587   /* If there is no interrupt pending, then perform parallel writeback.  This
588      may cause an interrupt.  */
589   if (frv_interrupt_state.queue_index <= 0)
590     frvbf_perform_writeback (current_cpu);
591 
592   /* If there is an interrupt pending, then process it.  */
593   if (frv_interrupt_state.queue_index > 0)
594     handle_interrupt (current_cpu, pc);
595 }
596 
597 /* Find the next available ESR and return its index */
598 static int
599 esr_for_data_access_exception (
600   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
601 )
602 {
603   SIM_DESC sd = CPU_STATE (current_cpu);
604   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
605     return 8; /* Use ESR8, EPCR8.  */
606 
607   if (item->slot == UNIT_I0)
608     return 8; /* Use ESR8, EPCR8, EAR8, EDR8.  */
609 
610   return 9; /* Use ESR9, EPCR9, EAR9.  */
611 }
612 
613 /* Set the next available EDR register with the data which was to be stored
614    and return the index of the register.  */
615 static int
616 set_edr_register (
617   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index
618 )
619 {
620   /* EDR0, EDR4 and EDR8 are available as blocks of 4.
621        SI data uses EDR3, EDR7 and EDR11
622        DI data uses EDR2, EDR6 and EDR10
623        XI data uses EDR0, EDR4 and EDR8.  */
624   int i;
625   edr_index += 4 - item->u.data_written.length;
626   for (i = 0; i < item->u.data_written.length; ++i)
627     SET_EDR (edr_index + i, item->u.data_written.words[i]);
628 
629   return edr_index;
630 };
631 
632 /* Clear ESFR0, EPCRx, ESRx, EARx and EDRx.  */
633 static void
634 clear_exception_status_registers (SIM_CPU *current_cpu)
635 {
636   int i;
637   /* It is only necessary to clear the flag bits indicating which registers
638      are valid.  */
639   SET_ESFR (0, 0);
640   SET_ESFR (1, 0);
641 
642   for (i = 0; i <= 2; ++i)
643     {
644       SI esr = GET_ESR (i);
645       CLEAR_ESR_VALID (esr);
646       SET_ESR (i, esr);
647     }
648   for (i = 8; i <= 15; ++i)
649     {
650       SI esr = GET_ESR (i);
651       CLEAR_ESR_VALID (esr);
652       SET_ESR (i, esr);
653     }
654 }
655 
656 /* Record state for media exception.  */
657 void
658 frv_set_mp_exception_registers (
659   SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie
660 )
661 {
662   /* Record the interrupt factor in MSR0.  */
663   SI msr0 = GET_MSR (0);
664   if (GET_MSR_MTT (msr0) == MTT_NONE)
665     SET_MSR_MTT (msr0, mtt);
666 
667   /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF.  */
668   if (mtt == MTT_OVERFLOW)
669     {
670       FRV_VLIW *vliw = CPU_VLIW (current_cpu);
671       int slot = vliw->next_slot - 1;
672       SIM_DESC sd = CPU_STATE (current_cpu);
673 
674       /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE,
675 	 otherwise set MSR0.OVF and MSR0.SIE.  */
676       if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550 && (*vliw->current_vliw)[slot] == UNIT_FM1)
677 	{
678 	  SI msr = GET_MSR (1);
679 	  OR_MSR_SIE (msr, sie);
680 	  SET_MSR_OVF (msr);
681 	  SET_MSR (1, msr);
682 	}
683       else
684 	{
685 	  OR_MSR_SIE (msr0, sie);
686 	  SET_MSR_OVF (msr0);
687 	}
688 
689       /* Generate the interrupt now if MSR0.MPEM is set on fr550 */
690       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550 && GET_MSR_MPEM (msr0))
691 	frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION);
692       else
693 	{
694 	  /* Regardless of the slot, set MSR0.AOVF.  */
695 	  SET_MSR_AOVF (msr0);
696 	}
697     }
698 
699   SET_MSR (0, msr0);
700 }
701 
702 /* Determine the correct FQ register to use for the given exception.
703    Return -1 if a register is not available.  */
704 static int
705 fq_for_exception (
706   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
707 )
708 {
709   SI fq;
710   struct frv_fp_exception_info *fp_info = & item->u.fp_info;
711 
712   /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1.  */
713   if (fp_info->ftt == FTT_IEEE_754_EXCEPTION
714       && (fp_info->fsr_mask & (FSR_OVERFLOW | FSR_UNDERFLOW | FSR_INEXACT)))
715     {
716       fq = GET_FQ (0);
717       if (! GET_FQ_VALID (fq))
718 	return 0; /* FQ0 is available.  */
719       fq = GET_FQ (1);
720       if (! GET_FQ_VALID (fq))
721 	return 1; /* FQ1 is available.  */
722 
723       /* No FQ register is available */
724       {
725 	SIM_DESC sd = CPU_STATE (current_cpu);
726 	IADDR pc = CPU_PC_GET (current_cpu);
727 	sim_engine_abort (sd, current_cpu, pc, "No FQ register available\n");
728       }
729       return -1;
730     }
731   /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
732      otherwise.  */
733   if (item->slot == UNIT_FM0 || item->slot == UNIT_I0)
734     return 2;
735 
736   return 3;
737 }
738 
739 /* Set FSR0, FQ0-FQ9, depending on the interrupt.  */
740 static void
741 set_fp_exception_registers (
742   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
743 )
744 {
745   int fq_index;
746   SI fq;
747   SI insn;
748   SI fsr0;
749   IADDR pc;
750   struct frv_fp_exception_info *fp_info;
751   SIM_DESC sd = CPU_STATE (current_cpu);
752 
753   /* No FQ registers on fr550 */
754   if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
755     {
756       /* Update the fsr.  */
757       fp_info = & item->u.fp_info;
758       fsr0 = GET_FSR (0);
759       SET_FSR_FTT (fsr0, fp_info->ftt);
760       SET_FSR (0, fsr0);
761       return;
762     }
763 
764   /* Select an FQ and update it with the exception information.  */
765   fq_index = fq_for_exception (current_cpu, item);
766   if (fq_index == -1)
767     return;
768 
769   fp_info = & item->u.fp_info;
770   fq = GET_FQ (fq_index);
771   SET_FQ_MIV (fq, MIV_FLOAT);
772   SET_FQ_SIE (fq, SIE_NIL);
773   SET_FQ_FTT (fq, fp_info->ftt);
774   SET_FQ_CEXC (fq, fp_info->fsr_mask);
775   SET_FQ_VALID (fq);
776   SET_FQ (fq_index, fq);
777 
778   /* Write the failing insn into FQx.OPC.  */
779   pc = item->vpc;
780   insn = GETMEMSI (current_cpu, pc, pc);
781   SET_FQ_OPC (fq_index, insn);
782 
783   /* Update the fsr.  */
784   fsr0 = GET_FSR (0);
785   SET_FSR_QNE (fsr0); /* FQ not empty */
786   SET_FSR_FTT (fsr0, fp_info->ftt);
787   SET_FSR (0, fsr0);
788 }
789 
790 /* Record the state of a division exception in the ISR.  */
791 static void
792 set_isr_exception_fields (
793   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
794 )
795 {
796   USI isr = GET_ISR ();
797   int dtt = GET_ISR_DTT (isr);
798   dtt |= item->u.dtt;
799   SET_ISR_DTT (isr, dtt);
800   SET_ISR (isr);
801 }
802 
803 /* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
804    interrupt.  */
805 static void
806 set_exception_status_registers (
807   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
808 )
809 {
810   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
811   int reg_index = -1;
812   int set_ear = 0;
813   int set_edr = 0;
814   int set_daec = 0;
815   int set_epcr = 0;
816   SI esr = 0;
817   SIM_DESC sd = CPU_STATE (current_cpu);
818 
819   /* If the interrupt is strict (precise) or the interrupt is on the insns
820      in the I0 pipe, then set the 0 registers.  */
821   if (interrupt->precise)
822     {
823       reg_index = 0;
824       if (interrupt->kind == FRV_REGISTER_EXCEPTION)
825 	SET_ESR_REC (esr, item->u.rec);
826       else if (interrupt->kind == FRV_INSTRUCTION_ACCESS_EXCEPTION)
827 	SET_ESR_IAEC (esr, item->u.iaec);
828       /* For fr550, don't set epcr for precise interrupts.  */
829       if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
830 	set_epcr = 1;
831     }
832   else
833     {
834       switch (interrupt->kind)
835 	{
836 	case FRV_DIVISION_EXCEPTION:
837 	  set_isr_exception_fields (current_cpu, item);
838 	  ATTRIBUTE_FALLTHROUGH;  /* To set reg_index.  */
839 	case FRV_COMMIT_EXCEPTION:
840 	  /* For fr550, always use ESR0.  */
841 	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
842 	    reg_index = 0;
843 	  else if (item->slot == UNIT_I0)
844 	    reg_index = 0;
845 	  else if (item->slot == UNIT_I1)
846 	    reg_index = 1;
847 	  set_epcr = 1;
848 	  break;
849 	case FRV_DATA_STORE_ERROR:
850 	  reg_index = 14; /* Use ESR14.  */
851 	  break;
852 	case FRV_DATA_ACCESS_ERROR:
853 	  reg_index = 15; /* Use ESR15, EPCR15.  */
854 	  set_ear = 1;
855 	  break;
856 	case FRV_DATA_ACCESS_EXCEPTION:
857 	  set_daec = 1;
858 	  ATTRIBUTE_FALLTHROUGH;
859 	case FRV_DATA_ACCESS_MMU_MISS:
860 	case FRV_MEM_ADDRESS_NOT_ALIGNED:
861 	  /* Get the appropriate ESR, EPCR, EAR and EDR.
862 	     EAR will be set. EDR will not be set if this is a store insn.  */
863 	  set_ear = 1;
864 	  /* For fr550, never use EDRx.  */
865 	  if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
866 	    if (item->u.data_written.length != 0)
867 	      set_edr = 1;
868 	  reg_index = esr_for_data_access_exception (current_cpu, item);
869 	  set_epcr = 1;
870 	  break;
871 	case FRV_MP_EXCEPTION:
872 	  /* For fr550, use EPCR2 and ESR2.  */
873 	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
874 	    {
875 	      reg_index = 2;
876 	      set_epcr = 1;
877 	    }
878 	  break; /* MSR0-1, FQ0-9 are already set.  */
879 	case FRV_FP_EXCEPTION:
880 	  set_fp_exception_registers (current_cpu, item);
881 	  /* For fr550, use EPCR2 and ESR2.  */
882 	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
883 	    {
884 	      reg_index = 2;
885 	      set_epcr = 1;
886 	    }
887 	  break;
888 	default:
889 	  {
890 	    IADDR pc = CPU_PC_GET (current_cpu);
891 	    sim_engine_abort (sd, current_cpu, pc,
892 			      "invalid non-strict program interrupt kind: %d\n",
893 			      interrupt->kind);
894 	    break;
895 	  }
896 	}
897     } /* non-strict (imprecise) interrupt */
898 
899   /* Now fill in the selected exception status registers.  */
900   if (reg_index != -1)
901     {
902       /* Now set the exception status registers.  */
903       SET_ESFR_FLAG (reg_index);
904       SET_ESR_EC (esr, interrupt->ec);
905 
906       if (set_epcr)
907 	{
908 	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
909 	    SET_EPCR (reg_index, previous_vliw_pc);
910 	  else
911 	    SET_EPCR (reg_index, item->vpc);
912 	}
913 
914       if (set_ear)
915 	{
916 	  SET_EAR (reg_index, item->eaddress);
917 	  SET_ESR_EAV (esr);
918 	}
919       else
920 	CLEAR_ESR_EAV (esr);
921 
922       if (set_edr)
923 	{
924 	  int edn = set_edr_register (current_cpu, item, 0/* EDR0-3 */);
925 	  SET_ESR_EDN (esr, edn);
926 	  SET_ESR_EDV (esr);
927 	}
928       else
929 	CLEAR_ESR_EDV (esr);
930 
931       if (set_daec)
932 	SET_ESR_DAEC (esr, item->u.daec);
933 
934       SET_ESR_VALID (esr);
935       SET_ESR (reg_index, esr);
936     }
937 }
938 
939 /* Check for compound interrupts.
940    Returns NULL if no interrupt is to be processed.  */
941 static struct frv_interrupt *
942 check_for_compound_interrupt (
943   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
944 )
945 {
946   struct frv_interrupt *interrupt;
947 
948   /* Set the exception status registers for the original interrupt.  */
949   set_exception_status_registers (current_cpu, item);
950   interrupt = & frv_interrupt_table[item->kind];
951 
952   if (! interrupt->precise)
953     {
954       IADDR vpc = 0;
955       int mask = 0;
956 
957       vpc = item->vpc;
958       mask = (1 << item->kind);
959 
960       /* Look for more queued program interrupts which are non-deferred
961 	 (pending inhibit), imprecise (non-strict) different than an interrupt
962 	 already found and caused by a different insn.  A bit mask is used
963 	 to keep track of interrupts which have already been detected.  */
964       while (item != frv_interrupt_state.queue)
965 	{
966 	  enum frv_interrupt_kind kind;
967 	  struct frv_interrupt *next_interrupt;
968 	  --item;
969 	  kind = item->kind;
970 	  next_interrupt = & frv_interrupt_table[kind];
971 
972 	  if (next_interrupt->iclass != FRV_PROGRAM_INTERRUPT)
973 	    break; /* no program interrupts left.  */
974 
975 	  if (item->vpc == vpc)
976 	    continue; /* caused by the same insn.  */
977 
978 	  vpc = item->vpc;
979 	  if (! next_interrupt->precise && ! next_interrupt->deferred)
980 	    {
981 	      if (! (mask & (1 << kind)))
982 		{
983 		  /* Set the exception status registers for the additional
984 		     interrupt.  */
985 		  set_exception_status_registers (current_cpu, item);
986 		  mask |= (1 << kind);
987 		  interrupt = & frv_interrupt_table[FRV_COMPOUND_EXCEPTION];
988 		}
989 	    }
990 	}
991     }
992 
993   /* Return with either the original interrupt, a compound_exception,
994      or no exception.  */
995   return interrupt;
996 }
997 
998 /* Handle a program interrupt.  */
999 void
1000 frv_program_interrupt (
1001   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1002 )
1003 {
1004   struct frv_interrupt *interrupt;
1005 
1006   clear_exception_status_registers (current_cpu);
1007   /* If two or more non-deferred imprecise (non-strict) interrupts occur
1008      on two or more insns, then generate a compound_exception.  */
1009   interrupt = check_for_compound_interrupt (current_cpu, item);
1010   if (interrupt != NULL)
1011     {
1012       frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1013       frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT,
1014 				   FRV_PROGRAM_INTERRUPT);
1015     }
1016 }
1017 
1018 /* Handle a software interrupt.  */
1019 void
1020 frv_software_interrupt (
1021   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1022 )
1023 {
1024   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1025   frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1026 }
1027 
1028 /* Handle a program interrupt or a software interrupt in non-operating mode.  */
1029 void
1030 frv_non_operating_interrupt (
1031   SIM_CPU *current_cpu, enum frv_interrupt_kind kind, IADDR pc
1032 )
1033 {
1034   SIM_DESC sd = CPU_STATE (current_cpu);
1035   switch (kind)
1036     {
1037     case FRV_INTERRUPT_LEVEL_1:
1038     case FRV_INTERRUPT_LEVEL_2:
1039     case FRV_INTERRUPT_LEVEL_3:
1040     case FRV_INTERRUPT_LEVEL_4:
1041     case FRV_INTERRUPT_LEVEL_5:
1042     case FRV_INTERRUPT_LEVEL_6:
1043     case FRV_INTERRUPT_LEVEL_7:
1044     case FRV_INTERRUPT_LEVEL_8:
1045     case FRV_INTERRUPT_LEVEL_9:
1046     case FRV_INTERRUPT_LEVEL_10:
1047     case FRV_INTERRUPT_LEVEL_11:
1048     case FRV_INTERRUPT_LEVEL_12:
1049     case FRV_INTERRUPT_LEVEL_13:
1050     case FRV_INTERRUPT_LEVEL_14:
1051     case FRV_INTERRUPT_LEVEL_15:
1052       sim_engine_abort (sd, current_cpu, pc,
1053 			"interrupt: external %d\n", kind + 1);
1054       break;
1055     case FRV_TRAP_INSTRUCTION:
1056       break; /* handle as in operating mode.  */
1057     case FRV_COMMIT_EXCEPTION:
1058       sim_engine_abort (sd, current_cpu, pc,
1059 			"interrupt: commit_exception\n");
1060       break;
1061     case FRV_DIVISION_EXCEPTION:
1062       sim_engine_abort (sd, current_cpu, pc,
1063 			"interrupt: division_exception\n");
1064       break;
1065     case FRV_DATA_STORE_ERROR:
1066       sim_engine_abort (sd, current_cpu, pc,
1067 			"interrupt: data_store_error\n");
1068       break;
1069     case FRV_DATA_ACCESS_EXCEPTION:
1070       sim_engine_abort (sd, current_cpu, pc,
1071 			"interrupt: data_access_exception\n");
1072       break;
1073     case FRV_DATA_ACCESS_MMU_MISS:
1074       sim_engine_abort (sd, current_cpu, pc,
1075 			"interrupt: data_access_mmu_miss\n");
1076       break;
1077     case FRV_DATA_ACCESS_ERROR:
1078       sim_engine_abort (sd, current_cpu, pc,
1079 			"interrupt: data_access_error\n");
1080       break;
1081     case FRV_MP_EXCEPTION:
1082       sim_engine_abort (sd, current_cpu, pc,
1083 			"interrupt: mp_exception\n");
1084       break;
1085     case FRV_FP_EXCEPTION:
1086       sim_engine_abort (sd, current_cpu, pc,
1087 			"interrupt: fp_exception\n");
1088       break;
1089     case FRV_MEM_ADDRESS_NOT_ALIGNED:
1090       sim_engine_abort (sd, current_cpu, pc,
1091 			"interrupt: mem_address_not_aligned\n");
1092       break;
1093     case FRV_REGISTER_EXCEPTION:
1094       sim_engine_abort (sd, current_cpu, pc,
1095 			"interrupt: register_exception\n");
1096       break;
1097     case FRV_MP_DISABLED:
1098       sim_engine_abort (sd, current_cpu, pc,
1099 			"interrupt: mp_disabled\n");
1100       break;
1101     case FRV_FP_DISABLED:
1102       sim_engine_abort (sd, current_cpu, pc,
1103 			"interrupt: fp_disabled\n");
1104       break;
1105     case FRV_PRIVILEGED_INSTRUCTION:
1106       sim_engine_abort (sd, current_cpu, pc,
1107 			"interrupt: privileged_instruction\n");
1108       break;
1109     case FRV_ILLEGAL_INSTRUCTION:
1110       sim_engine_abort (sd, current_cpu, pc,
1111 			"interrupt: illegal_instruction\n");
1112       break;
1113     case FRV_INSTRUCTION_ACCESS_EXCEPTION:
1114       sim_engine_abort (sd, current_cpu, pc,
1115 			"interrupt: instruction_access_exception\n");
1116       break;
1117     case FRV_INSTRUCTION_ACCESS_MMU_MISS:
1118       sim_engine_abort (sd, current_cpu, pc,
1119 			"interrupt: instruction_access_mmu_miss\n");
1120       break;
1121     case FRV_INSTRUCTION_ACCESS_ERROR:
1122       sim_engine_abort (sd, current_cpu, pc,
1123 			"interrupt: insn_access_error\n");
1124       break;
1125     case FRV_COMPOUND_EXCEPTION:
1126       sim_engine_abort (sd, current_cpu, pc,
1127 			"interrupt: compound_exception\n");
1128       break;
1129     case FRV_BREAK_EXCEPTION:
1130       sim_engine_abort (sd, current_cpu, pc,
1131 			"interrupt: break_exception\n");
1132       break;
1133     case FRV_RESET:
1134       sim_engine_abort (sd, current_cpu, pc,
1135 			"interrupt: reset\n");
1136       break;
1137     default:
1138       sim_engine_abort (sd, current_cpu, pc,
1139 			"unhandled interrupt kind: %d\n", kind);
1140       break;
1141     }
1142 }
1143 
1144 /* Handle a break interrupt.  */
1145 void
1146 frv_break_interrupt (
1147   SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1148 )
1149 {
1150   IADDR new_pc;
1151 
1152   /* BPCSR=PC
1153      BPSR.BS=PSR.S
1154      BPSR.BET=PSR.ET
1155      PSR.S=1
1156      PSR.ET=0
1157      TBR.TT=0xff
1158      PC=TBR
1159   */
1160   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1161   SET_H_BPSR_BS (GET_H_PSR_S ());
1162   SET_H_BPSR_BET (GET_H_PSR_ET ());
1163   SET_H_PSR_S (1);
1164   SET_H_PSR_ET (0);
1165   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1166   SET_H_SPR (H_SPR_BPCSR, current_pc);
1167 
1168   /* Set the new PC in the TBR.  */
1169   SET_H_TBR_TT (interrupt->handler_offset);
1170   new_pc = GET_H_SPR (H_SPR_TBR);
1171   SET_H_PC (new_pc);
1172 
1173   CPU_DEBUG_STATE (current_cpu) = 1;
1174 }
1175 
1176 /* Handle a program interrupt or a software interrupt.  */
1177 void
1178 frv_program_or_software_interrupt (
1179   SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1180 )
1181 {
1182   USI new_pc;
1183   int original_psr_et;
1184 
1185   /* PCSR=PC
1186      PSR.PS=PSR.S
1187      PSR.ET=0
1188      PSR.S=1
1189      if PSR.ESR==1
1190        SR0 through SR3=GR4 through GR7
1191        TBR.TT=interrupt handler offset
1192        PC=TBR
1193   */
1194   original_psr_et = GET_H_PSR_ET ();
1195 
1196   SET_H_PSR_PS (GET_H_PSR_S ());
1197   SET_H_PSR_ET (0);
1198   SET_H_PSR_S (1);
1199 
1200   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1201   /* The PCSR depends on the precision of the interrupt.  */
1202   if (interrupt->precise)
1203     SET_H_SPR (H_SPR_PCSR, previous_vliw_pc);
1204   else
1205     SET_H_SPR (H_SPR_PCSR, current_pc);
1206 
1207   /* Set the new PC in the TBR.  */
1208   SET_H_TBR_TT (interrupt->handler_offset);
1209   new_pc = GET_H_SPR (H_SPR_TBR);
1210   SET_H_PC (new_pc);
1211 
1212   /* If PSR.ET was not originally set, then enter the stopped state.  */
1213   if (! original_psr_et)
1214     {
1215       SIM_DESC sd = CPU_STATE (current_cpu);
1216       frv_non_operating_interrupt (current_cpu, interrupt->kind, current_pc);
1217       sim_engine_halt (sd, current_cpu, NULL, new_pc, sim_stopped, SIM_SIGINT);
1218     }
1219 }
1220 
1221 /* Handle a program interrupt or a software interrupt.  */
1222 void
1223 frv_external_interrupt (
1224   SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1225 )
1226 {
1227   USI new_pc;
1228   struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1229 
1230   /* Don't process the interrupt if PSR.ET is not set or if it is masked.
1231      Interrupt 15 is processed even if it appears to be masked.  */
1232   if (! GET_H_PSR_ET ()
1233       || (interrupt->kind != FRV_INTERRUPT_LEVEL_15
1234 	  && interrupt->kind < GET_H_PSR_PIL ()))
1235     return; /* Leave it for later.  */
1236 
1237   /* Remove the interrupt from the queue.  */
1238   --frv_interrupt_state.queue_index;
1239 
1240   /* PCSR=PC
1241      PSR.PS=PSR.S
1242      PSR.ET=0
1243      PSR.S=1
1244      if PSR.ESR==1
1245        SR0 through SR3=GR4 through GR7
1246        TBR.TT=interrupt handler offset
1247        PC=TBR
1248   */
1249   SET_H_PSR_PS (GET_H_PSR_S ());
1250   SET_H_PSR_ET (0);
1251   SET_H_PSR_S (1);
1252   /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1253   SET_H_SPR (H_SPR_PCSR, GET_H_PC ());
1254 
1255   /* Set the new PC in the TBR.  */
1256   SET_H_TBR_TT (interrupt->handler_offset);
1257   new_pc = GET_H_SPR (H_SPR_TBR);
1258   SET_H_PC (new_pc);
1259 }
1260 
1261 /* Clear interrupts which fall within the range of classes given.  */
1262 void
1263 frv_clear_interrupt_classes (
1264   enum frv_interrupt_class low_class, enum frv_interrupt_class high_class
1265 )
1266 {
1267   int i;
1268   int j;
1269   int limit = frv_interrupt_state.queue_index;
1270 
1271   /* Find the lowest priority interrupt to be removed.  */
1272   for (i = 0; i < limit; ++i)
1273     {
1274       enum frv_interrupt_kind kind = frv_interrupt_state.queue[i].kind;
1275       struct frv_interrupt* interrupt = & frv_interrupt_table[kind];
1276       if (interrupt->iclass >= low_class)
1277 	break;
1278     }
1279 
1280   /* Find the highest priority interrupt to be removed.  */
1281   for (j = limit - 1; j >= i; --j)
1282     {
1283       enum frv_interrupt_kind kind = frv_interrupt_state.queue[j].kind;
1284       struct frv_interrupt* interrupt = & frv_interrupt_table[kind];
1285       if (interrupt->iclass <= high_class)
1286 	break;
1287     }
1288 
1289   /* Shuffle the remaining high priority interrupts down into the empty space
1290      left by the deleted interrupts.  */
1291   if (j >= i)
1292     {
1293       for (++j; j < limit; ++j)
1294 	frv_interrupt_state.queue[i++] = frv_interrupt_state.queue[j];
1295       frv_interrupt_state.queue_index -= (j - i);
1296     }
1297 }
1298 
1299 /* Save data written to memory into the interrupt state so that it can be
1300    copied to the appropriate EDR register, if necessary, in the event of an
1301    interrupt.  */
1302 void
1303 frv_save_data_written_for_interrupts (
1304   SIM_CPU *current_cpu, CGEN_WRITE_QUEUE_ELEMENT *item
1305 )
1306 {
1307   /* Record the slot containing the insn doing the write in the
1308      interrupt state.  */
1309   frv_interrupt_state.slot = CGEN_WRITE_QUEUE_ELEMENT_PIPE (item);
1310 
1311   /* Now record any data written to memory in the interrupt state.  */
1312   switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item))
1313     {
1314     case CGEN_BI_WRITE:
1315     case CGEN_QI_WRITE:
1316     case CGEN_SI_WRITE:
1317     case CGEN_SF_WRITE:
1318     case CGEN_PC_WRITE:
1319     case CGEN_FN_HI_WRITE:
1320     case CGEN_FN_SI_WRITE:
1321     case CGEN_FN_SF_WRITE:
1322     case CGEN_FN_DI_WRITE:
1323     case CGEN_FN_DF_WRITE:
1324     case CGEN_FN_XI_WRITE:
1325     case CGEN_FN_PC_WRITE:
1326       break; /* Ignore writes to registers.  */
1327     case CGEN_MEM_QI_WRITE:
1328       frv_interrupt_state.data_written.length = 1;
1329       frv_interrupt_state.data_written.words[0]
1330 	= item->kinds.mem_qi_write.value;
1331       break;
1332     case CGEN_MEM_HI_WRITE:
1333       frv_interrupt_state.data_written.length = 1;
1334       frv_interrupt_state.data_written.words[0]
1335 	= item->kinds.mem_hi_write.value;
1336       break;
1337     case CGEN_MEM_SI_WRITE:
1338       frv_interrupt_state.data_written.length = 1;
1339       frv_interrupt_state.data_written.words[0]
1340 	= item->kinds.mem_si_write.value;
1341       break;
1342     case CGEN_MEM_DI_WRITE:
1343       frv_interrupt_state.data_written.length = 2;
1344       frv_interrupt_state.data_written.words[0]
1345 	= item->kinds.mem_di_write.value >> 32;
1346       frv_interrupt_state.data_written.words[1]
1347 	= item->kinds.mem_di_write.value;
1348       break;
1349     case CGEN_MEM_DF_WRITE:
1350       frv_interrupt_state.data_written.length = 2;
1351       frv_interrupt_state.data_written.words[0]
1352 	= item->kinds.mem_df_write.value >> 32;
1353       frv_interrupt_state.data_written.words[1]
1354 	= item->kinds.mem_df_write.value;
1355       break;
1356     case CGEN_MEM_XI_WRITE:
1357       frv_interrupt_state.data_written.length = 4;
1358       frv_interrupt_state.data_written.words[0]
1359 	= item->kinds.mem_xi_write.value[0];
1360       frv_interrupt_state.data_written.words[1]
1361 	= item->kinds.mem_xi_write.value[1];
1362       frv_interrupt_state.data_written.words[2]
1363 	= item->kinds.mem_xi_write.value[2];
1364       frv_interrupt_state.data_written.words[3]
1365 	= item->kinds.mem_xi_write.value[3];
1366       break;
1367     case CGEN_FN_MEM_QI_WRITE:
1368       frv_interrupt_state.data_written.length = 1;
1369       frv_interrupt_state.data_written.words[0]
1370 	= item->kinds.fn_mem_qi_write.value;
1371       break;
1372     case CGEN_FN_MEM_HI_WRITE:
1373       frv_interrupt_state.data_written.length = 1;
1374       frv_interrupt_state.data_written.words[0]
1375 	= item->kinds.fn_mem_hi_write.value;
1376       break;
1377     case CGEN_FN_MEM_SI_WRITE:
1378       frv_interrupt_state.data_written.length = 1;
1379       frv_interrupt_state.data_written.words[0]
1380 	= item->kinds.fn_mem_si_write.value;
1381       break;
1382     case CGEN_FN_MEM_DI_WRITE:
1383       frv_interrupt_state.data_written.length = 2;
1384       frv_interrupt_state.data_written.words[0]
1385 	= item->kinds.fn_mem_di_write.value >> 32;
1386       frv_interrupt_state.data_written.words[1]
1387 	= item->kinds.fn_mem_di_write.value;
1388       break;
1389     case CGEN_FN_MEM_DF_WRITE:
1390       frv_interrupt_state.data_written.length = 2;
1391       frv_interrupt_state.data_written.words[0]
1392 	= item->kinds.fn_mem_df_write.value >> 32;
1393       frv_interrupt_state.data_written.words[1]
1394 	= item->kinds.fn_mem_df_write.value;
1395       break;
1396     case CGEN_FN_MEM_XI_WRITE:
1397       frv_interrupt_state.data_written.length = 4;
1398       frv_interrupt_state.data_written.words[0]
1399 	= item->kinds.fn_mem_xi_write.value[0];
1400       frv_interrupt_state.data_written.words[1]
1401 	= item->kinds.fn_mem_xi_write.value[1];
1402       frv_interrupt_state.data_written.words[2]
1403 	= item->kinds.fn_mem_xi_write.value[2];
1404       frv_interrupt_state.data_written.words[3]
1405 	= item->kinds.fn_mem_xi_write.value[3];
1406       break;
1407     default:
1408       {
1409 	SIM_DESC sd = CPU_STATE (current_cpu);
1410 	IADDR pc = CPU_PC_GET (current_cpu);
1411 	sim_engine_abort (sd, current_cpu, pc,
1412 			  "unknown write kind during save for interrupt\n");
1413       }
1414       break;
1415     }
1416 }
1417