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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [ppc/] [interrupts.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*  This file is part of the program psim.
2
 
3
    Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _INTERRUPTS_C_
23
#define _INTERRUPTS_C_
24
 
25
#include <signal.h>
26
 
27
#include "cpu.h"
28
#include "idecode.h"
29
#include "os_emul.h"
30
 
31
 
32
/* Operating environment support code
33
 
34
   Unlike the VEA, the OEA must fully model the effect an interrupt
35
   has on the processors state.
36
 
37
   Each function below return updated values for registers effected by
38
   interrupts */
39
 
40
 
41
STATIC_INLINE_INTERRUPTS\
42
(msreg)
43
interrupt_msr(msreg old_msr,
44
              msreg msr_clear,
45
              msreg msr_set)
46
{
47
  msreg msr_set_to_0 = (msr_branch_trace_enable
48
                        | msr_data_relocate
49
                        | msr_external_interrupt_enable
50
                        | msr_floating_point_exception_mode_0
51
                        | msr_floating_point_exception_mode_1
52
                        | msr_floating_point_available
53
                        | msr_instruction_relocate
54
                        | msr_power_management_enable
55
                        | msr_problem_state
56
                        | msr_recoverable_interrupt
57
                        | msr_single_step_trace_enable);
58
  /* remember, in 32bit mode msr_64bit_mode is zero */
59
  msreg new_msr = ((((old_msr & ~msr_set_to_0)
60
                     | msr_64bit_mode)
61
                    & ~msr_clear)
62
                   | msr_set);
63
  return new_msr;
64
}
65
 
66
 
67
STATIC_INLINE_INTERRUPTS\
68
(msreg)
69
interrupt_srr1(msreg old_msr,
70
               msreg srr1_clear,
71
               msreg srr1_set)
72
{
73
  spreg srr1_mask = (MASK(0,32)
74
                     | MASK(37, 41)
75
                     | MASK(48, 63));
76
  spreg srr1 = (old_msr & srr1_mask & ~srr1_clear) | srr1_set;
77
  return srr1;
78
}
79
 
80
 
81
STATIC_INLINE_INTERRUPTS\
82
(unsigned_word)
83
interrupt_base_ea(msreg msr)
84
{
85
  if (msr & msr_interrupt_prefix)
86
    return MASK(0, 43);
87
  else
88
    return 0;
89
}
90
 
91
 
92
/* finish off an interrupt for the OEA model, updating all registers
93
   and forcing a restart of the processor */
94
 
95
STATIC_INLINE_INTERRUPTS\
96
(unsigned_word)
97
perform_oea_interrupt(cpu *processor,
98
                      unsigned_word cia,
99
                      unsigned_word vector_offset,
100
                      msreg msr_clear,
101
                      msreg msr_set,
102
                      msreg srr1_clear,
103
                      msreg srr1_set)
104
{
105
  msreg old_msr = MSR;
106
  msreg new_msr = interrupt_msr(old_msr, msr_clear, msr_set);
107
  unsigned_word nia;
108
  if (!(old_msr & msr_recoverable_interrupt)) {
109
    cpu_error(processor, cia,
110
              "double interrupt - MSR[RI] bit clear when attempting to deliver interrupt, cia=0x%lx, msr=0x%lx; srr0=0x%lx(cia), srr1=0x%lx(msr); trap-vector=0x%lx, trap-msr=0x%lx",
111
              (unsigned long)cia,
112
              (unsigned long)old_msr,
113
              (unsigned long)SRR0,
114
              (unsigned long)SRR1,
115
              (unsigned long)vector_offset,
116
              (unsigned long)new_msr);
117
  }
118
  SRR0 = (spreg)(cia);
119
  SRR1 = interrupt_srr1(old_msr, srr1_clear, srr1_set);
120
  MSR = new_msr;
121
  nia = interrupt_base_ea(new_msr) + vector_offset;
122
  cpu_synchronize_context(processor, cia);
123
  return nia;
124
}
125
 
126
 
127
INLINE_INTERRUPTS\
128
(void)
129
machine_check_interrupt(cpu *processor,
130
                        unsigned_word cia)
131
{
132
  switch (CURRENT_ENVIRONMENT) {
133
 
134
  case USER_ENVIRONMENT:
135
  case VIRTUAL_ENVIRONMENT:
136
    cpu_error(processor, cia, "machine-check interrupt");
137
 
138
  case OPERATING_ENVIRONMENT:
139
    TRACE(trace_interrupts, ("machine-check interrupt - cia=0x%lx\n",
140
                             (unsigned long)cia));
141
    cia = perform_oea_interrupt(processor, cia, 0x00200, 0, 0, 0, 0);
142
    cpu_restart(processor, cia);
143
 
144
  default:
145
    error("internal error - machine_check_interrupt - bad switch");
146
 
147
  }
148
}
149
 
150
 
151
INLINE_INTERRUPTS\
152
(void)
153
data_storage_interrupt(cpu *processor,
154
                       unsigned_word cia,
155
                       unsigned_word ea,
156
                       storage_interrupt_reasons reason,
157
                       int is_store)
158
{
159
  switch (CURRENT_ENVIRONMENT) {
160
 
161
  case USER_ENVIRONMENT:
162
  case VIRTUAL_ENVIRONMENT:
163
    error("internal error - data_storage_interrupt - should not be called in VEA mode");
164
    break;
165
 
166
  case OPERATING_ENVIRONMENT:
167
    {
168
      spreg direction = (is_store ? dsisr_store_operation : 0);
169
      switch (reason) {
170
      case direct_store_storage_interrupt:
171
        DSISR = dsisr_direct_store_error_exception | direction;
172
        break;
173
      case hash_table_miss_storage_interrupt:
174
        DSISR = dsisr_hash_table_or_dbat_miss | direction;
175
        break;
176
      case protection_violation_storage_interrupt:
177
        DSISR = dsisr_protection_violation | direction;
178
        break;
179
      case earwax_violation_storage_interrupt:
180
        DSISR = dsisr_earwax_violation | direction;
181
        break;
182
      case segment_table_miss_storage_interrupt:
183
        DSISR = dsisr_segment_table_miss | direction;
184
        break;
185
      case earwax_disabled_storage_interrupt:
186
        DSISR = dsisr_earwax_disabled | direction;
187
        break;
188
      default:
189
        error("internal error - data_storage_interrupt - reason %d not implemented", reason);
190
        break;
191
      }
192
      DAR = (spreg)ea;
193
      TRACE(trace_interrupts, ("data storage interrupt - cia=0x%lx DAR=0x%lx DSISR=0x%lx\n",
194
                               (unsigned long)cia,
195
                               (unsigned long)DAR,
196
                               (unsigned long)DSISR));
197
      cia = perform_oea_interrupt(processor, cia, 0x00300, 0, 0, 0, 0);
198
      cpu_restart(processor, cia);
199
    }
200
 
201
  default:
202
    error("internal error - data_storage_interrupt - bad switch");
203
 
204
  }
205
}
206
 
207
 
208
INLINE_INTERRUPTS\
209
(void)
210
instruction_storage_interrupt(cpu *processor,
211
                              unsigned_word cia,
212
                              storage_interrupt_reasons reason)
213
{
214
  switch (CURRENT_ENVIRONMENT) {
215
 
216
  case USER_ENVIRONMENT:
217
  case VIRTUAL_ENVIRONMENT:
218
    error("internal error - instruction_storage_interrupt - should not be called in VEA mode");
219
 
220
  case OPERATING_ENVIRONMENT:
221
    {
222
      msreg srr1_set;
223
      switch(reason) {
224
      case hash_table_miss_storage_interrupt:
225
        srr1_set = srr1_hash_table_or_ibat_miss;
226
        break;
227
      case direct_store_storage_interrupt:
228
        srr1_set = srr1_direct_store_error_exception;
229
        break;
230
      case protection_violation_storage_interrupt:
231
        srr1_set = srr1_protection_violation;
232
        break;
233
      case segment_table_miss_storage_interrupt:
234
        srr1_set = srr1_segment_table_miss;
235
        break;
236
      default:
237
        srr1_set = 0;
238
        error("internal error - instruction_storage_interrupt - reason %d not implemented");
239
        break;
240
      }
241
      TRACE(trace_interrupts, ("instruction storage interrupt - cia=0x%lx SRR1|=0x%lx\n",
242
                               (unsigned long)cia,
243
                               (unsigned long)srr1_set));
244
      cia = perform_oea_interrupt(processor, cia, 0x00400, 0, 0, 0, srr1_set);
245
      cpu_restart(processor, cia);
246
    }
247
 
248
  default:
249
    error("internal error - instruction_storage_interrupt - bad switch");
250
 
251
  }
252
}
253
 
254
 
255
 
256
INLINE_INTERRUPTS\
257
(void)
258
alignment_interrupt(cpu *processor,
259
                    unsigned_word cia,
260
                    unsigned_word ra)
261
{
262
  switch (CURRENT_ENVIRONMENT) {
263
 
264
  case USER_ENVIRONMENT:
265
  case VIRTUAL_ENVIRONMENT:
266
    cpu_error(processor, cia, "alignment interrupt - ra=0x%lx", ra);
267
 
268
  case OPERATING_ENVIRONMENT:
269
    DAR = (spreg)ra;
270
    DSISR = 0; /* FIXME */
271
    TRACE(trace_interrupts, ("alignment interrupt - cia=0x%lx DAR=0x%lx DSISR=0x%lx\n",
272
                             (unsigned long)cia,
273
                             (unsigned long)DAR,
274
                             (unsigned long)DSISR));
275
    cia = perform_oea_interrupt(processor, cia, 0x00600, 0, 0, 0, 0);
276
    cpu_restart(processor, cia);
277
 
278
  default:
279
    error("internal error - alignment_interrupt - bad switch");
280
 
281
  }
282
}
283
 
284
 
285
 
286
 
287
INLINE_INTERRUPTS\
288
(void)
289
program_interrupt(cpu *processor,
290
                  unsigned_word cia,
291
                  program_interrupt_reasons reason)
292
{
293
  switch (CURRENT_ENVIRONMENT) {
294
 
295
  case USER_ENVIRONMENT:
296
  case VIRTUAL_ENVIRONMENT:
297
    switch (reason) {
298
    case floating_point_enabled_program_interrupt:
299
      cpu_error(processor, cia, "program interrupt - %s",
300
                "floating point enabled");
301
      break;
302
    case illegal_instruction_program_interrupt:
303
      cpu_error(processor, cia, "program interrupt - %s",
304
                "illegal instruction");
305
      break;
306
    case privileged_instruction_program_interrupt:
307
      cpu_error(processor, cia, "program interrupt - %s",
308
                "privileged instruction");
309
      break;
310
    case trap_program_interrupt:
311
      cpu_error(processor, cia, "program interrupt - %s",
312
                "trap");
313
      break;
314
    case optional_instruction_program_interrupt:
315
      cpu_error(processor, cia, "program interrupt - %s",
316
                "illegal instruction (optional instruction not supported)");
317
      break;
318
    case mpc860c0_instruction_program_interrupt:
319
      cpu_error(processor, cia, "program interrupt - %s",
320
                "problematic branch detected, see MPC860 C0 errata");
321
      break;
322
    default:
323
      error("internal error - program_interrupt - reason %d not implemented", reason);
324
    }
325
 
326
  case OPERATING_ENVIRONMENT:
327
    {
328
      msreg srr1_set;
329
      switch (reason) {
330
      case floating_point_enabled_program_interrupt:
331
        srr1_set = srr1_floating_point_enabled;
332
        break;
333
      case optional_instruction_program_interrupt:
334
      case illegal_instruction_program_interrupt:
335
        srr1_set = srr1_illegal_instruction;
336
        break;
337
      case privileged_instruction_program_interrupt:
338
        srr1_set = srr1_priviliged_instruction;
339
        break;
340
      case trap_program_interrupt:
341
        srr1_set = srr1_trap;
342
        break;
343
      case mpc860c0_instruction_program_interrupt:
344
        srr1_set = 0;
345
        cpu_error(processor, cia, "program interrupt - %s",
346
              "problematic branch detected, see MPC860 C0 errata");
347
        break;
348
      default:
349
        srr1_set = 0;
350
        error("internal error - program_interrupt - reason %d not implemented", reason);
351
        break;
352
      }
353
      TRACE(trace_interrupts, ("program interrupt - cia=0x%lx SRR1|=0x%lx\n",
354
                               (unsigned long)cia,
355
                               (unsigned long)srr1_set));
356
      cia = perform_oea_interrupt(processor, cia, 0x00700, 0, 0, 0, srr1_set);
357
      cpu_restart(processor, cia);
358
    }
359
 
360
  default:
361
    error("internal error - program_interrupt - bad switch");
362
 
363
  }
364
}
365
 
366
 
367
INLINE_INTERRUPTS\
368
(void)
369
floating_point_unavailable_interrupt(cpu *processor,
370
                                     unsigned_word cia)
371
{
372
  switch (CURRENT_ENVIRONMENT) {
373
 
374
  case USER_ENVIRONMENT:
375
  case VIRTUAL_ENVIRONMENT:
376
    cpu_error(processor, cia, "floating-point unavailable interrupt");
377
 
378
  case OPERATING_ENVIRONMENT:
379
    TRACE(trace_interrupts, ("floating-point unavailable interrupt - cia=0x%lx\n",
380
                             (unsigned long)cia));
381
    cia = perform_oea_interrupt(processor, cia, 0x00800, 0, 0, 0, 0);
382
    cpu_restart(processor, cia);
383
 
384
  default:
385
    error("internal error - floating_point_unavailable_interrupt - bad switch");
386
 
387
  }
388
}
389
 
390
 
391
INLINE_INTERRUPTS\
392
(void)
393
system_call_interrupt(cpu *processor,
394
                      unsigned_word cia)
395
{
396
  TRACE(trace_interrupts, ("system-call interrupt - cia=0x%lx\n", (unsigned long)cia));
397
 
398
  switch (CURRENT_ENVIRONMENT) {
399
 
400
  case USER_ENVIRONMENT:
401
  case VIRTUAL_ENVIRONMENT:
402
    os_emul_system_call(processor, cia);
403
    cpu_restart(processor, cia+4);
404
 
405
  case OPERATING_ENVIRONMENT:
406
    cia = perform_oea_interrupt(processor, cia+4, 0x00c00, 0, 0, 0, 0);
407
    cpu_restart(processor, cia);
408
 
409
  default:
410
    error("internal error - system_call_interrupt - bad switch");
411
 
412
  }
413
}
414
 
415
INLINE_INTERRUPTS\
416
(void)
417
floating_point_assist_interrupt(cpu *processor,
418
                                unsigned_word cia)
419
{
420
  switch (CURRENT_ENVIRONMENT) {
421
 
422
  case USER_ENVIRONMENT:
423
  case VIRTUAL_ENVIRONMENT:
424
    cpu_error(processor, cia, "floating-point assist interrupt");
425
 
426
  case OPERATING_ENVIRONMENT:
427
    TRACE(trace_interrupts, ("floating-point assist interrupt - cia=0x%lx\n", (unsigned long)cia));
428
    cia = perform_oea_interrupt(processor, cia, 0x00e00, 0, 0, 0, 0);
429
    cpu_restart(processor, cia);
430
 
431
  default:
432
    error("internal error - floating_point_assist_interrupt - bad switch");
433
 
434
  }
435
}
436
 
437
 
438
 
439
/* handle an externally generated event or an interrupt that has just
440
   been enabled through changes to the MSR. */
441
 
442
STATIC_INLINE_INTERRUPTS\
443
(void)
444
deliver_hardware_interrupt(void *data)
445
{
446
  cpu *processor = (cpu*)data;
447
  interrupts *ints = cpu_interrupts(processor);
448
  ints->delivery_scheduled = NULL;
449
  if ((cpu_registers(processor)->msr & (msr_floating_point_exception_mode_0
450
                                        | msr_floating_point_exception_mode_1))
451
      && cpu_registers(processor)->fpscr & fpscr_fex) {
452
    msreg srr1_set = srr1_floating_point_enabled | srr1_subsequent_instruction;
453
    unsigned_word cia = cpu_get_program_counter(processor);
454
    unsigned_word nia = perform_oea_interrupt(processor,
455
                                              cia, 0x00700, 0, 0, 0, srr1_set);
456
    cpu_set_program_counter(processor, nia);
457
  }
458
  else if (cpu_registers(processor)->msr & msr_external_interrupt_enable) {
459
    /* external interrupts have a high priority and remain pending */
460
    if (ints->pending_interrupts & external_interrupt_pending) {
461
      unsigned_word cia = cpu_get_program_counter(processor);
462
      unsigned_word nia = perform_oea_interrupt(processor,
463
                                                cia, 0x00500, 0, 0, 0, 0);
464
      TRACE(trace_interrupts, ("external interrupt - cia=0x%lx\n", (unsigned long)cia));
465
      cpu_set_program_counter(processor, nia);
466
    }
467
    /* decrementer interrupts have a lower priority and are once only */
468
    else if (ints->pending_interrupts & decrementer_interrupt_pending) {
469
      unsigned_word cia = cpu_get_program_counter(processor);
470
      unsigned_word nia = perform_oea_interrupt(processor,
471
                                                cia, 0x00900, 0, 0, 0, 0);
472
      TRACE(trace_interrupts, ("decrementer interrupt - cia 0x%lx, time %ld\n",
473
                               (unsigned long)cia,
474
                               (unsigned long)event_queue_time(psim_event_queue(cpu_system(processor)))
475
                               ));
476
      cpu_set_program_counter(processor, nia);
477
      ints->pending_interrupts &= ~decrementer_interrupt_pending;
478
    }
479
  }
480
}
481
 
482
STATIC_INLINE_INTERRUPTS\
483
(void)
484
schedule_hardware_interrupt_delivery(cpu *processor)
485
{
486
  interrupts *ints = cpu_interrupts(processor);
487
  if (ints->delivery_scheduled == NULL) {
488
    ints->delivery_scheduled =
489
      event_queue_schedule(psim_event_queue(cpu_system(processor)),
490
                           0, deliver_hardware_interrupt, processor);
491
  }
492
}
493
 
494
 
495
INLINE_INTERRUPTS\
496
(void)
497
check_masked_interrupts(cpu *processor)
498
{
499
  if (((cpu_registers(processor)->msr & (msr_floating_point_exception_mode_0
500
                                         | msr_floating_point_exception_mode_1))
501
       && cpu_registers(processor)->fpscr & fpscr_fex)
502
      || ((cpu_registers(processor)->msr & msr_external_interrupt_enable)
503
          && (cpu_interrupts(processor)->pending_interrupts)))
504
    schedule_hardware_interrupt_delivery(processor);
505
}
506
 
507
INLINE_INTERRUPTS\
508
(void)
509
decrementer_interrupt(cpu *processor)
510
{
511
  interrupts *ints = cpu_interrupts(processor);
512
  ints->pending_interrupts |= decrementer_interrupt_pending;
513
  if (cpu_registers(processor)->msr & msr_external_interrupt_enable) {
514
    schedule_hardware_interrupt_delivery(processor);
515
  }
516
}
517
 
518
INLINE_INTERRUPTS\
519
(void)
520
external_interrupt(cpu *processor,
521
                   int is_asserted)
522
{
523
  interrupts *ints = cpu_interrupts(processor);
524
  if (is_asserted) {
525
    if (!(ints->pending_interrupts & external_interrupt_pending)) {
526
      ints->pending_interrupts |= external_interrupt_pending;
527
      if (cpu_registers(processor)->msr & msr_external_interrupt_enable)
528
        schedule_hardware_interrupt_delivery(processor);
529
    }
530
    else {
531
      /* check that we haven't missed out on a chance to deliver an
532
         interrupt */
533
      ASSERT(!(cpu_registers(processor)->msr & msr_external_interrupt_enable));
534
    }
535
  }
536
  else {
537
    ints->pending_interrupts &= ~external_interrupt_pending;
538
  }
539
}
540
 
541
#endif /* _INTERRUPTS_C_ */

powered by: WebSVN 2.1.0

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