1 /* interrupts.c -- 68HC11 Interrupts Emulation
2 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
5 This file is part of GDB, GAS, and the GNU binutils.
7 GDB, GAS, and the GNU binutils are free software; you can redistribute
8 them and/or modify them under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either version
10 1, or (at your option) any later version.
12 GDB, GAS, and the GNU binutils are distributed in the hope that they
13 will be useful, but WITHOUT ANY WARRANTY; without even the implied
14 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this file; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "sim-options.h"
24 static const char *interrupt_names[] = {
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 },
68 { M6811_INT_SPI, M6811_SPSR, M6811_SPIF, M6811_SPCR, M6811_SPIE },
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 },
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 },
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 },
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},
90 { M6811_INT_COPRESET, M6811_CONFIG, M6811_NOCOP, 0, 0 },
91 { M6811_INT_COPFAIL, M6811_CONFIG, M6811_NOCOP, 0, 0 }
95 #define TableSize(X) (sizeof X / sizeof(X[0]))
96 #define CYCLES_MAX ((((signed64) 1) << 62) - 1)
100 OPTION_INTERRUPT_INFO = OPTION_START,
101 OPTION_INTERRUPT_CATCH,
102 OPTION_INTERRUPT_CLEAR
105 static DECLARE_OPTION_HANDLER (interrupt_option_handler);
107 static const OPTION interrupt_options[] =
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 },
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 },
122 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
125 /* Initialize the interrupts module. */
127 interrupts_initialize (SIM_DESC sd, struct _sim_cpu *proc)
129 struct interrupts *interrupts = &proc->cpu_interrupts;
131 interrupts->cpu = proc;
133 sim_add_option_table (sd, 0, interrupt_options);
136 /* Initialize the interrupts of the processor. */
138 interrupts_reset (struct interrupts *interrupts)
142 interrupts->pending_mask = 0;
143 if (interrupts->cpu->cpu_mode & M6811_SMOD)
144 interrupts->vectors_addr = 0xbfc0;
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;
157 for (i = 0; i < M6811_INT_NUMBER; i++)
159 interrupts->interrupt_order[i] = i;
162 /* Clear the interrupt history table. */
163 interrupts->history_index = 0;
164 memset (interrupts->interrupts_history, 0,
165 sizeof (interrupts->interrupts_history));
167 memset (interrupts->interrupts, 0,
168 sizeof (interrupts->interrupts));
172 find_interrupt (const char *name)
177 for (i = 0; i < M6811_INT_NUMBER; i++)
178 if (strcasecmp (name, interrupt_names[i]) == 0)
185 interrupt_option_handler (SIM_DESC sd, sim_cpu *cpu,
186 int opt, char *arg, int is_command)
191 struct interrupts *interrupts;
194 cpu = STATE_CPU (sd, 0);
196 interrupts = &cpu->cpu_interrupts;
199 case OPTION_INTERRUPT_INFO:
200 for (id = 0; id < M6811_INT_NUMBER; id++)
202 sim_io_eprintf (sd, "%-10.10s ", interrupt_names[id]);
203 switch (interrupts->interrupts[id].stop_mode)
205 case SIM_STOP_WHEN_RAISED:
206 sim_io_eprintf (sd, "catch raised ");
209 case SIM_STOP_WHEN_TAKEN:
210 sim_io_eprintf (sd, "catch taken ");
213 case SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN:
214 sim_io_eprintf (sd, "catch all ");
218 sim_io_eprintf (sd, " ");
221 sim_io_eprintf (sd, "%ld\n",
222 interrupts->interrupts[id].raised_count);
226 case OPTION_INTERRUPT_CATCH:
227 p = strchr (arg, ',');
231 mode = SIM_STOP_WHEN_RAISED;
232 id = find_interrupt (arg);
234 sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);
236 if (p && strcasecmp (p, "raised") == 0)
237 mode = SIM_STOP_WHEN_RAISED;
238 else if (p && strcasecmp (p, "taken") == 0)
239 mode = SIM_STOP_WHEN_TAKEN;
240 else if (p && strcasecmp (p, "all") == 0)
241 mode = SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN;
244 sim_io_eprintf (sd, "Invalid argument: %s\n", p);
248 interrupts->interrupts[id].stop_mode = mode;
251 case OPTION_INTERRUPT_CLEAR:
252 mode = SIM_STOP_WHEN_RAISED;
253 id = find_interrupt (arg);
255 sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);
257 interrupts->interrupts[id].stop_mode = 0;
264 /* Update the mask of pending interrupts. This operation must be called
265 when the state of some 68HC11 IO register changes. It looks the
266 different registers that indicate a pending interrupt (timer, SCI, SPI,
267 ...) and records the interrupt if it's there and enabled. */
269 interrupts_update_pending (struct interrupts *interrupts)
273 unsigned long clear_mask;
274 unsigned long set_mask;
278 ioregs = &interrupts->cpu->ios[0];
280 for (i = 0; i < TableSize(idefs); i++)
282 struct interrupt_def *idef = &idefs[i];
285 /* Look if the interrupt is enabled. */
286 if (idef->enable_paddr)
288 data = ioregs[idef->enable_paddr];
289 if (!(data & idef->enabled_mask))
292 clear_mask |= (1 << idef->int_number);
297 /* Interrupt is enabled, see if it's there. */
298 data = ioregs[idef->int_paddr];
299 if (!(data & idef->int_mask))
302 clear_mask |= (1 << idef->int_number);
307 set_mask |= (1 << idef->int_number);
310 /* Some interrupts are shared (M6811_INT_SCI) so clear
311 the interrupts before setting the new ones. */
312 interrupts->pending_mask &= ~clear_mask;
313 interrupts->pending_mask |= set_mask;
315 /* Keep track of when the interrupt is raised by the device.
316 Also implements the breakpoint-on-interrupt. */
319 signed64 cycle = cpu_current_cycle (interrupts->cpu);
322 for (i = 0; i < M6811_INT_NUMBER; i++)
324 if (!(set_mask & (1 << i)))
327 interrupts->interrupts[i].cpu_cycle = cycle;
328 if (interrupts->interrupts[i].stop_mode & SIM_STOP_WHEN_RAISED)
331 sim_io_printf (CPU_STATE (interrupts->cpu),
332 "Interrupt %s raised\n",
337 sim_engine_halt (CPU_STATE (interrupts->cpu),
339 0, cpu_get_pc (interrupts->cpu),
346 /* Finds the current active and non-masked interrupt.
347 Returns the interrupt number (index in the vector table) or -1
348 if no interrupt can be serviced. */
350 interrupts_get_current (struct interrupts *interrupts)
354 if (interrupts->pending_mask == 0)
357 /* SWI and illegal instructions are simulated by an interrupt.
358 They are not maskable. */
359 if (interrupts->pending_mask & (1 << M6811_INT_SWI))
361 interrupts->pending_mask &= ~(1 << M6811_INT_SWI);
362 return M6811_INT_SWI;
364 if (interrupts->pending_mask & (1 << M6811_INT_ILLEGAL))
366 interrupts->pending_mask &= ~(1 << M6811_INT_ILLEGAL);
367 return M6811_INT_ILLEGAL;
370 /* If there is a non maskable interrupt, go for it (unless we are masked
372 if (interrupts->pending_mask & (1 << M6811_INT_XIRQ))
374 if (cpu_get_ccr_X (interrupts->cpu) == 0)
376 interrupts->pending_mask &= ~(1 << M6811_INT_XIRQ);
377 return M6811_INT_XIRQ;
382 /* Interrupts are masked, do nothing. */
383 if (cpu_get_ccr_I (interrupts->cpu) == 1)
388 /* Returns the first interrupt number which is pending.
389 The interrupt priority is specified by the table `interrupt_order'.
390 For these interrupts, the pending mask is cleared when the program
391 performs some actions on the corresponding device. If the device
392 is not reset, the interrupt remains and will be re-raised when
393 we return from the interrupt (see 68HC11 pink book). */
394 for (i = 0; i < M6811_INT_NUMBER; i++)
396 enum M6811_INT int_number = interrupts->interrupt_order[i];
398 if (interrupts->pending_mask & (1 << int_number))
407 /* Process the current interrupt if there is one. This operation must
408 be called after each instruction to handle the interrupts. If interrupts
409 are masked, it does nothing. */
411 interrupts_process (struct interrupts *interrupts)
416 /* See if interrupts are enabled/disabled and keep track of the
417 number of cycles the interrupts are masked. Such information is
418 then reported by the info command. */
419 ccr = cpu_get_ccr (interrupts->cpu);
420 if (ccr & M6811_I_BIT)
422 if (interrupts->start_mask_cycle < 0)
423 interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
425 else if (interrupts->start_mask_cycle >= 0
426 && (ccr & M6811_I_BIT) == 0)
428 signed64 t = cpu_current_cycle (interrupts->cpu);
430 t -= interrupts->start_mask_cycle;
431 if (t < interrupts->min_mask_cycles)
432 interrupts->min_mask_cycles = t;
433 if (t > interrupts->max_mask_cycles)
434 interrupts->max_mask_cycles = t;
435 interrupts->start_mask_cycle = -1;
436 interrupts->last_mask_cycles = t;
438 if (ccr & M6811_X_BIT)
440 if (interrupts->xirq_start_mask_cycle < 0)
441 interrupts->xirq_start_mask_cycle
442 = cpu_current_cycle (interrupts->cpu);
444 else if (interrupts->xirq_start_mask_cycle >= 0
445 && (ccr & M6811_X_BIT) == 0)
447 signed64 t = cpu_current_cycle (interrupts->cpu);
449 t -= interrupts->xirq_start_mask_cycle;
450 if (t < interrupts->xirq_min_mask_cycles)
451 interrupts->xirq_min_mask_cycles = t;
452 if (t > interrupts->xirq_max_mask_cycles)
453 interrupts->xirq_max_mask_cycles = t;
454 interrupts->xirq_start_mask_cycle = -1;
455 interrupts->xirq_last_mask_cycles = t;
458 id = interrupts_get_current (interrupts);
462 struct interrupt_history *h;
464 /* Implement the breakpoint-on-interrupt. */
465 if (interrupts->interrupts[id].stop_mode & SIM_STOP_WHEN_TAKEN)
467 sim_io_printf (CPU_STATE (interrupts->cpu),
468 "Interrupt %s will be handled\n",
469 interrupt_names[id]);
470 sim_engine_halt (CPU_STATE (interrupts->cpu),
472 0, cpu_get_pc (interrupts->cpu),
477 cpu_push_all (interrupts->cpu);
478 addr = memory_read16 (interrupts->cpu,
479 interrupts->vectors_addr + id * 2);
480 cpu_call (interrupts->cpu, addr);
482 /* Now, protect from nested interrupts. */
483 if (id == M6811_INT_XIRQ)
485 cpu_set_ccr_X (interrupts->cpu, 1);
489 cpu_set_ccr_I (interrupts->cpu, 1);
492 /* Update the interrupt history table. */
493 h = &interrupts->interrupts_history[interrupts->history_index];
495 h->taken_cycle = cpu_current_cycle (interrupts->cpu);
496 h->raised_cycle = interrupts->interrupts[id].cpu_cycle;
498 if (interrupts->history_index >= MAX_INT_HISTORY-1)
499 interrupts->history_index = 0;
501 interrupts->history_index++;
503 interrupts->nb_interrupts_raised++;
504 cpu_add_cycles (interrupts->cpu, 14);
511 interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
513 interrupts->pending_mask |= (1 << number);
514 interrupts->nb_interrupts_raised ++;
518 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
523 sim_io_printf (sd, "Interrupts Info:\n");
524 sim_io_printf (sd, " Interrupts raised: %lu\n",
525 interrupts->nb_interrupts_raised);
527 if (interrupts->start_mask_cycle >= 0)
529 t = cpu_current_cycle (interrupts->cpu);
531 t -= interrupts->start_mask_cycle;
532 if (t > interrupts->max_mask_cycles)
533 interrupts->max_mask_cycles = t;
535 sim_io_printf (sd, " Current interrupts masked sequence: %s\n",
536 cycle_to_string (interrupts->cpu, t));
538 t = interrupts->min_mask_cycles == CYCLES_MAX ?
539 interrupts->max_mask_cycles :
540 interrupts->min_mask_cycles;
541 sim_io_printf (sd, " Shortest interrupts masked sequence: %s\n",
542 cycle_to_string (interrupts->cpu, t));
544 t = interrupts->max_mask_cycles;
545 sim_io_printf (sd, " Longest interrupts masked sequence: %s\n",
546 cycle_to_string (interrupts->cpu, t));
548 t = interrupts->last_mask_cycles;
549 sim_io_printf (sd, " Last interrupts masked sequence: %s\n",
550 cycle_to_string (interrupts->cpu, t));
552 if (interrupts->xirq_start_mask_cycle >= 0)
554 t = cpu_current_cycle (interrupts->cpu);
556 t -= interrupts->xirq_start_mask_cycle;
557 if (t > interrupts->xirq_max_mask_cycles)
558 interrupts->xirq_max_mask_cycles = t;
560 sim_io_printf (sd, " XIRQ Current interrupts masked sequence: %s\n",
561 cycle_to_string (interrupts->cpu, t));
564 t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
565 interrupts->xirq_max_mask_cycles :
566 interrupts->xirq_min_mask_cycles;
567 sim_io_printf (sd, " XIRQ Min interrupts masked sequence: %s\n",
568 cycle_to_string (interrupts->cpu, t));
570 t = interrupts->xirq_max_mask_cycles;
571 sim_io_printf (sd, " XIRQ Max interrupts masked sequence: %s\n",
572 cycle_to_string (interrupts->cpu, t));
574 t = interrupts->xirq_last_mask_cycles;
575 sim_io_printf (sd, " XIRQ Last interrupts masked sequence: %s\n",
576 cycle_to_string (interrupts->cpu, t));
578 if (interrupts->pending_mask)
580 sim_io_printf (sd, " Pending interrupts : ");
581 for (i = 0; i < M6811_INT_NUMBER; i++)
583 enum M6811_INT int_number = interrupts->interrupt_order[i];
585 if (interrupts->pending_mask & (1 << int_number))
587 sim_io_printf (sd, "%s ", interrupt_names[int_number]);
590 sim_io_printf (sd, "\n");
593 for (i = 0; i < MAX_INT_HISTORY; i++)
596 struct interrupt_history *h;
599 which = interrupts->history_index - i - 1;
601 which += MAX_INT_HISTORY;
602 h = &interrupts->interrupts_history[which];
603 if (h->taken_cycle == 0)
606 dt = h->taken_cycle - h->raised_cycle;
607 sim_io_printf (sd, "%2d %-10.10s %30.30s ", i,
608 interrupt_names[h->type],
609 cycle_to_string (interrupts->cpu, h->taken_cycle));
610 sim_io_printf (sd, "%s\n",
611 cycle_to_string (interrupts->cpu, dt));