* dv-m68hc11sio.c (m68hc11sio_tx_poll): Always check for
[external/binutils.git] / sim / m68hc11 / interrupts.c
1 /* interrupts.c -- 68HC11 Interrupts Emulation
2    Copyright 1999, 2000, 2001 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->last_mask_cycles = 0;
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;
75   interrupts->xirq_last_mask_cycles = 0;
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.  */
89 void
90 interrupts_update_pending (struct interrupts *interrupts)
91 {
92   int i;
93   uint8 *ioregs;
94   unsigned long clear_mask;
95   unsigned long set_mask;
96
97   clear_mask = 0;
98   set_mask = 0;
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))
111             {
112               /* Disable it.  */
113               clear_mask |= (1 << idef->int_number);
114               continue;
115             }
116         }
117
118       /* Interrupt is enabled, see if it's there.  */
119       data = ioregs[idef->int_paddr];
120       if (!(data & idef->int_mask))
121         {
122           /* Disable it.  */
123           clear_mask |= (1 << idef->int_number);
124           continue;
125         }
126
127       /* Ok, raise it.  */
128       set_mask |= (1 << idef->int_number);
129     }
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;
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.  */
141 int
142 interrupts_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.
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).  */
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         {
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.  */
202 int
203 interrupts_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;
228       interrupts->last_mask_cycles = t;
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;
247       interrupts->xirq_last_mask_cycles = t;
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
277 void
278 interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
279 {
280   interrupts->pending_mask |= (1 << number);
281   interrupts->nb_interrupts_raised ++;
282 }
283
284
285
286 void
287 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
288 {
289   signed64 t;
290   
291   sim_io_printf (sd, "Interrupts Info:\n");
292   sim_io_printf (sd, "  Interrupts raised: %lu\n",
293                  interrupts->nb_interrupts_raised);
294
295   if (interrupts->start_mask_cycle >= 0)
296     {
297       t = cpu_current_cycle (interrupts->cpu);
298
299       t -= interrupts->start_mask_cycle;
300       if (t > interrupts->max_mask_cycles)
301         interrupts->max_mask_cycles = t;
302
303       sim_io_printf (sd, "  Current interrupts masked sequence: %s\n",
304                      cycle_to_string (interrupts->cpu, t));
305     }
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
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
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));
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));
345 }