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

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [monitor/] [monitor-digilent/] [asm.c] - Blame information for rev 279

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

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

powered by: WebSVN 2.1.0

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