OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [frv/] [interrupts.c] - Blame information for rev 299

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

Line No. Rev Author Line
1 227 jeremybenn
/* frv exception and interrupt support
2
   Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Red Hat.
5
 
6
This file is part of the GNU simulators.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#define WANT_CPU frvbf
22
#define WANT_CPU_FRVBF
23
 
24
#include "sim-main.h"
25
#include "bfd.h"
26
 
27
/* FR-V Interrupt table.
28
   Describes the interrupts supported by the FR-V.
29
   This table *must* be maintained in order of interrupt priority as defined by
30
   frv_interrupt_kind.  */
31
#define DEFERRED 1
32
#define PRECISE  1
33
#define ITABLE_ENTRY(name, class, deferral, precision, offset) \
34
  {FRV_##name, FRV_EC_##name, class, deferral, precision, offset}
35
 
36
struct frv_interrupt frv_interrupt_table[NUM_FRV_INTERRUPT_KINDS] =
37
{
38
  /* External interrupts */
39
  ITABLE_ENTRY(INTERRUPT_LEVEL_1,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x21),
40
  ITABLE_ENTRY(INTERRUPT_LEVEL_2,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x22),
41
  ITABLE_ENTRY(INTERRUPT_LEVEL_3,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x23),
42
  ITABLE_ENTRY(INTERRUPT_LEVEL_4,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x24),
43
  ITABLE_ENTRY(INTERRUPT_LEVEL_5,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x25),
44
  ITABLE_ENTRY(INTERRUPT_LEVEL_6,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x26),
45
  ITABLE_ENTRY(INTERRUPT_LEVEL_7,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x27),
46
  ITABLE_ENTRY(INTERRUPT_LEVEL_8,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x28),
47
  ITABLE_ENTRY(INTERRUPT_LEVEL_9,            FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x29),
48
  ITABLE_ENTRY(INTERRUPT_LEVEL_10,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2a),
49
  ITABLE_ENTRY(INTERRUPT_LEVEL_11,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2b),
50
  ITABLE_ENTRY(INTERRUPT_LEVEL_12,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2c),
51
  ITABLE_ENTRY(INTERRUPT_LEVEL_13,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2d),
52
  ITABLE_ENTRY(INTERRUPT_LEVEL_14,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2e),
53
  ITABLE_ENTRY(INTERRUPT_LEVEL_15,           FRV_EXTERNAL_INTERRUPT, !DEFERRED, !PRECISE, 0x2f),
54
  /* Software interrupt */
55
  ITABLE_ENTRY(TRAP_INSTRUCTION,             FRV_SOFTWARE_INTERRUPT, !DEFERRED, !PRECISE, 0x80),
56
  /* Program interrupts */
57
  ITABLE_ENTRY(COMMIT_EXCEPTION,             FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x19),
58
  ITABLE_ENTRY(DIVISION_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x17),
59
  ITABLE_ENTRY(DATA_STORE_ERROR,             FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x14),
60
  ITABLE_ENTRY(DATA_ACCESS_EXCEPTION,        FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x13),
61
  ITABLE_ENTRY(DATA_ACCESS_MMU_MISS,         FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x12),
62
  ITABLE_ENTRY(DATA_ACCESS_ERROR,            FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x11),
63
  ITABLE_ENTRY(MP_EXCEPTION,                 FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x0e),
64
  ITABLE_ENTRY(FP_EXCEPTION,                 FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x0d),
65
  ITABLE_ENTRY(MEM_ADDRESS_NOT_ALIGNED,      FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x10),
66
  ITABLE_ENTRY(REGISTER_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x08),
67
  ITABLE_ENTRY(MP_DISABLED,                  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x0b),
68
  ITABLE_ENTRY(FP_DISABLED,                  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x0a),
69
  ITABLE_ENTRY(PRIVILEGED_INSTRUCTION,       FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x06),
70
  ITABLE_ENTRY(ILLEGAL_INSTRUCTION,          FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x07),
71
  ITABLE_ENTRY(INSTRUCTION_ACCESS_EXCEPTION, FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x03),
72
  ITABLE_ENTRY(INSTRUCTION_ACCESS_ERROR,     FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x02),
73
  ITABLE_ENTRY(INSTRUCTION_ACCESS_MMU_MISS,  FRV_PROGRAM_INTERRUPT,  !DEFERRED,  PRECISE, 0x01),
74
  ITABLE_ENTRY(COMPOUND_EXCEPTION,           FRV_PROGRAM_INTERRUPT,  !DEFERRED, !PRECISE, 0x20),
75
  /* Break interrupt */
76
  ITABLE_ENTRY(BREAK_EXCEPTION,              FRV_BREAK_INTERRUPT,    !DEFERRED, !PRECISE, 0xff),
77
  /* Reset interrupt */
78
  ITABLE_ENTRY(RESET,                        FRV_RESET_INTERRUPT,    !DEFERRED, !PRECISE, 0x00)
79
};
80
 
81
/* The current interrupt state.  */
82
struct frv_interrupt_state frv_interrupt_state;
83
 
84
/* maintain the address of the start of the previous VLIW insn sequence.  */
85
IADDR previous_vliw_pc;
86
 
87
/* Add a break interrupt to the interrupt queue.  */
88
struct frv_interrupt_queue_element *
89
frv_queue_break_interrupt (SIM_CPU *current_cpu)
90
{
91
  return frv_queue_interrupt (current_cpu, FRV_BREAK_EXCEPTION);
92
}
93
 
94
/* Add a software interrupt to the interrupt queue.  */
95
struct frv_interrupt_queue_element *
96
frv_queue_software_interrupt (SIM_CPU *current_cpu, SI offset)
97
{
98
  struct frv_interrupt_queue_element *new_element
99
    = frv_queue_interrupt (current_cpu, FRV_TRAP_INSTRUCTION);
100
 
101
  struct frv_interrupt *interrupt = & frv_interrupt_table[new_element->kind];
102
  interrupt->handler_offset = offset;
103
 
104
  return new_element;
105
}
106
 
107
/* Add a program interrupt to the interrupt queue.  */
108
struct frv_interrupt_queue_element *
109
frv_queue_program_interrupt (
110
  SIM_CPU *current_cpu, enum frv_interrupt_kind kind
111
)
112
{
113
  return frv_queue_interrupt (current_cpu, kind);
114
}
115
 
116
/* Add an external interrupt to the interrupt queue.  */
117
struct frv_interrupt_queue_element *
118
frv_queue_external_interrupt (
119
  SIM_CPU *current_cpu, enum frv_interrupt_kind kind
120
)
121
{
122
  if (! GET_H_PSR_ET ()
123
      || (kind != FRV_INTERRUPT_LEVEL_15 && kind < GET_H_PSR_PIL ()))
124
    return NULL; /* Leave it for later.  */
125
 
126
  return frv_queue_interrupt (current_cpu, kind);
127
}
128
 
129
/* Add any interrupt to the interrupt queue. It will be added in reverse
130
   priority order.  This makes it easy to find the highest priority interrupt
131
   at the end of the queue and to remove it after processing.  */
132
struct frv_interrupt_queue_element *
133
frv_queue_interrupt (SIM_CPU *current_cpu, enum frv_interrupt_kind kind)
134
{
135
  int i;
136
  int j;
137
  int limit = frv_interrupt_state.queue_index;
138
  struct frv_interrupt_queue_element *new_element;
139
  enum frv_interrupt_class iclass;
140
 
141
  if (limit >= FRV_INTERRUPT_QUEUE_SIZE)
142
    abort (); /* TODO: Make the queue dynamic */
143
 
144
  /* Find the right place in the queue.  */
145
  for (i = 0; i < limit; ++i)
146
    {
147
      if (frv_interrupt_state.queue[i].kind >= kind)
148
        break;
149
    }
150
 
151
  /* Don't queue two external interrupts of the same priority.  */
152
  iclass = frv_interrupt_table[kind].iclass;
153
  if (i < limit && iclass == FRV_EXTERNAL_INTERRUPT)
154
    {
155
      if (frv_interrupt_state.queue[i].kind == kind)
156
        return & frv_interrupt_state.queue[i];
157
    }
158
 
159
  /* Make room for the new interrupt in this spot.  */
160
  for (j = limit - 1; j >= i; --j)
161
    frv_interrupt_state.queue[j + 1] = frv_interrupt_state.queue[j];
162
 
163
  /* Add the new interrupt.  */
164
  frv_interrupt_state.queue_index++;
165
  new_element = & frv_interrupt_state.queue[i];
166
  new_element->kind = kind;
167
  new_element->vpc = CPU_PC_GET (current_cpu);
168
  new_element->u.data_written.length = 0;
169
  frv_set_interrupt_queue_slot (current_cpu, new_element);
170
 
171
  return new_element;
172
}
173
 
174
struct frv_interrupt_queue_element *
175
frv_queue_register_exception_interrupt (SIM_CPU *current_cpu, enum frv_rec rec)
176
{
177
  struct frv_interrupt_queue_element *new_element =
178
    frv_queue_program_interrupt (current_cpu, FRV_REGISTER_EXCEPTION);
179
 
180
  new_element->u.rec = rec;
181
 
182
  return new_element;
183
}
184
 
185
struct frv_interrupt_queue_element *
186
frv_queue_mem_address_not_aligned_interrupt (SIM_CPU *current_cpu, USI addr)
187
{
188
  struct frv_interrupt_queue_element *new_element;
189
  USI isr = GET_ISR ();
190
 
191
  /* Make sure that this exception is not masked.  */
192
  if (GET_ISR_EMAM (isr))
193
    return NULL;
194
 
195
  /* Queue the interrupt.  */
196
  new_element = frv_queue_program_interrupt (current_cpu,
197
                                             FRV_MEM_ADDRESS_NOT_ALIGNED);
198
  new_element->eaddress = addr;
199
  new_element->u.data_written = frv_interrupt_state.data_written;
200
  frv_interrupt_state.data_written.length = 0;
201
 
202
  return new_element;
203
}
204
 
205
struct frv_interrupt_queue_element *
206
frv_queue_data_access_error_interrupt (SIM_CPU *current_cpu, USI addr)
207
{
208
  struct frv_interrupt_queue_element *new_element;
209
  new_element = frv_queue_program_interrupt (current_cpu,
210
                                             FRV_DATA_ACCESS_ERROR);
211
  new_element->eaddress = addr;
212
  return new_element;
213
}
214
 
215
struct frv_interrupt_queue_element *
216
frv_queue_data_access_exception_interrupt (SIM_CPU *current_cpu)
217
{
218
  return frv_queue_program_interrupt (current_cpu, FRV_DATA_ACCESS_EXCEPTION);
219
}
220
 
221
struct frv_interrupt_queue_element *
222
frv_queue_instruction_access_error_interrupt (SIM_CPU *current_cpu)
223
{
224
  return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_ERROR);
225
}
226
 
