Update copyright year range in all GDB files.
[deliverable/binutils-gdb.git] / sim / m68hc11 / interrupts.c
CommitLineData
e0709f50 1/* interrupts.c -- 68HC11 Interrupts Emulation
b811d2c2 2 Copyright 1999-2020 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
AC
19
20#include "sim-main.h"
26128965
SC
21#include "sim-options.h"
22
23static 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};
e0709f50
AC
58
59struct 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 },
26128965
SC
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},
e0709f50
AC
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
e0709f50
AC
94#define CYCLES_MAX ((((signed64) 1) << 62) - 1)
95
26128965
SC
96enum
97{
98 OPTION_INTERRUPT_INFO = OPTION_START,
99 OPTION_INTERRUPT_CATCH,
100 OPTION_INTERRUPT_CLEAR
101};
102
103static DECLARE_OPTION_HANDLER (interrupt_option_handler);
104
105static 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. */
124void
6f64fd48 125interrupts_initialize (SIM_DESC sd, sim_cpu *cpu)
e0709f50 126{
6f64fd48 127 struct interrupts *interrupts = &cpu->cpu_interrupts;
e0709f50 128
6f64fd48 129 interrupts->cpu = cpu;
26128965
SC
130
131 sim_add_option_table (sd, 0, interrupt_options);
132}
133
134/* Initialize the interrupts of the processor. */
135void
136interrupts_reset (struct interrupts *interrupts)
137{
138 int i;
139
e0709f50 140 interrupts->pending_mask = 0;
26128965
SC
141 if (interrupts->cpu->cpu_mode & M6811_SMOD)
142 interrupts->vectors_addr = 0xbfc0;
143 else
144 interrupts->vectors_addr = 0xffc0;
e0709f50
AC
145 interrupts->nb_interrupts_raised = 0;
146 interrupts->min_mask_cycles = CYCLES_MAX;
147 interrupts->max_mask_cycles = 0;
11115521 148 interrupts->last_mask_cycles = 0;
e0709f50
AC
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;
11115521 153 interrupts->xirq_last_mask_cycles = 0;
e0709f50
AC
154
155 for (i = 0; i < M6811_INT_NUMBER; i++)
156 {
157 interrupts->interrupt_order[i] = i;
158 }
26128965
SC
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));
a685700c
SC
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 }
26128965
SC
181}
182
183static int
184find_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;
e0709f50
AC
194}
195
26128965
SC
196static SIM_RC
197interrupt_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}
e0709f50
AC
275
276/* Update the mask of pending interrupts. This operation must be called
26128965 277 when the state of some 68HC11 IO register changes. It looks the
e0709f50
AC
278 different registers that indicate a pending interrupt (timer, SCI, SPI,
279 ...) and records the interrupt if it's there and enabled. */
280void
281interrupts_update_pending (struct interrupts *interrupts)
282{
283 int i;
284 uint8 *ioregs;
11115521
SC
285 unsigned long clear_mask;
286 unsigned long set_mask;
e0709f50 287
11115521
SC
288 clear_mask = 0;
289 set_mask = 0;
e0709f50
AC
290 ioregs = &interrupts->cpu->ios[0];
291
13a590ca 292 for (i = 0; i < ARRAY_SIZE (idefs); i++)
e0709f50
AC
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))
a8afa79a
SC
302 {
303 /* Disable it. */
11115521 304 clear_mask |= (1 << idef->int_number);
a8afa79a
SC
305 continue;
306 }
e0709f50
AC
307 }
308
309 /* Interrupt is enabled, see if it's there. */
310 data = ioregs[idef->int_paddr];
311 if (!(data & idef->int_mask))
a8afa79a
SC
312 {
313 /* Disable it. */
11115521 314 clear_mask |= (1 << idef->int_number);
a8afa79a
SC
315 continue;
316 }
e0709f50
AC
317
318 /* Ok, raise it. */
11115521 319 set_mask |= (1 << idef->int_number);
e0709f50 320 }
11115521
SC
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;
26128965
SC
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 }
e0709f50
AC
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. */
361int
362interrupts_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.
a8afa79a
SC
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). */
e0709f50
AC
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 {
e0709f50
AC
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. */
422int
423interrupts_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;
11115521 448 interrupts->last_mask_cycles = t;
e0709f50
AC
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;
11115521 467 interrupts->xirq_last_mask_cycles = t;
e0709f50
AC
468 }
469
470 id = interrupts_get_current (interrupts);
471 if (id >= 0)
472 {
473 uint16 addr;
26128965
SC
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
e0709f50
AC
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
26128965
SC
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
e0709f50
AC
515 interrupts->nb_interrupts_raised++;
516 cpu_add_cycles (interrupts->cpu, 14);
517 return 1;
518 }
519 return 0;
520}
521
522void
523interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
524{
525 interrupts->pending_mask |= (1 << number);
526 interrupts->nb_interrupts_raised ++;
527}
528
e0709f50
AC
529void
530interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
531{
a685700c 532 signed64 t, prev_interrupt;
26128965 533 int i;
2990a9f4 534
11115521
SC
535 sim_io_printf (sd, "Interrupts Info:\n");
536 sim_io_printf (sd, " Interrupts raised: %lu\n",
537 interrupts->nb_interrupts_raised);
538
e0709f50
AC
539 if (interrupts->start_mask_cycle >= 0)
540 {
2990a9f4 541 t = cpu_current_cycle (interrupts->cpu);
e0709f50
AC
542
543 t -= interrupts->start_mask_cycle;
544 if (t > interrupts->max_mask_cycles)
545 interrupts->max_mask_cycles = t;
e0709f50 546
26128965 547 sim_io_printf (sd, " Current interrupts masked sequence: %s\n",
a685700c
SC
548 cycle_to_string (interrupts->cpu, t,
549 PRINT_TIME | PRINT_CYCLE));
e0709f50 550 }
2990a9f4
SC
551 t = interrupts->min_mask_cycles == CYCLES_MAX ?
552 interrupts->max_mask_cycles :
553 interrupts->min_mask_cycles;
26128965 554 sim_io_printf (sd, " Shortest interrupts masked sequence: %s\n",
a685700c
SC
555 cycle_to_string (interrupts->cpu, t,
556 PRINT_TIME | PRINT_CYCLE));
2990a9f4
SC
557
558 t = interrupts->max_mask_cycles;
26128965 559 sim_io_printf (sd, " Longest interrupts masked sequence: %s\n",
a685700c
SC
560 cycle_to_string (interrupts->cpu, t,
561 PRINT_TIME | PRINT_CYCLE));
2990a9f4 562
11115521 563 t = interrupts->last_mask_cycles;
26128965 564 sim_io_printf (sd, " Last interrupts masked sequence: %s\n",
a685700c
SC
565 cycle_to_string (interrupts->cpu, t,
566 PRINT_TIME | PRINT_CYCLE));
11115521
SC
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",
a685700c
SC
577 cycle_to_string (interrupts->cpu, t,
578 PRINT_TIME | PRINT_CYCLE));
11115521
SC
579 }
580
2990a9f4
SC
581 t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
582 interrupts->xirq_max_mask_cycles :
583 interrupts->xirq_min_mask_cycles;
26128965 584 sim_io_printf (sd, " XIRQ Min interrupts masked sequence: %s\n",
a685700c
SC
585 cycle_to_string (interrupts->cpu, t,
586 PRINT_TIME | PRINT_CYCLE));
2990a9f4
SC
587
588 t = interrupts->xirq_max_mask_cycles;
26128965 589 sim_io_printf (sd, " XIRQ Max interrupts masked sequence: %s\n",
a685700c
SC
590 cycle_to_string (interrupts->cpu, t,
591 PRINT_TIME | PRINT_CYCLE));
11115521
SC
592
593 t = interrupts->xirq_last_mask_cycles;
594 sim_io_printf (sd, " XIRQ Last interrupts masked sequence: %s\n",
a685700c
SC
595 cycle_to_string (interrupts->cpu, t,
596 PRINT_TIME | PRINT_CYCLE));
26128965
SC
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
a685700c
SC
613 prev_interrupt = 0;
614 sim_io_printf (sd, "N Interrupt Cycle Taken Latency"
615 " Delta between interrupts\n");
26128965
SC
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;
a685700c 630 sim_io_printf (sd, "%2d %-9.9s %15.15s ", i,
26128965 631 interrupt_names[h->type],
a685700c
SC
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;
26128965 643 }
e0709f50 644}
This page took 0.883516 seconds and 4 git commands to generate.