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