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