227
struct frv_interrupt_queue_element *
228
frv_queue_instruction_access_exception_interrupt (SIM_CPU *current_cpu)
229
{
230
  return frv_queue_program_interrupt (current_cpu, FRV_INSTRUCTION_ACCESS_EXCEPTION);
231
}
232
 
233
struct frv_interrupt_queue_element *
234
frv_queue_illegal_instruction_interrupt (
235
  SIM_CPU *current_cpu, const CGEN_INSN *insn
236
)
237
{
238
  SIM_DESC sd = CPU_STATE (current_cpu);
239
  switch (STATE_ARCHITECTURE (sd)->mach)
240
    {
241
    case bfd_mach_fr400:
242
    case bfd_mach_fr450:
243
    case bfd_mach_fr550:
244
      break;
245
    default:
246
      /* Some machines generate fp_exception for this case.  */
247
      if (frv_is_float_insn (insn) || frv_is_media_insn (insn))
248
        {
249
          struct frv_fp_exception_info fp_info = {
250
            FSR_NO_EXCEPTION, FTT_SEQUENCE_ERROR
251
          };
252
          return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
253
        }
254
      break;
255
    }
256
 
257
  return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
258
}
259
 
260
struct frv_interrupt_queue_element *
261
frv_queue_privileged_instruction_interrupt (SIM_CPU *current_cpu, const CGEN_INSN *insn)
262
{
263
  /* The fr550 has no privileged instruction interrupt. It uses
264
     illegal_instruction.  */
265
  SIM_DESC sd = CPU_STATE (current_cpu);
266
  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
267
    return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
268
 
269
  return frv_queue_program_interrupt (current_cpu, FRV_PRIVILEGED_INSTRUCTION);
270
}
271
 
272
struct frv_interrupt_queue_element *
273
frv_queue_float_disabled_interrupt (SIM_CPU *current_cpu)
274
{
275
  /* The fr550 has no fp_disabled interrupt. It uses illegal_instruction.  */
276
  SIM_DESC sd = CPU_STATE (current_cpu);
277
  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
278
    return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
279
 
280
  return frv_queue_program_interrupt (current_cpu, FRV_FP_DISABLED);
281
}
282
 
283
struct frv_interrupt_queue_element *
284
frv_queue_media_disabled_interrupt (SIM_CPU *current_cpu)
285
{
286
  /* The fr550 has no mp_disabled interrupt. It uses illegal_instruction.  */
287
  SIM_DESC sd = CPU_STATE (current_cpu);
288
  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
289
    return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
290
 
291
  return frv_queue_program_interrupt (current_cpu, FRV_MP_DISABLED);
292
}
293
 
294
struct frv_interrupt_queue_element *
295
frv_queue_non_implemented_instruction_interrupt (
296
  SIM_CPU *current_cpu, const CGEN_INSN *insn
297
)
298
{
299
  SIM_DESC sd = CPU_STATE (current_cpu);
300
  switch (STATE_ARCHITECTURE (sd)->mach)
301
    {
302
    case bfd_mach_fr400:
303
    case bfd_mach_fr450:
304
    case bfd_mach_fr550:
305
      break;
306
    default:
307
      /* Some machines generate fp_exception or mp_exception for this case.  */
308
      if (frv_is_float_insn (insn))
309
        {
310
          struct frv_fp_exception_info fp_info = {
311
            FSR_NO_EXCEPTION, FTT_UNIMPLEMENTED_FPOP
312
          };
313
          return frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
314
        }
315
      if (frv_is_media_insn (insn))
316
        {
317
          frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP,
318
                                          0);
319
          return NULL; /* no interrupt queued at this time.  */
320
        }
321
      break;
322
    }
