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

Subversion Repositories eco32

[/] [eco32/] [trunk/] [monitor/] [monitor/] [common/] [cpu.c] - Blame information for rev 190

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

Line No. Rev Author Line
1 59 hellwig
/*
2
 * cpu.c -- execute instructions
3
 */
4
 
5
 
6
#include "common.h"
7
#include "stdarg.h"
8
#include "romlib.h"
9
#include "instr.h"
10
#include "cpu.h"
11
#include "mmu.h"
12
#include "start.h"
13
 
14
 
15
#define RR(n)           r[n]
16
#define WR(n,d)         ((void) ((n) != 0 ? r[n] = (d) : (d)))
17
 
18
#define BREAK           (OP_TRAP << 26)
19
 
20
 
21
/**************************************************************/
22
 
23
 
24
static Word pc;                 /* program counter */
25
static Word psw;                /* processor status word */
26
static Word r[32];              /* general purpose registers */
27
 
28
static Bool breakSet;           /* breakpoint set if true */
29
static Word breakAddr;          /* if breakSet, this is where */
30
 
31
 
32
/**************************************************************/
33
 
34
 
35
Word cpuGetPC(void) {
36
  return pc;
37
}
38
 
39
 
40
void cpuSetPC(Word addr) {
41
  pc = addr;
42
}
43
 
44
 
45
Word cpuGetReg(int regnum) {
46
  return RR(regnum & 0x1F);
47
}
48
 
49
 
50
void cpuSetReg(int regnum, Word value) {
51
  WR(regnum & 0x1F, value);
52
}
53
 
54
 
55
Word cpuGetPSW(void) {
56
  return psw;
57
}
58
 
59
 
60
void cpuSetPSW(Word value) {
61
  psw = value;
62
}
63
 
64
 
65
Bool cpuTestBreak(void) {
66
  return breakSet;
67
}
68
 
69
 
70
Word cpuGetBreak(void) {
71
  return breakAddr;
72
}
73
 
74
 
75
void cpuSetBreak(Word addr) {
76
  breakAddr = addr;
77
  breakSet = true;
78
}
79
 
80
 
81
void cpuResetBreak(void) {
82
  breakSet = false;
83
}
84
 
85
 
86
/**************************************************************/
87
 
88
 
89
static char *cause[32] = {
90
  /*  0 */  "serial line 0 xmt interrupt",
91
  /*  1 */  "serial line 0 rcv interrupt",
92
  /*  2 */  "serial line 1 xmt interrupt",
93
  /*  3 */  "serial line 1 rcv interrupt",
94
  /*  4 */  "keyboard interrupt",
95
  /*  5 */  "unknown interrupt",
96
  /*  6 */  "unknown interrupt",
97
  /*  7 */  "unknown interrupt",
98
  /*  8 */  "disk interrupt",
99
  /*  9 */  "unknown interrupt",
100
  /* 10 */  "unknown interrupt",
101
  /* 11 */  "unknown interrupt",
102
  /* 12 */  "unknown interrupt",
103
  /* 13 */  "unknown interrupt",
104
  /* 14 */  "timer 0 interrupt",
105
  /* 15 */  "timer 1 interrupt",
106
  /* 16 */  "bus timeout exception",
107
  /* 17 */  "illegal instruction exception",
108
  /* 18 */  "privileged instruction exception",
109
  /* 19 */  "divide instruction exception",
110
  /* 20 */  "trap instruction exception",
111
  /* 21 */  "TLB miss exception",
112
  /* 22 */  "TLB write exception",
113
  /* 23 */  "TLB invalid exception",
114
  /* 24 */  "illegal address exception",
115
  /* 25 */  "privileged address exception",
116
  /* 26 */  "unknown exception",
117
  /* 27 */  "unknown exception",
118
  /* 28 */  "unknown exception",
119
  /* 29 */  "unknown exception",
120
  /* 30 */  "unknown exception",
121
  /* 31 */  "unknown exception"
122
};
123
 
124
 
