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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [sim/] [frv/] [interrupts.c] - Blame information for rev 853

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

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

powered by: WebSVN 2.1.0

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