New 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             continue;
106         }
107
108       /* Interrupt is enabled, see if it's there.  */
109       data = ioregs[idef->int_paddr];
110       if (!(data & idef->int_mask))
111         continue;
112
113       /* Ok, raise it.  */
114       interrupts->pending_mask |= (1 << idef->int_number);
115     }
116 }
117
118
119 /* Finds the current active and non-masked interrupt.
120    Returns the interrupt number (index in the vector table) or -1
121    if no interrupt can be serviced.  */
122 int
123 interrupts_get_current (struct interrupts *interrupts)
124 {
125   int i;
126   
127   if (interrupts->pending_mask == 0)
128     return -1;
129
130   /* SWI and illegal instructions are simulated by an interrupt.
131      They are not maskable.  */
132   if (interrupts->pending_mask & (1 << M6811_INT_SWI))
133     {
134       interrupts->pending_mask &= ~(1 << M6811_INT_SWI);
135       return M6811_INT_SWI;
136     }
137   if (interrupts->pending_mask & (1 << M6811_INT_ILLEGAL))
138     {
139       interrupts->pending_mask &= ~(1 << M6811_INT_ILLEGAL);
140       return M6811_INT_ILLEGAL;
141     }
142   
143   /* If there is a non maskable interrupt, go for it (unless we are masked
144      by the X-bit.  */
145   if (interrupts->pending_mask & (1 << M6811_INT_XIRQ))
146     {
147       if (cpu_get_ccr_X (interrupts->cpu) == 0)
148         {
149           interrupts->pending_mask &= ~(1 << M6811_INT_XIRQ);
150           return M6811_INT_XIRQ;
151         }
152       return -1;
153     }
154
155   /* Interrupts are masked, do nothing.  */
156   if (cpu_get_ccr_I (interrupts->cpu) == 1)
157     {
158       return -1;
159     }
160
161   /* Returns the first interrupt number which is pending.
162      The interrupt priority is specified by the table `interrupt_order'.  */
163   for (i = 0; i < M6811_INT_NUMBER; i++)
164     {
165       enum M6811_INT int_number = interrupts->interrupt_order[i];
166
167       if (interrupts->pending_mask & (1 << int_number))
168         {
169           interrupts->pending_mask &= ~(1 << int_number);
170           return int_number;
171         }
172     }
173   return -1;
174 }
175
176
177 /* Process the current interrupt if there is one.  This operation must
178    be called after each instruction to handle the interrupts.  If interrupts
179    are masked, it does nothing.  */
180 int
181 interrupts_process (struct interrupts *interrupts)
182 {
183   int id;
184   uint8 ccr;
185
186   /* See if interrupts are enabled/disabled and keep track of the
187      number of cycles the interrupts are masked.  Such information is
188      then reported by the info command.  */
189   ccr = cpu_get_ccr (interrupts->cpu);
190   if (ccr & M6811_I_BIT)
191     {
192       if (interrupts->start_mask_cycle < 0)
193         interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
194     }
195   else if (interrupts->start_mask_cycle >= 0
196            && (ccr & M6811_I_BIT) == 0)
197     {
198       signed64 t = cpu_current_cycle (interrupts->cpu);
199
200       t -= interrupts->start_mask_cycle;
201       if (t < interrupts->min_mask_cycles)
202         interrupts->min_mask_cycles = t;
203       if (t > interrupts->max_mask_cycles)
204         interrupts->max_mask_cycles = t;
205       interrupts->start_mask_cycle = -1;
206     }
207   if (ccr & M6811_X_BIT)
208     {
209       if (interrupts->xirq_start_mask_cycle < 0)
210         interrupts->xirq_start_mask_cycle
211           = cpu_current_cycle (interrupts->cpu);
212     }
213   else if (interrupts->xirq_start_mask_cycle >= 0
214            && (ccr & M6811_X_BIT) == 0)
215     {
216       signed64 t = cpu_current_cycle (interrupts->cpu);
217
218       t -= interrupts->xirq_start_mask_cycle;
219       if (t < interrupts->xirq_min_mask_cycles)
220         interrupts->xirq_min_mask_cycles = t;
221       if (t > interrupts->xirq_max_mask_cycles)
222         interrupts->xirq_max_mask_cycles = t;
223       interrupts->xirq_start_mask_cycle = -1;
224     }
225
226   id = interrupts_get_current (interrupts);
227   if (id >= 0)
228     {
229       uint16 addr;
230       
231       cpu_push_all (interrupts->cpu);
232       addr = memory_read16 (interrupts->cpu,
233                             interrupts->vectors_addr + id * 2);
234       cpu_call (interrupts->cpu, addr);
235
236       /* Now, protect from nested interrupts.  */
237       if (id == M6811_INT_XIRQ)
238         {
239           cpu_set_ccr_X (interrupts->cpu, 1);
240         }
241       else
242         {
243           cpu_set_ccr_I (interrupts->cpu, 1);
244         }
245
246       interrupts->nb_interrupts_raised++;
247       cpu_add_cycles (interrupts->cpu, 14);
248       return 1;
249     }
250   return 0;
251 }
252
253 void
254 interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
255 {
256   interrupts->pending_mask |= (1 << number);
257   interrupts->nb_interrupts_raised ++;
258 }
259
260
261
262 void
263 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
264 {
265   if (interrupts->start_mask_cycle >= 0)
266     {
267       signed64 t = cpu_current_cycle (interrupts->cpu);
268
269       t -= interrupts->start_mask_cycle;
270       if (t > interrupts->max_mask_cycles)
271         interrupts->max_mask_cycles = t;
272     }
273   if (interrupts->xirq_start_mask_cycle >= 0)
274     {
275       signed64 t = cpu_current_cycle (interrupts->cpu);
276
277       t -= interrupts->xirq_start_mask_cycle;
278       if (t > interrupts->xirq_max_mask_cycles)
279         interrupts->xirq_max_mask_cycles = t;
280     }
281
282   sim_io_printf (sd, "Interrupts Info:\n");
283   sim_io_printf (sd, "  Interrupts raised: %lu\n",
284                  interrupts->nb_interrupts_raised);
285   sim_io_printf (sd, "  Min interrupts masked sequence: %llu cycles\n",
286                  interrupts->min_mask_cycles == CYCLES_MAX ?
287                  interrupts->max_mask_cycles :
288                  interrupts->min_mask_cycles);
289   sim_io_printf (sd, "  Max interrupts masked sequence: %llu cycles\n",
290                  interrupts->max_mask_cycles);
291   sim_io_printf (sd, "  XIRQ Min interrupts masked sequence: %llu cycles\n",
292                  interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
293                  interrupts->xirq_max_mask_cycles :
294                  interrupts->xirq_min_mask_cycles);
295   sim_io_printf (sd, "  XIRQ Max interrupts masked sequence: %llu cycles\n",
296                  interrupts->xirq_max_mask_cycles);
297 }