125
char *exceptionToString(int exception) {
126
  if (exception < 0 ||
127
      exception >= sizeof(cause)/sizeof(cause[0])) {
128
    return "<exception number out of bounds>";
129
  }
130
  return cause[exception];
131
}
132
 
133
 
134
/**************************************************************/
135
 
136
 
137
static Byte stepType[64] = {
138
  /*          0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  */
139
  /* 0x00 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
140
  /* 0x10 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
141
  /* 0x20 */  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 3, 4, 1, 0,
142
  /* 0x30 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
143
};
144
 
145
 
146
static Bool evalCond(int cc, Word a, Word b) {
147
  switch (cc) {
148
    case 0:
149
      /* equal */
150
      if (a == b) {
151
        return true;
152
      }
153
      break;
154
    case 1:
155
      /* not equal */
156
      if (a != b) {
157
        return true;
158
      }
159
      break;
160
    case 2:
161
      /* less or equal (signed) */
162
      if ((signed int) a <= (signed int) b) {
163
        return true;
164
      }
165
      break;
166
    case 3:
167
      /* less or equal (unsigned) */
168
      if (a <= b) {
169
        return true;
170
      }
171
      break;
172
    case 4:
173
      /* less than (signed) */
174
      if ((signed int) a < (signed int) b) {
175
        return true;
176
      }
177
      break;
178
    case 5:
179
      /* less than (unsigned) */
180
      if (a < b) {
181
        return true;
182
      }
183
      break;
184
    case 6:
185
      /* greater or equal (signed) */
186
      if ((signed int) a >= (signed int) b) {
187
        return true;
188
      }
189
      break;
190
    case 7:
191
      /* greater or equal (unsigned) */
192
      if (a >= b) {
193
        return true;
194
      }
195
      break;
196
    case 8:
197
      /* greater than (signed) */
198
      if ((signed int) a > (signed int) b) {
199
        return true;
200
      }
201
      break;
202
    case 9:
203
      /* greater than (unsigned) */
204
      if (a > b) {
205
        return true;
206
      }
207
      break;
208
    default:
209
      /* this should never happen */
210
      printf("cannot compute condition code %d\n", cc);
211
      break;
212
  }
213
  return false;
214
}
215
 
216
 
217
void cpuStep(void) {
218
  Word instr;
219
  int opcode;
220
  int reg1, reg2;
221
  Half immed;
222
  Word offset;
223
  Word nextAddr;
224
  Word nextInstr;
225
  int i;
226
  MonitorState stepState;
227
  MonitorState *origReturn;
228
 
229
  instr = mmuReadWord(pc);
230
  opcode = (instr >> 26) & 0x3F;
231
  reg1 = (instr >> 21) & 0x1F;
232
  reg2 = (instr >> 16) & 0x1F;
233
  immed = instr & 0x0000FFFF;
234
  offset = instr & 0x03FFFFFF;
235
  switch (stepType[opcode]) {
236
    case 1:
237
      /* next instruction follows current one immediately */
238
      nextAddr = pc + 4;
239
      break;
240
    case 2:
241
      /* next instruction conditionally reached by PC relative branch */
242
      nextAddr = pc + 4;
243
      if (evalCond(opcode - OP_BEQ, RR(reg1), RR(reg2))) {
244
        nextAddr += SEXT16(immed) << 2;
245
      }
246
      break;
247
    case 3:
248
      /* next instruction reached by PC relative jump */
249
      nextAddr = pc + 4 + (SEXT26(offset) << 2);
250
      break;
251
    case 4:
252
      /* next instruction reached by jump to register contents */
253
      nextAddr = RR(reg1) & 0xFFFFFFFC;
254
      break;
255
    default:
256
      printf("cannot single-step instruction with opcode 0x%02X\n",
257
             opcode);
258
      return;
259
  }
260
  nextInstr = mmuReadWord(nextAddr);
261
  mmuWriteWord(nextAddr, BREAK);
262
  for (i = 0; i < 32; i++) {
263
    userContext.reg[i] = RR(i);
264
  }
265
  userContext.reg[30] = pc;
266
  userContext.psw = psw;
267
  userContext.tlbIndex = mmuGetIndex();
268
  userContext.tlbHi = mmuGetEntryHi();
269
  userContext.tlbLo = mmuGetEntryLo();
270 84 hellwig
  userContext.badAddr = mmuGetBadAddr();
271 180 hellwig
  userContext.badAccs = mmuGetBadAccs();
272 59 hellwig
  if (saveState(&stepState)) {
273
    origReturn = monitorReturn;
274
    monitorReturn = &stepState;
275
    resume();
276
  }
277
  monitorReturn = origReturn;
278
  for (i = 0; i < 32; i++) {
279
    WR(i, userContext.reg[i]);
280
  }
281
  pc = userContext.reg[30];
282
  psw = userContext.psw;
283
  mmuSetIndex(userContext.tlbIndex);
284
  mmuSetEntryHi(userContext.tlbHi);
285
  mmuSetEntryLo(userContext.tlbLo);
286 84 hellwig
  mmuSetBadAddr(userContext.badAddr);
287 180 hellwig
  mmuSetBadAccs(userContext.badAccs);
288 59 hellwig
  mmuWriteWord(nextAddr, nextInstr);
289
  if (nextAddr == pc) {
290
    return;
291
  }
292
  if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
293
      (mmuGetEntryHi() & 0x80000000) == 0) {
294
    /* TLB user miss */
295 182 hellwig
    printf("unexpected TLB user miss exception occurred\n");
296
    return;
297 59 hellwig
  } else {
298
    /* any other exception */
299 182 hellwig
    printf("unexpected %s occurred\n",
300
           exceptionToString((psw & PSW_PRIO_MASK) >> 16));
301
    return;
302 59 hellwig
  }
