xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/m68hc11/interrupts.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* interrupts.c -- 68HC11 Interrupts Emulation
2    Copyright 1999-2023 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 "sim-main.h"
24 #include "sim-options.h"
25 #include "sim-signal.h"
26 
27 static 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 };
62 
63 struct 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 },
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},
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 
98 #define CYCLES_MAX ((((int64_t) 1) << 62) - 1)
99 
100 enum
101 {
102   OPTION_INTERRUPT_INFO = OPTION_START,
103   OPTION_INTERRUPT_CATCH,
104   OPTION_INTERRUPT_CLEAR
105 };
106 
107 static DECLARE_OPTION_HANDLER (interrupt_option_handler);
108 
109 static 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.  */
128 void
129 interrupts_initialize (SIM_DESC sd, sim_cpu *cpu)
130 {
131   struct interrupts *interrupts = &cpu->cpu_interrupts;
132 
133   interrupts->cpu          = cpu;
134 
135   sim_add_option_table (sd, 0, interrupt_options);
136 }
137 
138 /* Initialize the interrupts of the processor.  */
139 void
140 interrupts_reset (struct interrupts *interrupts)
141 {
142   int i;
143 
144   interrupts->pending_mask = 0;
145   if (interrupts->cpu->cpu_mode & M6811_SMOD)
146     interrupts->vectors_addr = 0xbfc0;
147   else
148     interrupts->vectors_addr = 0xffc0;
149   interrupts->nb_interrupts_raised = 0;
150   interrupts->min_mask_cycles = CYCLES_MAX;
151   interrupts->max_mask_cycles = 0;
152   interrupts->last_mask_cycles = 0;
153   interrupts->start_mask_cycle = -1;
154   interrupts->xirq_start_mask_cycle = -1;
155   interrupts->xirq_max_mask_cycles = 0;
156   interrupts->xirq_min_mask_cycles = CYCLES_MAX;
157   interrupts->xirq_last_mask_cycles = 0;
158 
159   for (i = 0; i < M6811_INT_NUMBER; i++)
160     {
161       interrupts->interrupt_order[i] = i;
162     }
163 
164   /* Clear the interrupt history table.  */
165   interrupts->history_index = 0;
166   memset (interrupts->interrupts_history, 0,
167           sizeof (interrupts->interrupts_history));
168 
169   memset (interrupts->interrupts, 0,
170           sizeof (interrupts->interrupts));
171 
172   /* In bootstrap mode, initialize the vector table to point
173      to the RAM location.  */
174   if (interrupts->cpu->cpu_mode == M6811_SMOD)
175     {
176       bfd_vma addr = interrupts->vectors_addr;
177       uint16_t vector = 0x0100 - 3 * (M6811_INT_NUMBER - 1);
178       for (i = 0; i < M6811_INT_NUMBER; i++)
179         {
180           memory_write16 (interrupts->cpu, addr, vector);
181           addr += 2;
182           vector += 3;
183         }
184     }
185 }
186 
187 static int
188 find_interrupt (const char *name)
189 {
190   int i;
191 
192   if (name)
193     for (i = 0; i < M6811_INT_NUMBER; i++)
194       if (strcasecmp (name, interrupt_names[i]) == 0)
195         return i;
196 
197   return -1;
198 }
199 
200 static SIM_RC
201 interrupt_option_handler (SIM_DESC sd, sim_cpu *cpu,
202                           int opt, char *arg, int is_command)
203 {
204   char *p;
205   int mode;
206   int id;
207   struct interrupts *interrupts;
208 
209   if (cpu == 0)
210     cpu = STATE_CPU (sd, 0);
211 
212   interrupts = &cpu->cpu_interrupts;
213   switch (opt)
214     {
215     case OPTION_INTERRUPT_INFO:
216       for (id = 0; id < M6811_INT_NUMBER; id++)
217         {
218           sim_io_eprintf (sd, "%-10.10s ", interrupt_names[id]);
219           switch (interrupts->interrupts[id].stop_mode)
220             {
221             case SIM_STOP_WHEN_RAISED:
222               sim_io_eprintf (sd, "catch raised ");
223               break;
224 
225             case SIM_STOP_WHEN_TAKEN:
226               sim_io_eprintf (sd, "catch taken  ");
227               break;
228 
229             case SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN:
230               sim_io_eprintf (sd, "catch all    ");
231               break;
232 
233             default:
234               sim_io_eprintf (sd, "             ");
235               break;
236             }
237           sim_io_eprintf (sd, "%ld\n",
238                           interrupts->interrupts[id].raised_count);
239         }
240       break;
241 
242     case OPTION_INTERRUPT_CATCH:
243       p = strchr (arg, ',');
244       if (p)
245         *p++ = 0;
246 
247       mode = SIM_STOP_WHEN_RAISED;
248       id = find_interrupt (arg);
249       if (id < 0)
250         sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);
251 
252       if (p && strcasecmp (p, "raised") == 0)
253         mode = SIM_STOP_WHEN_RAISED;
254       else if (p && strcasecmp (p, "taken") == 0)
255         mode = SIM_STOP_WHEN_TAKEN;
256       else if (p && strcasecmp (p, "all") == 0)
257         mode = SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN;
258       else if (p)
259         {
260           sim_io_eprintf (sd, "Invalid argument: %s\n", p);
261           break;
262         }
263       if (id >= 0)
264         interrupts->interrupts[id].stop_mode = mode;
265       break;
266 
267     case OPTION_INTERRUPT_CLEAR:
268       mode = SIM_STOP_WHEN_RAISED;
269       id = find_interrupt (arg);
270       if (id < 0)
271         sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);
272       else
273         interrupts->interrupts[id].stop_mode = 0;
274       break;
275     }
276 
277   return SIM_RC_OK;
278 }
279 
280 /* Update the mask of pending interrupts.  This operation must be called
281    when the state of some 68HC11 IO register changes.  It looks the
282    different registers that indicate a pending interrupt (timer, SCI, SPI,
283    ...) and records the interrupt if it's there and enabled.  */
284 void
285 interrupts_update_pending (struct interrupts *interrupts)
286 {
287   int i;
288   uint8_t *ioregs;
289   unsigned long clear_mask;
290   unsigned long set_mask;
291 
292   clear_mask = 0;
293   set_mask = 0;
294   ioregs = &interrupts->cpu->ios[0];
295 
296   for (i = 0; i < ARRAY_SIZE (idefs); i++)
297     {
298       struct interrupt_def *idef = &idefs[i];
299       uint8_t data;
300 
301       /* Look if the interrupt is enabled.  */
302       if (idef->enable_paddr)
303 	{
304 	  data = ioregs[idef->enable_paddr];
305 	  if (!(data & idef->enabled_mask))
306             {
307               /* Disable it.  */
308               clear_mask |= (1 << idef->int_number);
309               continue;
310             }
311 	}
312 
313       /* Interrupt is enabled, see if it's there.  */
314       data = ioregs[idef->int_paddr];
315       if (!(data & idef->int_mask))
316         {
317           /* Disable it.  */
318           clear_mask |= (1 << idef->int_number);
319           continue;
320         }
321 
322       /* Ok, raise it.  */
323       set_mask |= (1 << idef->int_number);
324     }
325 
326   /* Some interrupts are shared (M6811_INT_SCI) so clear
327      the interrupts before setting the new ones.  */
328   interrupts->pending_mask &= ~clear_mask;
329   interrupts->pending_mask |= set_mask;
330 
331   /* Keep track of when the interrupt is raised by the device.
332      Also implements the breakpoint-on-interrupt.  */
333   if (set_mask)
334     {
335       int64_t cycle = cpu_current_cycle (interrupts->cpu);
336       int must_stop = 0;
337 
338       for (i = 0; i < M6811_INT_NUMBER; i++)
339         {
340           if (!(set_mask & (1 << i)))
341             continue;
342 
343           interrupts->interrupts[i].cpu_cycle = cycle;
344           if (interrupts->interrupts[i].stop_mode & SIM_STOP_WHEN_RAISED)
345             {
346               must_stop = 1;
347               sim_io_printf (CPU_STATE (interrupts->cpu),
348                              "Interrupt %s raised\n",
349                              interrupt_names[i]);
350             }
351         }
352       if (must_stop)
353         sim_engine_halt (CPU_STATE (interrupts->cpu),
354                          interrupts->cpu,
355                          0, cpu_get_pc (interrupts->cpu),
356                          sim_stopped,
357                          SIM_SIGTRAP);
358     }
359 }
360 
361 
362 /* Finds the current active and non-masked interrupt.
363    Returns the interrupt number (index in the vector table) or -1
364    if no interrupt can be serviced.  */
365 int
366 interrupts_get_current (struct interrupts *interrupts)
367 {
368   int i;
369 
370   if (interrupts->pending_mask == 0)
371     return -1;
372 
373   /* SWI and illegal instructions are simulated by an interrupt.
374      They are not maskable.  */
375   if (interrupts->pending_mask & (1 << M6811_INT_SWI))
376     {
377       interrupts->pending_mask &= ~(1 << M6811_INT_SWI);
378       return M6811_INT_SWI;
379     }
380   if (interrupts->pending_mask & (1 << M6811_INT_ILLEGAL))
381     {
382       interrupts->pending_mask &= ~(1 << M6811_INT_ILLEGAL);
383       return M6811_INT_ILLEGAL;
384     }
385 
386   /* If there is a non maskable interrupt, go for it (unless we are masked
387      by the X-bit.  */
388   if (interrupts->pending_mask & (1 << M6811_INT_XIRQ))
389     {
390       if (cpu_get_ccr_X (interrupts->cpu) == 0)
391 	{
392 	  interrupts->pending_mask &= ~(1 << M6811_INT_XIRQ);
393 	  return M6811_INT_XIRQ;
394 	}
395       return -1;
396     }
397 
398   /* Interrupts are masked, do nothing.  */
399   if (cpu_get_ccr_I (interrupts->cpu) == 1)
400     {
401       return -1;
402     }
403 
404   /* Returns the first interrupt number which is pending.
405      The interrupt priority is specified by the table `interrupt_order'.
406      For these interrupts, the pending mask is cleared when the program
407      performs some actions on the corresponding device.  If the device
408      is not reset, the interrupt remains and will be re-raised when
409      we return from the interrupt (see 68HC11 pink book).  */
410   for (i = 0; i < M6811_INT_NUMBER; i++)
411     {
412       enum M6811_INT int_number = interrupts->interrupt_order[i];
413 
414       if (interrupts->pending_mask & (1 << int_number))
415 	{
416 	  return int_number;
417 	}
418     }
419   return -1;
420 }
421 
422 
423 /* Process the current interrupt if there is one.  This operation must
424    be called after each instruction to handle the interrupts.  If interrupts
425    are masked, it does nothing.  */
426 int
427 interrupts_process (struct interrupts *interrupts)
428 {
429   int id;
430   uint8_t ccr;
431 
432   /* See if interrupts are enabled/disabled and keep track of the
433      number of cycles the interrupts are masked.  Such information is
434      then reported by the info command.  */
435   ccr = cpu_get_ccr (interrupts->cpu);
436   if (ccr & M6811_I_BIT)
437     {
438       if (interrupts->start_mask_cycle < 0)
439         interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
440     }
441   else if (interrupts->start_mask_cycle >= 0
442            && (ccr & M6811_I_BIT) == 0)
443     {
444       int64_t t = cpu_current_cycle (interrupts->cpu);
445 
446       t -= interrupts->start_mask_cycle;
447       if (t < interrupts->min_mask_cycles)
448         interrupts->min_mask_cycles = t;
449       if (t > interrupts->max_mask_cycles)
450         interrupts->max_mask_cycles = t;
451       interrupts->start_mask_cycle = -1;
452       interrupts->last_mask_cycles = t;
453     }
454   if (ccr & M6811_X_BIT)
455     {
456       if (interrupts->xirq_start_mask_cycle < 0)
457         interrupts->xirq_start_mask_cycle
458 	  = cpu_current_cycle (interrupts->cpu);
459     }
460   else if (interrupts->xirq_start_mask_cycle >= 0
461            && (ccr & M6811_X_BIT) == 0)
462     {
463       int64_t t = cpu_current_cycle (interrupts->cpu);
464 
465       t -= interrupts->xirq_start_mask_cycle;
466       if (t < interrupts->xirq_min_mask_cycles)
467         interrupts->xirq_min_mask_cycles = t;
468       if (t > interrupts->xirq_max_mask_cycles)
469         interrupts->xirq_max_mask_cycles = t;
470       interrupts->xirq_start_mask_cycle = -1;
471       interrupts->xirq_last_mask_cycles = t;
472     }
473 
474   id = interrupts_get_current (interrupts);
475   if (id >= 0)
476     {
477       uint16_t addr;
478       struct interrupt_history *h;
479 
480       /* Implement the breakpoint-on-interrupt.  */
481       if (interrupts->interrupts[id].stop_mode & SIM_STOP_WHEN_TAKEN)
482         {
483           sim_io_printf (CPU_STATE (interrupts->cpu),
484                          "Interrupt %s will be handled\n",
485                          interrupt_names[id]);
486           sim_engine_halt (CPU_STATE (interrupts->cpu),
487                            interrupts->cpu,
488                            0, cpu_get_pc (interrupts->cpu),
489                            sim_stopped,
490                            SIM_SIGTRAP);
491         }
492 
493       cpu_push_all (interrupts->cpu);
494       addr = memory_read16 (interrupts->cpu,
495                             interrupts->vectors_addr + id * 2);
496       cpu_call (interrupts->cpu, addr);
497 
498       /* Now, protect from nested interrupts.  */
499       if (id == M6811_INT_XIRQ)
500 	{
501 	  cpu_set_ccr_X (interrupts->cpu, 1);
502 	}
503       else
504 	{
505 	  cpu_set_ccr_I (interrupts->cpu, 1);
506 	}
507 
508       /* Update the interrupt history table.  */
509       h = &interrupts->interrupts_history[interrupts->history_index];
510       h->type = id;
511       h->taken_cycle = cpu_current_cycle (interrupts->cpu);
512       h->raised_cycle = interrupts->interrupts[id].cpu_cycle;
513 
514       if (interrupts->history_index >= MAX_INT_HISTORY-1)
515         interrupts->history_index = 0;
516       else
517         interrupts->history_index++;
518 
519       interrupts->nb_interrupts_raised++;
520       cpu_add_cycles (interrupts->cpu, 14);
521       return 1;
522     }
523   return 0;
524 }
525 
526 void
527 interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
528 {
529   interrupts->pending_mask |= (1 << number);
530   interrupts->nb_interrupts_raised ++;
531 }
532 
533 void
534 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
535 {
536   int64_t t, prev_interrupt;
537   int i;
538 
539   sim_io_printf (sd, "Interrupts Info:\n");
540   sim_io_printf (sd, "  Interrupts raised: %lu\n",
541                  interrupts->nb_interrupts_raised);
542 
543   if (interrupts->start_mask_cycle >= 0)
544     {
545       t = cpu_current_cycle (interrupts->cpu);
546 
547       t -= interrupts->start_mask_cycle;
548       if (t > interrupts->max_mask_cycles)
549         interrupts->max_mask_cycles = t;
550 
551       sim_io_printf (sd, "  Current interrupts masked sequence:   %s\n",
552                      cycle_to_string (interrupts->cpu, t,
553                                       PRINT_TIME | PRINT_CYCLE));
554     }
555   t = interrupts->min_mask_cycles == CYCLES_MAX ?
556     interrupts->max_mask_cycles :
557     interrupts->min_mask_cycles;
558   sim_io_printf (sd, "  Shortest interrupts masked sequence:  %s\n",
559                  cycle_to_string (interrupts->cpu, t,
560                                   PRINT_TIME | PRINT_CYCLE));
561 
562   t = interrupts->max_mask_cycles;
563   sim_io_printf (sd, "  Longest interrupts masked sequence:   %s\n",
564                  cycle_to_string (interrupts->cpu, t,
565                                   PRINT_TIME | PRINT_CYCLE));
566 
567   t = interrupts->last_mask_cycles;
568   sim_io_printf (sd, "  Last interrupts masked sequence:      %s\n",
569                  cycle_to_string (interrupts->cpu, t,
570                                   PRINT_TIME | PRINT_CYCLE));
571 
572   if (interrupts->xirq_start_mask_cycle >= 0)
573     {
574       t = cpu_current_cycle (interrupts->cpu);
575 
576       t -= interrupts->xirq_start_mask_cycle;
577       if (t > interrupts->xirq_max_mask_cycles)
578         interrupts->xirq_max_mask_cycles = t;
579 
580       sim_io_printf (sd, "  XIRQ Current interrupts masked sequence: %s\n",
581                      cycle_to_string (interrupts->cpu, t,
582                                       PRINT_TIME | PRINT_CYCLE));
583     }
584 
585   t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
586     interrupts->xirq_max_mask_cycles :
587     interrupts->xirq_min_mask_cycles;
588   sim_io_printf (sd, "  XIRQ Min interrupts masked sequence:  %s\n",
589                  cycle_to_string (interrupts->cpu, t,
590                                   PRINT_TIME | PRINT_CYCLE));
591 
592   t = interrupts->xirq_max_mask_cycles;
593   sim_io_printf (sd, "  XIRQ Max interrupts masked sequence:  %s\n",
594                  cycle_to_string (interrupts->cpu, t,
595                                   PRINT_TIME | PRINT_CYCLE));
596 
597   t = interrupts->xirq_last_mask_cycles;
598   sim_io_printf (sd, "  XIRQ Last interrupts masked sequence: %s\n",
599                  cycle_to_string (interrupts->cpu, t,
600                                   PRINT_TIME | PRINT_CYCLE));
601 
602   if (interrupts->pending_mask)
603     {
604       sim_io_printf (sd, "  Pending interrupts : ");
605       for (i = 0; i < M6811_INT_NUMBER; i++)
606         {
607           enum M6811_INT int_number = interrupts->interrupt_order[i];
608 
609           if (interrupts->pending_mask & (1 << int_number))
610             {
611               sim_io_printf (sd, "%s ", interrupt_names[int_number]);
612             }
613         }
614       sim_io_printf (sd, "\n");
615     }
616 
617   prev_interrupt = 0;
618   sim_io_printf (sd, "N  Interrupt     Cycle Taken         Latency"
619                  "   Delta between interrupts\n");
620   for (i = 0; i < MAX_INT_HISTORY; i++)
621     {
622       int which;
623       struct interrupt_history *h;
624       int64_t dt;
625 
626       which = interrupts->history_index - i - 1;
627       if (which < 0)
628         which += MAX_INT_HISTORY;
629       h = &interrupts->interrupts_history[which];
630       if (h->taken_cycle == 0)
631         break;
632 
633       dt = h->taken_cycle - h->raised_cycle;
634       sim_io_printf (sd, "%2d %-9.9s %15.15s ", i,
635                      interrupt_names[h->type],
636                      cycle_to_string (interrupts->cpu, h->taken_cycle, 0));
637       sim_io_printf (sd, "%15.15s",
638                      cycle_to_string (interrupts->cpu, dt, 0));
639       if (prev_interrupt)
640         {
641           dt = prev_interrupt - h->taken_cycle;
642           sim_io_printf (sd, " %s",
643                          cycle_to_string (interrupts->cpu, dt, PRINT_TIME));
644         }
645       sim_io_printf (sd, "\n");
646       prev_interrupt = h->taken_cycle;
647     }
648 }
649