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