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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [cpu/] [or1k/] [sprs.c] - Blame information for rev 98

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

Line No. Rev Author Line
1 19 jeremybenn
/* sprs.c -- Simulation of OR1K special-purpose registers
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
#include "port.h"
30
 
31
/* System includes */
32
#include <stdlib.h>
33
#include <stdio.h>
34
#include <errno.h>
35
 
36
/* Package includes */
37
#include "sprs.h"
38
#include "sim-config.h"
39
#include "debug.h"
40
#include "execute.h"
41
#include "spr-defs.h"
42
#include "tick.h"
43
#include "dcache-model.h"
44
#include "icache-model.h"
45
#include "dmmu.h"
46
#include "immu.h"
47
#include "toplevel-support.h"
48
#include "pic.h"
49
 
50
 
51
DECLARE_DEBUG_CHANNEL(immu);
52
 
53
/* Set a specific SPR with a value. */
54
void mtspr(uint16_t regno, const uorreg_t value)
55
{
56
  uorreg_t prev_val;
57
 
58
  prev_val = cpu_state.sprs[regno];
59
  cpu_state.sprs[regno] = value;
60
 
61
  /* MM: Register hooks.  */
62
  switch (regno) {
63
  case SPR_TTCR:
64
    spr_write_ttcr (value);
65
    break;
66
  case SPR_TTMR:
67
    spr_write_ttmr (prev_val);
68
    break;
69
  /* Data cache simulateing stuff */
70
  case SPR_DCBPR:
71
    /* FIXME: This is not correct.  The arch. manual states: "Memory accesses
72
     * are not recorded (Unlike load or store instructions) and cannot invoke
73
     * any exception".  If the physical address is invalid a bus error will be
74
     * generated.  Also if the effective address is not resident in the mmu
75
     * the read will happen from address 0, which is naturally not correct. */
76
    dc_simulate_read(peek_into_dtlb(value, 0, 1), value, 4);
77
    cpu_state.sprs[SPR_DCBPR] = 0;
78
    break;
79
  case SPR_DCBFR:
80
    dc_inv(value);
81
    cpu_state.sprs[SPR_DCBFR] = -1;
82
    break;
83
  case SPR_DCBIR:
84
    dc_inv(value);
85
    cpu_state.sprs[SPR_DCBIR] = 0;
86
    break;
87
  case SPR_DCBWR:
88
    cpu_state.sprs[SPR_DCBWR] = 0;
89
    break;
90
  case SPR_DCBLR:
91
    cpu_state.sprs[SPR_DCBLR] = 0;
92
    break;
93
  /* Instruction cache simulateing stuff */
94
  case SPR_ICBPR:
95
    /* FIXME: The arch manual does not say what happens when an invalid memory
96
     * location is specified.  I guess the same as for the DCBPR register */
97
    ic_simulate_fetch(peek_into_itlb(value), value);
98
    cpu_state.sprs[SPR_ICBPR] = 0;
99
    break;
100
  case SPR_ICBIR:
101
    ic_inv(value);
102
    cpu_state.sprs[SPR_ICBIR] = 0;
103
    break;
104
  case SPR_ICBLR:
105
    cpu_state.sprs[SPR_ICBLR] = 0;
106
    break;
107
  case SPR_SR:
108
    cpu_state.sprs[regno] |= SPR_SR_FO;
109
    if((value & SPR_SR_IEE) && !(prev_val & SPR_SR_IEE))
110
      pic_ints_en();
111
#if DYNAMIC_EXECUTION
112
    if((value & SPR_SR_IME) && !(prev_val & SPR_SR_IME)) {
113
      TRACE_(immu)("IMMU just became enabled (%lli).\n", runtime.sim.cycles);
114
      recheck_immu(IMMU_GOT_ENABLED);
115
    } else if(!(value & SPR_SR_IME) && (prev_val & SPR_SR_IME)) {
116
      TRACE_(immu)("Remove counting of mmu hit delay with cycles (%lli)\n",
117
                   runtime.sim.cycles);
118
      recheck_immu(IMMU_GOT_DISABLED);
119
    }
120
#endif
121
    break;
122
  case SPR_NPC:
123
    {
124
      /* The debugger has redirected us to a new address */
125
      /* This is usually done to reissue an instruction
126
         which just caused a breakpoint exception. */
127
 
128
      /* JPB patch. When GDB stepi, this may be used to set the PC to the
129
         value it is already at. If this is the case, then we do nothing (in
130
         particular we do not trash a delayed branch) */
131
 
132
      if (value != cpu_state.pc)
133
        {
134
          cpu_state.pc = value;
135
 
136
          if(!value && config.sim.verbose)
137
            PRINTF("WARNING: PC just set to 0!\n");
138
 
139
          /* Clear any pending delay slot jumps also */
140
          cpu_state.delay_insn = 0;
141
          pcnext = value + 4;
142
 
143
          /* Further JPB patch. If the processor is stalled, then subsequent
144
             reads of the NPC should return 0 until the processor is
145
             unstalled. If the processor is stalled, note that the NPC has
146
             been updated while the processor was stalled. */
147
 
148
          if (runtime.cpu.stalled)
149
            {
150
              cpu_state.npc_not_valid = 1;
151
            }
152
        }
153
    }
154
    break;
155
  case SPR_PICSR:
156
    if(!config.pic.edge_trigger)
157
      cpu_state.sprs[SPR_PICSR] = prev_val;
158
    break;
159
  case SPR_PICMR:
160
    if(cpu_state.sprs[SPR_SR] & SPR_SR_IEE)
161
      pic_ints_en();
162
    break;
163
  case SPR_PMR:
164
    /* PMR[SDF] and PMR[DCGE] are ignored completely. */
165
    if (config.pm.enabled && (value & SPR_PMR_SUME)) {
166
      PRINTF ("SUSPEND: PMR[SUME] bit was set.\n");
167
      sim_done();
168
    }
169
    break;
170
  default:
171
    /* Mask reserved bits in DTLBMR and DTLBMR registers */
172
    if ( (regno >= SPR_DTLBMR_BASE(0)) && (regno < SPR_DTLBTR_LAST(3))) {
173
      if((regno & 0xff) < 0x80)
174
        cpu_state.sprs[regno] = DADDR_PAGE(value) |
175
                              (value & (SPR_DTLBMR_V | SPR_DTLBMR_PL1 | SPR_DTLBMR_CID | SPR_DTLBMR_LRU));
176
      else
177
        cpu_state.sprs[regno] = DADDR_PAGE(value) |
178
                              (value & (SPR_DTLBTR_CC | SPR_DTLBTR_CI | SPR_DTLBTR_WBC | SPR_DTLBTR_WOM |
179
                              SPR_DTLBTR_A | SPR_DTLBTR_D | SPR_DTLBTR_URE | SPR_DTLBTR_UWE | SPR_DTLBTR_SRE |
180
                              SPR_DTLBTR_SWE));
181
    }
182
 
183
    /* Mask reseved bits in ITLBMR and ITLBMR registers */
184
    if ( (regno >= SPR_ITLBMR_BASE(0)) && (regno < SPR_ITLBTR_LAST(3))) {
185
      if((regno & 0xff) < 0x80)
186
        cpu_state.sprs[regno] = IADDR_PAGE(value) |
187
                              (value & (SPR_ITLBMR_V | SPR_ITLBMR_PL1 | SPR_ITLBMR_CID | SPR_ITLBMR_LRU));
188
      else
189
        cpu_state.sprs[regno] = IADDR_PAGE(value) |
190
                              (value & (SPR_ITLBTR_CC | SPR_ITLBTR_CI | SPR_ITLBTR_WBC | SPR_ITLBTR_WOM |
191
                              SPR_ITLBTR_A | SPR_ITLBTR_D | SPR_ITLBTR_SXE | SPR_ITLBTR_UXE));
192
 
193
#if DYNAMIC_EXECUTION
194
      if(cpu_state.sprs[SPR_SR] & SPR_SR_IME) {
195
        /* The immu got reconfigured.  Recheck if the current page in execution
196
         * is resident in the immu ways.  This check would be done during the
197
         * instruction fetch but since the dynamic execution model does not do
198
         * instruction fetchs, do it now. */
199
        recheck_immu(0);
200
      }
201
#endif
202
    }
203
 
204
    /* Links to GPRS */
205
    if(regno >= 0x0400 && regno < 0x0420) {
206
      cpu_state.reg[regno - 0x0400] = value;
207
    }
208
    break;
209
  }
210
}
211
 
