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