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