323
 
324
  return frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
325
}
326
 
327
/* Queue the given fp_exception interrupt. Also update fp_info by removing
328
   masked interrupts and updating the 'slot' flield.  */
329
struct frv_interrupt_queue_element *
330
frv_queue_fp_exception_interrupt (
331
  SIM_CPU *current_cpu, struct frv_fp_exception_info *fp_info
332
)
333
{
334
  SI fsr0 = GET_FSR (0);
335
  int tem = GET_FSR_TEM (fsr0);
336
  int aexc = GET_FSR_AEXC (fsr0);
337
  struct frv_interrupt_queue_element *new_element = NULL;
338
 
339
  /* Update AEXC with the interrupts that are masked.  */
340
  aexc |= fp_info->fsr_mask & ~tem;
341
  SET_FSR_AEXC (fsr0, aexc);
342
  SET_FSR (0, fsr0);
343
 
344
  /* update fsr_mask with the exceptions that are enabled.  */
345
  fp_info->fsr_mask &= tem;
346
 
347
  /* If there is an unmasked interrupt then queue it, unless
348
     this was a non-excepting insn, in which case simply set the NE
349
     status registers.  */
350
  if (frv_interrupt_state.ne_index != NE_NOFLAG
351
      && fp_info->fsr_mask != FSR_NO_EXCEPTION)
352
    {
353
      SET_NE_FLAG (frv_interrupt_state.f_ne_flags,
354
                   frv_interrupt_state.ne_index);
355
      /* TODO -- Set NESR for chips which support it.  */
356
      new_element = NULL;
357
    }
358
  else if (fp_info->fsr_mask != FSR_NO_EXCEPTION
359
           || fp_info->ftt == FTT_UNIMPLEMENTED_FPOP
360
           || fp_info->ftt == FTT_SEQUENCE_ERROR
361
           || fp_info->ftt == FTT_INVALID_FR)
362
    {
363
      new_element = frv_queue_program_interrupt (current_cpu, FRV_FP_EXCEPTION);
364
      new_element->u.fp_info = *fp_info;
365
    }
366
 
367
  return new_element;
368
}
369
 
370
struct frv_interrupt_queue_element *
371
frv_queue_division_exception_interrupt (SIM_CPU *current_cpu, enum frv_dtt dtt)
372
{
373
  struct frv_interrupt_queue_element *new_element =
374
    frv_queue_program_interrupt (current_cpu, FRV_DIVISION_EXCEPTION);
375
 
376
  new_element->u.dtt = dtt;
377
 
378
  return new_element;
379
}
380
 
381
/* Check for interrupts caused by illegal insn access.  These conditions are
382
   checked in the order specified by the fr400 and fr500 LSI specs.  */
383
void
384
frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc)
385
{
386
 
387
  const CGEN_INSN *insn = sc->argbuf.idesc->idata;
388
  SIM_DESC sd = CPU_STATE (current_cpu);
389
  FRV_VLIW *vliw = CPU_VLIW (current_cpu);
390
 
391
  /* Check for vliw constraints.  */
392
  if (vliw->constraint_violation)
393
    frv_queue_illegal_instruction_interrupt (current_cpu, insn);
394
  /* Check for non-excepting insns.  */
395
  else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING)
396
      && ! GET_H_PSR_NEM ())
397
    frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
398
  /* Check for conditional insns.  */
399
  else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL)
400
      && ! GET_H_PSR_CM ())
401
    frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
402
  /* Make sure floating point support is enabled.  */
403
  else if (! GET_H_PSR_EF ())
404
    {
405
      /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
406
         off and the insns accesses a fp register.  */
407
      if (frv_is_float_insn (insn)
408
          || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)
409
              && ! GET_H_PSR_EM ()))
410
        frv_queue_float_disabled_interrupt (current_cpu);
411
    }
412
  /* Make sure media support is enabled.  */
413
  else if (! GET_H_PSR_EM ())
414
    {
415
      /* Generate mp_disabled if it is a media insn.  */
416
      if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP)
417
        frv_queue_media_disabled_interrupt (current_cpu);
418
    }
419
  /* Check for privileged insns.  */
420
  else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) &&
421
           ! GET_H_PSR_S ())
422
    frv_queue_privileged_instruction_interrupt (current_cpu, insn);
423
#if 0 /* disable for now until we find out how FSR0.QNE gets reset.  */
424
  else
425
    {
426
      /* Enter the halt state if FSR0.QNE is set and we are executing a
427
         floating point insn, a media insn or an insn which access a FR
428
         register.  */
429
      SI fsr0 = GET_FSR (0);
430
      if (GET_FSR_QNE (fsr0)
431
          && (frv_is_float_insn (insn) || frv_is_media_insn (insn)
432
              || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)))
433
        {
434
          sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped,
435
                           SIM_SIGINT);
436
        }
437
    }
438
#endif
439
}
440
 
441
/* Record the current VLIW slot in the given interrupt queue element.  */
442
void
443
frv_set_interrupt_queue_slot (
444
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
445
)
446
{
447
  FRV_VLIW *vliw = CPU_VLIW (current_cpu);
448
  int slot = vliw->next_slot - 1;
449
  item->slot = (*vliw->current_vliw)[slot];
450
}
451
 
452
/* Handle an individual interrupt.  */
453
static void
454
handle_interrupt (SIM_CPU *current_cpu, IADDR pc)
455
{
456
  struct frv_interrupt *interrupt;
457
  int writeback_done = 0;
458
  while (1)
459
    {
460
      /* Interrupts are queued in priority order with the highest priority
461
         last.  */
462
      int index = frv_interrupt_state.queue_index - 1;
463
      struct frv_interrupt_queue_element *item
464
        = & frv_interrupt_state.queue[index];
465
      interrupt = & frv_interrupt_table[item->kind];
466
 
467
      switch (interrupt->iclass)
468
        {
469
        case FRV_EXTERNAL_INTERRUPT:
470
          /* Perform writeback first. This may cause a higher priority
471
             interrupt.  */
472
          if (! writeback_done)
473
            {
474
              frvbf_perform_writeback (current_cpu);
475
              writeback_done = 1;
476
              continue;
477
            }
478
          frv_external_interrupt (current_cpu, item, pc);
479
          return;
480
        case FRV_SOFTWARE_INTERRUPT:
481
          frv_interrupt_state.queue_index = index;
482
          frv_software_interrupt (current_cpu, item, pc);
483
          return;
484
        case FRV_PROGRAM_INTERRUPT:
485
          /* If the program interrupt is not strict (imprecise), then perform
486
             writeback first. This may, in turn, cause a higher priority
487
             interrupt.  */
488
          if (! interrupt->precise && ! writeback_done)
489
            {
490
              frv_interrupt_state.imprecise_interrupt = item;
491
              frvbf_perform_writeback (current_cpu);
492
              writeback_done = 1;
493
              continue;
494
            }
495
          frv_interrupt_state.queue_index = index;
496
          frv_program_interrupt (current_cpu, item, pc);
497
          return;
498
        case FRV_BREAK_INTERRUPT:
499
          frv_interrupt_state.queue_index = index;
500
          frv_break_interrupt (current_cpu, interrupt, pc);
501
          return;
502
        case FRV_RESET_INTERRUPT:
503
          break;
504
        default:
505
          break;
506
        }
507
      frv_interrupt_state.queue_index = index;
508
      break; /* out of loop.  */
509
    }
510
 
511
  /* We should never get here.  */
512
  {
513
    SIM_DESC sd = CPU_STATE (current_cpu);
514
    sim_engine_abort (sd, current_cpu, pc,
515
                      "interrupt class not supported %d\n",
516
                      interrupt->iclass);
517
  }
518
}
519
 
