Commit | Line | Data |
---|---|---|
e0709f50 | 1 | /* interrupts.h -- 68HC11 Interrupts Emulation |
b811d2c2 | 2 | Copyright 1999-2020 Free Software Foundation, Inc. |
e0709f50 AC |
3 | Written by Stephane Carrez (stcarrez@worldnet.fr) |
4 | ||
5 | This file is part of GDB, GAS, and the GNU binutils. | |
6 | ||
4744ac1b JB |
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. | |
e0709f50 | 11 | |
4744ac1b JB |
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. | |
e0709f50 AC |
16 | |
17 | You should have received a copy of the GNU General Public License | |
4744ac1b | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
e0709f50 AC |
19 | |
20 | #ifndef _M6811_SIM_INTERRUPTS_H | |
21 | #define _M6811_SIM_INTERRUPTS_H | |
22 | ||
23 | /* Definition of 68HC11 interrupts. These enum are used as an index | |
24 | in the interrupt table. */ | |
25 | enum M6811_INT | |
26 | { | |
27 | M6811_INT_RESERVED1 = 0, | |
28 | M6811_INT_RESERVED2, | |
29 | M6811_INT_RESERVED3, | |
30 | M6811_INT_RESERVED4, | |
31 | M6811_INT_RESERVED5, | |
32 | M6811_INT_RESERVED6, | |
33 | M6811_INT_RESERVED7, | |
34 | M6811_INT_RESERVED8, | |
35 | ||
36 | M6811_INT_RESERVED9, | |
37 | M6811_INT_RESERVED10, | |
38 | M6811_INT_RESERVED11, | |
39 | ||
40 | M6811_INT_SCI, | |
41 | M6811_INT_SPI, | |
42 | M6811_INT_AINPUT, | |
43 | M6811_INT_AOVERFLOW, | |
44 | M6811_INT_TCTN, | |
45 | ||
46 | M6811_INT_OUTCMP5, | |
47 | M6811_INT_OUTCMP4, | |
48 | M6811_INT_OUTCMP3, | |
49 | M6811_INT_OUTCMP2, | |
50 | M6811_INT_OUTCMP1, | |
51 | ||
52 | M6811_INT_INCMP3, | |
53 | M6811_INT_INCMP2, | |
54 | M6811_INT_INCMP1, | |
55 | ||
56 | M6811_INT_RT, | |
57 | M6811_INT_IRQ, | |
58 | M6811_INT_XIRQ, | |
59 | M6811_INT_SWI, | |
60 | M6811_INT_ILLEGAL, | |
61 | ||
62 | M6811_INT_COPRESET, | |
63 | M6811_INT_COPFAIL, | |
64 | ||
65 | M6811_INT_RESET, | |
66 | M6811_INT_NUMBER | |
67 | }; | |
68 | ||
69 | ||
70 | /* Structure to describe how to recognize an interrupt in the | |
71 | 68hc11 IO regs. */ | |
72 | struct interrupt_def | |
73 | { | |
74 | enum M6811_INT int_number; | |
75 | unsigned char int_paddr; | |
76 | unsigned char int_mask; | |
77 | unsigned char enable_paddr; | |
78 | unsigned char enabled_mask; | |
79 | }; | |
80 | ||
26128965 SC |
81 | #define MAX_INT_HISTORY 64 |
82 | ||
83 | /* Structure used to keep track of interrupt history. | |
84 | This is used to understand in which order interrupts were | |
85 | raised and when. */ | |
86 | struct interrupt_history | |
87 | { | |
88 | enum M6811_INT type; | |
89 | ||
90 | /* CPU cycle when interrupt handler is called. */ | |
91 | signed64 taken_cycle; | |
92 | ||
93 | /* CPU cycle when the interrupt is first raised by the device. */ | |
94 | signed64 raised_cycle; | |
95 | }; | |
96 | ||
97 | #define SIM_STOP_WHEN_RAISED 1 | |
98 | #define SIM_STOP_WHEN_TAKEN 2 | |
99 | ||
100 | /* Information and control of pending interrupts. */ | |
101 | struct interrupt | |
102 | { | |
103 | /* CPU cycle when the interrupt is raised by the device. */ | |
104 | signed64 cpu_cycle; | |
105 | ||
106 | /* Number of times the interrupt was raised. */ | |
107 | unsigned long raised_count; | |
108 | ||
109 | /* Controls whether we must stop the simulator. */ | |
110 | int stop_mode; | |
111 | }; | |
112 | ||
113 | ||
e0709f50 AC |
114 | /* Management of 68HC11 interrupts: |
115 | - We use a table of 'interrupt_def' to describe the interrupts that must be | |
116 | raised depending on IO register flags (enable and present flags). | |
117 | - We keep a mask of pending interrupts. This mask is refreshed by | |
118 | calling 'interrupts_update_pending'. It must be refreshed each time | |
119 | an IO register is changed. | |
120 | - 'interrupts_process' must be called after each insn. It has two purposes: | |
121 | first it maintains a min/max count of CPU cycles between which interrupts | |
122 | are masked; second it checks for pending interrupts and raise one if | |
123 | interrupts are enabled. */ | |
124 | struct interrupts { | |
6f64fd48 | 125 | sim_cpu *cpu; |
e0709f50 AC |
126 | |
127 | /* Mask of current pending interrupts. */ | |
128 | unsigned long pending_mask; | |
129 | ||
130 | /* Address of vector table. This is set depending on the | |
131 | 68hc11 init mode. */ | |
132 | uint16 vectors_addr; | |
133 | ||
134 | /* Priority order of interrupts. This is controlled by setting the HPRIO | |
135 | IO register. */ | |
136 | enum M6811_INT interrupt_order[M6811_INT_NUMBER]; | |
26128965 | 137 | struct interrupt interrupts[M6811_INT_NUMBER]; |
e0709f50 AC |
138 | |
139 | /* Simulator statistics to report useful debug information to users. */ | |
140 | ||
141 | /* - Max/Min number of CPU cycles executed with interrupts masked. */ | |
142 | signed64 start_mask_cycle; | |
143 | signed64 min_mask_cycles; | |
144 | signed64 max_mask_cycles; | |
11115521 | 145 | signed64 last_mask_cycles; |
e0709f50 AC |
146 | |
147 | /* - Same for XIRQ. */ | |
148 | signed64 xirq_start_mask_cycle; | |
149 | signed64 xirq_min_mask_cycles; | |
150 | signed64 xirq_max_mask_cycles; | |
11115521 | 151 | signed64 xirq_last_mask_cycles; |
e0709f50 AC |
152 | |
153 | /* - Total number of interrupts raised. */ | |
154 | unsigned long nb_interrupts_raised; | |
26128965 SC |
155 | |
156 | /* Interrupt history to help understand which interrupts | |
157 | were raised recently and in which order. */ | |
158 | int history_index; | |
159 | struct interrupt_history interrupts_history[MAX_INT_HISTORY]; | |
e0709f50 AC |
160 | }; |
161 | ||
6f64fd48 | 162 | extern void interrupts_initialize (SIM_DESC sd, sim_cpu *cpu); |
26128965 | 163 | extern void interrupts_reset (struct interrupts* interrupts); |
e0709f50 AC |
164 | extern void interrupts_update_pending (struct interrupts* interrupts); |
165 | extern int interrupts_get_current (struct interrupts* interrupts); | |
166 | extern int interrupts_process (struct interrupts* interrupts); | |
167 | extern void interrupts_raise (struct interrupts* interrupts, | |
168 | enum M6811_INT number); | |
169 | ||
170 | extern void interrupts_info (SIM_DESC sd, | |
171 | struct interrupts* interrupts); | |
172 | ||
173 | #endif |