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