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

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_1_x/] [or1ksim/] [cpu/] [or1k/] [except.c] - Blame information for rev 464

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
#include "abstract.h"
25
#include "except.h"
26
#include "sprs.h"
27 344 markom
#include "sim-config.h"
28 33 lampret
 
29 139 chris
static void except_handle_backend(int,unsigned long,unsigned long);
30
 
31 33 lampret
extern int cont_run;
32
extern struct iqueue_entry iqueue[20];
33
extern unsigned long pc;
34 82 lampret
extern unsigned long pcnext;
35 123 markom
extern unsigned long pc_phy;
36 51 lampret
extern struct iqueue_entry iqueue[];
37 33 lampret
 
38 82 lampret
extern int delay_insn;
39 123 markom
int cycle_delay = 0;  /* Added by CZ 27/05/01 */
40 82 lampret
 
41 437 simons
struct _pending pending;
42 139 chris
 
43
void ClearPendingException()
44
{
45
  if(pending.valid && pending.type != EXCEPT_RESET)
46
    {
47
      pending.valid = 0;
48
      pending.type = 0;
49
      pending.address = 0;
50
      pending.saved = 0;
51
    }
52
}
53
 
54
/* The delayed_pc and delayed_pcnext are fields which hold
55
   the original value of the PC across breakpoint exceptions
56
   in the case of a development interface. Due to an implementation
57
   issues, DIR injected instructions can modify these values
58
   when in fact they should not. So we save and restore them
59
   later on. */
60
static unsigned long delayed_pc = 0;
61
static unsigned long delayed_pcnext = 0;
62
static int delayed_pc_valid = 0;
63
 
64 182 chris
void ClearPreparedPCState()
65
{
66
  delayed_pc_valid = 0;
67
}
68
 
69
/* This routine is never called if the cpu is not stalled...
70
   i.e. cpu_stalled == 0. _execute_update_pc is called
71
   directly in that case. This routine exists to sort out
72
   the difference between a single step break and a full
73
   software break. */
74 139 chris
void PrepareExceptionPC(unsigned long t_pc,unsigned long t_pcnext)
75
{
76
  /* If a real exception occurred which has stalled
77
     the CPU, we are expecting to halt before the end
78
     of the instruction. Otherwise, if it is a single
79
     step that has caused the halt, we are expected to
80
     complete the entire instruction and stop after
81
     it is finished. */
82
 
83
  if(pending.valid)
84
    {
85
      delayed_pc = t_pc;
86
      delayed_pcnext = t_pcnext;
87
      delayed_pc_valid = 1;
88
    }
89
  else
90
    _execute_update_pc(t_pc,t_pcnext);
91
}
92
 
93
void PrepareException()
94
{
95
  if(delayed_pc_valid)
96
    {
97
      pc = delayed_pc;
98
      pcnext = delayed_pcnext;
99
      pc_phy = simulate_ic_mmu_fetch(pc);
100 221 markom
      if (verify_memoryarea(pc_phy))
101
              except_handle(EXCEPT_BUSERR, pc);
102 139 chris
      delayed_pc_valid = delayed_pc = delayed_pcnext = 0;
103
    }
104
 
105
  if(pending.valid)
106
    except_handle_backend(pending.type,pending.address,pending.saved);
107
}
108
 
109 33 lampret
/* Handle OR1K exceptions. */
110
void except_handle(int except, unsigned long ea)
111
{
112 139 chris
  pending.valid = 1;
113
  pending.type = except;
114
  pending.address = ea;
115 464 simons
  if (delay_insn)
116
    pending.saved = pc - 4;
117
  else
118
    pending.saved = pc;
119 139 chris
 
120
  if(DebugCheckException(except))
121
    {
122
      pending.valid = 0;
123
      pending.type = 0;
124
      pending.address = 0;
125
      pending.saved = 0;
126
    }
127 152 chris
  else
128
    {
129
      printf("Exception 0x%x (%s): ", except, EXCEPT_NAME(except));
130
      printf("Iqueue[0].insn_addr: 0x%x  Eff ADDR: 0x%x\n",  iqueue[0].insn_addr, ea);
131
      printf("  pc: 0x%x  pcnext: 0x%x\n",  pc, pcnext);
132
    }
133 139 chris
 
134
  cycle_delay = 0;  /* An exception stalls the CPU 0 clock cycles */
135
}
136
 