520
/* Check to see the if the RSTR.HR or RSTR.SR bits have been set.  If so, handle
521
   the appropriate reset interrupt.  */
522
static int
523
check_reset (SIM_CPU *current_cpu, IADDR pc)
524
{
525
  int hsr0;
526
  int hr;
527
  int sr;
528
  SI rstr;
529
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
530
  IADDR address = RSTR_ADDRESS;
531
 
532
  /* We don't want this to show up in the cache statistics, so read the
533
     cache passively.  */
534
  if (! frv_cache_read_passive_SI (cache, address, & rstr))
535
    rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address);
536
 
537
  hr = GET_RSTR_HR (rstr);
538
  sr = GET_RSTR_SR (rstr);
539
 
540
  if (! hr && ! sr)
541
    return 0; /* no reset.  */
542
 
543
  /* Reinitialize the machine state.  */
544
  if (hr)
545
    frv_hardware_reset (current_cpu);
546
  else
547
    frv_software_reset (current_cpu);
548
 
549
  /* Branch to the reset address.  */
550
  hsr0 = GET_HSR0 ();
551
  if (GET_HSR0_SA (hsr0))
552
    SET_H_PC (0xff000000);
553
  else
554
    SET_H_PC (0);
555
 
556
  return 1; /* reset */
557
}
558
 
559
/* Process any pending interrupt(s) after a group of parallel insns.  */
560
void
561
frv_process_interrupts (SIM_CPU *current_cpu)
562
{
563
  SI NE_flags[2];
564
  /* Need to save the pc here because writeback may change it (due to a
565
     branch).  */
566
  IADDR pc = CPU_PC_GET (current_cpu);
567
 
568
  /* Check for a reset before anything else.  */
569
  if (check_reset (current_cpu, pc))
570
    return;
571
 
572
  /* First queue the writes for any accumulated NE flags.  */
573
  if (frv_interrupt_state.f_ne_flags[0] != 0
574
      || frv_interrupt_state.f_ne_flags[1] != 0)
575
    {
576
      GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
577
      NE_flags[0] |= frv_interrupt_state.f_ne_flags[0];
578
      NE_flags[1] |= frv_interrupt_state.f_ne_flags[1];
579
      SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
580
    }
581
 
582
  /* If there is no interrupt pending, then perform parallel writeback.  This
583
     may cause an interrupt.  */
584
  if (frv_interrupt_state.queue_index <= 0)
585
    frvbf_perform_writeback (current_cpu);
586
 
587
  /* If there is an interrupt pending, then process it.  */
588
  if (frv_interrupt_state.queue_index > 0)
589
    handle_interrupt (current_cpu, pc);
590
}
591
 
592
/* Find the next available ESR and return its index */
593
static int
594
esr_for_data_access_exception (
595
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
596
)
597
{
598
  SIM_DESC sd = CPU_STATE (current_cpu);
599
  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
600
    return 8; /* Use ESR8, EPCR8.  */
601
 
602
  if (item->slot == UNIT_I0)
603
    return 8; /* Use ESR8, EPCR8, EAR8, EDR8.  */
604
 
605
  return 9; /* Use ESR9, EPCR9, EAR9.  */
606
}
607
 
608
/* Set the next available EDR register with the data which was to be stored
609
   and return the index of the register.  */
610
static int
611
set_edr_register (
612
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index
613
)
614
{
615
  /* EDR0, EDR4 and EDR8 are available as blocks of 4.
616
       SI data uses EDR3, EDR7 and EDR11
617
       DI data uses EDR2, EDR6 and EDR10
618
       XI data uses EDR0, EDR4 and EDR8.  */
619
  int i;
620
  edr_index += 4 - item->u.data_written.length;
621
  for (i = 0; i < item->u.data_written.length; ++i)
622
    SET_EDR (edr_index + i, item->u.data_written.words[i]);
623
 
624
  return edr_index;
625
};
626
 
627
/* Clear ESFR0, EPCRx, ESRx, EARx and EDRx.  */
628
static void
629
clear_exception_status_registers (SIM_CPU *current_cpu)
630
{
631
  int i;
632
  /* It is only necessary to clear the flag bits indicating which registers
633
     are valid.  */
634
  SET_ESFR (0, 0);
635
  SET_ESFR (1, 0);
636
 
637
  for (i = 0; i <= 2; ++i)
638
    {
639
      SI esr = GET_ESR (i);
640
      CLEAR_ESR_VALID (esr);
641
      SET_ESR (i, esr);
642
    }
643
  for (i = 8; i <= 15; ++i)
644
    {
645
      SI esr = GET_ESR (i);
646
      CLEAR_ESR_VALID (esr);
647
      SET_ESR (i, esr);
648
    }
649
}
650
 
651
/* Record state for media exception.  */
652
void
653
frv_set_mp_exception_registers (
654
  SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie
655
)
656
{
657
  /* Record the interrupt factor in MSR0.  */
658
  SI msr0 = GET_MSR (0);
659
  if (GET_MSR_MTT (msr0) == MTT_NONE)
660
    SET_MSR_MTT (msr0, mtt);
661
 
662
  /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF.  */
663
  if (mtt == MTT_OVERFLOW)
664
    {
665
      FRV_VLIW *vliw = CPU_VLIW (current_cpu);
666
      int slot = vliw->next_slot - 1;
667
      SIM_DESC sd = CPU_STATE (current_cpu);
668
 
669
      /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE,
670
         otherwise set MSR0.OVF and MSR0.SIE.  */
671
      if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550 && (*vliw->current_vliw)[slot] == UNIT_FM1)
672
        {
673
          SI msr = GET_MSR (1);
674
          OR_MSR_SIE (msr, sie);
675
          SET_MSR_OVF (msr);
676
          SET_MSR (1, msr);
677
        }
678
      else
679
        {
680
          OR_MSR_SIE (msr0, sie);
681
          SET_MSR_OVF (msr0);
682
        }
683
 
684
      /* Generate the interrupt now if MSR0.MPEM is set on fr550 */
685
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550 && GET_MSR_MPEM (msr0))
686
        frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION);
687
      else
688
        {
689
          /* Regardless of the slot, set MSR0.AOVF.  */
690
          SET_MSR_AOVF (msr0);
691
        }
692
    }
693
 
694
  SET_MSR (0, msr0);
695
}
696
 
697
/* Determine the correct FQ register to use for the given exception.
698
   Return -1 if a register is not available.  */
