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

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [monitor/] [monitor/] [cpu.c] - Blame information for rev 150

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

Line No. Rev Author Line
1 16 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 */  "terminal 0 transmitter interrupt",
91
  /*  1 */  "terminal 0 receiver interrupt",
92
  /*  2 */  "terminal 1 transmitter interrupt",
93
  /*  3 */  "terminal 1 receiver 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 interrupt",
105
  /* 15 */  "unknown 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
      printf("cannot compute condition code %d\n", cc);
210
      break;
211
  }
212
  return false;
213
}
214
 
215
 
216
Bool cpuStep(void) {
217
  Word instr;
218
  int opcode;
219
  int reg1, reg2;
220
  Half immed;
221
  Word offset;
222
  Bool canStep;
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
  canStep = true;
236
  switch (stepType[opcode]) {
237
    case 1:
238
      /* next instruction follows current one */
239
      nextAddr = pc + 4;
240
      break;
241
    case 2:
242
      /* next instruction conditionally reached by PC relative branch */
243
      nextAddr = pc + 4;
244
      if (evalCond(opcode - OP_BEQ, RR(reg1), RR(reg2))) {
245
        nextAddr += SEXT16(immed) << 2;
246
      }
247
      break;
248
    case 3:
249
      /* next instruction reached by PC relative jump */
250
      nextAddr = pc + 4 + (SEXT26(offset) << 2);
251
      break;
252
    case 4:
253
      /* next instruction reached by jump to register contents */
254
      nextAddr = RR(reg1);
255
      break;
256
    default:
257
      printf("cannot single-step instruction with opcode 0x%02X\n",
258
             opcode);
259
      canStep = false;
260
      break;
261
  }
262
  if (!canStep) {
263
    return false;
264
  }
265
  nextInstr = mmuReadWord(nextAddr);
266
  mmuWriteWord(nextAddr, BREAK);
267
  for (i = 0; i < 32; i++) {
268
    userContext.reg[i] = RR(i);
269
  }
270
  userContext.reg[30] = pc;
271
  userContext.psw = psw & ~PSW_V;
272
  userContext.tlbIndex = mmuGetIndex();
273
  userContext.tlbHi = mmuGetEntryHi();
274
  userContext.tlbLo = mmuGetEntryLo();
275
  if (saveState(&stepState)) {
276
    origReturn = monitorReturn;
277
    monitorReturn = &stepState;
278
    resume();
279
  }
280
  monitorReturn = origReturn;
281
  for (i = 0; i < 32; i++) {
282
    WR(i, userContext.reg[i]);
283
  }
284
  pc = userContext.reg[30];
285
  psw = userContext.psw | (psw & PSW_V);
286
  mmuSetIndex(userContext.tlbIndex);
287
  mmuSetEntryHi(userContext.tlbHi);
288
  mmuSetEntryLo(userContext.tlbLo);
289
  mmuWriteWord(nextAddr, nextInstr);
290
  if (nextAddr == pc) {
291
    return true;
292
  }
293
  if ((psw & PSW_V) == 0) {
294
    printf("unexpected %s occurred\n",
295
           exceptionToString((psw & PSW_PRIO_MASK) >> 16));
296
    return false;
297
  }
298
  if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
299
      (mmuGetEntryHi() & 0x80000000) == 0) {
300
    pc = 0xC0000008;
301
  } else {
302
    pc = 0xC0000004;
303
  }
304
  return true;
305
}
306
 
307
 
308
Bool cpuRun(void) {
309
  Word instr;
310
  int i;
311
  MonitorState runState;
312
  MonitorState *origReturn;
313
 
314
  if (breakSet && breakAddr == pc) {
315
    /* single-step one instruction */
316
    if (!cpuStep()) {
317
      return false;
318
    }
319
  }
320
  while (1) {
321
    if (breakSet) {
322
      instr = mmuReadWord(breakAddr);
323
      mmuWriteWord(breakAddr, BREAK);
324
    }
325
    for (i = 0; i < 32; i++) {
326
      userContext.reg[i] = RR(i);
327
    }
328
    userContext.reg[30] = pc;
329
    userContext.psw = psw & ~PSW_V;
330
    userContext.tlbIndex = mmuGetIndex();
331
    userContext.tlbHi = mmuGetEntryHi();
332
    userContext.tlbLo = mmuGetEntryLo();
333
    if (saveState(&runState)) {
334
      origReturn = monitorReturn;
335
      monitorReturn = &runState;
336
      resume();
337
    }
338
    monitorReturn = origReturn;
339
    for (i = 0; i < 32; i++) {
340
      WR(i, userContext.reg[i]);
341
    }
342
    pc = userContext.reg[30];
343
    psw = userContext.psw | (psw & PSW_V);
344
    mmuSetIndex(userContext.tlbIndex);
345
    mmuSetEntryHi(userContext.tlbHi);
346
    mmuSetEntryLo(userContext.tlbLo);
347
    if (breakSet) {
348
      mmuWriteWord(breakAddr, instr);
349
    }
350
    if (breakSet && breakAddr == pc) {
351
      return true;
352
    }
353
    if ((psw & PSW_V) == 0) {
354
      printf("unexpected %s occurred\n",
355
             exceptionToString((psw & PSW_PRIO_MASK) >> 16));
356
      return false;
357
    }
358
    if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
359
        (mmuGetEntryHi() & 0x80000000) == 0) {
360
      pc = 0xC0000008;
361
    } else {
362
      pc = 0xC0000004;
363
    }
364
  }
365
  /* never reached */
366
  return false;
367
}

powered by: WebSVN 2.1.0

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