OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [m68hc11/] [interrupts.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.