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