699
static int
700
fq_for_exception (
701
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
702
)
703
{
704
  SI fq;
705
  struct frv_fp_exception_info *fp_info = & item->u.fp_info;
706
 
707
  /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1.  */
708
  if (fp_info->ftt == FTT_IEEE_754_EXCEPTION
709
      && (fp_info->fsr_mask & (FSR_OVERFLOW | FSR_UNDERFLOW | FSR_INEXACT)))
710
    {
711
      fq = GET_FQ (0);
712
      if (! GET_FQ_VALID (fq))
713
        return 0; /* FQ0 is available.  */
714
      fq = GET_FQ (1);
715
      if (! GET_FQ_VALID (fq))
716
        return 1; /* FQ1 is available.  */
717
 
718
      /* No FQ register is available */
719
      {
720
        SIM_DESC sd = CPU_STATE (current_cpu);
721
        IADDR pc = CPU_PC_GET (current_cpu);
722
        sim_engine_abort (sd, current_cpu, pc, "No FQ register available\n");
723
      }
724
      return -1;
725
    }
726
  /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3
727
     otherwise.  */
728
  if (item->slot == UNIT_FM0 || item->slot == UNIT_I0)
729
    return 2;
730
 
731
  return 3;
732
}
733
 
734
/* Set FSR0, FQ0-FQ9, depending on the interrupt.  */
735
static void
736
set_fp_exception_registers (
737
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
738
)
739
{
740
  int fq_index;
741
  SI fq;
742
  SI insn;
743
  SI fsr0;
744
  IADDR pc;
745
  struct frv_fp_exception_info *fp_info;
746
  SIM_DESC sd = CPU_STATE (current_cpu);
747
 
748
  /* No FQ registers on fr550 */
749
  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
750
    {
751
      /* Update the fsr.  */
752
      fp_info = & item->u.fp_info;
753
      fsr0 = GET_FSR (0);
754
      SET_FSR_FTT (fsr0, fp_info->ftt);
755
      SET_FSR (0, fsr0);
756
      return;
757
    }
758
 
759
  /* Select an FQ and update it with the exception information.  */
760
  fq_index = fq_for_exception (current_cpu, item);
761
  if (fq_index == -1)
762
    return;
763
 
764
  fp_info = & item->u.fp_info;
765
  fq = GET_FQ (fq_index);
766
  SET_FQ_MIV (fq, MIV_FLOAT);
767
  SET_FQ_SIE (fq, SIE_NIL);
768
  SET_FQ_FTT (fq, fp_info->ftt);
769
  SET_FQ_CEXC (fq, fp_info->fsr_mask);
770
  SET_FQ_VALID (fq);
771
  SET_FQ (fq_index, fq);
772
 
773
  /* Write the failing insn into FQx.OPC.  */
774
  pc = item->vpc;
775
  insn = GETMEMSI (current_cpu, pc, pc);
776
  SET_FQ_OPC (fq_index, insn);
777
 
778
  /* Update the fsr.  */
779
  fsr0 = GET_FSR (0);
780
  SET_FSR_QNE (fsr0); /* FQ not empty */
781
  SET_FSR_FTT (fsr0, fp_info->ftt);
782
  SET_FSR (0, fsr0);
783
}
784
 
785
/* Record the state of a division exception in the ISR.  */
786
static void
787
set_isr_exception_fields (
788
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
789
)
790
{
791
  USI isr = GET_ISR ();
792
  int dtt = GET_ISR_DTT (isr);
793
  dtt |= item->u.dtt;
794
  SET_ISR_DTT (isr, dtt);
795
  SET_ISR (isr);
796
}
797
 
798
/* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program
799
   interrupt.  */
800
static void
801
set_exception_status_registers (
802
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
803
)
804
{
805
  struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
806
  int slot = (item->vpc - previous_vliw_pc) / 4;
807
  int reg_index = -1;
808
  int set_ear = 0;
809
  int set_edr = 0;
810
  int set_daec = 0;
811
  int set_epcr = 0;
812
  SI esr = 0;
813
  SIM_DESC sd = CPU_STATE (current_cpu);
814
 
815
  /* If the interrupt is strict (precise) or the interrupt is on the insns
816
     in the I0 pipe, then set the 0 registers.  */
817
  if (interrupt->precise)
818
    {
819
      reg_index = 0;
820
      if (interrupt->kind == FRV_REGISTER_EXCEPTION)
821
        SET_ESR_REC (esr, item->u.rec);
822
      else if (interrupt->kind == FRV_INSTRUCTION_ACCESS_EXCEPTION)
823
        SET_ESR_IAEC (esr, item->u.iaec);
824
      /* For fr550, don't set epcr for precise interrupts.  */
825
      if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
826
        set_epcr = 1;
827
    }
828
  else
829
    {
830
      switch (interrupt->kind)
831
        {
832
        case FRV_DIVISION_EXCEPTION:
833
          set_isr_exception_fields (current_cpu, item);
834
          /* fall thru to set reg_index.  */
835
        case FRV_COMMIT_EXCEPTION:
836
          /* For fr550, always use ESR0.  */
837
          if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
838
            reg_index = 0;
839
          else if (item->slot == UNIT_I0)
840
            reg_index = 0;
841
          else if (item->slot == UNIT_I1)
842
            reg_index = 1;
843
          set_epcr = 1;
844
          break;
845
        case FRV_DATA_STORE_ERROR:
846
          reg_index = 14; /* Use ESR14.  */
847
          break;
848
        case FRV_DATA_ACCESS_ERROR:
849
          reg_index = 15; /* Use ESR15, EPCR15.  */
850
          set_ear = 1;
851
          break;
852
        case FRV_DATA_ACCESS_EXCEPTION:
853
          set_daec = 1;
854
          /* fall through */
855
        case FRV_DATA_ACCESS_MMU_MISS:
856
        case FRV_MEM_ADDRESS_NOT_ALIGNED:
857
          /* Get the appropriate ESR, EPCR, EAR and EDR.
858
             EAR will be set. EDR will not be set if this is a store insn.  */
859
          set_ear = 1;
860
          /* For fr550, never use EDRx.  */
861
          if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
862
            if (item->u.data_written.length != 0)
863
              set_edr = 1;
864
          reg_index = esr_for_data_access_exception (current_cpu, item);
865
          set_epcr = 1;
866
          break;
867
        case FRV_MP_EXCEPTION:
868
          /* For fr550, use EPCR2 and ESR2.  */
869
          if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
870
            {
871
              reg_index = 2;
872
              set_epcr = 1;
873
            }
874
          break; /* MSR0-1, FQ0-9 are already set.  */
875
        case FRV_FP_EXCEPTION:
876
          set_fp_exception_registers (current_cpu, item);
877
          /* For fr550, use EPCR2 and ESR2.  */
878
          if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
879
            {
880
              reg_index = 2;
881
              set_epcr = 1;
882
            }
883
          break;
884
        default:
885
          {
886
            SIM_DESC sd = CPU_STATE (current_cpu);
887
            IADDR pc = CPU_PC_GET (current_cpu);
888
            sim_engine_abort (sd, current_cpu, pc,
889
                              "invalid non-strict program interrupt kind: %d\n",
890
                              interrupt->kind);
891
            break;
892
          }
893
        }
894
    } /* non-strict (imprecise) interrupt */
895
 
896
  /* Now fill in the selected exception status registers.  */
897
  if (reg_index != -1)
898
    {
899
      /* Now set the exception status registers.  */
900
      SET_ESFR_FLAG (reg_index);
901
      SET_ESR_EC (esr, interrupt->ec);
902
 
903
      if (set_epcr)
904
        {
905
          if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
906
            SET_EPCR (reg_index, previous_vliw_pc);
907
          else
908
            SET_EPCR (reg_index, item->vpc);
909
        }
910
 
911
      if (set_ear)
912
        {
913
          SET_EAR (reg_index, item->eaddress);
914
          SET_ESR_EAV (esr);
915
        }
916
      else
917
        CLEAR_ESR_EAV (esr);
918
 
919
      if (set_edr)
920
        {
921
          int edn = set_edr_register (current_cpu, item, 0/* EDR0-3 */);
922
          SET_ESR_EDN (esr, edn);
923
          SET_ESR_EDV (esr);
924
        }
925
      else
926
        CLEAR_ESR_EDV (esr);
927
 
928
      if (set_daec)
929
        SET_ESR_DAEC (esr, item->u.daec);
930
 
931
      SET_ESR_VALID (esr);
932
      SET_ESR (reg_index, esr);
933
    }
934
}
935
 
