OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [m68hc11/] [interrupts.c] - Blame information for rev 309

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* interrupts.c -- 68HC11 Interrupts Emulation
2
   Copyright 1999, 2000, 2001, 2002, 2003, 2007, 2008
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.