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