936
/* Check for compound interrupts.
937
   Returns NULL if no interrupt is to be processed.  */
938
static struct frv_interrupt *
939
check_for_compound_interrupt (
940
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
941
)
942
{
943
  struct frv_interrupt *interrupt;
944
 
945
  /* Set the exception status registers for the original interrupt.  */
946
  set_exception_status_registers (current_cpu, item);
947
  interrupt = & frv_interrupt_table[item->kind];
948
 
949
  if (! interrupt->precise)
950
    {
951
      IADDR vpc = 0;
952
      int mask = 0;
953
 
954
      vpc = item->vpc;
955
      mask = (1 << item->kind);
956
 
957
      /* Look for more queued program interrupts which are non-deferred
958
         (pending inhibit), imprecise (non-strict) different than an interrupt
959
         already found and caused by a different insn.  A bit mask is used
960
         to keep track of interrupts which have already been detected.  */
961
      while (item != frv_interrupt_state.queue)
962
        {
963
          enum frv_interrupt_kind kind;
964
          struct frv_interrupt *next_interrupt;
965
          --item;
966
          kind = item->kind;
967
          next_interrupt = & frv_interrupt_table[kind];
968
 
969
          if (next_interrupt->iclass != FRV_PROGRAM_INTERRUPT)
970
            break; /* no program interrupts left.  */
971
 
972
          if (item->vpc == vpc)
973
            continue; /* caused by the same insn.  */
974
 
975
          vpc = item->vpc;
976
          if (! next_interrupt->precise && ! next_interrupt->deferred)
977
            {
978
              if (! (mask & (1 << kind)))
979
                {
980
                  /* Set the exception status registers for the additional
981
                     interrupt.  */
982
                  set_exception_status_registers (current_cpu, item);
983
                  mask |= (1 << kind);
984
                  interrupt = & frv_interrupt_table[FRV_COMPOUND_EXCEPTION];
985
                }
986
            }
987
        }
988
    }
989
 
990
  /* Return with either the original interrupt, a compound_exception,
991
     or no exception.  */
992
  return interrupt;
993
}
994
 
995
/* Handle a program interrupt.  */
996
void
997
frv_program_interrupt (
998
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
999
)
1000
{
1001
  struct frv_interrupt *interrupt;
1002
 
1003
  clear_exception_status_registers (current_cpu);
1004
  /* If two or more non-deferred imprecise (non-strict) interrupts occur
1005
     on two or more insns, then generate a compound_exception.  */
1006
  interrupt = check_for_compound_interrupt (current_cpu, item);
1007
  if (interrupt != NULL)
1008
    {
1009
      frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1010
      frv_clear_interrupt_classes (FRV_SOFTWARE_INTERRUPT,
1011
                                   FRV_PROGRAM_INTERRUPT);
1012
    }
1013
}
1014
 
1015
/* Handle a software interrupt.  */
1016
void
1017
frv_software_interrupt (
1018
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1019
)
1020
{
1021
  struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1022
  frv_program_or_software_interrupt (current_cpu, interrupt, pc);
1023
}
1024
 
1025
/* Handle a program interrupt or a software interrupt in non-operating mode.  */
1026
void
1027
frv_non_operating_interrupt (
1028
  SIM_CPU *current_cpu, enum frv_interrupt_kind kind, IADDR pc
1029
)
1030
{
1031
  SIM_DESC sd = CPU_STATE (current_cpu);
1032
  switch (kind)
1033
    {
1034
    case FRV_INTERRUPT_LEVEL_1:
1035
    case FRV_INTERRUPT_LEVEL_2:
1036
    case FRV_INTERRUPT_LEVEL_3:
1037
    case FRV_INTERRUPT_LEVEL_4:
1038
    case FRV_INTERRUPT_LEVEL_5:
1039
    case FRV_INTERRUPT_LEVEL_6:
1040
    case FRV_INTERRUPT_LEVEL_7:
1041
    case FRV_INTERRUPT_LEVEL_8:
1042
    case FRV_INTERRUPT_LEVEL_9:
1043
    case FRV_INTERRUPT_LEVEL_10:
1044
    case FRV_INTERRUPT_LEVEL_11:
1045
    case FRV_INTERRUPT_LEVEL_12:
1046
    case FRV_INTERRUPT_LEVEL_13:
1047
    case FRV_INTERRUPT_LEVEL_14:
1048
    case FRV_INTERRUPT_LEVEL_15:
1049
      sim_engine_abort (sd, current_cpu, pc,
1050
                        "interrupt: external %d\n", kind + 1);
1051
      break;
1052
    case FRV_TRAP_INSTRUCTION:
1053
      break; /* handle as in operating mode.  */
1054
    case FRV_COMMIT_EXCEPTION:
1055
      sim_engine_abort (sd, current_cpu, pc,
1056
                        "interrupt: commit_exception\n");
1057
      break;
1058
    case FRV_DIVISION_EXCEPTION:
1059
      sim_engine_abort (sd, current_cpu, pc,
1060
                        "interrupt: division_exception\n");
1061
      break;
1062
    case FRV_DATA_STORE_ERROR:
1063
      sim_engine_abort (sd, current_cpu, pc,
1064
                        "interrupt: data_store_error\n");
1065
      break;
1066
    case FRV_DATA_ACCESS_EXCEPTION:
1067
      sim_engine_abort (sd, current_cpu, pc,
1068
                        "interrupt: data_access_exception\n");
1069
      break;
1070
    case FRV_DATA_ACCESS_MMU_MISS:
1071
      sim_engine_abort (sd, current_cpu, pc,
1072
                        "interrupt: data_access_mmu_miss\n");
1073
      break;
1074
    case FRV_DATA_ACCESS_ERROR:
1075
      sim_engine_abort (sd, current_cpu, pc,
1076
                        "interrupt: data_access_error\n");
1077
      break;
1078
    case FRV_MP_EXCEPTION:
1079
      sim_engine_abort (sd, current_cpu, pc,
1080
                        "interrupt: mp_exception\n");
1081
      break;
1082
    case FRV_FP_EXCEPTION:
1083
      sim_engine_abort (sd, current_cpu, pc,
1084
                        "interrupt: fp_exception\n");
1085
      break;
1086
    case FRV_MEM_ADDRESS_NOT_ALIGNED:
1087
      sim_engine_abort (sd, current_cpu, pc,
1088
                        "interrupt: mem_address_not_aligned\n");
1089
      break;
1090
    case FRV_REGISTER_EXCEPTION:
1091
      sim_engine_abort (sd, current_cpu, pc,
1092
                        "interrupt: register_exception\n");
1093
      break;
1094
    case FRV_MP_DISABLED:
1095
      sim_engine_abort (sd, current_cpu, pc,
1096
                        "interrupt: mp_disabled\n");
1097
      break;
1098
    case FRV_FP_DISABLED:
1099
      sim_engine_abort (sd, current_cpu, pc,
1100
                        "interrupt: fp_disabled\n");
1101
      break;
1102
    case FRV_PRIVILEGED_INSTRUCTION:
1103
      sim_engine_abort (sd, current_cpu, pc,
1104
                        "interrupt: privileged_instruction\n");
1105
      break;
1106
    case FRV_ILLEGAL_INSTRUCTION:
1107
      sim_engine_abort (sd, current_cpu, pc,
1108
                        "interrupt: illegal_instruction\n");
1109
      break;
1110
    case FRV_INSTRUCTION_ACCESS_EXCEPTION:
1111
      sim_engine_abort (sd, current_cpu, pc,
1112
                        "interrupt: instruction_access_exception\n");
1113
      break;
1114
    case FRV_INSTRUCTION_ACCESS_MMU_MISS:
1115
      sim_engine_abort (sd, current_cpu, pc,
1116
                        "interrupt: instruction_access_mmu_miss\n");
1117
      break;
1118
    case FRV_INSTRUCTION_ACCESS_ERROR:
1119
      sim_engine_abort (sd, current_cpu, pc,
1120
                        "interrupt: insn_access_error\n");
1121
      break;
1122
    case FRV_COMPOUND_EXCEPTION:
1123
      sim_engine_abort (sd, current_cpu, pc,
1124
                        "interrupt: compound_exception\n");
1125
      break;
1126
    case FRV_BREAK_EXCEPTION:
1127
      sim_engine_abort (sd, current_cpu, pc,
1128
                        "interrupt: break_exception\n");
1129
      break;
1130
    case FRV_RESET:
1131
      sim_engine_abort (sd, current_cpu, pc,
1132
                        "interrupt: reset\n");
1133
      break;
1134
    default:
1135
      sim_engine_abort (sd, current_cpu, pc,
1136
                        "unhandled interrupt kind: %d\n", kind);
1137
      break;
1138
    }
1139
}
1140
 
