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

Subversion Repositories eco32

[/] [eco32/] [trunk/] [sim/] [asm.c] - Blame information for rev 274

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

Line No. Rev Author Line
1 8 hellwig
/*
2
 * asm.c -- assembler
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
 
10
#include "common.h"
11
#include "console.h"
12
#include "error.h"
13
#include "instr.h"
14
#include "asm.h"
15
 
16
 
17
#define MAX_TOKENS      10
18
 
19
 
20
static char *msgs[] = {
21
  /*  0 */  "too many tokens on line",
22
  /*  1 */  "empty line",
23
  /*  2 */  "unknown instruction name",
24
  /*  3 */  "unknown instruction format",
25
  /*  4 */  "excess tokens on line",
26
  /*  5 */  "too few operands",
27
  /*  6 */  "illegal register",
28
  /*  7 */  "illegal immediate value",
29
  /*  8 */  "immediate value out of range",
30
  /*  9 */  "target is not aligned",
31
  /* 10 */  "target cannot be reached"
32
};
33
 
34
 
35
static Bool asmReg(char *token, int *reg) {
36
  char *end;
37
 
38
  if (*token != '$') {
39
    return false;
40
  }
41
  *reg = strtoul(token + 1, &end, 10);
42
  if (*end != '\0') {
43
    return false;
44
  }
45
  if (*reg < 0 || *reg >= 32) {
46
    return false;
47
  }
48
  return true;
49
}
50
 
51
 
52
static Bool asmNum(char *token, unsigned int *val) {
53
  char *end;
54
 
55
  *val = strtoul(token, &end, 16);
56
  return *end == '\0';
57
}
58
 
59
 
