Fix clearing of interrupts in 68hc11 simulator
[external/binutils.git] / sim / m68hc11 / interrupts.c
1 /* interrupts.c -- 68HC11 Interrupts Emulation
2    Copyright 1999, 2000 Free Software Foundation, Inc.
3    Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
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.
11
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.
16
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.  */
20
21 #include "sim-main.h"
22
23 struct 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.  */
58 int
59 interrupts_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;
70   interrupts->start_mask_cycle = -1;
71   interrupts->xirq_start_mask_cycle = -1;
72   interrupts->xirq_max_mask_cycles = 0;
73   interrupts->xirq_min_mask_cycles = CYCLES_MAX;
74   
75   for (i = 0; i < M6811_INT_NUMBER; i++)
76     {
77       interrupts->interrupt_order[i] = i;
78     }
79   return 0;
80 }
81
82
83 /* Update the mask of pending interrupts.  This operation must be called
84    when the state of some 68HC11 IO registers changes.  It looks the
85    different registers that indicate a pending interrupt (timer, SCI, SPI,
86    ...) and records the interrupt if it's there and enabled.  */
87 void
88 interrupts_update_pending (struct interrupts *interrupts)
89 {
90   int i;
91   uint8 *ioregs;
92
93   ioregs = &interrupts->cpu->ios[0];
94   
95   for (i = 0; i < TableSize(idefs); i++)
96     {
97       struct interrupt_def *idef = &idefs[i];
98       uint8 data;
99       
100       /* Look if the interrupt is enabled.  */
101       if (idef->enable_paddr)
102         {
103           data = ioregs[idef->enable_paddr];
104           if (!(data & idef->enabled_mask))
105             {
106               /* Disable it.  */
107               interrupts->pending_mask &= ~(1 << idef->int_number);
108               continue;
109             }
110         }
111
112       /* Interrupt is enabled, see if it's there.  */
113       data = ioregs[idef->int_paddr];
114       if (!(data & idef->int_mask))
115         {
116           /* Disable it.  */
117           interrupts->pending_mask &= ~(1 << idef->int_number);
118           continue;
119         }
120
121       /* Ok, raise it.  */
122       interrupts->pending_mask |= (1 << idef->int_number);
123     }
124 }
125
126
127 /* Finds the current active and non-masked interrupt.
128    Returns the interrupt number (index in the vector table) or -1
129    if no interrupt can be serviced.  */
130 int
131 interrupts_get_current (struct interrupts *interrupts)
132 {
133   int i;
134   
135   if (interrupts->pending_mask == 0)
136     return -1;
137
138   /* SWI and illegal instructions are simulated by an interrupt.
139      They are not maskable.  */
140   if (interrupts->pending_mask & (1 << M6811_INT_SWI))
141     {
142       interrupts->pending_mask &= ~(1 << M6811_INT_SWI);
143       return M6811_INT_SWI;
144     }
145   if (interrupts->pending_mask & (1 << M6811_INT_ILLEGAL))
146     {
147       interrupts->pending_mask &= ~(1 << M6811_INT_ILLEGAL);
148       return M6811_INT_ILLEGAL;
149     }
150   
151   /* If there is a non maskable interrupt, go for it (unless we are masked
152      by the X-bit.  */
153   if (interrupts->pending_mask & (1 << M6811_INT_XIRQ))
154     {
155       if (cpu_get_ccr_X (interrupts->cpu) == 0)
156         {
157           interrupts->pending_mask &= ~(1 << M6811_INT_XIRQ);
158           return M6811_INT_XIRQ;
159         }
160       return -1;
161     }
162
163   /* Interrupts are masked, do nothing.  */
164   if (cpu_get_ccr_I (interrupts->cpu) == 1)
165     {
166       return -1;
167     }
168
169   /* Returns the first interrupt number which is pending.
170      The interrupt priority is specified by the table `interrupt_order'.
171      For these interrupts, the pending mask is cleared when the program
172      performs some actions on the corresponding device.  If the device
173      is not reset, the interrupt remains and will be re-raised when
174      we return from the interrupt (see 68HC11 pink book).  */
175   for (i = 0; i < M6811_INT_NUMBER; i++)
176     {
177       enum M6811_INT int_number = interrupts->interrupt_order[i];
178
179       if (interrupts->pending_mask & (1 << int_number))
180         {
181           return int_number;
182         }
183     }
184   return -1;
185 }
186
187
188 /* Process the current interrupt if there is one.  This operation must
189    be called after each instruction to handle the interrupts.  If interrupts
190    are masked, it does nothing.  */
191 int
192 interrupts_process (struct interrupts *interrupts)
193 {
194   int id;
195   uint8 ccr;
196
197   /* See if interrupts are enabled/disabled and keep track of the
198      number of cycles the interrupts are masked.  Such information is
199      then reported by the info command.  */
200   ccr = cpu_get_ccr (interrupts->cpu);
201   if (ccr & M6811_I_BIT)
202     {
203       if (interrupts->start_mask_cycle < 0)
204         interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
205     }
206   else if (interrupts->start_mask_cycle >= 0
207            && (ccr & M6811_I_BIT) == 0)
208     {
209       signed64 t = cpu_current_cycle (interrupts->cpu);
210
211       t -= interrupts->start_mask_cycle;
212       if (t < interrupts->min_mask_cycles)
213         interrupts->min_mask_cycles = t;
214       if (t > interrupts->max_mask_cycles)
215         interrupts->max_mask_cycles = t;
216       interrupts->start_mask_cycle = -1;
217     }
218   if (ccr & M6811_X_BIT)
219     {
220       if (interrupts->xirq_start_mask_cycle < 0)
221         interrupts->xirq_start_mask_cycle
222           = cpu_current_cycle (interrupts->cpu);
223     }
224   else if (interrupts->xirq_start_mask_cycle >= 0
225            && (ccr & M6811_X_BIT) == 0)
226     {
227       signed64 t = cpu_current_cycle (interrupts->cpu);
228
229       t -= interrupts->xirq_start_mask_cycle;
230       if (t < interrupts->xirq_min_mask_cycles)
231         interrupts->xirq_min_mask_cycles = t;
232       if (t > interrupts->xirq_max_mask_cycles)
233         interrupts->xirq_max_mask_cycles = t;
234       interrupts->xirq_start_mask_cycle = -1;
235     }
236
237   id = interrupts_get_current (interrupts);
238   if (id >= 0)
239     {
240       uint16 addr;
241       
242       cpu_push_all (interrupts->cpu);
243       addr = memory_read16 (interrupts->cpu,
244                             interrupts->vectors_addr + id * 2);
245       cpu_call (interrupts->cpu, addr);
246
247       /* Now, protect from nested interrupts.  */
248       if (id == M6811_INT_XIRQ)
249         {
250           cpu_set_ccr_X (interrupts->cpu, 1);
251         }
252       else
253         {
254           cpu_set_ccr_I (interrupts->cpu, 1);
255         }
256
257       interrupts->nb_interrupts_raised++;
258       cpu_add_cycles (interrupts->cpu, 14);
259       return 1;
260     }
261   return 0;
262 }
263
264 void
265 interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
266 {
267   interrupts->pending_mask |= (1 << number);
268   interrupts->nb_interrupts_raised ++;
269 }
270
271
272
273 void
274 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
275 {
276   signed64 t;
277   
278   if (interrupts->start_mask_cycle >= 0)
279     {
280       t = cpu_current_cycle (interrupts->cpu);
281
282       t -= interrupts->start_mask_cycle;
283       if (t > interrupts->max_mask_cycles)
284         interrupts->max_mask_cycles = t;
285     }
286   if (interrupts->xirq_start_mask_cycle >= 0)
287     {
288       t = cpu_current_cycle (interrupts->cpu);
289
290       t -= interrupts->xirq_start_mask_cycle;
291       if (t > interrupts->xirq_max_mask_cycles)
292         interrupts->xirq_max_mask_cycles = t;
293     }
294
295   sim_io_printf (sd, "Interrupts Info:\n");
296   sim_io_printf (sd, "  Interrupts raised: %lu\n",
297                  interrupts->nb_interrupts_raised);
298
299   t = interrupts->min_mask_cycles == CYCLES_MAX ?
300     interrupts->max_mask_cycles :
301     interrupts->min_mask_cycles;
302   sim_io_printf (sd, "  Shortest interrupts masked sequence: %s\n",
303                  cycle_to_string (interrupts->cpu, t));
304
305   t = interrupts->max_mask_cycles;
306   sim_io_printf (sd, "  Longest interrupts masked sequence: %s\n",
307                  cycle_to_string (interrupts->cpu, t));
308
309   t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
310     interrupts->xirq_max_mask_cycles :
311     interrupts->xirq_min_mask_cycles;
312   sim_io_printf (sd, "  XIRQ Min interrupts masked sequence: %s\n",
313                  cycle_to_string (interrupts->cpu, t));
314
315   t = interrupts->xirq_max_mask_cycles;
316   sim_io_printf (sd, "  XIRQ Max interrupts masked sequence: %s\n",
317                  cycle_to_string (interrupts->cpu, t));
318 }