1141
/* Handle a break interrupt.  */
1142
void
1143
frv_break_interrupt (
1144
  SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1145
)
1146
{
1147
  IADDR new_pc;
1148
 
1149
  /* BPCSR=PC
1150
     BPSR.BS=PSR.S
1151
     BPSR.BET=PSR.ET
1152
     PSR.S=1
1153
     PSR.ET=0
1154
     TBR.TT=0xff
1155
     PC=TBR
1156
  */
1157
  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1158
  SET_H_BPSR_BS (GET_H_PSR_S ());
1159
  SET_H_BPSR_BET (GET_H_PSR_ET ());
1160
  SET_H_PSR_S (1);
1161
  SET_H_PSR_ET (0);
1162
  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1163
  SET_H_SPR (H_SPR_BPCSR, current_pc);
1164
 
1165
  /* Set the new PC in the TBR.  */
1166
  SET_H_TBR_TT (interrupt->handler_offset);
1167
  new_pc = GET_H_SPR (H_SPR_TBR);
1168
  SET_H_PC (new_pc);
1169
 
1170
  CPU_DEBUG_STATE (current_cpu) = 1;
1171
}
1172
 
1173
/* Handle a program interrupt or a software interrupt.  */
1174
void
1175
frv_program_or_software_interrupt (
1176
  SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
1177
)
1178
{
1179
  USI new_pc;
1180
  int original_psr_et;
1181
 
1182
  /* PCSR=PC
1183
     PSR.PS=PSR.S
1184
     PSR.ET=0
1185
     PSR.S=1
1186
     if PSR.ESR==1
1187
       SR0 through SR3=GR4 through GR7
1188
       TBR.TT=interrupt handler offset
1189
       PC=TBR
1190
  */
1191
  original_psr_et = GET_H_PSR_ET ();
1192
 
1193
  SET_H_PSR_PS (GET_H_PSR_S ());
1194
  SET_H_PSR_ET (0);
1195
  SET_H_PSR_S (1);
1196
 
1197
  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1198
  /* The PCSR depends on the precision of the interrupt.  */
1199
  if (interrupt->precise)
1200
    SET_H_SPR (H_SPR_PCSR, previous_vliw_pc);
1201
  else
1202
    SET_H_SPR (H_SPR_PCSR, current_pc);
1203
 
1204
  /* Set the new PC in the TBR.  */
1205
  SET_H_TBR_TT (interrupt->handler_offset);
1206
  new_pc = GET_H_SPR (H_SPR_TBR);
1207
  SET_H_PC (new_pc);
1208
 
1209
  /* If PSR.ET was not originally set, then enter the stopped state.  */
1210
  if (! original_psr_et)
1211
    {
1212
      SIM_DESC sd = CPU_STATE (current_cpu);
1213
      frv_non_operating_interrupt (current_cpu, interrupt->kind, current_pc);
1214
      sim_engine_halt (sd, current_cpu, NULL, new_pc, sim_stopped, SIM_SIGINT);
1215
    }
1216
}
1217
 
1218
/* Handle a program interrupt or a software interrupt.  */
1219
void
1220
frv_external_interrupt (
1221
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
1222
)
1223
{
1224
  USI new_pc;
1225
  struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];
1226
 
1227
  /* Don't process the interrupt if PSR.ET is not set or if it is masked.
1228
     Interrupt 15 is processed even if it appears to be masked.  */
1229
  if (! GET_H_PSR_ET ()
1230
      || (interrupt->kind != FRV_INTERRUPT_LEVEL_15
1231
          && interrupt->kind < GET_H_PSR_PIL ()))
1232
    return; /* Leave it for later.  */
1233
 
1234
  /* Remove the interrupt from the queue.  */
1235
  --frv_interrupt_state.queue_index;
1236
 
1237
  /* PCSR=PC
1238
     PSR.PS=PSR.S
1239
     PSR.ET=0
1240
     PSR.S=1
1241
     if PSR.ESR==1
1242
       SR0 through SR3=GR4 through GR7
1243
       TBR.TT=interrupt handler offset
1244
       PC=TBR
1245
  */
1246
  SET_H_PSR_PS (GET_H_PSR_S ());
1247
  SET_H_PSR_ET (0);
1248
  SET_H_PSR_S (1);
1249
  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
1250
  SET_H_SPR (H_SPR_PCSR, GET_H_PC ());
1251
 
1252
  /* Set the new PC in the TBR.  */
1253
  SET_H_TBR_TT (interrupt->handler_offset);
1254
  new_pc = GET_H_SPR (H_SPR_TBR);
1255
  SET_H_PC (new_pc);
1256
}
1257
 