137
static void except_handle_backend(int except, unsigned long ea, unsigned long pc_saved)
138
{
139 344 markom
  /* Ignore masked exceptions */
140
  if (! IS_NME(except) && (!(mfspr(SPR_SR) & SPR_SR_EXR))) {
141
    if (config.sim.verbose)
142
                  printf("INFO: Exception occured while exception detection was disabled.\n");
143
                return;
144
        }
145 139 chris
 
146 33 lampret
#if ONLY_VIRTUAL_MACHINE
147 344 markom
        fprintf(stderr, "WARNING: No exception processing while ONLY_VIRTUAL_MACHINE is defined.\n");
148 51 lampret
        cont_run = 0;
149 33 lampret
#else
150 51 lampret
 
151 82 lampret
        if (delay_insn) {
152 344 markom
                printf("INFO: Exception during execution of delay slot insn.\n");
153 82 lampret
                pc -= 4;
154
        }
155
#if 0
156
        if ((pcnext != (pc + 4)) && (except != EXCEPT_ITLBMISS)) {      /* Always execute delay slot insn */
157
                printf("XXXXXXXXXXXXXX\n");
158 77 lampret
                fetch();                                                /* before starting with exception */
159
                decode(&iqueue[0]);                                      /* (itlbmiss is special case) */
160 51 lampret
                execute();
161
        }
162 82 lampret
#endif
163 123 markom
 
164 64 lampret
        pc_saved = pc & ~0x3;
165 458 simons
  if (except == EXCEPT_ILLEGAL)
166
        mtspr(SPR_EPCR_BASE, pending.saved);
167
  else if (except == EXCEPT_ALIGN)
168
    mtspr(SPR_EPCR_BASE, pending.saved);
169
  else if (except == EXCEPT_DTLBMISS)
170
    mtspr(SPR_EPCR_BASE, pending.saved);
171
  else if (except == EXCEPT_DPF)
172
    mtspr(SPR_EPCR_BASE, pending.saved);
173
  else if (except == EXCEPT_BUSERR)
174
    mtspr(SPR_EPCR_BASE, pending.saved);
175
  else if (except == EXCEPT_TRAP)
176
    mtspr(SPR_EPCR_BASE, pending.saved);
177
  else if (except == EXCEPT_RANGE)
178
    mtspr(SPR_EPCR_BASE, pending.saved);
179
  else
180
        mtspr(SPR_EPCR_BASE, pc_saved);
181
 
182 33 lampret
        mtspr(SPR_EEAR_BASE, ea);
183 64 lampret
        mtspr(SPR_ESR_BASE, mfspr(SPR_SR));
184
 
185
        /* Address translation is always disabled when starting exception. */
186
        mtspr(SPR_SR, mfspr(SPR_SR) & ~(SPR_SR_DME));
187
        mtspr(SPR_SR, mfspr(SPR_SR) & ~(SPR_SR_IME));
188
 
189 458 simons
        mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_OVE);     /* Disable overflow flag exception. */
190
 
191 33 lampret
        mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_SUPV);     /* SUPV mode */
192 450 simons
        mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_EIR);     /* Disable interrupts. */
193 167 markom
 
194 458 simons
  pending.valid = 0;
195
  pending.type = 0;
196
  pending.address = 0;
197
  pending.saved = 0;
198
 
199 33 lampret
        pc = (unsigned long)except;
200 123 markom
 
201 139 chris
        /* This has been removed. All exceptions (not just SYSCALL) suffer
202
           from the same problem. The solution is to continue just like
203
           the pipeline would, and issue the exception on the next
204
           clock cycle. We assume now that this function is being called
205
           ->BEFORE<- the instruction fetch and after the previous update
206
           which always yields the correct behavior. This has the added
207
           advantage that a debugger can prevent an exception from
208
           taking place by resetting the pc. */
209
#if 0
210 123 markom
        /* MM: We do pc update after the execute (in the simulator), so we
211
           decrease it by 4 so that next instruction points to first exception
212 167 markom
           instruction.  Do NOT comment this out. */
213 123 markom
        if (except == EXCEPT_SYSCALL)
214
          pc -= 4;
215 139 chris
#endif
216 123 markom
        pcnext = pc+4;
217
 
218
        /* Added by CZ 27/05/01 */
219 139 chris
        pc_phy = pc;      /* An exception always turns off the MMU, so
220
                             pc is always pc_phy */
221
 
222 33 lampret
#endif
223
}

powered by: WebSVN 2.1.0

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