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