This source file includes following definitions.
- error
- Malloc
- Realloc
- Strdup
- define
- lookup
- patch
- backpatch
- output
- getl
- eval_operand
- eval_sdi
- eval_addr
- crack
- assemble
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 static char id[] = "$Id: aic7xxx_asm.c,v 1.8 1995/05/25 06:25:36 root Exp $";
32 #include <ctype.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37
38 #define MEMORY 448
39 #define MAXLINE 1024
40 #define MAXTOKEN 32
41 #define ADOTOUT "a.out"
42 #define NOVALUE -1
43
44
45
46
47 #define R_SINDEX 0x65
48 #define R_ALLONES 0x69
49 #define R_ALLZEROS 0x6a
50 #define R_NONE 0x6a
51
52 int debug;
53 int lineno, LC;
54 char *filename;
55 FILE *ifp, *ofp;
56 unsigned char M[MEMORY][4];
57
58 void
59 error(char *s)
60 {
61 fprintf(stderr, "%s: %s at line %d\n", filename, s, lineno);
62 exit(EXIT_FAILURE);
63 }
64
65 void *
66 Malloc(size_t size)
67 {
68 void *p = malloc(size);
69 if (!p)
70 error("out of memory");
71 return(p);
72 }
73
74 void *
75 Realloc(void *ptr, size_t size)
76 {
77 void *p = realloc(ptr, size);
78 if (!p)
79 error("out of memory");
80 return(p);
81 }
82
83 char *
84 Strdup(char *s)
85 {
86 char *p = (char *)Malloc(strlen(s) + 1);
87 strcpy(p, s);
88 return(p);
89 }
90
91 typedef struct sym_t {
92 struct sym_t *next;
93 char *name;
94 int value;
95 int npatch;
96 int *patch;
97 } sym_t;
98
99 sym_t *head;
100
101 void
102 define(char *name, int value)
103 {
104 sym_t *p, *q;
105
106 for (p = head, q = (sym_t *)&head; p; p = p->next) {
107 if (!strcmp(p->name, name))
108 error("redefined symbol");
109 q = p;
110 }
111
112 p = q->next = (sym_t *)Malloc(sizeof(sym_t));
113 p->next = NULL;
114 p->name = Strdup(name);
115 p->value = value;
116 p->npatch = 0;
117 p->patch = NULL;
118
119 if (debug) {
120 fprintf(stderr, "\"%s\" ", p->name);
121 if (p->value != NOVALUE)
122 fprintf(stderr, "defined as 0x%x\n", p->value);
123 else
124 fprintf(stderr, "undefined\n");
125 }
126 }
127
128 sym_t *
129 lookup(char *name)
130 {
131 sym_t *p;
132
133 for (p = head; p; p = p->next)
134 if (!strcmp(p->name, name))
135 return(p);
136 return(NULL);
137 }
138
139 void
140 patch(sym_t *p, int location)
141 {
142 p->npatch += 1;
143 p->patch = (int *)Realloc(p->patch, p->npatch * sizeof(int *));
144
145 p->patch[p->npatch - 1] = location;
146 }
147
148 void backpatch(void)
149 {
150 int i;
151 sym_t *p;
152
153 for (p = head; p; p = p->next) {
154
155 if (p->value == NOVALUE) {
156 fprintf(stderr,
157 "%s: undefined symbol \"%s\"\n",
158 filename, p->name);
159 exit(EXIT_FAILURE);
160 }
161
162 if (p->npatch) {
163 if (debug)
164 fprintf(stderr,
165 "\"%s\" (0x%x) patched at",
166 p->name, p->value);
167
168 for (i = 0; i < p->npatch; i++) {
169 M[p->patch[i]][0] &= ~1;
170 M[p->patch[i]][0] |= ((p->value >> 8) & 1);
171 M[p->patch[i]][1] = p->value & 0xff;
172
173 if (debug)
174 fprintf(stderr, " 0x%x", p->patch[i]);
175 }
176
177 if (debug)
178 fputc('\n', stderr);
179 }
180 }
181 }
182
183
184
185
186
187 void
188 output(FILE *fp)
189 {
190 int i;
191
192 for (i = 0; i < LC; i++)
193 fprintf(fp, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
194 M[i][3],
195 M[i][2],
196 M[i][1],
197 M[i][0]);
198 printf("%d out of %d instructions used.\n", LC, MEMORY);
199 }
200
201 char **
202 getl(int *n)
203 {
204 int i;
205 char *p, *quote;
206 static char buf[MAXLINE];
207 static char *a[MAXTOKEN];
208
209 i = 0;
210
211 while (fgets(buf, sizeof(buf), ifp)) {
212
213 lineno += 1;
214
215 if (buf[strlen(buf)-1] != '\n')
216 error("line too long");
217
218 p = strchr(buf, '#');
219 if (p)
220 *p = '\0';
221 p = buf;
222 rescan:
223 quote = strchr(p, '\"');
224 if (quote)
225 *quote = '\0';
226 for (p = strtok(p, ", \t\n"); p; p = strtok(NULL, ", \t\n"))
227 if (i < MAXTOKEN-1)
228 a[i++] = p;
229 else
230 error("too many tokens");
231 if (quote) {
232 quote++;
233 p = strchr(quote, '\"');
234 if (!p)
235 error("unterminated string constant");
236 else if (i < MAXTOKEN-1) {
237 a[i++] = quote;
238 *p = '\0';
239 p++;
240 }
241 else
242 error("too many tokens");
243 goto rescan;
244 }
245 if (i) {
246 *n = i;
247 return(a);
248 }
249 }
250 return(NULL);
251 }
252
253 #define A 0x8000
254 #define I 0x4000
255 #define SL 0x2000
256 #define SR 0x1000
257 #define RL 0x0800
258 #define RR 0x0400
259 #define LO 0x8000
260 #define LA 0x4000
261 #define LX 0x2000
262 #define NA -1
263
264 struct {
265 char *name;
266 int n;
267 unsigned int op;
268 unsigned int dest;
269 unsigned int src;
270 unsigned int imm;
271 unsigned int addr;
272 int fmt;
273 } instr[] = {
274
275
276
277 { "mov", 3, 1, 1, 2, I|0xff, NA, 1 },
278 { "mov", 4, LO|2, NA, 1, I|0, 3, 3 },
279 { "mvi", 3, 0, 1, I|R_ALLZEROS, A|2, NA, 1 },
280 { "mvi", 4, LO|2, NA, I|R_ALLZEROS, 1, 3, 3 },
281 { "not", 2, 2, 1, 1, I|0xff, NA, 1 },
282 { "and", 3, 1, 1, 1, A|2, NA, 1 },
283 { "and", 4, 1, 1, 3, A|2, NA, 1 },
284 { "or", 3, 0, 1, 1, A|2, NA, 1 },
285 { "or", 4, 0, 1, 3, A|2, NA, 1 },
286 { "or", 5, LO|3, NA, 1, 2, 4, 3 },
287 { "xor", 3, 2, 1, 1, A|2, NA, 1 },
288 { "xor", 4, 2, 1, 3, A|2, NA, 1 },
289 { "nop", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
290 { "inc", 2, 3, 1, 1, I|1, NA, 1 },
291 { "inc", 3, 3, 1, 2, I|1, NA, 1 },
292 { "dec", 2, 3, 1, 1, I|0xff, NA, 1 },
293 { "dec", 3, 3, 1, 2, I|0xff, NA, 1 },
294 { "jmp", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
295 { "jc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
296 { "jnc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
297 { "call", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
298 { "test", 5, LA|3, NA, 1, A|2, 4, 3 },
299 { "cmp", 5, LX|3, NA, 1, A|2, 4, 3 },
300 { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
301 { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
302 { "clc", 1, 3, I|R_NONE, I|R_ALLZEROS, I|1, NA, 1 },
303 { "clc", 4, 3, 2, I|R_ALLZEROS, A|3, NA, 1 },
304 { "stc", 2, 3, 1, I|R_ALLONES, I|1, NA, 1 },
305 { "add", 3, 3, 1, 1, A|2, NA, 1 },
306 { "add", 4, 3, 1, 3, A|2, NA, 1 },
307 { "adc", 3, 4, 1, 1, A|2, NA, 1 },
308 { "adc", 4, 4, 1, 3, A|2, NA, 1 },
309 { "shl", 3, 5, 1, 1, SL|2, NA, 2 },
310 { "shl", 4, 5, 1, 2, SL|3, NA, 2 },
311 { "shr", 3, 5, 1, 1, SR|2, NA, 2 },
312 { "shr", 4, 5, 1, 2, SR|3, NA, 2 },
313 { "rol", 3, 5, 1, 1, RL|2, NA, 2 },
314 { "rol", 4, 5, 1, 2, RL|3, NA, 2 },
315 { "ror", 3, 5, 1, 1, RR|2, NA, 2 },
316 { "ror", 4, 5, 1, 2, RR|3, NA, 2 },
317
318
319
320 { "clr", 2, 1, 1, I|R_ALLZEROS, I|0xff, NA, 1 },
321 { 0, 0, 0, 0, 0, 0, 0, 0 }
322 };
323
324 int
325 eval_operand(char **a, int spec)
326 {
327 int i;
328 unsigned int want = spec & (LO|LA|LX);
329
330 static struct {
331 unsigned int what;
332 char *name;
333 int value;
334 } jmptab[] = {
335 { LO, "jmp", 8 },
336 { LO, "jc", 9 },
337 { LO, "jnc", 10 },
338 { LO, "call", 11 },
339 { LA, "jz", 15 },
340 { LA, "jnz", 13 },
341 { LX, "je", 14 },
342 { LX, "jne", 12 },
343 };
344
345 spec &= ~(LO|LA|LX);
346
347 for (i = 0; i < sizeof(jmptab)/sizeof(jmptab[0]); i++)
348 if (jmptab[i].what == want &&
349 !strcmp(jmptab[i].name, a[spec]))
350 {
351 return(jmptab[i].value);
352 }
353
354 if (want)
355 error("invalid jump");
356
357 return(spec);
358 }
359
360 int
361 eval_sdi(char **a, int spec)
362 {
363 sym_t *p;
364 unsigned val;
365
366 if (spec == NA)
367 return(NA);
368
369 switch (spec & (A|I|SL|SR|RL|RR)) {
370 case SL:
371 case SR:
372 case RL:
373 case RR:
374 if (isdigit(*a[spec &~ (SL|SR|RL|RR)]))
375 val = strtol(a[spec &~ (SL|SR|RL|RR)], NULL, 0);
376 else {
377 p = lookup(a[spec &~ (SL|SR|RL|RR)]);
378 if (!p)
379 error("undefined symbol used");
380 val = p->value;
381 }
382
383 switch (spec & (SL|SR|RL|RR)) {
384 case SL:
385 if (val > 7)
386 return(0xf0);
387 return(((val % 8) << 4) |
388 (val % 8));
389 case SR:
390 if (val > 7)
391 return(0xf0);
392 return(((val % 8) << 4) |
393 (1 << 3) |
394 ((8 - (val % 8)) % 8));
395 case RL:
396 return(val % 8);
397 case RR:
398 return((8 - (val % 8)) % 8);
399 }
400 case I:
401 return(spec &~ I);
402 case A:
403
404
405
406
407
408
409 spec &= ~A;
410 if (!strcmp("A", a[spec]))
411 return(0);
412 if (isdigit(*a[spec]) &&
413 strtol(a[spec], NULL, 0) == 0)
414 {
415 error("immediate value of zero selects accumulator");
416 }
417
418 case 0:
419 if (isdigit(*a[spec]))
420 return(strtol(a[spec], NULL, 0));
421 p = lookup(a[spec]);
422 if (p)
423 return(p->value);
424 error("undefined symbol used");
425 }
426
427 return(NA);
428 }
429
430 int
431 eval_addr(char **a, int spec)
432 {
433 sym_t *p;
434
435 if (spec == NA)
436 return(NA);
437 if (isdigit(*a[spec]))
438 return(strtol(a[spec], NULL, 0));
439
440 p = lookup(a[spec]);
441
442 if (p) {
443 if (p->value != NOVALUE)
444 return(p->value);
445 patch(p, LC);
446 } else {
447 define(a[spec], NOVALUE);
448 p = lookup(a[spec]);
449 patch(p, LC);
450 }
451
452 return(NA);
453 }
454
455 int
456 crack(char **a, int n)
457 {
458 int i;
459 int I_imm, I_addr;
460 int I_op, I_dest, I_src, I_ret;
461
462
463
464
465
466
467 I_ret = (strcmp(a[n-1], "ret") ? 0 : !0);
468 if (I_ret && n > 1)
469 n -= 1;
470
471 for (i = 0; instr[i].name; i++) {
472
473
474
475
476
477 if (!strcmp(instr[i].name, *a) && instr[i].n == n)
478 break;
479 }
480 if (!instr[i].name)
481 error("unknown opcode or wrong number of operands");
482
483 I_op = eval_operand(a, instr[i].op);
484 I_src = eval_sdi(a, instr[i].src);
485 I_imm = eval_sdi(a, instr[i].imm);
486 I_dest = eval_sdi(a, instr[i].dest);
487 I_addr = eval_addr(a, instr[i].addr);
488
489 if( LC >= MEMORY )
490 error("Memory exhausted!\n");
491
492 switch (instr[i].fmt) {
493 case 1:
494 case 2:
495 M[LC][0] = (I_op << 1) | I_ret;
496 M[LC][1] = I_dest;
497 M[LC][2] = I_src;
498 M[LC][3] = I_imm;
499 break;
500 case 3:
501 if (I_ret)
502 error("illegal use of \"ret\"");
503 M[LC][0] = (I_op << 1) | ((I_addr >> 8) & 1);
504 M[LC][1] = I_addr & 0xff;
505 M[LC][2] = I_src;
506 M[LC][3] = I_imm;
507 break;
508 }
509
510 return (1);
511 }
512
513 #undef SL
514 #undef SR
515 #undef RL
516 #undef RR
517 #undef LX
518 #undef LA
519 #undef LO
520 #undef I
521 #undef A
522
523 void
524 assemble(void)
525 {
526 int n;
527 char **a;
528 sym_t *p;
529
530 while ((a = getl(&n))) {
531
532 while (a[0][strlen(*a)-1] == ':') {
533 a[0][strlen(*a)-1] = '\0';
534 p = lookup(*a);
535 if (p)
536 p->value = LC;
537 else
538 define(*a, LC);
539 a += 1;
540 n -= 1;
541 }
542
543 if (!n)
544 continue;
545
546 if (n == 3 && !strcmp("VERSION", *a))
547 fprintf(ofp, "#define %s \"%s\"\n", a[1], a[2]);
548 else {
549 if (n == 3 && !strcmp("=", a[1]))
550 define(*a, strtol(a[2], NULL, 0));
551 else
552 LC += crack(a, n);
553 }
554 }
555
556 backpatch();
557 output(ofp);
558
559 if (debug)
560 output(stderr);
561 }
562
563 int
564 main(int argc, char **argv)
565 {
566 int c;
567
568 while ((c = getopt(argc, argv, "dho:vD")) != EOF) {
569 switch (c) {
570 case 'd':
571 debug = !0;
572 break;
573 case 'D':
574 {
575 char *p;
576 if ((p = strchr(optarg, '=')) != NULL) {
577 *p = '\0';
578 define(optarg, strtol(p + 1, NULL, 0));
579 }
580 else
581 define(optarg, 1);
582 break;
583 }
584 case 'o':
585 ofp = fopen(optarg, "w");
586 if (!ofp) {
587 perror(optarg);
588 exit(EXIT_FAILURE);
589 }
590 break;
591 case 'h':
592 printf("usage: %s [-d] [-Dname] [-ooutput] input\n",
593 *argv);
594 exit(EXIT_SUCCESS);
595 break;
596 case 'v':
597 printf("%s\n", id);
598 exit(EXIT_SUCCESS);
599 break;
600 default:
601 exit(EXIT_FAILURE);
602 break;
603 }
604 }
605
606 if (argc - optind != 1) {
607 fprintf(stderr, "%s: must have one input file\n", *argv);
608 exit(EXIT_FAILURE);
609 }
610 filename = argv[optind];
611
612 ifp = fopen(filename, "r");
613 if (!ifp) {
614 perror(filename);
615 exit(EXIT_FAILURE);
616 }
617
618 if (!ofp) {
619 ofp = fopen(ADOTOUT, "w");
620 if (!ofp) {
621 perror(ADOTOUT);
622 exit(EXIT_FAILURE);
623 }
624 }
625
626 assemble();
627 exit(EXIT_SUCCESS);
628 }