212
/* Get a specific SPR. */
213
uorreg_t mfspr(const uint16_t regno)
214
{
215
  uorreg_t ret;
216
 
217
  ret = cpu_state.sprs[regno];
218
 
219
  switch (regno) {
220
  case SPR_NPC:
221
 
222
    /* The NPC is the program counter UNLESS the NPC has been changed and we
223
       are stalled, which will have flushed the pipeline, so the value is
224
       zero. Currently this is optional behavior, since it breaks GDB.
225
    */
226
 
227
    if (config.sim.strict_npc && cpu_state.npc_not_valid)
228
      {
229
        ret = 0;
230
      }
231
    else
232
      {
233
        ret = cpu_state.pc;
234
      }
235
    break;
236
 
237
  case SPR_TTCR:
238
    ret = spr_read_ttcr();
239
    break;
240
  default:
241
    /* Links to GPRS */
242
    if(regno >= 0x0400 && regno < 0x0420)
243
      ret = cpu_state.reg[regno - 0x0400];
244
  }
245
 
246
  return ret;
247
}
248
 
249
/* Show status of important SPRs. */
250
void sprs_status(void)
251
{
252
  PRINTF("VR   : 0x%"PRIxREG"  UPR  : 0x%"PRIxREG"\n", cpu_state.sprs[SPR_VR],
253
         cpu_state.sprs[SPR_UPR]);
254
  PRINTF("SR   : 0x%"PRIxREG"\n", cpu_state.sprs[SPR_SR]);
255
  PRINTF("MACLO: 0x%"PRIxREG"  MACHI: 0x%"PRIxREG"\n",
256
         cpu_state.sprs[SPR_MACLO], cpu_state.sprs[SPR_MACHI]);
257
  PRINTF("EPCR0: 0x%"PRIxADDR"  EPCR1: 0x%"PRIxADDR"\n",
258
         cpu_state.sprs[SPR_EPCR_BASE], cpu_state.sprs[SPR_EPCR_BASE+1]);
259
  PRINTF("EEAR0: 0x%"PRIxADDR"  EEAR1: 0x%"PRIxADDR"\n",
260
         cpu_state.sprs[SPR_EEAR_BASE], cpu_state.sprs[SPR_EEAR_BASE+1]);
261
  PRINTF("ESR0 : 0x%"PRIxREG"  ESR1 : 0x%"PRIxREG"\n",
262
         cpu_state.sprs[SPR_ESR_BASE], cpu_state.sprs[SPR_ESR_BASE+1]);
263
  PRINTF("TTMR : 0x%"PRIxREG"  TTCR : 0x%"PRIxREG"\n",
264
         cpu_state.sprs[SPR_TTMR], cpu_state.sprs[SPR_TTCR]);
265
  PRINTF("PICMR: 0x%"PRIxREG"  PICSR: 0x%"PRIxREG"\n",
266
         cpu_state.sprs[SPR_PICMR], cpu_state.sprs[SPR_PICSR]);
267
  PRINTF("PPC:   0x%"PRIxADDR"  NPC   : 0x%"PRIxADDR"\n",
268
         cpu_state.sprs[SPR_PPC], cpu_state.sprs[SPR_NPC]);
269
}

powered by: WebSVN 2.1.0

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