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