60
char *asmInstr(char *line, Word addr, Word *instrPtr) {
61
  char *tokens[MAX_TOKENS];
62
  int n;
63
  char *p;
64
  Instr *instr;
65
  Word result;
66
  int r1, r2, r3;
67
  unsigned int uimm;
68
  signed int simm;
69
 
70
  /* separate tokens */
71
  n = 0;
72
  p = strtok(line, " \t\n,");
73
  while (p != NULL) {
74
    if (n == MAX_TOKENS) {
75
      return msgs[0];
76
    }
77
    tokens[n++] = p;
78
    p = strtok(NULL, " \t\n,");
79
  }
80
  if (n == 0) {
81
    return msgs[1];
82
  }
83
  /* lookup mnemonic */
84
  instr = lookupInstr(tokens[0]);
85
  if (instr == NULL) {
86
    return msgs[2];
87
  }
88
  /* do processing according to format */
89
  switch (instr->format) {
90
    case FORMAT_N:
91
      /* no operands (but may get a constant operand) */
92
      if (n > 2) {
93
        return msgs[4];
94
      }
95
      if (n < 1) {
96
        return msgs[5];
97
      }
98
      if (n == 2) {
99
        if (!asmNum(tokens[1], &uimm)) {
100
          return msgs[7];
101
        }
102
      } else {
103
        uimm = 0;
104
      }
105
      result = ((Word) instr->opcode << 26) |
106
               (uimm & MASK(26));
107
      break;
108
    case FORMAT_RH:
109
      /* one register and a half operand */
110
      if (n > 3) {
111
        return msgs[4];
112
      }
113
      if (n < 3) {
114
        return msgs[5];
115
      }
116
      if (!asmReg(tokens[1], &r1)) {
117
        return msgs[6];
118
      }
119
      if (!asmNum(tokens[2], &uimm)) {
120
        return msgs[7];
121
      }
122
      if (uimm >= (unsigned) (1 << 16)) {
123
        return msgs[8];
124
      }
125
      result = ((Word) instr->opcode << 26) |
126
               (r1 << 16) |
127
               (uimm & MASK(16));
128
      break;
129
    case FORMAT_RHH:
130
      /* one register and a half operand */
131
      /* ATTENTION: high-order 16 bits encoded */
132
      if (n > 3) {
133
        return msgs[4];
134
      }
135
      if (n < 3) {
136
        return msgs[5];
137
      }
138
      if (!asmReg(tokens[1], &r1)) {
139
        return msgs[6];
140
      }
141
      if (!asmNum(tokens[2], &uimm)) {
142
        return msgs[7];
143
      }
144
      uimm >>= 16;
145
      if (uimm >= (unsigned) (1 << 16)) {
146
        return msgs[8];
147
      }
148
      result = ((Word) instr->opcode << 26) |
149
               (r1 << 16) |
150
               (uimm & MASK(16));
151
      break;
152
    case FORMAT_RRH:
153
      /* two registers and a half operand */
154
      if (n > 4) {
155
        return msgs[4];
156
      }
157
      if (n < 4) {
158
        return msgs[5];
159
      }
160
      if (!asmReg(tokens[1], &r1)) {
161
        return msgs[6];
162
      }
163
      if (!asmReg(tokens[2], &r2)) {
164
        return msgs[6];
165
      }
166
      if (!asmNum(tokens[3], &uimm)) {
167
        return msgs[7];
168
      }
169
      if (uimm >= (unsigned) (1 << 16)) {
170
        return msgs[8];
171
      }
172
      result = ((Word) instr->opcode << 26) |
173
               (r2 << 21) |
174
               (r1 << 16) |
175
               (uimm & MASK(16));
176
      break;
177
    case FORMAT_RRS:
178
      /* two registers and a signed half operand */
179
      if (n > 4) {
180
        return msgs[4];
181
      }
182
      if (n < 4) {
183
        return msgs[5];
184
      }
185
      if (!asmReg(tokens[1], &r1)) {
186
        return msgs[6];
187
      }
188
      if (!asmReg(tokens[2], &r2)) {
189
        return msgs[6];
190
      }
191
      if (!asmNum(tokens[3], (unsigned int *) &simm)) {
192
        return msgs[7];
193
      }
194
      if (simm >= (signed) (1 << 15) ||
195
          simm < - (signed) (1 << 15)) {
196
        return msgs[8];
197
      }
198
      result = ((Word) instr->opcode << 26) |
199
               (r2 << 21) |
200
               (r1 << 16) |
201
               (simm & MASK(16));
202
      break;
203
    case FORMAT_RRR:
204
      /* three register operands */
205
      if (n > 4) {
206
        return msgs[4];
207
      }
208
      if (n < 4) {
209
        return msgs[5];
210
      }
211
      if (!asmReg(tokens[1], &r1)) {
212
        return msgs[6];
213
      }
214
      if (!asmReg(tokens[2], &r2)) {
215
        return msgs[6];
216
      }
217
      if (!asmReg(tokens[3], &r3)) {
218
        return msgs[6];
219
      }
220
      result = ((Word) instr->opcode << 26) |
221
               (r2 << 21) |
222
               (r3 << 16) |
223
               (r1 << 11);
224
      break;
225
    case FORMAT_RRX:
226
      /* either FORMAT_RRR or FORMAT_RRH */
227
      if (n > 4) {
228
        return msgs[4];
229
      }
230
      if (n < 4) {
231
        return msgs[5];
232
      }
233
      if (!asmReg(tokens[1], &r1)) {
234
        return msgs[6];
235
      }
236
      if (!asmReg(tokens[2], &r2)) {
237
        return msgs[6];
238
      }
239
      if (*tokens[3] == '$') {
240
        /* FORMAT_RRR */
241
        if (!asmReg(tokens[3], &r3)) {
242
          return msgs[6];
243
        }
244
        result = ((Word) instr->opcode << 26) |
245
                 (r2 << 21) |
246
                 (r3 << 16) |
247
                 (r1 << 11);
248
      } else {
249
        /* FORMAT_RRH */
250
        if (!asmNum(tokens[3], &uimm)) {
251
          return msgs[7];
252
        }
253
        if (uimm >= (unsigned) (1 << 16)) {
254
          return msgs[8];
255
        }
256
        result = (((Word) instr->opcode + 1) << 26) |
257
                 (r2 << 21) |
258
                 (r1 << 16) |
259
                 (uimm & MASK(16));
260
      }
261
      break;
262
    case FORMAT_RRY:
263
      /* either FORMAT_RRR or FORMAT_RRS */
264
      if (n > 4) {
265
        return msgs[4];
266
      }
267
      if (n < 4) {
268
        return msgs[5];
269
      }
270
      if (!asmReg(tokens[1], &r1)) {
271
        return msgs[6];
272
      }
273
      if (!asmReg(tokens[2], &r2)) {
274
        return msgs[6];
275
      }
276
      if (*tokens[3] == '$') {
277
        /* FORMAT_RRR */
278
        if (!asmReg(tokens[3], &r3)) {
279
          return msgs[6];
280
        }
281
        result = ((Word) instr->opcode << 26) |
282
                 (r2 << 21) |
283
                 (r3 << 16) |
284
                 (r1 << 11);
285
      } else {
286
        /* FORMAT_RRS */
287
        if (!asmNum(tokens[3], (unsigned int *) &simm)) {
288
          return msgs[7];
289
        }
290
        if (simm >= (signed) (1 << 15) ||
291
            simm < - (signed) (1 << 15)) {
292
          return msgs[8];
293
        }
294
        result = (((Word) instr->opcode + 1) << 26) |
295
                 (r2 << 21) |
296
                 (r1 << 16) |
297
                 (simm & MASK(16));
298
      }
299
      break;
300
    case FORMAT_RRB:
301
      /* two registers and a 16 bit signed offset operand */
302
      if (n > 4) {
303
        return msgs[4];
304
      }
305
      if (n < 4) {
306
        return msgs[5];
307
      }
308
      if (!asmReg(tokens[1], &r1)) {
309
        return msgs[6];
310
      }
311
      if (!asmReg(tokens[2], &r2)) {
312
        return msgs[6];
313
      }
314
      if (!asmNum(tokens[3], (unsigned int *) &simm)) {
315
        return msgs[7];
316
      }
317
      if ((simm & 0x00000003) != 0) {
318
        return msgs[9];
319
      }
320
      simm -= addr + 4;
321
      simm /= 4;
322
      if (simm >= (signed) (1 << 15) ||
323
          simm < - (signed) (1 << 15)) {
324
        return msgs[10];
325
      }
326
      result = ((Word) instr->opcode << 26) |
327
               (r1 << 21) |
328
               (r2 << 16) |
329
               (simm & MASK(16));
330
      break;
331
    case FORMAT_J:
332
      /* no registers and a 26 bit signed offset operand */
333
      if (n > 2) {
334
        return msgs[4];
335
      }
336
      if (n < 2) {
337
        return msgs[5];
338
      }
339
      if (!asmNum(tokens[1], (unsigned int *) &simm)) {
340
        return msgs[7];
341
      }
342
      if ((simm & 0x00000003) != 0) {
343
        return msgs[9];
344
      }
345
      simm -= addr + 4;
346
      simm /= 4;
347
      if (simm >= (signed) (1 << 25) ||
348
          simm < - (signed) (1 << 25)) {
349
        return msgs[10];
350
      }
351
      result = ((Word) instr->opcode << 26) |
352
               (simm & MASK(26));
353
      break;
354
    case FORMAT_JR:
355
      /* one register operand */
356
      if (n > 2) {
357
        return msgs[4];
358
      }
359
      if (n < 2) {
360
        return msgs[5];
361
      }
362
      if (!asmReg(tokens[1], &r1)) {
363
        return msgs[6];
364
      }
365
      result = ((Word) instr->opcode << 26) |
366
               (r1 << 21);
367
      break;
368
    default:
369
      return msgs[3];
370
  }
371
  /* line successfully assembled */
372
  *instrPtr = result;
373
  return NULL;
374
}

powered by: WebSVN 2.1.0

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