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