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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [cpu/] [or1k/] [except.c] - Blame information for rev 1473

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

Line No. Rev Author Line
1 33 lampret
/* except.c -- Simulation of OR1K exceptions
2
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <string.h>
23
 
24 1350 nogj
#include "config.h"
25
 
26
#ifdef HAVE_INTTYPES_H
27
#include <inttypes.h>
28
#endif
29
 
30
#include "port.h"
31
#include "arch.h"
32 33 lampret
#include "abstract.h"
33
#include "except.h"
34 344 markom
#include "sim-config.h"
35 1308 phoenix
#include "debug_unit.h"
36 1432 nogj
#include "opcode/or32.h"
37
#include "spr_defs.h"
38 1350 nogj
#include "execute.h"
39 1432 nogj
#include "sprs.h"
40 33 lampret
 
41 1452 nogj
#if DYNAMIC_EXECUTION
42
#include "sched.h"
43
#include "rec_i386.h"
44
#include "op_support.h"
45
#endif
46
 
47 1386 nogj
extern oraddr_t pcprev;
48 82 lampret
 
49 1386 nogj
int except_pending = 0;
50 139 chris
 
51 1386 nogj
static const char *except_names[] = {
52
 NULL,
53
 "Reset",
54
 "Bus Error",
55
 "Data Page Fault",
56
 "Insn Page Fault",
57
 "Tick timer",
58
 "Alignment",
59
 "Illegal instruction",
60
 "Interrupt",
61
 "Data TLB Miss",
62
 "Insn TLB Miss",
63
 "Range",
64
 "System Call",
65
 "Trap" };
66
 
67 1452 nogj
const char *except_name(oraddr_t except)
68 139 chris
{
69 1386 nogj
  return except_names[except >> 8];
70 139 chris
}
71
 
72 1452 nogj
#if DYNAMIC_EXECUTION
73
/* FIXME: Remove the need for this */
74
/* This is needed because immu_translate can be called from do_rfe and do_jump
75
 * in which case the scheduler does not need to get run. immu_translate can also
76
 * be called from mtspr in which case the exceptions that it generates happen
77
 * during an instruction and the scheduler needs to get run. */
78
int immu_ex_from_insn = 0;
79
#endif
80
 
81 479 markom
/* Asserts OR1K exception. */
82 1473 nogj
/* WARNING: Don't excpect except_handle to return.  Sometimes it _may_ return at
83
 * other times it may not. */
