xref: /netbsd-src/external/gpl3/gdb/dist/sim/m68hc11/interrupts.c (revision 9b2a9e00295c5af9c57a466f299054d5910e47d6)
1 /* interrupts.c -- 68HC11 Interrupts Emulation
2    Copyright 1999-2024 Free Software Foundation, Inc.
3    Written by Stephane Carrez (stcarrez@nerim.fr)
4 
5 This file is part of GDB, GAS, and the GNU binutils.
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 /* This must come before any other includes.  */
21 #include "defs.h"
22 
23 #include "bfd.h"
24 
25 #include "sim-main.h"
26 #include "sim-options.h"
27 #include "sim-signal.h"
28 
29 #include "m68hc11-sim.h"
30 
31 static 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 };
66 
67 struct 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 },
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},
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 
102 #define CYCLES_MAX ((((int64_t) 1) << 62) - 1)
103 
104 enum
105 {
106   OPTION_INTERRUPT_INFO = OPTION_START,
107   OPTION_INTERRUPT_CATCH,
108   OPTION_INTERRUPT_CLEAR
109 };
110 
111 static DECLARE_OPTION_HANDLER (interrupt_option_handler);
112 
113 static 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.  */
132 void
133 interrupts_initialize (SIM_DESC sd, sim_cpu *cpu)
134 {
135   struct interrupts *interrupts = &M68HC11_SIM_CPU (cpu)->cpu_interrupts;
136 
137   interrupts->cpu          = cpu;
138 
139   sim_add_option_table (sd, 0, interrupt_options);
140 }
141 
142 /* Initialize the interrupts of the processor.  */
143 void
144 interrupts_reset (struct interrupts *interrupts)
145 {
146   sim_cpu *cpu = interrupts->cpu;
147   struct m68hc11_sim_cpu *m68hc11_cpu = M68HC11_SIM_CPU (cpu);
148   int i;
149 
150   interrupts->pending_mask = 0;
151   if (m68hc11_cpu->cpu_mode & M6811_SMOD)
152     interrupts->vectors_addr = 0xbfc0;
153   else
154     interrupts->vectors_addr = 0xffc0;
155   interrupts->nb_interrupts_raised = 0;
156   interrupts->min_mask_cycles = CYCLES_MAX;
157   interrupts->max_mask_cycles = 0;
158   interrupts->last_mask_cycles = 0;
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;
163   interrupts->xirq_last_mask_cycles = 0;
164 
165   for (i = 0; i < M6811_INT_NUMBER; i++)
166     {
167       interrupts->interrupt_order[i] = i;
168     }
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));
177 
178   /* In bootstrap mode, initialize the vector table to point
179      to the RAM location.  */
180   if (m68hc11_cpu->cpu_mode == M6811_SMOD)
181     {
182       bfd_vma addr = interrupts->vectors_addr;
183       uint16_t vector = 0x0100 - 3 * (M6811_INT_NUMBER - 1);
184       for (i = 0; i < M6811_INT_NUMBER; i++)
185         {
186           memory_write16 (cpu, addr, vector);
187           addr += 2;
188           vector += 3;
189         }
190     }
191 }
192 
193 static int
194 find_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;
204 }
205 
206 static SIM_RC
207 interrupt_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 
218   interrupts = &M68HC11_SIM_CPU (cpu)->cpu_interrupts;
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 }
285 
286 /* Update the mask of pending interrupts.  This operation must be called
287    when the state of some 68HC11 IO register changes.  It looks the
288    different registers that indicate a pending interrupt (timer, SCI, SPI,
289    ...) and records the interrupt if it's there and enabled.  */
290 void
291 interrupts_update_pending (struct interrupts *interrupts)
292 {
293   int i;
294   uint8_t *ioregs;
295   unsigned long clear_mask;
296   unsigned long set_mask;
297 
298   clear_mask = 0;
299   set_mask = 0;
300   ioregs = &M68HC11_SIM_CPU (interrupts->cpu)->ios[0];
301 
302   for (i = 0; i < ARRAY_SIZE (idefs); i++)
303     {
304       struct interrupt_def *idef = &idefs[i];
305       uint8_t data;
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))
312             {
313               /* Disable it.  */
314               clear_mask |= (1 << idef->int_number);
315               continue;
316             }
317 	}
318 
319       /* Interrupt is enabled, see if it's there.  */
320       data = ioregs[idef->int_paddr];
321       if (!(data & idef->int_mask))
322         {
323           /* Disable it.  */
324           clear_mask |= (1 << idef->int_number);
325           continue;
326         }
327 
328       /* Ok, raise it.  */
329       set_mask |= (1 << idef->int_number);
330     }
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;
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     {
341       int64_t cycle = cpu_current_cycle (interrupts->cpu);
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     }
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.  */
371 int
372 interrupts_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.
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).  */
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 	{
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.  */
432 int
433 interrupts_process (struct interrupts *interrupts)
434 {
435   int id;
436   uint8_t ccr;
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     {
450       int64_t t = cpu_current_cycle (interrupts->cpu);
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;
458       interrupts->last_mask_cycles = t;
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     {
469       int64_t t = cpu_current_cycle (interrupts->cpu);
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;
477       interrupts->xirq_last_mask_cycles = t;
478     }
479 
480   id = interrupts_get_current (interrupts);
481   if (id >= 0)
482     {
483       uint16_t addr;
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 
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 
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 
525       interrupts->nb_interrupts_raised++;
526       cpu_add_cycles (interrupts->cpu, 14);
527       return 1;
528     }
529   return 0;
530 }
531 
532 void
533 interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
534 {
535   interrupts->pending_mask |= (1 << number);
536   interrupts->nb_interrupts_raised ++;
537 }
538 
539 void
540 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
541 {
542   int64_t t, prev_interrupt;
543   int i;
544 
545   sim_io_printf (sd, "Interrupts Info:\n");
546   sim_io_printf (sd, "  Interrupts raised: %lu\n",
547                  interrupts->nb_interrupts_raised);
548 
549   if (interrupts->start_mask_cycle >= 0)
550     {
551       t = cpu_current_cycle (interrupts->cpu);
552 
553       t -= interrupts->start_mask_cycle;
554       if (t > interrupts->max_mask_cycles)
555         interrupts->max_mask_cycles = t;
556 
557       sim_io_printf (sd, "  Current interrupts masked sequence:   %s\n",
558                      cycle_to_string (interrupts->cpu, t,
559                                       PRINT_TIME | PRINT_CYCLE));
560     }
561   t = interrupts->min_mask_cycles == CYCLES_MAX ?
562     interrupts->max_mask_cycles :
563     interrupts->min_mask_cycles;
564   sim_io_printf (sd, "  Shortest interrupts masked sequence:  %s\n",
565                  cycle_to_string (interrupts->cpu, t,
566                                   PRINT_TIME | PRINT_CYCLE));
567 
568   t = interrupts->max_mask_cycles;
569   sim_io_printf (sd, "  Longest interrupts masked sequence:   %s\n",
570                  cycle_to_string (interrupts->cpu, t,
571                                   PRINT_TIME | PRINT_CYCLE));
572 
573   t = interrupts->last_mask_cycles;
574   sim_io_printf (sd, "  Last interrupts masked sequence:      %s\n",
575                  cycle_to_string (interrupts->cpu, t,
576                                   PRINT_TIME | PRINT_CYCLE));
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",
587                      cycle_to_string (interrupts->cpu, t,
588                                       PRINT_TIME | PRINT_CYCLE));
589     }
590 
591   t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
592     interrupts->xirq_max_mask_cycles :
593     interrupts->xirq_min_mask_cycles;
594   sim_io_printf (sd, "  XIRQ Min interrupts masked sequence:  %s\n",
595                  cycle_to_string (interrupts->cpu, t,
596                                   PRINT_TIME | PRINT_CYCLE));
597 
598   t = interrupts->xirq_max_mask_cycles;
599   sim_io_printf (sd, "  XIRQ Max interrupts masked sequence:  %s\n",
600                  cycle_to_string (interrupts->cpu, t,
601                                   PRINT_TIME | PRINT_CYCLE));
602 
603   t = interrupts->xirq_last_mask_cycles;
604   sim_io_printf (sd, "  XIRQ Last interrupts masked sequence: %s\n",
605                  cycle_to_string (interrupts->cpu, t,
606                                   PRINT_TIME | PRINT_CYCLE));
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 
623   prev_interrupt = 0;
624   sim_io_printf (sd, "N  Interrupt     Cycle Taken         Latency"
625                  "   Delta between interrupts\n");
626   for (i = 0; i < MAX_INT_HISTORY; i++)
627     {
628       int which;
629       struct interrupt_history *h;
630       int64_t dt;
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;
640       sim_io_printf (sd, "%2d %-9.9s %15.15s ", i,
641                      interrupt_names[h->type],
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;
653     }
654 }
655