303
}
304
 
305
 
306
void cpuRun(void) {
307
  Word instr;
308
  int i;
309
  MonitorState runState;
310
  MonitorState *origReturn;
311
 
312
  if (breakSet && breakAddr == pc) {
313
    /* single-step one instruction */
314
    cpuStep();
315
  }
316
  while (1) {
317
    if (breakSet) {
318
      instr = mmuReadWord(breakAddr);
319
      mmuWriteWord(breakAddr, BREAK);
320
    }
321
    for (i = 0; i < 32; i++) {
322
      userContext.reg[i] = RR(i);
323
    }
324
    userContext.reg[30] = pc;
325
    userContext.psw = psw;
326
    userContext.tlbIndex = mmuGetIndex();
327
    userContext.tlbHi = mmuGetEntryHi();
328
    userContext.tlbLo = mmuGetEntryLo();
329 84 hellwig
    userContext.badAddr = mmuGetBadAddr();
330 180 hellwig
    userContext.badAccs = mmuGetBadAccs();
331 59 hellwig
    if (saveState(&runState)) {
332
      origReturn = monitorReturn;
333
      monitorReturn = &runState;
334
      resume();
335
    }
336
    monitorReturn = origReturn;
337
    for (i = 0; i < 32; i++) {
338
      WR(i, userContext.reg[i]);
339
    }
340
    pc = userContext.reg[30];
341
    psw = userContext.psw;
342
    mmuSetIndex(userContext.tlbIndex);
343
    mmuSetEntryHi(userContext.tlbHi);
344
    mmuSetEntryLo(userContext.tlbLo);
345 84 hellwig
    mmuSetBadAddr(userContext.badAddr);
346 180 hellwig
    mmuSetBadAccs(userContext.badAccs);
347 59 hellwig
    if (breakSet) {
348
      mmuWriteWord(breakAddr, instr);
349
    }
350
    if (breakSet && breakAddr == pc) {
351
      return;
352
    }
353
    if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
354
        (mmuGetEntryHi() & 0x80000000) == 0) {
355
      /* TLB user miss */
356 182 hellwig
      printf("unexpected TLB user miss exception occurred\n");
357
      return;
358 59 hellwig
    } else {
359
      /* any other exception */
360 182 hellwig
      printf("unexpected %s occurred\n",
361
             exceptionToString((psw & PSW_PRIO_MASK) >> 16));
362
      return;
363 59 hellwig
    }
364
  }
365
}

powered by: WebSVN 2.1.0

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