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 = 'v';
13 thestring = "mips";
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 'L': /* for little-endian mips */
40 thechar = '0';
41 thestring = "spim";
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 "HI", LHI, D_HI,
172 "LO", LLO, D_LO,
173
174 "R", LR, 0,
175 "R0", LREG, 0,
176 "R1", LREG, 1,
177 "R2", LREG, 2,
178 "R3", LREG, 3,
179 "R4", LREG, 4,
180 "R5", LREG, 5,
181 "R6", LREG, 6,
182 "R7", LREG, 7,
183 "R8", LREG, 8,
184 "R9", LREG, 9,
185 "R10", LREG, 10,
186 "R11", LREG, 11,
187 "R12", LREG, 12,
188 "R13", LREG, 13,
189 "R14", LREG, 14,
190 "R15", LREG, 15,
191 "R16", LREG, 16,
192 "R17", LREG, 17,
193 "R18", LREG, 18,
194 "R19", LREG, 19,
195 "R20", LREG, 20,
196 "R21", LREG, 21,
197 "R22", LREG, 22,
198 "R23", LREG, 23,
199 "R24", LREG, 24,
200 "R25", LREG, 25,
201 "R26", LREG, 26,
202 "R27", LREG, 27,
203 "R28", LREG, 28,
204 "R29", LREG, 29,
205 "R30", LREG, 30,
206 "R31", LREG, 31,
207
208 "M", LM, 0,
209 "M0", LMREG, 0,
210 "M1", LMREG, 1,
211 "M2", LMREG, 2,
212 "M3", LMREG, 3,
213 "M4", LMREG, 4,
214 "M5", LMREG, 5,
215 "M6", LMREG, 6,
216 "M7", LMREG, 7,
217 "M8", LMREG, 8,
218 "M9", LMREG, 9,
219 "M10", LMREG, 10,
220 "M11", LMREG, 11,
221 "M12", LMREG, 12,
222 "M13", LMREG, 13,
223 "M14", LMREG, 14,
224 "M15", LMREG, 15,
225 "M16", LMREG, 16,
226 "M17", LMREG, 17,
227 "M18", LMREG, 18,
228 "M19", LMREG, 19,
229 "M20", LMREG, 20,
230 "M21", LMREG, 21,
231 "M22", LMREG, 22,
232 "M23", LMREG, 23,
233 "M24", LMREG, 24,
234 "M25", LMREG, 25,
235 "M26", LMREG, 26,
236 "M27", LMREG, 27,
237 "M28", LMREG, 28,
238 "M29", LMREG, 29,
239 "M30", LMREG, 30,
240 "M31", LMREG, 31,
241
242 "F", LF, 0,
243
244 "F0", LFREG, 0,
245 "F1", LFREG, 1,
246 "F2", LFREG, 2,
247 "F3", LFREG, 3,
248 "F4", LFREG, 4,
249 "F5", LFREG, 5,
250 "F6", LFREG, 6,
251 "F7", LFREG, 7,
252 "F8", LFREG, 8,
253 "F9", LFREG, 9,
254 "F10", LFREG, 10,
255 "F11", LFREG, 11,
256 "F12", LFREG, 12,
257 "F13", LFREG, 13,
258 "F14", LFREG, 14,
259 "F15", LFREG, 15,
260 "F16", LFREG, 16,
261 "F17", LFREG, 17,
262 "F18", LFREG, 18,
263 "F19", LFREG, 19,
264 "F20", LFREG, 20,
265 "F21", LFREG, 21,
266 "F22", LFREG, 22,
267 "F23", LFREG, 23,
268 "F24", LFREG, 24,
269 "F25", LFREG, 25,
270 "F26", LFREG, 26,
271 "F27", LFREG, 27,
272 "F28", LFREG, 28,
273 "F29", LFREG, 29,
274 "F30", LFREG, 30,
275 "F31", LFREG, 31,
276
277 "FCR", LFCR, 0,
278 "FCR0", LFCREG, 0,
279 "FCR1", LFCREG, 1,
280 "FCR2", LFCREG, 2,
281 "FCR3", LFCREG, 3,
282 "FCR4", LFCREG, 4,
283 "FCR5", LFCREG, 5,
284 "FCR6", LFCREG, 6,
285 "FCR7", LFCREG, 7,
286 "FCR8", LFCREG, 8,
287 "FCR9", LFCREG, 9,
288 "FCR10", LFCREG, 10,
289 "FCR11", LFCREG, 11,
290 "FCR12", LFCREG, 12,
291 "FCR13", LFCREG, 13,
292 "FCR14", LFCREG, 14,
293 "FCR15", LFCREG, 15,
294 "FCR16", LFCREG, 16,
295 "FCR17", LFCREG, 17,
296 "FCR18", LFCREG, 18,
297 "FCR19", LFCREG, 19,
298 "FCR20", LFCREG, 20,
299 "FCR21", LFCREG, 21,
300 "FCR22", LFCREG, 22,
301 "FCR23", LFCREG, 23,
302 "FCR24", LFCREG, 24,
303 "FCR25", LFCREG, 25,
304 "FCR26", LFCREG, 26,
305 "FCR27", LFCREG, 27,
306 "FCR28", LFCREG, 28,
307 "FCR29", LFCREG, 29,
308 "FCR30", LFCREG, 30,
309 "FCR31", LFCREG, 31,
310
311 "ADD", LTYPE1, AADD,
312 "ADDU", LTYPE1, AADDU,
313 "SUB", LTYPE1, ASUB, /* converted to ADD(-) in loader */
314 "SUBU", LTYPE1, ASUBU,
315 "SGT", LTYPE1, ASGT,
316 "SGTU", LTYPE1, ASGTU,
317 "AND", LTYPE1, AAND,
318 "OR", LTYPE1, AOR,
319 "XOR", LTYPE1, AXOR,
320 "SLL", LTYPE1, ASLL,
321 "SRL", LTYPE1, ASRL,
322 "SRA", LTYPE1, ASRA,
323
324 "ADDV", LTYPE1, AADDV,
325 "ADDVU", LTYPE1, AADDVU,
326 "SUBV", LTYPE1, ASUBV, /* converted to ADD(-) in loader */
327 "SUBVU", LTYPE1, ASUBVU,
328 "SLLV", LTYPE1, ASLLV,
329 "SRLV", LTYPE1, ASRLV,
330 "SRAV", LTYPE1, ASRAV,
331
332 "NOR", LTYPE2, ANOR,
333
334 "MOVB", LTYPE3, AMOVB,
335 "MOVBU", LTYPE3, AMOVBU,
336 "MOVH", LTYPE3, AMOVH,
337 "MOVHU", LTYPE3, AMOVHU,
338 "MOVWL", LTYPE3, AMOVWL,
339 "MOVWR", LTYPE3, AMOVWR,
340 "MOVVL", LTYPE3, AMOVVL,
341 "MOVVR", LTYPE3, AMOVVR,
342
343 "BREAK", LTYPEJ, ABREAK, /* overloaded CACHE opcode */
344 "END", LTYPE4, AEND,
345 "REM", LTYPE6, AREM,
346 "REMU", LTYPE6, AREMU,
347 "RET", LTYPE4, ARET,
348 "SYSCALL", LTYPE4, ASYSCALL,
349 "TLBP", LTYPE4, ATLBP,
350 "TLBR", LTYPE4, ATLBR,
351 "TLBWI", LTYPE4, ATLBWI,
352 "TLBWR", LTYPE4, ATLBWR,
353
354 "MOVW", LTYPE5, AMOVW,
355 "MOVV", LTYPE5, AMOVV,
356 "MOVD", LTYPE5, AMOVD,
357 "MOVF", LTYPE5, AMOVF,
358
359 "DIV", LTYPE6, ADIV,
360 "DIVU", LTYPE6, ADIVU,
361 "MUL", LTYPE6, AMUL,
362 "MULU", LTYPE6, AMULU,
363 "DIVV", LTYPE6, ADIVV,
364 "DIVVU", LTYPE6, ADIVVU,
365 "MULV", LTYPE6, AMULV,
366 "MULVU", LTYPE6, AMULVU,
367
368 "RFE", LTYPE7, ARFE,
369 "JMP", LTYPE7, AJMP,
370
371 "JAL", LTYPE8, AJAL,
372
373 "BEQ", LTYPE9, ABEQ,
374 "BNE", LTYPE9, ABNE,
375
376 "BGEZ", LTYPEA, ABGEZ,
377 "BGEZAL", LTYPEA, ABGEZAL,
378 "BGTZ", LTYPEA, ABGTZ,
379 "BLEZ", LTYPEA, ABLEZ,
380 "BLTZ", LTYPEA, ABLTZ,
381 "BLTZAL", LTYPEA, ABLTZAL,
382
383 "TEXT", LTYPEB, ATEXT,
384 "GLOBL", LTYPEB, AGLOBL,
385
386 "DATA", LTYPEC, ADATA,
387
388 "MOVDF", LTYPE5, AMOVDF,
389 "MOVDW", LTYPE5, AMOVDW,
390 "MOVFD", LTYPE5, AMOVFD,
391 "MOVFW", LTYPE5, AMOVFW,
392 "MOVWD", LTYPE5, AMOVWD,
393 "MOVWF", LTYPE5, AMOVWF,
394
395 "ABSD", LTYPED, AABSD,
396 "ABSF", LTYPED, AABSF,
397 "ABSW", LTYPED, AABSW,
398 "NEGD", LTYPED, ANEGD,
399 "NEGF", LTYPED, ANEGF,
400 "NEGW", LTYPED, ANEGW,
401
402 "CMPEQD", LTYPEF, ACMPEQD,
403 "CMPEQF", LTYPEF, ACMPEQF,
404 "CMPGED", LTYPEF, ACMPGED,
405 "CMPGEF", LTYPEF, ACMPGEF,
406 "CMPGTD", LTYPEF, ACMPGTD,
407 "CMPGTF", LTYPEF, ACMPGTF,
408
409 "ADDD", LTYPEE, AADDD,
410 "ADDF", LTYPEE, AADDF,
411 "ADDW", LTYPEE, AADDW,
412 "DIVD", LTYPEE, ADIVD,
413 "DIVF", LTYPEE, ADIVF,
414 "DIVW", LTYPEE, ADIVW,
415 "MULD", LTYPEE, AMULD,
416 "MULF", LTYPEE, AMULF,
417 "MULW", LTYPEE, AMULW,
418 "SUBD", LTYPEE, ASUBD,
419 "SUBF", LTYPEE, ASUBF,
420 "SUBW", LTYPEE, ASUBW,
421
422 "BFPT", LTYPEG, ABFPT,
423 "BFPF", LTYPEG, ABFPF,
424
425 "WORD", LTYPEH, AWORD,
426 "NOP", LTYPEI, ANOP,
427 "SCHED", LSCHED, 0,
428 "NOSCHED", LSCHED, 0x80,
429 0
430 };
431
432 void
cinit(void)433 cinit(void)
434 {
435 Sym *s;
436 int i;
437
438 nullgen.sym = S;
439 nullgen.offset = 0;
440 nullgen.type = D_NONE;
441 nullgen.name = D_NONE;
442 nullgen.reg = NREG;
443 if(FPCHIP)
444 nullgen.dval = 0;
445 for(i=0; i<sizeof(nullgen.sval); i++)
446 nullgen.sval[i] = 0;
447
448 nerrors = 0;
449 iostack = I;
450 iofree = I;
451 peekc = IGN;
452 nhunk = 0;
453 for(i=0; i<NHASH; i++)
454 hash[i] = S;
455 for(i=0; itab[i].name; i++) {
456 s = slookup(itab[i].name);
457 s->type = itab[i].type;
458 s->value = itab[i].value;
459 }
460
461 pathname = allocn(pathname, 0, 100);
462 if(mygetwd(pathname, 99) == 0) {
463 pathname = allocn(pathname, 100, 900);
464 if(mygetwd(pathname, 999) == 0)
465 strcpy(pathname, "/???");
466 }
467 }
468
469 void
syminit(Sym * s)470 syminit(Sym *s)
471 {
472
473 s->type = LNAME;
474 s->value = 0;
475 }
476
477 int
isreg(Gen * g)478 isreg(Gen *g)
479 {
480
481 USED(g);
482 return 1;
483 }
484
485 void
cclean(void)486 cclean(void)
487 {
488
489 outcode(AEND, &nullgen, NREG, &nullgen);
490 Bflush(&obuf);
491 }
492
493 void
zname(char * n,int t,int s)494 zname(char *n, int t, int s)
495 {
496
497 Bputc(&obuf, ANAME);
498 Bputc(&obuf, t); /* type */
499 Bputc(&obuf, s); /* sym */
500 while(*n) {
501 Bputc(&obuf, *n);
502 n++;
503 }
504 Bputc(&obuf, 0);
505 }
506
507 void
zaddr(Gen * a,int s)508 zaddr(Gen *a, int s)
509 {
510 long l;
511 int i;
512 char *n;
513 Ieee e;
514
515 Bputc(&obuf, a->type);
516 Bputc(&obuf, a->reg);
517 Bputc(&obuf, s);
518 Bputc(&obuf, a->name);
519 switch(a->type) {
520 default:
521 print("unknown type %d\n", a->type);
522 exits("arg");
523
524 case D_NONE:
525 case D_REG:
526 case D_FREG:
527 case D_MREG:
528 case D_FCREG:
529 case D_LO:
530 case D_HI:
531 break;
532
533 case D_OREG:
534 case D_CONST:
535 case D_OCONST:
536 case D_BRANCH:
537 l = a->offset;
538 Bputc(&obuf, l);
539 Bputc(&obuf, l>>8);
540 Bputc(&obuf, l>>16);
541 Bputc(&obuf, l>>24);
542 break;
543
544 case D_SCONST:
545 n = a->sval;
546 for(i=0; i<NSNAME; i++) {
547 Bputc(&obuf, *n);
548 n++;
549 }
550 break;
551
552 case D_FCONST:
553 ieeedtod(&e, a->dval);
554 Bputc(&obuf, e.l);
555 Bputc(&obuf, e.l>>8);
556 Bputc(&obuf, e.l>>16);
557 Bputc(&obuf, e.l>>24);
558 Bputc(&obuf, e.h);
559 Bputc(&obuf, e.h>>8);
560 Bputc(&obuf, e.h>>16);
561 Bputc(&obuf, e.h>>24);
562 break;
563 }
564 }
565
566 void
outcode(int a,Gen * g1,int reg,Gen * g2)567 outcode(int a, Gen *g1, int reg, Gen *g2)
568 {
569 int sf, st, t;
570 Sym *s;
571
572 if(pass == 1)
573 goto out;
574 jackpot:
575 sf = 0;
576 s = g1->sym;
577 while(s != S) {
578 sf = s->sym;
579 if(sf < 0 || sf >= NSYM)
580 sf = 0;
581 t = g1->name;
582 if(h[sf].type == t)
583 if(h[sf].sym == s)
584 break;
585 zname(s->name, t, sym);
586 s->sym = sym;
587 h[sym].sym = s;
588 h[sym].type = t;
589 sf = sym;
590 sym++;
591 if(sym >= NSYM)
592 sym = 1;
593 break;
594 }
595 st = 0;
596 s = g2->sym;
597 while(s != S) {
598 st = s->sym;
599 if(st < 0 || st >= NSYM)
600 st = 0;
601 t = g2->name;
602 if(h[st].type == t)
603 if(h[st].sym == s)
604 break;
605 zname(s->name, t, sym);
606 s->sym = sym;
607 h[sym].sym = s;
608 h[sym].type = t;
609 st = sym;
610 sym++;
611 if(sym >= NSYM)
612 sym = 1;
613 if(st == sf)
614 goto jackpot;
615 break;
616 }
617 Bputc(&obuf, a);
618 Bputc(&obuf, reg|nosched);
619 Bputc(&obuf, lineno);
620 Bputc(&obuf, lineno>>8);
621 Bputc(&obuf, lineno>>16);
622 Bputc(&obuf, lineno>>24);
623 zaddr(g1, sf);
624 zaddr(g2, st);
625
626 out:
627 if(a != AGLOBL && a != ADATA)
628 pc++;
629 }
630
631 void
outhist(void)632 outhist(void)
633 {
634 Gen g;
635 Hist *h;
636 char *p, *q, *op, c;
637 int n;
638
639 g = nullgen;
640 c = pathchar();
641 for(h = hist; h != H; h = h->link) {
642 p = h->name;
643 op = 0;
644 /* on windows skip drive specifier in pathname */
645 if(systemtype(Windows) && p && p[1] == ':'){
646 p += 2;
647 c = *p;
648 }
649 if(p && p[0] != c && h->offset == 0 && pathname){
650 /* on windows skip drive specifier in pathname */
651 if(systemtype(Windows) && pathname[1] == ':') {
652 op = p;
653 p = pathname+2;
654 c = *p;
655 } else if(pathname[0] == c){
656 op = p;
657 p = pathname;
658 }
659 }
660 while(p) {
661 q = strchr(p, c);
662 if(q) {
663 n = q-p;
664 if(n == 0){
665 n = 1; /* leading "/" */
666 *p = '/'; /* don't emit "\" on windows */
667 }
668 q++;
669 } else {
670 n = strlen(p);
671 q = 0;
672 }
673 if(n) {
674 Bputc(&obuf, ANAME);
675 Bputc(&obuf, D_FILE); /* type */
676 Bputc(&obuf, 1); /* sym */
677 Bputc(&obuf, '<');
678 Bwrite(&obuf, p, n);
679 Bputc(&obuf, 0);
680 }
681 p = q;
682 if(p == 0 && op) {
683 p = op;
684 op = 0;
685 }
686 }
687 g.offset = h->offset;
688
689 Bputc(&obuf, AHISTORY);
690 Bputc(&obuf, 0);
691 Bputc(&obuf, h->line);
692 Bputc(&obuf, h->line>>8);
693 Bputc(&obuf, h->line>>16);
694 Bputc(&obuf, h->line>>24);
695 zaddr(&nullgen, 0);
696 zaddr(&g, 0);
697 }
698 }
699
700 #include "../cc/lexbody"
701 #include "../cc/macbody"
702 #include "../cc/compat"
703