[PATCH 5/57][Arm][GAS] Add support for MVE instructions: vmull{b,t}
[binutils-gdb.git] / sim / m68hc11 / interrupts.c
blob496ea516c21654730c5bf81b1342a948c3d2bc5e
1 /* interrupts.c -- 68HC11 Interrupts Emulation
2 Copyright 1999-2019 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.fr)
5 This file is part of GDB, GAS, and the GNU binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "sim-main.h"
21 #include "sim-options.h"
23 static 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",
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"
59 struct 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 },
66 /* SPI interrupts. */
67 { M6811_INT_SPI, M6811_SPSR, M6811_SPIF, M6811_SPCR, M6811_SPIE },
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 },
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 },
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 },
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
94 #define CYCLES_MAX ((((signed64) 1) << 62) - 1)
96 enum
98 OPTION_INTERRUPT_INFO = OPTION_START,
99 OPTION_INTERRUPT_CATCH,
100 OPTION_INTERRUPT_CLEAR
103 static DECLARE_OPTION_HANDLER (interrupt_option_handler);
105 static const OPTION interrupt_options[] =
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 },
120 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
123 /* Initialize the interrupts module. */
124 void
125 interrupts_initialize (SIM_DESC sd, sim_cpu *cpu)
127 struct interrupts *interrupts = &cpu->cpu_interrupts;
129 interrupts->cpu = cpu;
131 sim_add_option_table (sd, 0, interrupt_options);
134 /* Initialize the interrupts of the processor. */
135 void
136 interrupts_reset (struct interrupts *interrupts)
138 int i;
140 interrupts->pending_mask = 0;
141 if (interrupts->cpu->cpu_mode & M6811_SMOD)
142 interrupts->vectors_addr = 0xbfc0;
143 else
144 interrupts->vectors_addr = 0xffc0;
145 interrupts->nb_interrupts_raised = 0;
146 interrupts->min_mask_cycles = CYCLES_MAX;
147 interrupts->max_mask_cycles = 0;
148 interrupts->last_mask_cycles = 0;
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;
153 interrupts->xirq_last_mask_cycles = 0;
155 for (i = 0; i < M6811_INT_NUMBER; i++)
157 interrupts->interrupt_order[i] = i;
160 /* Clear the interrupt history table. */
161 interrupts->history_index = 0;
162 memset (interrupts->interrupts_history, 0,
163 sizeof (interrupts->interrupts_history));
165 memset (interrupts->interrupts, 0,
166 sizeof (interrupts->interrupts));
168 /* In bootstrap mode, initialize the vector table to point
169 to the RAM location. */
170 if (interrupts->cpu->cpu_mode == M6811_SMOD)
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++)
176 memory_write16 (interrupts->cpu, addr, vector);
177 addr += 2;
178 vector += 3;
183 static int
184 find_interrupt (const char *name)
186 int i;
188 if (name)
189 for (i = 0; i < M6811_INT_NUMBER; i++)
190 if (strcasecmp (name, interrupt_names[i]) == 0)
191 return i;
193 return -1;
196 static SIM_RC
197 interrupt_option_handler (SIM_DESC sd, sim_cpu *cpu,
198 int opt, char *arg, int is_command)
200 char *p;
201 int mode;
202 int id;
203 struct interrupts *interrupts;
205 if (cpu == 0)
206 cpu = STATE_CPU (sd, 0);
208 interrupts = &cpu->cpu_interrupts;
209 switch (opt)
211 case OPTION_INTERRUPT_INFO:
212 for (id = 0; id < M6811_INT_NUMBER; id++)
214 sim_io_eprintf (sd, "%-10.10s ", interrupt_names[id]);
215 switch (interrupts->interrupts[id].stop_mode)
217 case SIM_STOP_WHEN_RAISED:
218 sim_io_eprintf (sd, "catch raised ");
219 break;
221 case SIM_STOP_WHEN_TAKEN:
222 sim_io_eprintf (sd, "catch taken ");
223 break;
225 case SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN:
226 sim_io_eprintf (sd, "catch all ");
227 break;
229 default:
230 sim_io_eprintf (sd, " ");
231 break;
233 sim_io_eprintf (sd, "%ld\n",
234 interrupts->interrupts[id].raised_count);
236 break;
238 case OPTION_INTERRUPT_CATCH:
239 p = strchr (arg, ',');
240 if (p)
241 *p++ = 0;
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);
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)
256 sim_io_eprintf (sd, "Invalid argument: %s\n", p);
257 break;
259 if (id >= 0)
260 interrupts->interrupts[id].stop_mode = mode;
261 break;
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;
273 return SIM_RC_OK;
276 /* Update the mask of pending interrupts. This operation must be called
277 when the state of some 68HC11 IO register changes. It looks the
278 different registers that indicate a pending interrupt (timer, SCI, SPI,
279 ...) and records the interrupt if it's there and enabled. */
280 void
281 interrupts_update_pending (struct interrupts *interrupts)
283 int i;
284 uint8 *ioregs;
285 unsigned long clear_mask;
286 unsigned long set_mask;
288 clear_mask = 0;
289 set_mask = 0;
290 ioregs = &interrupts->cpu->ios[0];
292 for (i = 0; i < ARRAY_SIZE (idefs); i++)
294 struct interrupt_def *idef = &idefs[i];
295 uint8 data;
297 /* Look if the interrupt is enabled. */
298 if (idef->enable_paddr)
300 data = ioregs[idef->enable_paddr];
301 if (!(data & idef->enabled_mask))
303 /* Disable it. */
304 clear_mask |= (1 << idef->int_number);
305 continue;
309 /* Interrupt is enabled, see if it's there. */
310 data = ioregs[idef->int_paddr];
311 if (!(data & idef->int_mask))
313 /* Disable it. */
314 clear_mask |= (1 << idef->int_number);
315 continue;
318 /* Ok, raise it. */
319 set_mask |= (1 << idef->int_number);
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;
327 /* Keep track of when the interrupt is raised by the device.
328 Also implements the breakpoint-on-interrupt. */
329 if (set_mask)
331 signed64 cycle = cpu_current_cycle (interrupts->cpu);
332 int must_stop = 0;
334 for (i = 0; i < M6811_INT_NUMBER; i++)
336 if (!(set_mask & (1 << i)))
337 continue;
339 interrupts->interrupts[i].cpu_cycle = cycle;
340 if (interrupts->interrupts[i].stop_mode & SIM_STOP_WHEN_RAISED)
342 must_stop = 1;
343 sim_io_printf (CPU_STATE (interrupts->cpu),
344 "Interrupt %s raised\n",
345 interrupt_names[i]);
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);
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. */
362 interrupts_get_current (struct interrupts *interrupts)
364 int i;
366 if (interrupts->pending_mask == 0)
367 return -1;
369 /* SWI and illegal instructions are simulated by an interrupt.
370 They are not maskable. */
371 if (interrupts->pending_mask & (1 << M6811_INT_SWI))
373 interrupts->pending_mask &= ~(1 << M6811_INT_SWI);
374 return M6811_INT_SWI;
376 if (interrupts->pending_mask & (1 << M6811_INT_ILLEGAL))
378 interrupts->pending_mask &= ~(1 << M6811_INT_ILLEGAL);
379 return M6811_INT_ILLEGAL;
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))
386 if (cpu_get_ccr_X (interrupts->cpu) == 0)
388 interrupts->pending_mask &= ~(1 << M6811_INT_XIRQ);
389 return M6811_INT_XIRQ;
391 return -1;
394 /* Interrupts are masked, do nothing. */
395 if (cpu_get_ccr_I (interrupts->cpu) == 1)
397 return -1;
400 /* Returns the first interrupt number which is pending.
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). */
406 for (i = 0; i < M6811_INT_NUMBER; i++)
408 enum M6811_INT int_number = interrupts->interrupt_order[i];
410 if (interrupts->pending_mask & (1 << int_number))
412 return int_number;
415 return -1;
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. */
423 interrupts_process (struct interrupts *interrupts)
425 int id;
426 uint8 ccr;
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)
434 if (interrupts->start_mask_cycle < 0)
435 interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
437 else if (interrupts->start_mask_cycle >= 0
438 && (ccr & M6811_I_BIT) == 0)
440 signed64 t = cpu_current_cycle (interrupts->cpu);
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;
448 interrupts->last_mask_cycles = t;
450 if (ccr & M6811_X_BIT)
452 if (interrupts->xirq_start_mask_cycle < 0)
453 interrupts->xirq_start_mask_cycle
454 = cpu_current_cycle (interrupts->cpu);
456 else if (interrupts->xirq_start_mask_cycle >= 0
457 && (ccr & M6811_X_BIT) == 0)
459 signed64 t = cpu_current_cycle (interrupts->cpu);
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;
467 interrupts->xirq_last_mask_cycles = t;
470 id = interrupts_get_current (interrupts);
471 if (id >= 0)
473 uint16 addr;
474 struct interrupt_history *h;
476 /* Implement the breakpoint-on-interrupt. */
477 if (interrupts->interrupts[id].stop_mode & SIM_STOP_WHEN_TAKEN)
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);
489 cpu_push_all (interrupts->cpu);
490 addr = memory_read16 (interrupts->cpu,
491 interrupts->vectors_addr + id * 2);
492 cpu_call (interrupts->cpu, addr);
494 /* Now, protect from nested interrupts. */
495 if (id == M6811_INT_XIRQ)
497 cpu_set_ccr_X (interrupts->cpu, 1);
499 else
501 cpu_set_ccr_I (interrupts->cpu, 1);
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;
510 if (interrupts->history_index >= MAX_INT_HISTORY-1)
511 interrupts->history_index = 0;
512 else
513 interrupts->history_index++;
515 interrupts->nb_interrupts_raised++;
516 cpu_add_cycles (interrupts->cpu, 14);
517 return 1;
519 return 0;
522 void
523 interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
525 interrupts->pending_mask |= (1 << number);
526 interrupts->nb_interrupts_raised ++;
529 void
530 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
532 signed64 t, prev_interrupt;
533 int i;
535 sim_io_printf (sd, "Interrupts Info:\n");
536 sim_io_printf (sd, " Interrupts raised: %lu\n",
537 interrupts->nb_interrupts_raised);
539 if (interrupts->start_mask_cycle >= 0)
541 t = cpu_current_cycle (interrupts->cpu);
543 t -= interrupts->start_mask_cycle;
544 if (t > interrupts->max_mask_cycles)
545 interrupts->max_mask_cycles = t;
547 sim_io_printf (sd, " Current interrupts masked sequence: %s\n",
548 cycle_to_string (interrupts->cpu, t,
549 PRINT_TIME | PRINT_CYCLE));
551 t = interrupts->min_mask_cycles == CYCLES_MAX ?
552 interrupts->max_mask_cycles :
553 interrupts->min_mask_cycles;
554 sim_io_printf (sd, " Shortest interrupts masked sequence: %s\n",
555 cycle_to_string (interrupts->cpu, t,
556 PRINT_TIME | PRINT_CYCLE));
558 t = interrupts->max_mask_cycles;
559 sim_io_printf (sd, " Longest interrupts masked sequence: %s\n",
560 cycle_to_string (interrupts->cpu, t,
561 PRINT_TIME | PRINT_CYCLE));
563 t = interrupts->last_mask_cycles;
564 sim_io_printf (sd, " Last interrupts masked sequence: %s\n",
565 cycle_to_string (interrupts->cpu, t,
566 PRINT_TIME | PRINT_CYCLE));
568 if (interrupts->xirq_start_mask_cycle >= 0)
570 t = cpu_current_cycle (interrupts->cpu);
572 t -= interrupts->xirq_start_mask_cycle;
573 if (t > interrupts->xirq_max_mask_cycles)
574 interrupts->xirq_max_mask_cycles = t;
576 sim_io_printf (sd, " XIRQ Current interrupts masked sequence: %s\n",
577 cycle_to_string (interrupts->cpu, t,
578 PRINT_TIME | PRINT_CYCLE));
581 t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
582 interrupts->xirq_max_mask_cycles :
583 interrupts->xirq_min_mask_cycles;
584 sim_io_printf (sd, " XIRQ Min interrupts masked sequence: %s\n",
585 cycle_to_string (interrupts->cpu, t,
586 PRINT_TIME | PRINT_CYCLE));
588 t = interrupts->xirq_max_mask_cycles;
589 sim_io_printf (sd, " XIRQ Max interrupts masked sequence: %s\n",
590 cycle_to_string (interrupts->cpu, t,
591 PRINT_TIME | PRINT_CYCLE));
593 t = interrupts->xirq_last_mask_cycles;
594 sim_io_printf (sd, " XIRQ Last interrupts masked sequence: %s\n",
595 cycle_to_string (interrupts->cpu, t,
596 PRINT_TIME | PRINT_CYCLE));
598 if (interrupts->pending_mask)
600 sim_io_printf (sd, " Pending interrupts : ");
601 for (i = 0; i < M6811_INT_NUMBER; i++)
603 enum M6811_INT int_number = interrupts->interrupt_order[i];
605 if (interrupts->pending_mask & (1 << int_number))
607 sim_io_printf (sd, "%s ", interrupt_names[int_number]);
610 sim_io_printf (sd, "\n");
613 prev_interrupt = 0;
614 sim_io_printf (sd, "N Interrupt Cycle Taken Latency"
615 " Delta between interrupts\n");
616 for (i = 0; i < MAX_INT_HISTORY; i++)
618 int which;
619 struct interrupt_history *h;
620 signed64 dt;
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;
629 dt = h->taken_cycle - h->raised_cycle;
630 sim_io_printf (sd, "%2d %-9.9s %15.15s ", i,
631 interrupt_names[h->type],
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)
637 dt = prev_interrupt - h->taken_cycle;
638 sim_io_printf (sd, " %s",
639 cycle_to_string (interrupts->cpu, dt, PRINT_TIME));
641 sim_io_printf (sd, "\n");
642 prev_interrupt = h->taken_cycle;