Define and use pe_get_data_import_dll_name().
[deliverable/binutils-gdb.git] / sim / m68hc11 / interrupts.c
CommitLineData
e0709f50 1/* interrupts.c -- 68HC11 Interrupts Emulation
11115521 2 Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
e0709f50
AC
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5This file is part of GDB, GAS, and the GNU binutils.
6
7GDB, GAS, and the GNU binutils are free software; you can redistribute
8them and/or modify them under the terms of the GNU General Public
9License as published by the Free Software Foundation; either version
101, or (at your option) any later version.
11
12GDB, GAS, and the GNU binutils are distributed in the hope that they
13will be useful, but WITHOUT ANY WARRANTY; without even the implied
14warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15the GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this file; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "sim-main.h"
22
23struct interrupt_def idefs[] = {
24 /* Serial interrupts. */
25 { M6811_INT_SCI, M6811_SCSR, M6811_TDRE, M6811_SCCR2, M6811_TIE },
26 { M6811_INT_SCI, M6811_SCSR, M6811_TC, M6811_SCCR2, M6811_TCIE },
27 { M6811_INT_SCI, M6811_SCSR, M6811_RDRF, M6811_SCCR2, M6811_RIE },
28 { M6811_INT_SCI, M6811_SCSR, M6811_IDLE, M6811_SCCR2, M6811_ILIE },
29
30 /* SPI interrupts. */
31 { M6811_INT_SPI, M6811_SPSR, M6811_SPIF, M6811_SPCR, M6811_SPIE },
32
33 /* Realtime interrupts. */
34 { M6811_INT_TCTN, M6811_TFLG2, M6811_TOF, M6811_TMSK2, M6811_TOI },
35 { M6811_INT_RT, M6811_TFLG2, M6811_RTIF, M6811_TMSK2, M6811_RTII },
36
37 /* Output compare interrupts. */
38 { M6811_INT_OUTCMP1, M6811_TFLG1, M6811_OC1F, M6811_TMSK1, M6811_OC1I },
39 { M6811_INT_OUTCMP2, M6811_TFLG1, M6811_OC2F, M6811_TMSK1, M6811_OC2I },
40 { M6811_INT_OUTCMP3, M6811_TFLG1, M6811_OC3F, M6811_TMSK1, M6811_OC3I },
41 { M6811_INT_OUTCMP4, M6811_TFLG1, M6811_OC4F, M6811_TMSK1, M6811_OC4I },
42 { M6811_INT_OUTCMP5, M6811_TFLG1, M6811_OC5F, M6811_TMSK1, M6811_OC5I },
43
44 /* Input compare interrupts. */
45 { M6811_INT_INCMP1, M6811_TFLG1, M6811_IC1F, M6811_TMSK1, M6811_IC1I },
46 { M6811_INT_INCMP2, M6811_TFLG1, M6811_IC2F, M6811_TMSK1, M6811_IC2I },
47 { M6811_INT_INCMP3, M6811_TFLG1, M6811_IC3F, M6811_TMSK1, M6811_IC3I },
48#if 0
49 { M6811_INT_COPRESET, M6811_CONFIG, M6811_NOCOP, 0, 0 },
50 { M6811_INT_COPFAIL, M6811_CONFIG, M6811_NOCOP, 0, 0 }
51#endif
52};
53
54#define TableSize(X) (sizeof X / sizeof(X[0]))
55#define CYCLES_MAX ((((signed64) 1) << 62) - 1)
56
57/* Initialize the interrupts of the processor. */
58int
59interrupts_initialize (struct _sim_cpu *proc)
60{
61 struct interrupts *interrupts = &proc->cpu_interrupts;
62 int i;
63
64 interrupts->cpu = proc;
65 interrupts->pending_mask = 0;
66 interrupts->vectors_addr = 0xffc0;
67 interrupts->nb_interrupts_raised = 0;
68 interrupts->min_mask_cycles = CYCLES_MAX;
69 interrupts->max_mask_cycles = 0;
11115521 70 interrupts->last_mask_cycles = 0;
e0709f50
AC
71 interrupts->start_mask_cycle = -1;
72 interrupts->xirq_start_mask_cycle = -1;
73 interrupts->xirq_max_mask_cycles = 0;
74 interrupts->xirq_min_mask_cycles = CYCLES_MAX;
11115521 75 interrupts->xirq_last_mask_cycles = 0;
e0709f50
AC
76
77 for (i = 0; i < M6811_INT_NUMBER; i++)
78 {
79 interrupts->interrupt_order[i] = i;
80 }
81 return 0;
82}
83
84
85/* Update the mask of pending interrupts. This operation must be called
86 when the state of some 68HC11 IO registers changes. It looks the
87 different registers that indicate a pending interrupt (timer, SCI, SPI,
88 ...) and records the interrupt if it's there and enabled. */
89void
90interrupts_update_pending (struct interrupts *interrupts)
91{
92 int i;
93 uint8 *ioregs;
11115521
SC
94 unsigned long clear_mask;
95 unsigned long set_mask;
e0709f50 96
11115521
SC
97 clear_mask = 0;
98 set_mask = 0;
e0709f50
AC
99 ioregs = &interrupts->cpu->ios[0];
100
101 for (i = 0; i < TableSize(idefs); i++)
102 {
103 struct interrupt_def *idef = &idefs[i];
104 uint8 data;
105
106 /* Look if the interrupt is enabled. */
107 if (idef->enable_paddr)
108 {
109 data = ioregs[idef->enable_paddr];
110 if (!(data & idef->enabled_mask))
a8afa79a
SC
111 {
112 /* Disable it. */
11115521 113 clear_mask |= (1 << idef->int_number);
a8afa79a
SC
114 continue;
115 }
e0709f50
AC
116 }
117
118 /* Interrupt is enabled, see if it's there. */
119 data = ioregs[idef->int_paddr];
120 if (!(data & idef->int_mask))
a8afa79a
SC
121 {
122 /* Disable it. */
11115521 123 clear_mask |= (1 << idef->int_number);
a8afa79a
SC
124 continue;
125 }
e0709f50
AC
126
127 /* Ok, raise it. */
11115521 128 set_mask |= (1 << idef->int_number);
e0709f50 129 }
11115521
SC
130
131 /* Some interrupts are shared (M6811_INT_SCI) so clear
132 the interrupts before setting the new ones. */
133 interrupts->pending_mask &= ~clear_mask;
134 interrupts->pending_mask |= set_mask;
e0709f50
AC
135}
136
137
138/* Finds the current active and non-masked interrupt.
139 Returns the interrupt number (index in the vector table) or -1
140 if no interrupt can be serviced. */
141int
142interrupts_get_current (struct interrupts *interrupts)
143{
144 int i;
145
146 if (interrupts->pending_mask == 0)
147 return -1;
148
149 /* SWI and illegal instructions are simulated by an interrupt.
150 They are not maskable. */
151 if (interrupts->pending_mask & (1 << M6811_INT_SWI))
152 {
153 interrupts->pending_mask &= ~(1 << M6811_INT_SWI);
154 return M6811_INT_SWI;
155 }
156 if (interrupts->pending_mask & (1 << M6811_INT_ILLEGAL))
157 {
158 interrupts->pending_mask &= ~(1 << M6811_INT_ILLEGAL);
159 return M6811_INT_ILLEGAL;
160 }
161
162 /* If there is a non maskable interrupt, go for it (unless we are masked
163 by the X-bit. */
164 if (interrupts->pending_mask & (1 << M6811_INT_XIRQ))
165 {
166 if (cpu_get_ccr_X (interrupts->cpu) == 0)
167 {
168 interrupts->pending_mask &= ~(1 << M6811_INT_XIRQ);
169 return M6811_INT_XIRQ;
170 }
171 return -1;
172 }
173
174 /* Interrupts are masked, do nothing. */
175 if (cpu_get_ccr_I (interrupts->cpu) == 1)
176 {
177 return -1;
178 }
179
180 /* Returns the first interrupt number which is pending.
a8afa79a
SC
181 The interrupt priority is specified by the table `interrupt_order'.
182 For these interrupts, the pending mask is cleared when the program
183 performs some actions on the corresponding device. If the device
184 is not reset, the interrupt remains and will be re-raised when
185 we return from the interrupt (see 68HC11 pink book). */
e0709f50
AC
186 for (i = 0; i < M6811_INT_NUMBER; i++)
187 {
188 enum M6811_INT int_number = interrupts->interrupt_order[i];
189
190 if (interrupts->pending_mask & (1 << int_number))
191 {
e0709f50
AC
192 return int_number;
193 }
194 }
195 return -1;
196}
197
198
199/* Process the current interrupt if there is one. This operation must
200 be called after each instruction to handle the interrupts. If interrupts
201 are masked, it does nothing. */
202int
203interrupts_process (struct interrupts *interrupts)
204{
205 int id;
206 uint8 ccr;
207
208 /* See if interrupts are enabled/disabled and keep track of the
209 number of cycles the interrupts are masked. Such information is
210 then reported by the info command. */
211 ccr = cpu_get_ccr (interrupts->cpu);
212 if (ccr & M6811_I_BIT)
213 {
214 if (interrupts->start_mask_cycle < 0)
215 interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
216 }
217 else if (interrupts->start_mask_cycle >= 0
218 && (ccr & M6811_I_BIT) == 0)
219 {
220 signed64 t = cpu_current_cycle (interrupts->cpu);
221
222 t -= interrupts->start_mask_cycle;
223 if (t < interrupts->min_mask_cycles)
224 interrupts->min_mask_cycles = t;
225 if (t > interrupts->max_mask_cycles)
226 interrupts->max_mask_cycles = t;
227 interrupts->start_mask_cycle = -1;
11115521 228 interrupts->last_mask_cycles = t;
e0709f50
AC
229 }
230 if (ccr & M6811_X_BIT)
231 {
232 if (interrupts->xirq_start_mask_cycle < 0)
233 interrupts->xirq_start_mask_cycle
234 = cpu_current_cycle (interrupts->cpu);
235 }
236 else if (interrupts->xirq_start_mask_cycle >= 0
237 && (ccr & M6811_X_BIT) == 0)
238 {
239 signed64 t = cpu_current_cycle (interrupts->cpu);
240
241 t -= interrupts->xirq_start_mask_cycle;
242 if (t < interrupts->xirq_min_mask_cycles)
243 interrupts->xirq_min_mask_cycles = t;
244 if (t > interrupts->xirq_max_mask_cycles)
245 interrupts->xirq_max_mask_cycles = t;
246 interrupts->xirq_start_mask_cycle = -1;
11115521 247 interrupts->xirq_last_mask_cycles = t;
e0709f50
AC
248 }
249
250 id = interrupts_get_current (interrupts);
251 if (id >= 0)
252 {
253 uint16 addr;
254
255 cpu_push_all (interrupts->cpu);
256 addr = memory_read16 (interrupts->cpu,
257 interrupts->vectors_addr + id * 2);
258 cpu_call (interrupts->cpu, addr);
259
260 /* Now, protect from nested interrupts. */
261 if (id == M6811_INT_XIRQ)
262 {
263 cpu_set_ccr_X (interrupts->cpu, 1);
264 }
265 else
266 {
267 cpu_set_ccr_I (interrupts->cpu, 1);
268 }
269
270 interrupts->nb_interrupts_raised++;
271 cpu_add_cycles (interrupts->cpu, 14);
272 return 1;
273 }
274 return 0;
275}
276
277void
278interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
279{
280 interrupts->pending_mask |= (1 << number);
281 interrupts->nb_interrupts_raised ++;
282}
283
284
285
286void
287interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
288{
2990a9f4
SC
289 signed64 t;
290
11115521
SC
291 sim_io_printf (sd, "Interrupts Info:\n");
292 sim_io_printf (sd, " Interrupts raised: %lu\n",
293 interrupts->nb_interrupts_raised);
294
e0709f50
AC
295 if (interrupts->start_mask_cycle >= 0)
296 {
2990a9f4 297 t = cpu_current_cycle (interrupts->cpu);
e0709f50
AC
298
299 t -= interrupts->start_mask_cycle;
300 if (t > interrupts->max_mask_cycles)
301 interrupts->max_mask_cycles = t;
e0709f50 302
11115521
SC
303 sim_io_printf (sd, " Current interrupts masked sequence: %s\n",
304 cycle_to_string (interrupts->cpu, t));
e0709f50 305 }
2990a9f4
SC
306 t = interrupts->min_mask_cycles == CYCLES_MAX ?
307 interrupts->max_mask_cycles :
308 interrupts->min_mask_cycles;
309 sim_io_printf (sd, " Shortest interrupts masked sequence: %s\n",
310 cycle_to_string (interrupts->cpu, t));
311
312 t = interrupts->max_mask_cycles;
313 sim_io_printf (sd, " Longest interrupts masked sequence: %s\n",
314 cycle_to_string (interrupts->cpu, t));
315
11115521
SC
316 t = interrupts->last_mask_cycles;
317 sim_io_printf (sd, " Last interrupts masked sequence: %s\n",
318 cycle_to_string (interrupts->cpu, t));
319
320 if (interrupts->xirq_start_mask_cycle >= 0)
321 {
322 t = cpu_current_cycle (interrupts->cpu);
323
324 t -= interrupts->xirq_start_mask_cycle;
325 if (t > interrupts->xirq_max_mask_cycles)
326 interrupts->xirq_max_mask_cycles = t;
327
328 sim_io_printf (sd, " XIRQ Current interrupts masked sequence: %s\n",
329 cycle_to_string (interrupts->cpu, t));
330 }
331
2990a9f4
SC
332 t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
333 interrupts->xirq_max_mask_cycles :
334 interrupts->xirq_min_mask_cycles;
335 sim_io_printf (sd, " XIRQ Min interrupts masked sequence: %s\n",
336 cycle_to_string (interrupts->cpu, t));
337
338 t = interrupts->xirq_max_mask_cycles;
339 sim_io_printf (sd, " XIRQ Max interrupts masked sequence: %s\n",
340 cycle_to_string (interrupts->cpu, t));
11115521
SC
341
342 t = interrupts->xirq_last_mask_cycles;
343 sim_io_printf (sd, " XIRQ Last interrupts masked sequence: %s\n",
344 cycle_to_string (interrupts->cpu, t));
e0709f50 345}
This page took 0.071656 seconds and 4 git commands to generate.