1 #include <ctype.h>
2 #define EXTERN
3 #include "a.h"
4 #include "y.tab.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 = 'i';
13 p = strrchr(argv[0], '/');
14 if(p == nil)
15 p = argv[0];
16 else
17 p++;
18 if(*p == 'j')
19 thechar = 'j';
20 memset(debug, 0, sizeof(debug));
21 cinit();
22 outfile = 0;
23 include[ninclude++] = ".";
24 ARGBEGIN {
25 default:
26 c = ARGC();
27 if(c >= 0 || c < sizeof(debug))
28 debug[c] = 1;
29 break;
30
31 case 'o':
32 outfile = ARGF();
33 break;
34
35 case 'D':
36 p = ARGF();
37 if(p)
38 Dlist[nDlist++] = p;
39 break;
40
41 case 'I':
42 p = ARGF();
43 setinclude(p);
44 break;
45
46 } ARGEND
47 if(*argv == 0) {
48 print("usage: %ca [-options] file.s\n", thechar);
49 errorexit();
50 }
51 if(debug['j'])
52 thechar = 'j';
53 thestring = (thechar == 'j'? "riscv64" : "riscv");
54 if(argc > 1 && systemtype(Windows)){
55 print("can't assemble multiple files on windows\n");
56 errorexit();
57 }
58 if(argc > 1 && !systemtype(Windows)) {
59 nproc = 1;
60 if(p = getenv("NPROC"))
61 nproc = atol(p); /* */
62 c = 0;
63 nout = 0;
64 for(;;) {
65 while(nout < nproc && argc > 0) {
66 i = myfork();
67 if(i < 0) {
68 i = mywait(&status);
69 if(i < 0)
70 errorexit();
71 if(status)
72 c++;
73 nout--;
74 continue;
75 }
76 if(i == 0) {
77 print("%s:\n", *argv);
78 if(assemble(*argv))
79 errorexit();
80 exits(0);
81 }
82 nout++;
83 argc--;
84 argv++;
85 }
86 i = mywait(&status);
87 if(i < 0) {
88 if(c)
89 errorexit();
90 exits(0);
91 }
92 if(status)
93 c++;
94 nout--;
95 }
96 }
97 if(assemble(argv[0]))
98 errorexit();
99 exits(0);
100 }
101
102 int
assemble(char * file)103 assemble(char *file)
104 {
105 char ofile[100], incfile[20], *p;
106 int i, of;
107
108 strcpy(ofile, file);
109 p = utfrrune(ofile, pathchar());
110 if(p) {
111 include[0] = ofile;
112 *p++ = 0;
113 } else
114 p = ofile;
115 if(outfile == 0) {
116 outfile = p;
117 if(outfile){
118 p = utfrrune(outfile, '.');
119 if(p)
120 if(p[1] == 's' && p[2] == 0)
121 p[0] = 0;
122 p = utfrune(outfile, 0);
123 p[0] = '.';
124 p[1] = thechar;
125 p[2] = 0;
126 } else
127 outfile = "/dev/null";
128 }
129 p = getenv("INCLUDE");
130 if(p) {
131 setinclude(p);
132 } else {
133 if(systemtype(Plan9)) {
134 sprint(incfile,"/%s/include", thestring);
135 setinclude(strdup(incfile));
136 }
137 }
138
139 of = mycreat(outfile, 0664);
140 if(of < 0) {
141 yyerror("%ca: cannot create %s", thechar, outfile);
142 errorexit();
143 }
144 Binit(&obuf, of, OWRITE);
145
146 pass = 1;
147 pinit(file);
148 if(thechar == 'j')
149 dodefine("XLEN=8");
150 else
151 dodefine("XLEN=4");
152 for(i=0; i<nDlist; i++)
153 dodefine(Dlist[i]);
154 yyparse();
155 if(nerrors) {
156 cclean();
157 return nerrors;
158 }
159
160 pass = 2;
161 outhist();
162 pinit(file);
163 if(thechar == 'j')
164 dodefine("XLEN=8");
165 else
166 dodefine("XLEN=4");
167 for(i=0; i<nDlist; i++)
168 dodefine(Dlist[i]);
169 yyparse();
170 cclean();
171 return nerrors;
172 }
173
174 struct
175 {
176 char *name;
177 ushort type;
178 ushort value;
179 } itab[] =
180 {
181 "SP", LSP, D_AUTO,
182 "SB", LSB, D_EXTERN,
183 "FP", LFP, D_PARAM,
184 "PC", LPC, D_BRANCH,
185
186 "R", LR, 0,
187 "R0", LREG, 0,
188 "R1", LREG, 1,
189 "R2", LREG, 2,
190 "R3", LREG, 3,
191 "R4", LREG, 4,
192 "R5", LREG, 5,
193 "R6", LREG, 6,
194 "R7", LREG, 7,
195 "R8", LREG, 8,
196 "R9", LREG, 9,
197 "R10", LREG, 10,
198 "R11", LREG, 11,
199 "R12", LREG, 12,
200 "R13", LREG, 13,
201 "R14", LREG, 14,
202 "R15", LREG, 15,
203 "R16", LREG, 16,
204 "R17", LREG, 17,
205 "R18", LREG, 18,
206 "R19", LREG, 19,
207 "R20", LREG, 20,
208 "R21", LREG, 21,
209 "R22", LREG, 22,
210 "R23", LREG, 23,
211 "R24", LREG, 24,
212 "R25", LREG, 25,
213 "R26", LREG, 26,
214 "R27", LREG, 27,
215 "R28", LREG, 28,
216 "R29", LREG, 29,
217 "R30", LREG, 30,
218 "R31", LREG, 31,
219
220 "F", FR, 0,
221 "F0", LFREG, 0,
222 "F1", LFREG, 1,
223 "F2", LFREG, 2,
224 "F3", LFREG, 3,
225 "F4", LFREG, 4,
226 "F5", LFREG, 5,
227 "F6", LFREG, 6,
228 "F7", LFREG, 7,
229 "F8", LFREG, 8,
230 "F9", LFREG, 9,
231 "F10", LFREG, 10,
232 "F11", LFREG, 11,
233 "F12", LFREG, 12,
234 "F13", LFREG, 13,
235 "F14", LFREG, 14,
236 "F15", LFREG, 15,
237 "F16", LFREG, 16,
238 "F17", LFREG, 17,
239 "F18", LFREG, 18,
240 "F19", LFREG, 19,
241 "F20", LFREG, 20,
242 "F21", LFREG, 21,
243 "F22", LFREG, 22,
244 "F23", LFREG, 23,
245 "F24", LFREG, 24,
246 "F25", LFREG, 25,
247 "F26", LFREG, 26,
248 "F27", LFREG, 27,
249 "F28", LFREG, 28,
250 "F29", LFREG, 29,
251 "F30", LFREG, 30,
252 "F31", LFREG, 31,
253
254 "CSR", LCTL, 0,
255
256 "ADD", LADD, AADD,
257 "SLL", LADD, ASLL,
258 "SLT", LADD, ASLT,
259 "SLTU", LADD, ASLTU,
260 "XOR", LADD, AXOR,
261 "SRL", LADD, ASRL,
262 "OR", LADD, AOR,
263 "AND", LADD, AAND,
264 "SRA", LADD, ASRA,
265 "ADDW", LADD, AADDW,
266 "SLLW", LADD, ASLLW,
267 "SRLW", LADD, ASRLW,
268 "SRAW", LADD, ASRAW,
269 "SUB", LADD, ASUB,
270 "SUBW", LADD, ASUBW,
271
272 "MUL", LMUL, AMUL,
273 "MULH", LMUL, AMULH,
274 "MULHSU", LMUL, AMULHSU,
275 "MULHU", LMUL, AMULHU,
276 "DIV", LMUL, ADIV,
277 "DIVU", LMUL, ADIVU,
278 "REM", LMUL, AREM,
279 "REMU", LMUL, AREMU,
280 "MULW", LMUL, AMULW,
281 "DIVW", LMUL, ADIVW,
282 "DIVUW", LMUL, ADIVUW,
283 "REMW", LMUL, AREMW,
284 "REMUW", LMUL, AREMUW,
285
286 "BEQ", LBEQ, ABEQ,
287 "BNE", LBEQ, ABNE,
288 "BLT", LBEQ, ABLT,
289 "BGE", LBEQ, ABGE,
290 "BLTU", LBEQ, ABLTU,
291 "BGEU", LBEQ, ABGEU,
292 "BGT", LBEQ, ABGT,
293 "BGTU", LBEQ, ABGTU,
294 "BLE", LBEQ, ABLE,
295 "BLEU", LBEQ, ABLEU,
296
297 "JMP", LBR, AJMP,
298
299 "RET", LBRET, ARET,
300 "FENCE_I", LBRET, AFENCE_I,
301 "NOP", LBRET, ANOP,
302 "END", LBRET, AEND,
303
304 "JAL", LCALL, AJAL,
305 "JALR", LCALL, AJAL,
306
307 "MOVB", LMOVB, AMOVB,
308 "MOVH", LMOVB, AMOVH,
309
310 "MOVF", LMOVF, AMOVF,
311 "MOVD", LMOVF, AMOVD,
312
313 "MOVBU", LMOVBU, AMOVBU,
314 "MOVHU", LMOVBU, AMOVHU,
315
316 "MOVW", LMOVW, AMOVW,
317
318 "MOVFD", LFLT2, AMOVFD,
319 "MOVDF", LFLT2, AMOVDF,
320 "MOVWF", LFLT2, AMOVWF,
321 "MOVUF", LFLT2, AMOVUF,
322 "MOVFW", LFLT2, AMOVFW,
323 "MOVWD", LFLT2, AMOVWD,
324 "MOVUD", LFLT2, AMOVUD,
325 "MOVDW", LFLT2, AMOVDW,
326 "ADDF", LFLT3, AADDF,
327 "ADDD", LFLT3, AADDD,
328 "SUBF", LFLT3, ASUBF,
329 "SUBD", LFLT3, ASUBD,
330 "MULF", LFLT3, AMULF,
331 "MULD", LFLT3, AMULD,
332 "DIVF", LFLT3, ADIVF,
333 "DIVD", LFLT3, ADIVD,
334 "CMPLTF", LFLT3, ACMPLTF,
335 "CMPLTD", LFLT3, ACMPLTD,
336 "CMPEQF", LFLT3, ACMPEQF,
337 "CMPEQD", LFLT3, ACMPEQD,
338 "CMPLEF", LFLT3, ACMPLEF,
339 "CMPLED", LFLT3, ACMPLED,
340
341 "LUI", LLUI, ALUI,
342
343 "SYS", LSYS, ASYS,
344 "ECALL", LSYS0, 0,
345 "EBREAK", LSYS0, 1,
346 "CSRRW", LCSR, ACSRRW,
347 "CSRRS", LCSR, ACSRRS,
348 "CSRRC", LCSR, ACSRRC,
349
350 "SWAP_W", LSWAP, ASWAP_W,
351 "SWAP_D", LSWAP, ASWAP_D,
352 "LR_W", LSWAP, ALR_W,
353 "LR_D", LSWAP, ALR_D,
354 "SC_W", LSWAP, ASC_W,
355 "SC_D", LSWAP, ASC_D,
356
357 "AMO_W", LAMO, AAMO_W,
358 "AMO_D", LAMO, AAMO_D,
359
360 "DATA", LDATA, ADATA,
361 "GLOBL", LTEXT, AGLOBL,
362 "TEXT", LTEXT, ATEXT,
363 "WORD", LWORD, AWORD,
364 "DWORD", LWORD, ADWORD,
365
366 "MOV", LMOVW, AMOV,
367 "MOVWU", LMOVBU, AMOVWU,
368
369 0
370 };
371
372 void
cinit(void)373 cinit(void)
374 {
375 Sym *s;
376 int i;
377
378 nullgen.sym = S;
379 nullgen.offset = 0;
380 nullgen.type = D_NONE;
381 nullgen.name = D_NONE;
382 nullgen.reg = NREG;
383 if(FPCHIP)
384 nullgen.dval = 0;
385 for(i=0; i<sizeof(nullgen.sval); i++)
386 nullgen.sval[i] = 0;
387
388 nerrors = 0;
389 iostack = I;
390 iofree = I;
391 peekc = IGN;
392 nhunk = 0;
393 for(i=0; i<NHASH; i++)
394 hash[i] = S;
395 for(i=0; itab[i].name; i++) {
396 s = slookup(itab[i].name);
397 s->type = itab[i].type;
398 s->value = itab[i].value;
399 }
400
401 pathname = allocn(pathname, 0, 100);
402 if(mygetwd(pathname, 99) == 0) {
403 pathname = allocn(pathname, 100, 900);
404 if(mygetwd(pathname, 999) == 0)
405 strcpy(pathname, "/???");
406 }
407 }
408
409 void
syminit(Sym * s)410 syminit(Sym *s)
411 {
412
413 s->type = LNAME;
414 s->value = 0;
415 }
416
417 void
cclean(void)418 cclean(void)
419 {
420
421 outcode(AEND, &nullgen, NREG, &nullgen);
422 Bflush(&obuf);
423 }
424
425 void
zname(char * n,int t,int s)426 zname(char *n, int t, int s)
427 {
428
429 Bputc(&obuf, ANAME);
430 Bputc(&obuf, t); /* type */
431 Bputc(&obuf, s); /* sym */
432 while(*n) {
433 Bputc(&obuf, *n);
434 n++;
435 }
436 Bputc(&obuf, 0);
437 }
438
439 void
zaddr(Gen * a,int s)440 zaddr(Gen *a, int s)
441 {
442 vlong v;
443 long l;
444 int i;
445 char *n;
446 Ieee e;
447
448 Bputc(&obuf, a->type);
449 Bputc(&obuf, a->reg);
450 Bputc(&obuf, s);
451 Bputc(&obuf, a->name);
452 switch(a->type) {
453 default:
454 print("unknown type %d\n", a->type);
455 exits("arg");
456
457 case D_NONE:
458 case D_REG:
459 case D_FREG:
460 break;
461
462 case D_CTLREG:
463 case D_OREG:
464 case D_CONST:
465 case D_BRANCH:
466 l = a->offset;
467 Bputc(&obuf, l);
468 Bputc(&obuf, l>>8);
469 Bputc(&obuf, l>>16);
470 Bputc(&obuf, l>>24);
471 break;
472
473 case D_VCONST:
474 v = a->vval;
475 Bputc(&obuf, v);
476 Bputc(&obuf, v>>8);
477 Bputc(&obuf, v>>16);
478 Bputc(&obuf, v>>24);
479 Bputc(&obuf, v>>32);
480 Bputc(&obuf, v>>40);
481 Bputc(&obuf, v>>48);
482 Bputc(&obuf, v>>56);
483 break;
484
485 case D_SCONST:
486 n = a->sval;
487 for(i=0; i<NSNAME; i++) {
488 Bputc(&obuf, *n);
489 n++;
490 }
491 break;
492
493 case D_FCONST:
494 ieeedtod(&e, a->dval);
495 Bputc(&obuf, e.l);
496 Bputc(&obuf, e.l>>8);
497 Bputc(&obuf, e.l>>16);
498 Bputc(&obuf, e.l>>24);
499 Bputc(&obuf, e.h);
500 Bputc(&obuf, e.h>>8);
501 Bputc(&obuf, e.h>>16);
502 Bputc(&obuf, e.h>>24);
503 break;
504 }
505 }
506
507 void
outcode(int a,Gen * g1,int reg,Gen * g2)508 outcode(int a, Gen *g1, int reg, Gen *g2)
509 {
510 int sf, st, t;
511 Sym *s;
512
513 if(pass == 1)
514 goto out;
515 jackpot:
516 sf = 0;
517 s = g1->sym;
518 while(s != S) {
519 sf = s->sym;
520 if(sf < 0 || sf >= NSYM)
521 sf = 0;
522 t = g1->name;
523 if(h[sf].type == t)
524 if(h[sf].sym == s)
525 break;
526 zname(s->name, t, sym);
527 s->sym = sym;
528 h[sym].sym = s;
529 h[sym].type = t;
530 sf = sym;
531 sym++;
532 if(sym >= NSYM)
533 sym = 1;
534 break;
535 }
536 st = 0;
537 s = g2->sym;
538 while(s != S) {
539 st = s->sym;
540 if(st < 0 || st >= NSYM)
541 st = 0;
542 t = g2->name;
543 if(h[st].type == t)
544 if(h[st].sym == s)
545 break;
546 zname(s->name, t, sym);
547 s->sym = sym;
548 h[sym].sym = s;
549 h[sym].type = t;
550 st = sym;
551 sym++;
552 if(sym >= NSYM)
553 sym = 1;
554 if(st == sf)
555 goto jackpot;
556 break;
557 }
558 Bputc(&obuf, a);
559 Bputc(&obuf, reg);
560 Bputc(&obuf, lineno);
561 Bputc(&obuf, lineno>>8);
562 Bputc(&obuf, lineno>>16);
563 Bputc(&obuf, lineno>>24);
564 zaddr(g1, sf);
565 zaddr(g2, st);
566
567 out:
568 if(a != AGLOBL && a != ADATA)
569 pc++;
570 }
571
572 void
outhist(void)573 outhist(void)
574 {
575 Gen g;
576 Hist *h;
577 char *p, *q, *op, c;
578 int n;
579
580 g = nullgen;
581 c = pathchar();
582 for(h = hist; h != H; h = h->link) {
583 p = h->name;
584 op = 0;
585 /* on windows skip drive specifier in pathname */
586 if(systemtype(Windows) && p && p[1] == ':'){
587 p += 2;
588 c = *p;
589 }
590 if(p && p[0] != c && h->offset == 0 && pathname){
591 /* on windows skip drive specifier in pathname */
592 if(systemtype(Windows) && pathname[1] == ':') {
593 op = p;
594 p = pathname+2;
595 c = *p;
596 } else if(pathname[0] == c){
597 op = p;
598 p = pathname;
599 }
600 }
601 while(p) {
602 q = strchr(p, c);
603 if(q) {
604 n = q-p;
605 if(n == 0){
606 n = 1; /* leading "/" */
607 *p = '/'; /* don't emit "\" on windows */
608 }
609 q++;
610 } else {
611 n = strlen(p);
612 q = 0;
613 }
614 if(n) {
615 Bputc(&obuf, ANAME);
616 Bputc(&obuf, D_FILE); /* type */
617 Bputc(&obuf, 1); /* sym */
618 Bputc(&obuf, '<');
619 Bwrite(&obuf, p, n);
620 Bputc(&obuf, 0);
621 }
622 p = q;
623 if(p == 0 && op) {
624 p = op;
625 op = 0;
626 }
627 }
628 g.offset = h->offset;
629
630 Bputc(&obuf, AHISTORY);
631 Bputc(&obuf, 0);
632 Bputc(&obuf, h->line);
633 Bputc(&obuf, h->line>>8);
634 Bputc(&obuf, h->line>>16);
635 Bputc(&obuf, h->line>>24);
636 zaddr(&nullgen, 0);
637 zaddr(&g, 0);
638 }
639 }
640
641 #include "../cc/lexbody"
642 #include "../cc/macbody"
643 #include "../cc/compat"
644