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