1258
/* Clear interrupts which fall within the range of classes given.  */
1259
void
1260
frv_clear_interrupt_classes (
1261
  enum frv_interrupt_class low_class, enum frv_interrupt_class high_class
1262
)
1263
{
1264
  int i;
1265
  int j;
1266
  int limit = frv_interrupt_state.queue_index;
1267
 
1268
  /* Find the lowest priority interrupt to be removed.  */
1269
  for (i = 0; i < limit; ++i)
1270
    {
1271
      enum frv_interrupt_kind kind = frv_interrupt_state.queue[i].kind;
1272
      struct frv_interrupt* interrupt = & frv_interrupt_table[kind];
1273
      if (interrupt->iclass >= low_class)
1274
        break;
1275
    }
1276
 
1277
  /* Find the highest priority interrupt to be removed.  */
1278
  for (j = limit - 1; j >= i; --j)
1279
    {
1280
      enum frv_interrupt_kind kind = frv_interrupt_state.queue[j].kind;
1281
      struct frv_interrupt* interrupt = & frv_interrupt_table[kind];
1282
      if (interrupt->iclass <= high_class)
1283
        break;
1284
    }
1285
 
1286
  /* Shuffle the remaining high priority interrupts down into the empty space
1287
     left by the deleted interrupts.  */
1288
  if (j >= i)
1289
    {
1290
      for (++j; j < limit; ++j)
1291
        frv_interrupt_state.queue[i++] = frv_interrupt_state.queue[j];
1292
      frv_interrupt_state.queue_index -= (j - i);
1293
    }
1294
}
1295
 
1296
/* Save data written to memory into the interrupt state so that it can be
1297
   copied to the appropriate EDR register, if necessary, in the event of an
1298
   interrupt.  */
1299
void
1300
frv_save_data_written_for_interrupts (
1301
  SIM_CPU *current_cpu, CGEN_WRITE_QUEUE_ELEMENT *item
1302
)
1303
{
1304
  /* Record the slot containing the insn doing the write in the
1305
     interrupt state.  */
1306
  frv_interrupt_state.slot = CGEN_WRITE_QUEUE_ELEMENT_PIPE (item);
1307
 
1308
  /* Now record any data written to memory in the interrupt state.  */
1309
  switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item))
1310
    {
1311
    case CGEN_BI_WRITE:
1312
    case CGEN_QI_WRITE:
1313
    case CGEN_SI_WRITE:
1314
    case CGEN_SF_WRITE:
1315
    case CGEN_PC_WRITE:
1316
    case CGEN_FN_HI_WRITE:
1317
    case CGEN_FN_SI_WRITE:
1318
    case CGEN_FN_SF_WRITE:
1319
    case CGEN_FN_DI_WRITE:
1320
    case CGEN_FN_DF_WRITE:
1321
    case CGEN_FN_XI_WRITE:
1322
    case CGEN_FN_PC_WRITE:
1323
      break; /* Ignore writes to registers.  */
1324
    case CGEN_MEM_QI_WRITE:
1325
      frv_interrupt_state.data_written.length = 1;
1326
      frv_interrupt_state.data_written.words[0]
1327
        = item->kinds.mem_qi_write.value;
1328
      break;
1329
    case CGEN_MEM_HI_WRITE:
1330
      frv_interrupt_state.data_written.length = 1;
1331
      frv_interrupt_state.data_written.words[0]
1332
        = item->kinds.mem_hi_write.value;
1333
      break;
1334
    case CGEN_MEM_SI_WRITE:
1335
      frv_interrupt_state.data_written.length = 1;
1336
      frv_interrupt_state.data_written.words[0]
1337
        = item->kinds.mem_si_write.value;
1338
      break;
1339
    case CGEN_MEM_DI_WRITE:
1340
      frv_interrupt_state.data_written.length = 2;
1341
      frv_interrupt_state.data_written.words[0]
1342
        = item->kinds.mem_di_write.value >> 32;
1343
      frv_interrupt_state.data_written.words[1]
1344
        = item->kinds.mem_di_write.value;
1345
      break;
1346
    case CGEN_MEM_DF_WRITE:
1347
      frv_interrupt_state.data_written.length = 2;
1348
      frv_interrupt_state.data_written.words[0]
1349
        = item->kinds.mem_df_write.value >> 32;
1350
      frv_interrupt_state.data_written.words[1]
1351
        = item->kinds.mem_df_write.value;
1352
      break;
1353
    case CGEN_MEM_XI_WRITE:
1354
      frv_interrupt_state.data_written.length = 4;
1355
      frv_interrupt_state.data_written.words[0]
1356
        = item->kinds.mem_xi_write.value[0];
1357
      frv_interrupt_state.data_written.words[1]
1358
        = item->kinds.mem_xi_write.value[1];
1359
      frv_interrupt_state.data_written.words[2]
1360
        = item->kinds.mem_xi_write.value[2];
1361
      frv_interrupt_state.data_written.words[3]
1362
        = item->kinds.mem_xi_write.value[3];
1363
      break;
1364
    case CGEN_FN_MEM_QI_WRITE:
1365
      frv_interrupt_state.data_written.length = 1;
1366
      frv_interrupt_state.data_written.words[0]
1367
        = item->kinds.fn_mem_qi_write.value;
1368
      break;
1369
    case CGEN_FN_MEM_HI_WRITE:
1370
      frv_interrupt_state.data_written.length = 1;
1371
      frv_interrupt_state.data_written.words[0]
1372
        = item->kinds.fn_mem_hi_write.value;
1373
      break;
1374
    case CGEN_FN_MEM_SI_WRITE:
1375
      frv_interrupt_state.data_written.length = 1;
1376
      frv_interrupt_state.data_written.words[0]
1377
        = item->kinds.fn_mem_si_write.value;
1378
      break;
1379
    case CGEN_FN_MEM_DI_WRITE:
1380
      frv_interrupt_state.data_written.length = 2;
1381
      frv_interrupt_state.data_written.words[0]
1382
        = item->kinds.fn_mem_di_write.value >> 32;
1383
      frv_interrupt_state.data_written.words[1]
1384
        = item->kinds.fn_mem_di_write.value;
1385
      break;
1386
    case CGEN_FN_MEM_DF_WRITE:
1387
      frv_interrupt_state.data_written.length = 2;
1388
      frv_interrupt_state.data_written.words[0]
1389
        = item->kinds.fn_mem_df_write.value >> 32;
1390
      frv_interrupt_state.data_written.words[1]
1391
        = item->kinds.fn_mem_df_write.value;
1392
      break;
1393
    case CGEN_FN_MEM_XI_WRITE:
1394
      frv_interrupt_state.data_written.length = 4;
1395
      frv_interrupt_state.data_written.words[0]
1396
        = item->kinds.fn_mem_xi_write.value[0];
1397
      frv_interrupt_state.data_written.words[1]
1398
        = item->kinds.fn_mem_xi_write.value[1];
1399
      frv_interrupt_state.data_written.words[2]
1400
        = item->kinds.fn_mem_xi_write.value[2];
1401
      frv_interrupt_state.data_written.words[3]
1402
        = item->kinds.fn_mem_xi_write.value[3];
1403
      break;
1404
    default:
1405
      {
1406
        SIM_DESC sd = CPU_STATE (current_cpu);
1407
        IADDR pc = CPU_PC_GET (current_cpu);
1408
        sim_engine_abort (sd, current_cpu, pc,
1409
                          "unknown write kind during save for interrupt\n");
1410
      }
1411
      break;
1412
    }
1413
}

powered by: WebSVN 2.1.0

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