84 1350 nogj
void except_handle(oraddr_t except, oraddr_t ea)
85 33 lampret
{
86 1452 nogj
  oraddr_t except_vector;
87
 
88 1386 nogj
  if(debug_ignore_exception (except))
89
    return;
90 139 chris
 
91 1452 nogj
#if !(DYNAMIC_EXECUTION)
92
  /* In the dynamic recompiler, this function never returns, so this is not
93
   * needed.  Ofcourse we could set it anyway, but then all code that checks
94
   * this variable would break, since it is never reset */
95 1386 nogj
  except_pending = 1;
96 1452 nogj
#endif
97 51 lampret
 
98 1386 nogj
  if (config.sim.verbose)
99
    PRINTF("Exception 0x%"PRIxADDR" (%s) at 0x%"PRIxADDR", EA: 0x%"PRIxADDR
100
           ", ppc: 0x%"PRIxADDR", npc: 0x%"PRIxADDR", dpc: 0x%"PRIxADDR
101
           ", cycles %lld, #%lld\n",
102 1432 nogj
           except, except_name(except), pcprev, ea, cpu_state.pc, pcnext,
103
           cpu_state.pc_delay, runtime.sim.cycles, runtime.cpu.instructions);
104 1386 nogj
 
105 1452 nogj
  except_vector = except + (testsprbits (SPR_SR, SPR_SR_EPH) ? 0xf0000000 : 0x00000000);
106 1386 nogj
 
107 1452 nogj
#if !(DYNAMIC_EXECUTION)
108
  pcnext = except_vector;
109
#endif
110
 
111 1442 nogj
  cpu_state.sprs[SPR_EEAR_BASE] =  ea;
112
  cpu_state.sprs[SPR_ESR_BASE] = cpu_state.sprs[SPR_SR];
113
 
114
  cpu_state.sprs[SPR_SR] &= ~SPR_SR_OVE;   /* Disable overflow flag exception. */
115
 
116
  cpu_state.sprs[SPR_SR] |= SPR_SR_SM;    /* SUPV mode */
117
  cpu_state.sprs[SPR_SR] &= ~(SPR_SR_IEE | SPR_SR_TEE);   /* Disable interrupts. */
118
 
119
  /* Address translation is always disabled when starting exception. */
120
  cpu_state.sprs[SPR_SR] &= ~SPR_SR_DME;
121
 
122 1452 nogj
#if DYNAMIC_EXECUTION
123
  /* If we were called from do_scheduler and there were more jobs scheduled to
124
   * run after this, they won't run unless the following call is made since this
125
   * function never returns.  (If we weren't called from do_scheduler, then the
126
   * job at the head of the queue will still have some time remaining) */
127
  if(scheduler.job_queue->time <= 0)
128
    do_scheduler();
129
#endif
130
 
131 1386 nogj
  switch(except) {
132
  /* EPCR is irrelevent */
133
  case EXCEPT_RESET:
134
    break;
135
  /* EPCR is loaded with address of instruction that caused the exception */
136 1452 nogj
  case EXCEPT_ITLBMISS:
137
  case EXCEPT_IPF:
138
#if DYNAMIC_EXECUTION
139
    /* In immu_translate except_handle is called with except_handle(..., virtaddr) */
140
    /* Add the immu miss delay to the cycle counter */
141
    if(!immu_ex_from_insn)
142
      mtspr(SPR_EPCR_BASE, get_pc() - (cpu_state.delay_insn ? 4 : 0));
143
    else
144
      /* This exception came from an l.mtspr instruction in which case the pc
145
       * points to the l.mtspr instruction when in acutal fact, it is the next
146
       * instruction that would have faulted/missed.  ea is used instead of
147
       * cpu_state.pc + 4 because in the event that the l.mtspr instruction is
148
       * in the delay slot of a page local jump the fault must happen on the
149
       * instruction that was jumped to.  This is handled in recheck_immu. */
150
      mtspr(SPR_EPCR_BASE, ea);
151
      run_sched_out_of_line(immu_ex_from_insn);
152
      immu_ex_from_insn = 0;
153
      break;
154
#endif
155 1386 nogj
  /* All these exceptions happen during a simulated instruction */
156
  case EXCEPT_BUSERR:
157
  case EXCEPT_DPF:
158
  case EXCEPT_ALIGN:
159
  case EXCEPT_ILLEGAL:
160
  case EXCEPT_DTLBMISS:
161
  case EXCEPT_RANGE:
162
  case EXCEPT_TRAP:
163 1452 nogj
#if DYNAMIC_EXECUTION
164
    /* Since these exceptions happen during a simulated instruction and this
165
     * function jumps out to the exception vector the scheduler would never have
166
     * a chance to run, therefore run it now */
167
    run_sched_out_of_line(1);
168
#endif
169 1432 nogj
    mtspr(SPR_EPCR_BASE, cpu_state.pc - (cpu_state.delay_insn ? 4 : 0));
170 1386 nogj
    break;
171
  /* EPCR is loaded with address of next not-yet-executed instruction */
172
  case EXCEPT_SYSCALL:
173 1432 nogj
    mtspr(SPR_EPCR_BASE, (cpu_state.pc + 4) - (cpu_state.delay_insn ? 4 : 0));
174 1386 nogj
    break;
175
  /* These exceptions happen AFTER (or before) an instruction has been
176
   * simulated, therefore the pc already points to the *next* instruction */
177
  case EXCEPT_TICK:
178
  case EXCEPT_INT:
179 1432 nogj
    mtspr(SPR_EPCR_BASE, cpu_state.pc - (cpu_state.delay_insn ? 4 : 0));
180 1452 nogj
#if !(DYNAMIC_EXECUTION)
181 1386 nogj
    /* If we don't update the pc now, then it will only happen *after* the next
182
     * instruction (There would be serious problems if the next instruction just
183
     * happens to be a branch), when it should happen NOW. */
184 1432 nogj
    cpu_state.pc = pcnext;
185 1386 nogj
    pcnext += 4;
186 1452 nogj
#else
187
    /* except_handle() mucks around with the temporaries, which are in the state
188
     * of the last instruction executed and not the next one, to which the pc
189
     * now points to */
190
    cpu_state.pc -= 4;
191
#endif
192 1386 nogj
    break;
193 479 markom
  }
194 693 markom
 
195 1452 nogj
  /* Address trnaslation is here because run_sched_out_of_line calls
196
   * eval_insn_direct which checks out the immu for the address translation but
197
   * if it would be disabled above then there would be not much point... */
198
  cpu_state.sprs[SPR_SR] &= ~SPR_SR_IME;
199
 
200
  /* Complex/simple execution strictly don't need this because of the
201
   * next_delay_insn thingy but in the dynamic execution modell that doesn't
202
   * exist and thus cpu_state.insn_delay would stick in the exception handler
203
   * causeing grief if the first instruction of the exception handler is also in
204
   * the delay slot of the previous instruction */
205 1432 nogj
  cpu_state.delay_insn = 0;
206 1452 nogj
 
207
#if DYNAMIC_EXECUTION
208
  /* Save the registers that are in the temporaries */
209
  if(!cpu_state.ts_current)
210
    upd_reg_from_t(cpu_state.pc);
211
 
212
  cpu_state.pc = except_vector;
213
  cpu_state.ts_current = 0;
214
  jump_dyn_code(except_vector);
215
#endif
216 33 lampret
}

powered by: WebSVN 2.1.0

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