1 #define EXTERN
2 #include "a.h"
3 #include "y.tab.h"
4 #include <ctype.h>
5
6 void
main(int argc,char * argv[])7 main(int argc, char *argv[])
8 {
9 char *p;
10 int nout, nproc, status, i, c;
11
12 thechar = '5';
13 thestring = "arm";
14 memset(debug, 0, sizeof(debug));
15 cinit();
16 outfile = 0;
17 include[ninclude++] = ".";
18 ARGBEGIN {
19 default:
20 c = ARGC();
21 if(c >= 0 || c < sizeof(debug))
22 debug[c] = 1;
23 break;
24
25 case 'o':
26 outfile = ARGF();
27 break;
28
29 case 'D':
30 p = ARGF();
31 if(p)
32 Dlist[nDlist++] = p;
33 break;
34
35 case 'I':
36 p = ARGF();
37 setinclude(p);
38 break;
39 case 't':
40 thechar = 't';
41 thestring = "thumb";
42 break;
43 } ARGEND
44 if(*argv == 0) {
45 print("usage: %ca [-options] file.s\n", thechar);
46 errorexit();
47 }
48 if(argc > 1 && systemtype(Windows)){
49 print("can't assemble multiple files on windows\n");
50 errorexit();
51 }
52 if(argc > 1 && !systemtype(Windows)) {
53 nproc = 1;
54 if(p = getenv("NPROC"))
55 nproc = atol(p); /* */
56 c = 0;
57 nout = 0;
58 for(;;) {
59 while(nout < nproc && argc > 0) {
60 i = myfork();
61 if(i < 0) {
62 i = mywait(&status);
63 if(i < 0)
64 errorexit();
65 if(status)
66 c++;
67 nout--;
68 continue;
69 }
70 if(i == 0) {
71 print("%s:\n", *argv);
72 if(assemble(*argv))
73 errorexit();
74 exits(0);
75 }
76 nout++;
77 argc--;
78 argv++;
79 }
80 i = mywait(&status);
81 if(i < 0) {
82 if(c)
83 errorexit();
84 exits(0);
85 }
86 if(status)
87 c++;
88 nout--;
89 }
90 }
91 if(assemble(argv[0]))
92 errorexit();
93 exits(0);
94 }
95
96 int
assemble(char * file)97 assemble(char *file)
98 {
99 char ofile[100], incfile[20], *p;
100 int i, of;
101
102 strcpy(ofile, file);
103 p = utfrrune(ofile, pathchar());
104 if(p) {
105 include[0] = ofile;
106 *p++ = 0;
107 } else
108 p = ofile;
109 if(outfile == 0) {
110 outfile = p;
111 if(outfile){
112 p = utfrrune(outfile, '.');
113 if(p)
114 if(p[1] == 's' && p[2] == 0)
115 p[0] = 0;
116 p = utfrune(outfile, 0);
117 p[0] = '.';
118 p[1] = thechar;
119 p[2] = 0;
120 } else
121 outfile = "/dev/null";
122 }
123 p = getenv("INCLUDE");
124 if(p) {
125 setinclude(p);
126 } else {
127 if(systemtype(Plan9)) {
128 sprint(incfile,"/%s/include", thestring);
129 setinclude(strdup(incfile));
130 }
131 }
132
133 of = mycreat(outfile, 0664);
134 if(of < 0) {
135 yyerror("%ca: cannot create %s", thechar, outfile);
136 errorexit();
137 }
138 Binit(&obuf, of, OWRITE);
139
140 pass = 1;
141 pinit(file);
142 for(i=0; i<nDlist; i++)
143 dodefine(Dlist[i]);
144 yyparse();
145 if(nerrors) {
146 cclean();
147 return nerrors;
148 }
149
150 pass = 2;
151 outhist();
152 pinit(file);
153 for(i=0; i<nDlist; i++)
154 dodefine(Dlist[i]);
155 yyparse();
156 cclean();
157 return nerrors;
158 }
159
160 struct
161 {
162 char *name;
163 ushort type;
164 ushort value;
165 } itab[] =
166 {
167 "SP", LSP, D_AUTO,
168 "SB", LSB, D_EXTERN,
169 "FP", LFP, D_PARAM,
170 "PC", LPC, D_BRANCH,
171
172 "R", LR, 0,
173 "R0", LREG, 0,
174 "R1", LREG, 1,
175 "R2", LREG, 2,
176 "R3", LREG, 3,
177 "R4", LREG, 4,
178 "R5", LREG, 5,
179 "R6", LREG, 6,
180 "R7", LREG, 7,
181 "R8", LREG, 8,
182 "R9", LREG, 9,
183 "R10", LREG, 10,
184 "R11", LREG, 11,
185 "R12", LREG, 12,
186 "R13", LREG, 13,
187 "R14", LREG, 14,
188 "R15", LREG, 15,
189
190 "F", LF, 0,
191
192 "F0", LFREG, 0,
193 "F1", LFREG, 1,
194 "F2", LFREG, 2,
195 "F3", LFREG, 3,
196 "F4", LFREG, 4,
197 "F5", LFREG, 5,
198 "F6", LFREG, 6,
199 "F7", LFREG, 7,
200 "F8", LFREG, 8,
201 "F9", LFREG, 9,
202 "F10", LFREG, 10,
203 "F11", LFREG, 11,
204 "F12", LFREG, 12,
205 "F13", LFREG, 13,
206 "F14", LFREG, 14,
207 "F15", LFREG, 15,
208
209 "C", LC, 0,
210
211 "C0", LCREG, 0,
212 "C1", LCREG, 1,
213 "C2", LCREG, 2,
214 "C3", LCREG, 3,
215 "C4", LCREG, 4,
216 "C5", LCREG, 5,
217 "C6", LCREG, 6,
218 "C7", LCREG, 7,
219 "C8", LCREG, 8,
220 "C9", LCREG, 9,
221 "C10", LCREG, 10,
222 "C11", LCREG, 11,
223 "C12", LCREG, 12,
224 "C13", LCREG, 13,
225 "C14", LCREG, 14,
226 "C15", LCREG, 15,
227
228 "CPSR", LPSR, 0,
229 "SPSR", LPSR, 1,
230
231 "FPSR", LFCR, 0,
232 "FPCR", LFCR, 1,
233
234 ".EQ", LCOND, 0,
235 ".NE", LCOND, 1,
236 ".CS", LCOND, 2,
237 ".HS", LCOND, 2,
238 ".CC", LCOND, 3,
239 ".LO", LCOND, 3,
240 ".MI", LCOND, 4,
241 ".PL", LCOND, 5,
242 ".VS", LCOND, 6,
243 ".VC", LCOND, 7,
244 ".HI", LCOND, 8,
245 ".LS", LCOND, 9,
246 ".GE", LCOND, 10,
247 ".LT", LCOND, 11,
248 ".GT", LCOND, 12,
249 ".LE", LCOND, 13,
250 ".AL", LCOND, Always,
251
252 ".U", LS, C_UBIT,
253 ".S", LS, C_SBIT,
254 ".W", LS, C_WBIT,
255 ".P", LS, C_PBIT,
256 ".PW", LS, C_WBIT|C_PBIT,
257 ".WP", LS, C_WBIT|C_PBIT,
258
259 ".F", LS, C_FBIT,
260
261 ".IBW", LS, C_WBIT|C_PBIT|C_UBIT,
262 ".IAW", LS, C_WBIT|C_UBIT,
263 ".DBW", LS, C_WBIT|C_PBIT,
264 ".DAW", LS, C_WBIT,
265 ".IB", LS, C_PBIT|C_UBIT,
266 ".IA", LS, C_UBIT,
267 ".DB", LS, C_PBIT,
268 ".DA", LS, 0,
269
270 "@", LAT, 0,
271
272 "AND", LTYPE1, AAND,
273 "EOR", LTYPE1, AEOR,
274 "SUB", LTYPE1, ASUB,
275 "RSB", LTYPE1, ARSB,
276 "ADD", LTYPE1, AADD,
277 "ADC", LTYPE1, AADC,
278 "SBC", LTYPE1, ASBC,
279 "RSC", LTYPE1, ARSC,
280 "ORR", LTYPE1, AORR,
281 "BIC", LTYPE1, ABIC,
282
283 "SLL", LTYPE1, ASLL,
284 "SRL", LTYPE1, ASRL,
285 "SRA", LTYPE1, ASRA,
286
287 "MUL", LTYPE1, AMUL,
288 "MULA", LTYPEN, AMULA,
289 "DIV", LTYPE1, ADIV,
290 "MOD", LTYPE1, AMOD,
291
292 "MULL", LTYPEM, AMULL,
293 "MULAL", LTYPEM, AMULAL,
294 "MULLU", LTYPEM, AMULLU,
295 "MULALU", LTYPEM, AMULALU,
296
297 "MVN", LTYPE2, AMVN, /* op2 ignored */
298
299 "MOVB", LTYPE3, AMOVB,
300 "MOVBU", LTYPE3, AMOVBU,
301 "MOVH", LTYPE3, AMOVH,
302 "MOVHU", LTYPE3, AMOVHU,
303 "MOVW", LTYPE3, AMOVW,
304
305 "MOVD", LTYPE3, AMOVD,
306 "MOVDF", LTYPE3, AMOVDF,
307 "MOVDW", LTYPE3, AMOVDW,
308 "MOVF", LTYPE3, AMOVF,
309 "MOVFD", LTYPE3, AMOVFD,
310 "MOVFW", LTYPE3, AMOVFW,
311 "MOVWD", LTYPE3, AMOVWD,
312 "MOVWF", LTYPE3, AMOVWF,
313
314 "LDREX", LTYPE3, ALDREX,
315 "LDREXD", LTYPE3, ALDREXD,
316 "STREX", LTYPE9, ASTREX,
317 "STREXD", LTYPE9, ASTREXD,
318
319 /*
320 "ABSF", LTYPEI, AABSF,
321 "ABSD", LTYPEI, AABSD,
322 "NEGF", LTYPEI, ANEGF,
323 "NEGD", LTYPEI, ANEGD,
324 "SQTF", LTYPEI, ASQTF,
325 "SQTD", LTYPEI, ASQTD,
326 "RNDF", LTYPEI, ARNDF,
327 "RNDD", LTYPEI, ARNDD,
328 "URDF", LTYPEI, AURDF,
329 "URDD", LTYPEI, AURDD,
330 "NRMF", LTYPEI, ANRMF,
331 "NRMD", LTYPEI, ANRMD,
332 */
333
334 "SQRTF", LTYPEI, ASQRTF,
335 "SQRTD", LTYPEI, ASQRTD,
336 "CMPF", LTYPEL, ACMPF,
337 "CMPD", LTYPEL, ACMPD,
338 "ADDF", LTYPEK, AADDF,
339 "ADDD", LTYPEK, AADDD,
340 "SUBF", LTYPEK, ASUBF,
341 "SUBD", LTYPEK, ASUBD,
342 "MULF", LTYPEK, AMULF,
343 "MULD", LTYPEK, AMULD,
344 "DIVF", LTYPEK, ADIVF,
345 "DIVD", LTYPEK, ADIVD,
346
347 "B", LTYPE4, AB,
348 "BL", LTYPE4, ABL,
349 "BX", LTYPEBX, ABX,
350
351 "BEQ", LTYPE5, ABEQ,
352 "BNE", LTYPE5, ABNE,
353 "BCS", LTYPE5, ABCS,
354 "BHS", LTYPE5, ABHS,
355 "BCC", LTYPE5, ABCC,
356 "BLO", LTYPE5, ABLO,
357 "BMI", LTYPE5, ABMI,
358 "BPL", LTYPE5, ABPL,
359 "BVS", LTYPE5, ABVS,
360 "BVC", LTYPE5, ABVC,
361 "BHI", LTYPE5, ABHI,
362 "BLS", LTYPE5, ABLS,
363 "BGE", LTYPE5, ABGE,
364 "BLT", LTYPE5, ABLT,
365 "BGT", LTYPE5, ABGT,
366 "BLE", LTYPE5, ABLE,
367 "BCASE", LTYPE5, ABCASE,
368
369 "SWI", LTYPE6, ASWI,
370
371 "CMP", LTYPE7, ACMP,
372 "TST", LTYPE7, ATST,
373 "TEQ", LTYPE7, ATEQ,
374 "CMN", LTYPE7, ACMN,
375
376 "MOVM", LTYPE8, AMOVM,
377
378 "SWPBU", LTYPE9, ASWPBU,
379 "SWPW", LTYPE9, ASWPW,
380
381 "RET", LTYPEA, ARET,
382 "RFE", LTYPEA, ARFE,
383
384 "TEXT", LTYPEB, ATEXT,
385 "GLOBL", LTYPEB, AGLOBL,
386 "DATA", LTYPEC, ADATA,
387 "CASE", LTYPED, ACASE,
388 "END", LTYPEE, AEND,
389 "WORD", LTYPEH, AWORD,
390 "NOP", LTYPEI, ANOP,
391
392 "MCR", LTYPEJ, 0,
393 "MRC", LTYPEJ, 1,
394 0
395 };
396
397 void
cinit(void)398 cinit(void)
399 {
400 Sym *s;
401 int i;
402
403 nullgen.sym = S;
404 nullgen.offset = 0;
405 nullgen.type = D_NONE;
406 nullgen.name = D_NONE;
407 nullgen.reg = NREG;
408 if(FPCHIP)
409 nullgen.dval = 0;
410 for(i=0; i<sizeof(nullgen.sval); i++)
411 nullgen.sval[i] = 0;
412
413 nerrors = 0;
414 iostack = I;
415 iofree = I;
416 peekc = IGN;
417 nhunk = 0;
418 for(i=0; i<NHASH; i++)
419 hash[i] = S;
420 for(i=0; itab[i].name; i++) {
421 s = slookup(itab[i].name);
422 s->type = itab[i].type;
423 s->value = itab[i].value;
424 }
425
426 pathname = allocn(pathname, 0, 100);
427 if(getwd(pathname, 99) == 0) {
428 pathname = allocn(pathname, 100, 900);
429 if(getwd(pathname, 999) == 0)
430 strcpy(pathname, "/???");
431 }
432 }
433
434 void
syminit(Sym * s)435 syminit(Sym *s)
436 {
437
438 s->type = LNAME;
439 s->value = 0;
440 }
441
442 int
isreg(Gen * g)443 isreg(Gen *g)
444 {
445
446 USED(g);
447 return 1;
448 }
449
450 void
cclean(void)451 cclean(void)
452 {
453
454 outcode(AEND, Always, &nullgen, NREG, &nullgen);
455 Bflush(&obuf);
456 }
457
458 void
zname(char * n,int t,int s)459 zname(char *n, int t, int s)
460 {
461
462 Bputc(&obuf, ANAME);
463 Bputc(&obuf, t); /* type */
464 Bputc(&obuf, s); /* sym */
465 while(*n) {
466 Bputc(&obuf, *n);
467 n++;
468 }
469 Bputc(&obuf, 0);
470 }
471
472 void
zaddr(Gen * a,int s)473 zaddr(Gen *a, int s)
474 {
475 long l;
476 int i;
477 char *n;
478 Ieee e;
479
480 Bputc(&obuf, a->type);
481 Bputc(&obuf, a->reg);
482 Bputc(&obuf, s);
483 Bputc(&obuf, a->name);
484 switch(a->type) {
485 default:
486 print("unknown type %d\n", a->type);
487 exits("arg");
488
489 case D_NONE:
490 case D_REG:
491 case D_FREG:
492 case D_PSR:
493 case D_FPCR:
494 break;
495
496 case D_REGREG:
497 Bputc(&obuf, a->offset);
498 break;
499
500 case D_OREG:
501 case D_CONST:
502 case D_BRANCH:
503 case D_SHIFT:
504 l = a->offset;
505 Bputc(&obuf, l);
506 Bputc(&obuf, l>>8);
507 Bputc(&obuf, l>>16);
508 Bputc(&obuf, l>>24);
509 break;
510
511 case D_SCONST:
512 n = a->sval;
513 for(i=0; i<NSNAME; i++) {
514 Bputc(&obuf, *n);
515 n++;
516 }
517 break;
518
519 case D_FCONST:
520 ieeedtod(&e, a->dval);
521 Bputc(&obuf, e.l);
522 Bputc(&obuf, e.l>>8);
523 Bputc(&obuf, e.l>>16);
524 Bputc(&obuf, e.l>>24);
525 Bputc(&obuf, e.h);
526 Bputc(&obuf, e.h>>8);
527 Bputc(&obuf, e.h>>16);
528 Bputc(&obuf, e.h>>24);
529 break;
530 }
531 }
532
533 static int bcode[] =
534 {
535 ABEQ,
536 ABNE,
537 ABCS,
538 ABCC,
539 ABMI,
540 ABPL,
541 ABVS,
542 ABVC,
543 ABHI,
544 ABLS,
545 ABGE,
546 ABLT,
547 ABGT,
548 ABLE,
549 AB,
550 ANOP,
551 };
552
553 void
outcode(int a,int scond,Gen * g1,int reg,Gen * g2)554 outcode(int a, int scond, Gen *g1, int reg, Gen *g2)
555 {
556 int sf, st, t;
557 Sym *s;
558
559 /* hack to make B.NE etc. work: turn it into the corresponding conditional */
560 if(a == AB){
561 a = bcode[scond&0xf];
562 scond = (scond & ~0xf) | Always;
563 }
564
565 if(pass == 1)
566 goto out;
567 jackpot:
568 sf = 0;
569 s = g1->sym;
570 while(s != S) {
571 sf = s->sym;
572 if(sf < 0 || sf >= NSYM)
573 sf = 0;
574 t = g1->name;
575 if(h[sf].type == t)
576 if(h[sf].sym == s)
577 break;
578 zname(s->name, t, sym);
579 s->sym = sym;
580 h[sym].sym = s;
581 h[sym].type = t;
582 sf = sym;
583 sym++;
584 if(sym >= NSYM)
585 sym = 1;
586 break;
587 }
588 st = 0;
589 s = g2->sym;
590 while(s != S) {
591 st = s->sym;
592 if(st < 0 || st >= NSYM)
593 st = 0;
594 t = g2->name;
595 if(h[st].type == t)
596 if(h[st].sym == s)
597 break;
598 zname(s->name, t, sym);
599 s->sym = sym;
600 h[sym].sym = s;
601 h[sym].type = t;
602 st = sym;
603 sym++;
604 if(sym >= NSYM)
605 sym = 1;
606 if(st == sf)
607 goto jackpot;
608 break;
609 }
610 Bputc(&obuf, a);
611 Bputc(&obuf, scond);
612 Bputc(&obuf, reg);
613 Bputc(&obuf, lineno);
614 Bputc(&obuf, lineno>>8);
615 Bputc(&obuf, lineno>>16);
616 Bputc(&obuf, lineno>>24);
617 zaddr(g1, sf);
618 zaddr(g2, st);
619
620 out:
621 if(a != AGLOBL && a != ADATA)
622 pc++;
623 }
624
625 void
outhist(void)626 outhist(void)
627 {
628 Gen g;
629 Hist *h;
630 char *p, *q, *op, c;
631 int n;
632
633 g = nullgen;
634 c = pathchar();
635 for(h = hist; h != H; h = h->link) {
636 p = h->name;
637 op = 0;
638 /* on windows skip drive specifier in pathname */
639 if(systemtype(Windows) && p && p[1] == ':'){
640 p += 2;
641 c = *p;
642 }
643 if(p && p[0] != c && h->offset == 0 && pathname){
644 /* on windows skip drive specifier in pathname */
645 if(systemtype(Windows) && pathname[1] == ':') {
646 op = p;
647 p = pathname+2;
648 c = *p;
649 } else if(pathname[0] == c){
650 op = p;
651 p = pathname;
652 }
653 }
654 while(p) {
655 q = strchr(p, c);
656 if(q) {
657 n = q-p;
658 if(n == 0){
659 n = 1; /* leading "/" */
660 *p = '/'; /* don't emit "\" on windows */
661 }
662 q++;
663 } else {
664 n = strlen(p);
665 q = 0;
666 }
667 if(n) {
668 Bputc(&obuf, ANAME);
669 Bputc(&obuf, D_FILE); /* type */
670 Bputc(&obuf, 1); /* sym */
671 Bputc(&obuf, '<');
672 Bwrite(&obuf, p, n);
673 Bputc(&obuf, 0);
674 }
675 p = q;
676 if(p == 0 && op) {
677 p = op;
678 op = 0;
679 }
680 }
681 g.offset = h->offset;
682
683 Bputc(&obuf, AHISTORY);
684 Bputc(&obuf, Always);
685 Bputc(&obuf, 0);
686 Bputc(&obuf, h->line);
687 Bputc(&obuf, h->line>>8);
688 Bputc(&obuf, h->line>>16);
689 Bputc(&obuf, h->line>>24);
690 zaddr(&nullgen, 0);
691 zaddr(&g, 0);
692 }
693 }
694
695 #include "../cc/lexbody"
696 #include "../cc/macbody"
697 #include "../cc/compat"
698