]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/interrupts.c
Copyright updates for 2007.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / interrupts.c
CommitLineData
e0709f50 1/* interrupts.c -- 68HC11 Interrupts Emulation
6aba47ca 2 Copyright 1999, 2000, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
a685700c 3 Written by Stephane Carrez (stcarrez@nerim.fr)
e0709f50
AC
4
5This file is part of GDB, GAS, and the GNU binutils.
6
7GDB, GAS, and the GNU binutils are free software; you can redistribute
8them and/or modify them under the terms of the GNU General Public
9License as published by the Free Software Foundation; either version
101, or (at your option) any later version.
11
12GDB, GAS, and the GNU binutils are distributed in the hope that they
13will be useful, but WITHOUT ANY WARRANTY; without even the implied
14warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15the GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this file; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "sim-main.h"
26128965
SC
22#include "sim-options.h"
23
24static const char *interrupt_names[] = {
25 "R1",
26 "R2",
27 "R3",
28 "R4",
29 "R5",
30 "R6",
31 "R7",
32 "R8",
33 "R9",
34 "R10",
35 "R11",
36
37 "SCI",
38 "SPI",
39 "AINPUT",
40 "AOVERFLOW",
41 "TOVERFLOW",
42 "OUT5",
43 "OUT4",
44 "OUT3",
45 "OUT2",
46 "OUT1",
47 "INC3",
48 "INC2",
49 "INC1",
50 "RT",
51 "IRQ",
52 "XIRQ",
53 "SWI",
54 "ILL",
55 "COPRESET",
56 "COPFAIL",
57 "RESET"
58};
e0709f50
AC
59
60struct interrupt_def idefs[] = {
61 /* Serial interrupts. */
62 { M6811_INT_SCI, M6811_SCSR, M6811_TDRE, M6811_SCCR2, M6811_TIE },
63 { M6811_INT_SCI, M6811_SCSR, M6811_TC, M6811_SCCR2, M6811_TCIE },
64 { M6811_INT_SCI, M6811_SCSR, M6811_RDRF, M6811_SCCR2, M6811_RIE },
65 { M6811_INT_SCI, M6811_SCSR, M6811_IDLE, M6811_SCCR2, M6811_ILIE },
66
67 /* SPI interrupts. */
68 { M6811_INT_SPI, M6811_SPSR, M6811_SPIF, M6811_SPCR, M6811_SPIE },
69
70 /* Realtime interrupts. */
71 { M6811_INT_TCTN, M6811_TFLG2, M6811_TOF, M6811_TMSK2, M6811_TOI },
72 { M6811_INT_RT, M6811_TFLG2, M6811_RTIF, M6811_TMSK2, M6811_RTII },
73
74 /* Output compare interrupts. */
75 { M6811_INT_OUTCMP1, M6811_TFLG1, M6811_OC1F, M6811_TMSK1, M6811_OC1I },
76 { M6811_INT_OUTCMP2, M6811_TFLG1, M6811_OC2F, M6811_TMSK1, M6811_OC2I },
77 { M6811_INT_OUTCMP3, M6811_TFLG1, M6811_OC3F, M6811_TMSK1, M6811_OC3I },
78 { M6811_INT_OUTCMP4, M6811_TFLG1, M6811_OC4F, M6811_TMSK1, M6811_OC4I },
79 { M6811_INT_OUTCMP5, M6811_TFLG1, M6811_OC5F, M6811_TMSK1, M6811_OC5I },
80
81 /* Input compare interrupts. */
82 { M6811_INT_INCMP1, M6811_TFLG1, M6811_IC1F, M6811_TMSK1, M6811_IC1I },
83 { M6811_INT_INCMP2, M6811_TFLG1, M6811_IC2F, M6811_TMSK1, M6811_IC2I },
84 { M6811_INT_INCMP3, M6811_TFLG1, M6811_IC3F, M6811_TMSK1, M6811_IC3I },
26128965
SC
85
86 /* Pulse accumulator. */
87 { M6811_INT_AINPUT, M6811_TFLG2, M6811_PAIF, M6811_TMSK2, M6811_PAII },
88 { M6811_INT_AOVERFLOW,M6811_TFLG2, M6811_PAOVF, M6811_TMSK2, M6811_PAOVI},
e0709f50
AC
89#if 0
90 { M6811_INT_COPRESET, M6811_CONFIG, M6811_NOCOP, 0, 0 },
91 { M6811_INT_COPFAIL, M6811_CONFIG, M6811_NOCOP, 0, 0 }
92#endif
93};
94
95#define TableSize(X) (sizeof X / sizeof(X[0]))
96#define CYCLES_MAX ((((signed64) 1) << 62) - 1)
97
26128965
SC
98enum
99{
100 OPTION_INTERRUPT_INFO = OPTION_START,
101 OPTION_INTERRUPT_CATCH,
102 OPTION_INTERRUPT_CLEAR
103};
104
105static DECLARE_OPTION_HANDLER (interrupt_option_handler);
106
107static const OPTION interrupt_options[] =
108{
109 { {"interrupt-info", no_argument, NULL, OPTION_INTERRUPT_INFO },
110 '\0', NULL, "Print information about interrupts",
111 interrupt_option_handler },
112 { {"interrupt-catch", required_argument, NULL, OPTION_INTERRUPT_CATCH },
113 '\0', "NAME[,MODE]",
114 "Catch interrupts when they are raised or taken\n"
115 "NAME Name of the interrupt\n"
116 "MODE Optional mode (`taken' or `raised')",
117 interrupt_option_handler },
118 { {"interrupt-clear", required_argument, NULL, OPTION_INTERRUPT_CLEAR },
119 '\0', "NAME", "No longer catch the interrupt",
120 interrupt_option_handler },
121
122 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
123};
124
125/* Initialize the interrupts module. */
126void
127interrupts_initialize (SIM_DESC sd, struct _sim_cpu *proc)
e0709f50
AC
128{
129 struct interrupts *interrupts = &proc->cpu_interrupts;
e0709f50
AC
130
131 interrupts->cpu = proc;
26128965
SC
132
133 sim_add_option_table (sd, 0, interrupt_options);
134}
135
136/* Initialize the interrupts of the processor. */
137void
138interrupts_reset (struct interrupts *interrupts)
139{
140 int i;
141
e0709f50 142 interrupts->pending_mask = 0;
26128965
SC
143 if (interrupts->cpu->cpu_mode & M6811_SMOD)
144 interrupts->vectors_addr = 0xbfc0;
145 else
146 interrupts->vectors_addr = 0xffc0;
e0709f50
AC
147 interrupts->nb_interrupts_raised = 0;
148 interrupts->min_mask_cycles = CYCLES_MAX;
149 interrupts->max_mask_cycles = 0;
11115521 150 interrupts->last_mask_cycles = 0;
e0709f50
AC
151 interrupts->start_mask_cycle = -1;
152 interrupts->xirq_start_mask_cycle = -1;
153 interrupts->xirq_max_mask_cycles = 0;
154 interrupts->xirq_min_mask_cycles = CYCLES_MAX;
11115521 155 interrupts->xirq_last_mask_cycles = 0;
e0709f50
AC
156
157 for (i = 0; i < M6811_INT_NUMBER; i++)
158 {
159 interrupts->interrupt_order[i] = i;
160 }
26128965
SC
161
162 /* Clear the interrupt history table. */
163 interrupts->history_index = 0;
164 memset (interrupts->interrupts_history, 0,
165 sizeof (interrupts->interrupts_history));
166
167 memset (interrupts->interrupts, 0,
168 sizeof (interrupts->interrupts));
a685700c
SC
169
170 /* In bootstrap mode, initialize the vector table to point
171 to the RAM location. */
172 if (interrupts->cpu->cpu_mode == M6811_SMOD)
173 {
174 bfd_vma addr = interrupts->vectors_addr;
175 uint16 vector = 0x0100 - 3 * (M6811_INT_NUMBER - 1);
176 for (i = 0; i < M6811_INT_NUMBER; i++)
177 {
178 memory_write16 (interrupts->cpu, addr, vector);
179 addr += 2;
180 vector += 3;
181 }
182 }
26128965
SC
183}
184
185static int
186find_interrupt (const char *name)
187{
188 int i;
189
190 if (name)
191 for (i = 0; i < M6811_INT_NUMBER; i++)
192 if (strcasecmp (name, interrupt_names[i]) == 0)
193 return i;
194
195 return -1;
e0709f50
AC
196}
197
26128965
SC
198static SIM_RC
199interrupt_option_handler (SIM_DESC sd, sim_cpu *cpu,
200 int opt, char *arg, int is_command)
201{
202 char *p;
203 int mode;
204 int id;
205 struct interrupts *interrupts;
206
207 if (cpu == 0)
208 cpu = STATE_CPU (sd, 0);
209
210 interrupts = &cpu->cpu_interrupts;
211 switch (opt)
212 {
213 case OPTION_INTERRUPT_INFO:
214 for (id = 0; id < M6811_INT_NUMBER; id++)
215 {
216 sim_io_eprintf (sd, "%-10.10s ", interrupt_names[id]);
217 switch (interrupts->interrupts[id].stop_mode)
218 {
219 case SIM_STOP_WHEN_RAISED:
220 sim_io_eprintf (sd, "catch raised ");
221 break;
222
223 case SIM_STOP_WHEN_TAKEN:
224 sim_io_eprintf (sd, "catch taken ");
225 break;
226
227 case SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN:
228 sim_io_eprintf (sd, "catch all ");
229 break;
230
231 default:
232 sim_io_eprintf (sd, " ");
233 break;
234 }
235 sim_io_eprintf (sd, "%ld\n",
236 interrupts->interrupts[id].raised_count);
237 }
238 break;
239
240 case OPTION_INTERRUPT_CATCH:
241 p = strchr (arg, ',');
242 if (p)
243 *p++ = 0;
244
245 mode = SIM_STOP_WHEN_RAISED;
246 id = find_interrupt (arg);
247 if (id < 0)
248 sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);
249
250 if (p && strcasecmp (p, "raised") == 0)
251 mode = SIM_STOP_WHEN_RAISED;
252 else if (p && strcasecmp (p, "taken") == 0)
253 mode = SIM_STOP_WHEN_TAKEN;
254 else if (p && strcasecmp (p, "all") == 0)
255 mode = SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN;
256 else if (p)
257 {
258 sim_io_eprintf (sd, "Invalid argument: %s\n", p);
259 break;
260 }
261 if (id >= 0)
262 interrupts->interrupts[id].stop_mode = mode;
263 break;
264
265 case OPTION_INTERRUPT_CLEAR:
266 mode = SIM_STOP_WHEN_RAISED;
267 id = find_interrupt (arg);
268 if (id < 0)
269 sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);
270 else
271 interrupts->interrupts[id].stop_mode = 0;
272 break;
273 }
274
275 return SIM_RC_OK;
276}
e0709f50
AC
277
278/* Update the mask of pending interrupts. This operation must be called
26128965 279 when the state of some 68HC11 IO register changes. It looks the
e0709f50
AC
280 different registers that indicate a pending interrupt (timer, SCI, SPI,
281 ...) and records the interrupt if it's there and enabled. */
282void
283interrupts_update_pending (struct interrupts *interrupts)
284{
285 int i;
286 uint8 *ioregs;
11115521
SC
287 unsigned long clear_mask;
288 unsigned long set_mask;
e0709f50 289
11115521
SC
290 clear_mask = 0;
291 set_mask = 0;
e0709f50
AC
292 ioregs = &interrupts->cpu->ios[0];
293
294 for (i = 0; i < TableSize(idefs); i++)
295 {
296 struct interrupt_def *idef = &idefs[i];
297 uint8 data;
298
299 /* Look if the interrupt is enabled. */
300 if (idef->enable_paddr)
301 {
302 data = ioregs[idef->enable_paddr];
303 if (!(data & idef->enabled_mask))
a8afa79a
SC
304 {
305 /* Disable it. */
11115521 306 clear_mask |= (1 << idef->int_number);
a8afa79a
SC
307 continue;
308 }
e0709f50
AC
309 }
310
311 /* Interrupt is enabled, see if it's there. */
312 data = ioregs[idef->int_paddr];
313 if (!(data & idef->int_mask))
a8afa79a
SC
314 {
315 /* Disable it. */
11115521 316 clear_mask |= (1 << idef->int_number);
a8afa79a
SC
317 continue;
318 }
e0709f50
AC
319
320 /* Ok, raise it. */
11115521 321 set_mask |= (1 << idef->int_number);
e0709f50 322 }
11115521
SC
323
324 /* Some interrupts are shared (M6811_INT_SCI) so clear
325 the interrupts before setting the new ones. */
326 interrupts->pending_mask &= ~clear_mask;
327 interrupts->pending_mask |= set_mask;
26128965
SC
328
329 /* Keep track of when the interrupt is raised by the device.
330 Also implements the breakpoint-on-interrupt. */
331 if (set_mask)
332 {
333 signed64 cycle = cpu_current_cycle (interrupts->cpu);
334 int must_stop = 0;
335
336 for (i = 0; i < M6811_INT_NUMBER; i++)
337 {
338 if (!(set_mask & (1 << i)))
339 continue;
340
341 interrupts->interrupts[i].cpu_cycle = cycle;
342 if (interrupts->interrupts[i].stop_mode & SIM_STOP_WHEN_RAISED)
343 {
344 must_stop = 1;
345 sim_io_printf (CPU_STATE (interrupts->cpu),
346 "Interrupt %s raised\n",
347 interrupt_names[i]);
348 }
349 }
350 if (must_stop)
351 sim_engine_halt (CPU_STATE (interrupts->cpu),
352 interrupts->cpu,
353 0, cpu_get_pc (interrupts->cpu),
354 sim_stopped,
355 SIM_SIGTRAP);
356 }
e0709f50
AC
357}
358
359
360/* Finds the current active and non-masked interrupt.
361 Returns the interrupt number (index in the vector table) or -1
362 if no interrupt can be serviced. */
363int
364interrupts_get_current (struct interrupts *interrupts)
365{
366 int i;
367
368 if (interrupts->pending_mask == 0)
369 return -1;
370
371 /* SWI and illegal instructions are simulated by an interrupt.
372 They are not maskable. */
373 if (interrupts->pending_mask & (1 << M6811_INT_SWI))
374 {
375 interrupts->pending_mask &= ~(1 << M6811_INT_SWI);
376 return M6811_INT_SWI;
377 }
378 if (interrupts->pending_mask & (1 << M6811_INT_ILLEGAL))
379 {
380 interrupts->pending_mask &= ~(1 << M6811_INT_ILLEGAL);
381 return M6811_INT_ILLEGAL;
382 }
383
384 /* If there is a non maskable interrupt, go for it (unless we are masked
385 by the X-bit. */
386 if (interrupts->pending_mask & (1 << M6811_INT_XIRQ))
387 {
388 if (cpu_get_ccr_X (interrupts->cpu) == 0)
389 {
390 interrupts->pending_mask &= ~(1 << M6811_INT_XIRQ);
391 return M6811_INT_XIRQ;
392 }
393 return -1;
394 }
395
396 /* Interrupts are masked, do nothing. */
397 if (cpu_get_ccr_I (interrupts->cpu) == 1)
398 {
399 return -1;
400 }
401
402 /* Returns the first interrupt number which is pending.
a8afa79a
SC
403 The interrupt priority is specified by the table `interrupt_order'.
404 For these interrupts, the pending mask is cleared when the program
405 performs some actions on the corresponding device. If the device
406 is not reset, the interrupt remains and will be re-raised when
407 we return from the interrupt (see 68HC11 pink book). */
e0709f50
AC
408 for (i = 0; i < M6811_INT_NUMBER; i++)
409 {
410 enum M6811_INT int_number = interrupts->interrupt_order[i];
411
412 if (interrupts->pending_mask & (1 << int_number))
413 {
e0709f50
AC
414 return int_number;
415 }
416 }
417 return -1;
418}
419
420
421/* Process the current interrupt if there is one. This operation must
422 be called after each instruction to handle the interrupts. If interrupts
423 are masked, it does nothing. */
424int
425interrupts_process (struct interrupts *interrupts)
426{
427 int id;
428 uint8 ccr;
429
430 /* See if interrupts are enabled/disabled and keep track of the
431 number of cycles the interrupts are masked. Such information is
432 then reported by the info command. */
433 ccr = cpu_get_ccr (interrupts->cpu);
434 if (ccr & M6811_I_BIT)
435 {
436 if (interrupts->start_mask_cycle < 0)
437 interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
438 }
439 else if (interrupts->start_mask_cycle >= 0
440 && (ccr & M6811_I_BIT) == 0)
441 {
442 signed64 t = cpu_current_cycle (interrupts->cpu);
443
444 t -= interrupts->start_mask_cycle;
445 if (t < interrupts->min_mask_cycles)
446 interrupts->min_mask_cycles = t;
447 if (t > interrupts->max_mask_cycles)
448 interrupts->max_mask_cycles = t;
449 interrupts->start_mask_cycle = -1;
11115521 450 interrupts->last_mask_cycles = t;
e0709f50
AC
451 }
452 if (ccr & M6811_X_BIT)
453 {
454 if (interrupts->xirq_start_mask_cycle < 0)
455 interrupts->xirq_start_mask_cycle
456 = cpu_current_cycle (interrupts->cpu);
457 }
458 else if (interrupts->xirq_start_mask_cycle >= 0
459 && (ccr & M6811_X_BIT) == 0)
460 {
461 signed64 t = cpu_current_cycle (interrupts->cpu);
462
463 t -= interrupts->xirq_start_mask_cycle;
464 if (t < interrupts->xirq_min_mask_cycles)
465 interrupts->xirq_min_mask_cycles = t;
466 if (t > interrupts->xirq_max_mask_cycles)
467 interrupts->xirq_max_mask_cycles = t;
468 interrupts->xirq_start_mask_cycle = -1;
11115521 469 interrupts->xirq_last_mask_cycles = t;
e0709f50
AC
470 }
471
472 id = interrupts_get_current (interrupts);
473 if (id >= 0)
474 {
475 uint16 addr;
26128965
SC
476 struct interrupt_history *h;
477
478 /* Implement the breakpoint-on-interrupt. */
479 if (interrupts->interrupts[id].stop_mode & SIM_STOP_WHEN_TAKEN)
480 {
481 sim_io_printf (CPU_STATE (interrupts->cpu),
482 "Interrupt %s will be handled\n",
483 interrupt_names[id]);
484 sim_engine_halt (CPU_STATE (interrupts->cpu),
485 interrupts->cpu,
486 0, cpu_get_pc (interrupts->cpu),
487 sim_stopped,
488 SIM_SIGTRAP);
489 }
490
e0709f50
AC
491 cpu_push_all (interrupts->cpu);
492 addr = memory_read16 (interrupts->cpu,
493 interrupts->vectors_addr + id * 2);
494 cpu_call (interrupts->cpu, addr);
495
496 /* Now, protect from nested interrupts. */
497 if (id == M6811_INT_XIRQ)
498 {
499 cpu_set_ccr_X (interrupts->cpu, 1);
500 }
501 else
502 {
503 cpu_set_ccr_I (interrupts->cpu, 1);
504 }
505
26128965
SC
506 /* Update the interrupt history table. */
507 h = &interrupts->interrupts_history[interrupts->history_index];
508 h->type = id;
509 h->taken_cycle = cpu_current_cycle (interrupts->cpu);
510 h->raised_cycle = interrupts->interrupts[id].cpu_cycle;
511
512 if (interrupts->history_index >= MAX_INT_HISTORY-1)
513 interrupts->history_index = 0;
514 else
515 interrupts->history_index++;
516
e0709f50
AC
517 interrupts->nb_interrupts_raised++;
518 cpu_add_cycles (interrupts->cpu, 14);
519 return 1;
520 }
521 return 0;
522}
523
524void
525interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
526{
527 interrupts->pending_mask |= (1 << number);
528 interrupts->nb_interrupts_raised ++;
529}
530
e0709f50
AC
531void
532interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
533{
a685700c 534 signed64 t, prev_interrupt;
26128965 535 int i;
2990a9f4 536
11115521
SC
537 sim_io_printf (sd, "Interrupts Info:\n");
538 sim_io_printf (sd, " Interrupts raised: %lu\n",
539 interrupts->nb_interrupts_raised);
540
e0709f50
AC
541 if (interrupts->start_mask_cycle >= 0)
542 {
2990a9f4 543 t = cpu_current_cycle (interrupts->cpu);
e0709f50
AC
544
545 t -= interrupts->start_mask_cycle;
546 if (t > interrupts->max_mask_cycles)
547 interrupts->max_mask_cycles = t;
e0709f50 548
26128965 549 sim_io_printf (sd, " Current interrupts masked sequence: %s\n",
a685700c
SC
550 cycle_to_string (interrupts->cpu, t,
551 PRINT_TIME | PRINT_CYCLE));
e0709f50 552 }
2990a9f4
SC
553 t = interrupts->min_mask_cycles == CYCLES_MAX ?
554 interrupts->max_mask_cycles :
555 interrupts->min_mask_cycles;
26128965 556 sim_io_printf (sd, " Shortest interrupts masked sequence: %s\n",
a685700c
SC
557 cycle_to_string (interrupts->cpu, t,
558 PRINT_TIME | PRINT_CYCLE));
2990a9f4
SC
559
560 t = interrupts->max_mask_cycles;
26128965 561 sim_io_printf (sd, " Longest interrupts masked sequence: %s\n",
a685700c
SC
562 cycle_to_string (interrupts->cpu, t,
563 PRINT_TIME | PRINT_CYCLE));
2990a9f4 564
11115521 565 t = interrupts->last_mask_cycles;
26128965 566 sim_io_printf (sd, " Last interrupts masked sequence: %s\n",
a685700c
SC
567 cycle_to_string (interrupts->cpu, t,
568 PRINT_TIME | PRINT_CYCLE));
11115521
SC
569
570 if (interrupts->xirq_start_mask_cycle >= 0)
571 {
572 t = cpu_current_cycle (interrupts->cpu);
573
574 t -= interrupts->xirq_start_mask_cycle;
575 if (t > interrupts->xirq_max_mask_cycles)
576 interrupts->xirq_max_mask_cycles = t;
577
578 sim_io_printf (sd, " XIRQ Current interrupts masked sequence: %s\n",
a685700c
SC
579 cycle_to_string (interrupts->cpu, t,
580 PRINT_TIME | PRINT_CYCLE));
11115521
SC
581 }
582
2990a9f4
SC
583 t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
584 interrupts->xirq_max_mask_cycles :
585 interrupts->xirq_min_mask_cycles;
26128965 586 sim_io_printf (sd, " XIRQ Min interrupts masked sequence: %s\n",
a685700c
SC
587 cycle_to_string (interrupts->cpu, t,
588 PRINT_TIME | PRINT_CYCLE));
2990a9f4
SC
589
590 t = interrupts->xirq_max_mask_cycles;
26128965 591 sim_io_printf (sd, " XIRQ Max interrupts masked sequence: %s\n",
a685700c
SC
592 cycle_to_string (interrupts->cpu, t,
593 PRINT_TIME | PRINT_CYCLE));
11115521
SC
594
595 t = interrupts->xirq_last_mask_cycles;
596 sim_io_printf (sd, " XIRQ Last interrupts masked sequence: %s\n",
a685700c
SC
597 cycle_to_string (interrupts->cpu, t,
598 PRINT_TIME | PRINT_CYCLE));
26128965
SC
599
600 if (interrupts->pending_mask)
601 {
602 sim_io_printf (sd, " Pending interrupts : ");
603 for (i = 0; i < M6811_INT_NUMBER; i++)
604 {
605 enum M6811_INT int_number = interrupts->interrupt_order[i];
606
607 if (interrupts->pending_mask & (1 << int_number))
608 {
609 sim_io_printf (sd, "%s ", interrupt_names[int_number]);
610 }
611 }
612 sim_io_printf (sd, "\n");
613 }
614
a685700c
SC
615 prev_interrupt = 0;
616 sim_io_printf (sd, "N Interrupt Cycle Taken Latency"
617 " Delta between interrupts\n");
26128965
SC
618 for (i = 0; i < MAX_INT_HISTORY; i++)
619 {
620 int which;
621 struct interrupt_history *h;
622 signed64 dt;
623
624 which = interrupts->history_index - i - 1;
625 if (which < 0)
626 which += MAX_INT_HISTORY;
627 h = &interrupts->interrupts_history[which];
628 if (h->taken_cycle == 0)
629 break;
630
631 dt = h->taken_cycle - h->raised_cycle;
a685700c 632 sim_io_printf (sd, "%2d %-9.9s %15.15s ", i,
26128965 633 interrupt_names[h->type],
a685700c
SC
634 cycle_to_string (interrupts->cpu, h->taken_cycle, 0));
635 sim_io_printf (sd, "%15.15s",
636 cycle_to_string (interrupts->cpu, dt, 0));
637 if (prev_interrupt)
638 {
639 dt = prev_interrupt - h->taken_cycle;
640 sim_io_printf (sd, " %s",
641 cycle_to_string (interrupts->cpu, dt, PRINT_TIME));
642 }
643 sim_io_printf (sd, "\n");
644 prev_interrupt = h->taken_cycle;
26128965 645 }
e0709f50 646}