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 = 'k';
13 thestring = "sparc";
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 } ARGEND
40 if(*argv == 0) {
41 print("usage: %ca [-options] file.s\n", thechar);
42 errorexit();
43 }
44 if(argc > 1 && systemtype(Windows)){
45 print("can't assemble multiple files on windows\n");
46 errorexit();
47 }
48 if(argc > 1 && !systemtype(Windows)) {
49 nproc = 1;
50 if(p = getenv("NPROC"))
51 nproc = atol(p); /* */
52 c = 0;
53 nout = 0;
54 for(;;) {
55 while(nout < nproc && argc > 0) {
56 i = myfork();
57 if(i < 0) {
58 i = mywait(&status);
59 if(i < 0)
60 errorexit();
61 if(status)
62 c++;
63 nout--;
64 continue;
65 }
66 if(i == 0) {
67 print("%s:\n", *argv);
68 if(assemble(*argv))
69 errorexit();
70 exits(0);
71 }
72 nout++;
73 argc--;
74 argv++;
75 }
76 i = mywait(&status);
77 if(i < 0) {
78 if(c)
79 errorexit();
80 exits(0);
81 }
82 if(status)
83 c++;
84 nout--;
85 }
86 }
87 if(assemble(argv[0]))
88 errorexit();
89 exits(0);
90 }
91
92 int
assemble(char * file)93 assemble(char *file)
94 {
95 char ofile[100], incfile[20], *p;
96 int i, of;
97
98 strcpy(ofile, file);
99 p = utfrrune(ofile, pathchar());
100 if(p) {
101 include[0] = ofile;
102 *p++ = 0;
103 } else
104 p = ofile;
105 if(outfile == 0) {
106 outfile = p;
107 if(outfile){
108 p = utfrrune(outfile, '.');
109 if(p)
110 if(p[1] == 's' && p[2] == 0)
111 p[0] = 0;
112 p = utfrune(outfile, 0);
113 p[0] = '.';
114 p[1] = thechar;
115 p[2] = 0;
116 } else
117 outfile = "/dev/null";
118 }
119 p = getenv("INCLUDE");
120 if(p) {
121 setinclude(p);
122 } else {
123 if(systemtype(Plan9)) {
124 sprint(incfile,"/%s/include", thestring);
125 setinclude(strdup(incfile));
126 }
127 }
128
129 of = mycreat(outfile, 0664);
130 if(of < 0) {
131 yyerror("%ca: cannot create %s", thechar, outfile);
132 errorexit();
133 }
134 Binit(&obuf, of, OWRITE);
135
136 pass = 1;
137 pinit(file);
138 for(i=0; i<nDlist; i++)
139 dodefine(Dlist[i]);
140 yyparse();
141 if(nerrors) {
142 cclean();
143 return nerrors;
144 }
145
146 pass = 2;
147 outhist();
148 pinit(file);
149 for(i=0; i<nDlist; i++)
150 dodefine(Dlist[i]);
151 yyparse();
152 cclean();
153 return nerrors;
154 }
155
156 struct
157 {
158 char *name;
159 ushort type;
160 ushort value;
161 } itab[] =
162 {
163 "SP", LSP, D_AUTO,
164 "SB", LSB, D_EXTERN,
165 "FP", LFP, D_PARAM,
166 "PC", LPC, D_BRANCH,
167
168 "FSR", LFSR, D_FSR,
169 "CSR", LFSR, D_CSR,
170
171 "FQ", LFPQ, D_FPQ,
172 "CQ", LFPQ, D_CPQ,
173
174 "Y", LPSR, D_Y,
175 "PSR", LPSR, D_PSR,
176 "WIM", LPSR, D_WIM,
177 "TBR", LPSR, D_TBR,
178
179 "R", LR, 0,
180 "R0", LREG, 0,
181 "R1", LREG, 1,
182 "R2", LREG, 2,
183 "R3", LREG, 3,
184 "R4", LREG, 4,
185 "R5", LREG, 5,
186 "R6", LREG, 6,
187 "R7", LREG, 7,
188 "R8", LREG, 8,
189 "R9", LREG, 9,
190 "R10", LREG, 10,
191 "R11", LREG, 11,
192 "R12", LREG, 12,
193 "R13", LREG, 13,
194 "R14", LREG, 14,
195 "R15", LREG, 15,
196 "R16", LREG, 16,
197 "R17", LREG, 17,
198 "R18", LREG, 18,
199 "R19", LREG, 19,
200 "R20", LREG, 20,
201 "R21", LREG, 21,
202 "R22", LREG, 22,
203 "R23", LREG, 23,
204 "R24", LREG, 24,
205 "R25", LREG, 25,
206 "R26", LREG, 26,
207 "R27", LREG, 27,
208 "R28", LREG, 28,
209 "R29", LREG, 29,
210 "R30", LREG, 30,
211 "R31", LREG, 31,
212
213 "C", LC, 0,
214 "C0", LCREG, 0,
215 "C1", LCREG, 1,
216 "C2", LCREG, 2,
217 "C3", LCREG, 3,
218 "C4", LCREG, 4,
219 "C5", LCREG, 5,
220 "C6", LCREG, 6,
221 "C7", LCREG, 7,
222 "C8", LCREG, 8,
223 "C9", LCREG, 9,
224 "C10", LCREG, 10,
225 "C11", LCREG, 11,
226 "C12", LCREG, 12,
227 "C13", LCREG, 13,
228 "C14", LCREG, 14,
229 "C15", LCREG, 15,
230 "C16", LCREG, 16,
231 "C17", LCREG, 17,
232 "C18", LCREG, 18,
233 "C19", LCREG, 19,
234 "C20", LCREG, 20,
235 "C21", LCREG, 21,
236 "C22", LCREG, 22,
237 "C23", LCREG, 23,
238 "C24", LCREG, 24,
239 "C25", LCREG, 25,
240 "C26", LCREG, 26,
241 "C27", LCREG, 27,
242 "C28", LCREG, 28,
243 "C29", LCREG, 29,
244 "C30", LCREG, 30,
245 "C31", LCREG, 31,
246
247 "F", LF, 0,
248 "F0", LFREG, 0,
249 "F2", LFREG, 2,
250 "F4", LFREG, 4,
251 "F6", LFREG, 6,
252 "F8", LFREG, 8,
253 "F10", LFREG, 10,
254 "F12", LFREG, 12,
255 "F14", LFREG, 14,
256 "F16", LFREG, 16,
257 "F18", LFREG, 18,
258 "F20", LFREG, 20,
259 "F22", LFREG, 22,
260 "F24", LFREG, 24,
261 "F26", LFREG, 26,
262 "F28", LFREG, 28,
263 "F30", LFREG, 30,
264 "F1", LFREG, 1,
265 "F3", LFREG, 3,
266 "F5", LFREG, 5,
267 "F7", LFREG, 7,
268 "F9", LFREG, 9,
269 "F11", LFREG, 11,
270 "F13", LFREG, 13,
271 "F15", LFREG, 15,
272 "F17", LFREG, 17,
273 "F19", LFREG, 19,
274 "F21", LFREG, 21,
275 "F23", LFREG, 23,
276 "F25", LFREG, 25,
277 "F27", LFREG, 27,
278 "F29", LFREG, 29,
279 "F31", LFREG, 31,
280
281 "ADD", LADDW, AADD,
282 "ADDCC", LADDW, AADDCC,
283 "ADDX", LADDW, AADDX,
284 "ADDXCC", LADDW, AADDXCC,
285 "AND", LADDW, AAND,
286 "ANDCC", LADDW, AANDCC,
287 "ANDN", LADDW, AANDN,
288 "ANDNCC", LADDW, AANDNCC,
289 "BA", LBRA, ABA,
290 "BCC", LBRA, ABCC,
291 "BCS", LBRA, ABCS,
292 "BE", LBRA, ABE,
293 "BG", LBRA, ABG,
294 "BGE", LBRA, ABGE,
295 "BGU", LBRA, ABGU,
296 "BL", LBRA, ABL,
297 "BLE", LBRA, ABLE,
298 "BLEU", LBRA, ABLEU,
299 "BN", LBRA, ABN,
300 "BNE", LBRA, ABNE,
301 "BNEG", LBRA, ABNEG,
302 "BPOS", LBRA, ABPOS,
303 "BVC", LBRA, ABVC,
304 "BVS", LBRA, ABVS,
305 "CB0", LBRA, ACB0,
306 "CB01", LBRA, ACB01,
307 "CB012", LBRA, ACB012,
308 "CB013", LBRA, ACB013,
309 "CB02", LBRA, ACB02,
310 "CB023", LBRA, ACB023,
311 "CB03", LBRA, ACB03,
312 "CB1", LBRA, ACB1,
313 "CB12", LBRA, ACB12,
314 "CB123", LBRA, ACB123,
315 "CB13", LBRA, ACB13,
316 "CB2", LBRA, ACB2,
317 "CB23", LBRA, ACB23,
318 "CB3", LBRA, ACB3,
319 "CBA", LBRA, ACBA,
320 "CBN", LBRA, ACBN,
321 "CMP", LCMP, ACMP,
322 "CPOP1", LCPOP, ACPOP1,
323 "CPOP2", LCPOP, ACPOP2,
324 "DATA", LDATA, ADATA,
325 "DIV", LADDW, ADIV,
326 "DIVL", LADDW, ADIVL,
327 "END", LEND, AEND,
328 "FABSD", LFCONV, AFABSD,
329 "FABSF", LFCONV, AFABSF,
330 "FABSX", LFCONV, AFABSX,
331 "FADDD", LFADD, AFADDD,
332 "FADDF", LFADD, AFADDF,
333 "FADDX", LFADD, AFADDX,
334 "FBA", LBRA, AFBA,
335 "FBE", LBRA, AFBE,
336 "FBG", LBRA, AFBG,
337 "FBGE", LBRA, AFBGE,
338 "FBL", LBRA, AFBL,
339 "FBLE", LBRA, AFBLE,
340 "FBLG", LBRA, AFBLG,
341 "FBN", LBRA, AFBN,
342 "FBNE", LBRA, AFBNE,
343 "FBO", LBRA, AFBO,
344 "FBU", LBRA, AFBU,
345 "FBUE", LBRA, AFBUE,
346 "FBUG", LBRA, AFBUG,
347 "FBUGE", LBRA, AFBUGE,
348 "FBUL", LBRA, AFBUL,
349 "FBULE", LBRA, AFBULE,
350 "FCMPD", LFADD, AFCMPD,
351 "FCMPED", LFADD, AFCMPED,
352 "FCMPEF", LFADD, AFCMPEF,
353 "FCMPEX", LFADD, AFCMPEX,
354 "FCMPF", LFADD, AFCMPF,
355 "FCMPX", LFADD, AFCMPX,
356 "FDIVD", LFADD, AFDIVD,
357 "FDIVF", LFADD, AFDIVF,
358 "FDIVX", LFADD, AFDIVX,
359 "FMOVD", LFMOV, AFMOVD,
360 "FMOVDF", LFCONV, AFMOVDF,
361 "FMOVDW", LFCONV, AFMOVDW,
362 "FMOVDX", LFCONV, AFMOVDX,
363 "FMOVF", LFMOV, AFMOVF,
364 "FMOVFD", LFCONV, AFMOVFD,
365 "FMOVFW", LFCONV, AFMOVFW,
366 "FMOVFX", LFCONV, AFMOVFX,
367 "FMOVWD", LFCONV, AFMOVWD,
368 "FMOVWF", LFCONV, AFMOVWF,
369 "FMOVWX", LFCONV, AFMOVWX,
370 "FMOVX", LFCONV, AFMOVX,
371 "FMOVXD", LFCONV, AFMOVXD,
372 "FMOVXF", LFCONV, AFMOVXF,
373 "FMOVXW", LFCONV, AFMOVXW,
374 "FMULD", LFADD, AFMULD,
375 "FMULF", LFADD, AFMULF,
376 "FMULX", LFADD, AFMULX,
377 "FNEGD", LFCONV, AFNEGD,
378 "FNEGF", LFCONV, AFNEGF,
379 "FNEGX", LFCONV, AFNEGX,
380 "FSQRTD", LFCONV, AFSQRTD,
381 "FSQRTF", LFCONV, AFSQRTF,
382 "FSQRTX", LFCONV, AFSQRTX,
383 "FSUBD", LFADD, AFSUBD,
384 "FSUBF", LFADD, AFSUBF,
385 "FSUBX", LFADD, AFSUBX,
386 "GLOBL", LTEXT, AGLOBL,
387 "IFLUSH", LFLUSH, AIFLUSH,
388 "JMPL", LJMPL, AJMPL,
389 "JMP", LJMPL, AJMP,
390 "MOD", LADDW, AMOD,
391 "MODL", LADDW, AMODL,
392 "MOVB", LMOVB, AMOVB,
393 "MOVBU", LMOVB, AMOVBU,
394 "MOVD", LMOVD, AMOVD,
395 "MOVH", LMOVB, AMOVH,
396 "MOVHU", LMOVB, AMOVHU,
397 "MOVW", LMOVW, AMOVW,
398 "MUL", LADDW, AMUL,
399 "MULSCC", LADDW, AMULSCC,
400 "NOP", LNOP, ANOP,
401 "OR", LADDW, AOR,
402 "ORCC", LADDW, AORCC,
403 "ORN", LADDW, AORN,
404 "ORNCC", LADDW, AORNCC,
405 "RESTORE", LADDW, ARESTORE,
406 "RETT", LRETT, ARETT,
407 "RETURN", LRETRN, ARETURN,
408 "SAVE", LADDW, ASAVE,
409 "SLL", LADDW, ASLL,
410 "SRA", LADDW, ASRA,
411 "SRL", LADDW, ASRL,
412 "SUB", LADDW, ASUB,
413 "SUBCC", LADDW, ASUBCC,
414 "SUBX", LADDW, ASUBX,
415 "SUBXCC", LADDW, ASUBXCC,
416 "SWAP", LSWAP, ASWAP,
417 "TA", LTRAP, ATA,
418 "TADDCC", LADDW, ATADDCC,
419 "TADDCCTV", LADDW, ATADDCCTV,
420 "TAS", LSWAP, ATAS,
421 "TCC", LTRAP, ATCC,
422 "TCS", LTRAP, ATCS,
423 "TE", LTRAP, ATE,
424 "TEXT", LTEXT, ATEXT,
425 "TG", LTRAP, ATG,
426 "TGE", LTRAP, ATGE,
427 "TGU", LTRAP, ATGU,
428 "TL", LTRAP, ATL,
429 "TLE", LTRAP, ATLE,
430 "TLEU", LTRAP, ATLEU,
431 "TN", LTRAP, ATN,
432 "TNE", LTRAP, ATNE,
433 "TNEG", LTRAP, ATNEG,
434 "TPOS", LTRAP, ATPOS,
435 "TSUBCC", LADDW, ATSUBCC,
436 "TSUBCCTV", LADDW, ATSUBCCTV,
437 "TVC", LTRAP, ATVC,
438 "TVS", LTRAP, ATVS,
439 "UNIMP", LUNIMP, AUNIMP,
440 "WORD", LUNIMP, AWORD,
441 "XNOR", LADDW, AXNOR,
442 "XNORCC", LADDW, AXNORCC,
443 "XOR", LXORW, AXOR,
444 "XORCC", LADDW, AXORCC,
445
446 "SCHED", LSCHED, 0,
447 "NOSCHED", LSCHED, 0x80,
448
449 0
450 };
451
452 void
cinit(void)453 cinit(void)
454 {
455 Sym *s;
456 int i;
457
458 nullgen.sym = S;
459 nullgen.offset = 0;
460 nullgen.type = D_NONE;
461 nullgen.name = D_NONE;
462 nullgen.reg = NREG;
463 nullgen.xreg = NREG;
464 if(FPCHIP)
465 nullgen.dval = 0;
466 for(i=0; i<sizeof(nullgen.sval); i++)
467 nullgen.sval[i] = 0;
468
469 nerrors = 0;
470 iostack = I;
471 iofree = I;
472 peekc = IGN;
473 nhunk = 0;
474 for(i=0; i<NHASH; i++)
475 hash[i] = S;
476 for(i=0; itab[i].name; i++) {
477 s = slookup(itab[i].name);
478 s->type = itab[i].type;
479 s->value = itab[i].value;
480 }
481
482 pathname = allocn(pathname, 0, 100);
483 if(mygetwd(pathname, 99) == 0) {
484 pathname = allocn(pathname, 100, 900);
485 if(mygetwd(pathname, 999) == 0)
486 strcpy(pathname, "/???");
487 }
488 }
489
490 void
syminit(Sym * s)491 syminit(Sym *s)
492 {
493
494 s->type = LNAME;
495 s->value = 0;
496 }
497
498 void
cclean(void)499 cclean(void)
500 {
501
502 outcode(AEND, &nullgen, NREG, &nullgen);
503 Bflush(&obuf);
504 }
505
506 void
zname(char * n,int t,int s)507 zname(char *n, int t, int s)
508 {
509
510 Bputc(&obuf, ANAME);
511 Bputc(&obuf, t); /* type */
512 Bputc(&obuf, s); /* sym */
513 while(*n) {
514 Bputc(&obuf, *n);
515 n++;
516 }
517 Bputc(&obuf, 0);
518 }
519
520 void
zaddr(Gen * a,int s)521 zaddr(Gen *a, int s)
522 {
523 long l;
524 int i;
525 char *n;
526 Ieee e;
527
528 Bputc(&obuf, a->type);
529 Bputc(&obuf, a->reg);
530 Bputc(&obuf, s);
531 Bputc(&obuf, a->name);
532 switch(a->type) {
533 default:
534 print("unknown type %d\n", a->type);
535 exits("arg");
536
537 case D_NONE:
538 case D_REG:
539 case D_FREG:
540 case D_CREG:
541 case D_PREG:
542 break;
543
544 case D_OREG:
545 case D_ASI:
546 case D_CONST:
547 case D_BRANCH:
548 l = a->offset;
549 Bputc(&obuf, l);
550 Bputc(&obuf, l>>8);
551 Bputc(&obuf, l>>16);
552 Bputc(&obuf, l>>24);
553 break;
554
555 case D_SCONST:
556 n = a->sval;
557 for(i=0; i<NSNAME; i++) {
558 Bputc(&obuf, *n);
559 n++;
560 }
561 break;
562
563 case D_FCONST:
564 ieeedtod(&e, a->dval);
565 Bputc(&obuf, e.l);
566 Bputc(&obuf, e.l>>8);
567 Bputc(&obuf, e.l>>16);
568 Bputc(&obuf, e.l>>24);
569 Bputc(&obuf, e.h);
570 Bputc(&obuf, e.h>>8);
571 Bputc(&obuf, e.h>>16);
572 Bputc(&obuf, e.h>>24);
573 break;
574 }
575 }
576
577 void
outcode(int a,Gen * g1,int reg,Gen * g2)578 outcode(int a, Gen *g1, int reg, Gen *g2)
579 {
580 int sf, st, t;
581 Sym *s;
582
583 if(pass == 1)
584 goto out;
585 if(g1->xreg != NREG) {
586 if(reg != NREG || g2->xreg != NREG)
587 yyerror("bad addressing modes");
588 reg = g1->xreg;
589 } else
590 if(g2->xreg != NREG) {
591 if(reg != NREG)
592 yyerror("bad addressing modes");
593 reg = g2->xreg;
594 }
595 jackpot:
596 sf = 0;
597 s = g1->sym;
598 while(s != S) {
599 sf = s->sym;
600 if(sf < 0 || sf >= NSYM)
601 sf = 0;
602 t = g1->name;
603 if(h[sf].type == t)
604 if(h[sf].sym == s)
605 break;
606 zname(s->name, t, sym);
607 s->sym = sym;
608 h[sym].sym = s;
609 h[sym].type = t;
610 sf = sym;
611 sym++;
612 if(sym >= NSYM)
613 sym = 1;
614 break;
615 }
616 st = 0;
617 s = g2->sym;
618 while(s != S) {
619 st = s->sym;
620 if(st < 0 || st >= NSYM)
621 st = 0;
622 t = g2->name;
623 if(h[st].type == t)
624 if(h[st].sym == s)
625 break;
626 zname(s->name, t, sym);
627 s->sym = sym;
628 h[sym].sym = s;
629 h[sym].type = t;
630 st = sym;
631 sym++;
632 if(sym >= NSYM)
633 sym = 1;
634 if(st == sf)
635 goto jackpot;
636 break;
637 }
638 Bputc(&obuf, a);
639 Bputc(&obuf, reg|nosched);
640 Bputc(&obuf, lineno);
641 Bputc(&obuf, lineno>>8);
642 Bputc(&obuf, lineno>>16);
643 Bputc(&obuf, lineno>>24);
644 zaddr(g1, sf);
645 zaddr(g2, st);
646
647 out:
648 if(a != AGLOBL && a != ADATA)
649 pc++;
650 }
651
652 void
outhist(void)653 outhist(void)
654 {
655 Gen g;
656 Hist *h;
657 char *p, *q, *op, c;
658 int n;
659
660 g = nullgen;
661 c = pathchar();
662 for(h = hist; h != H; h = h->link) {
663 p = h->name;
664 op = 0;
665 /* on windows skip drive specifier in pathname */
666 if(systemtype(Windows) && p && p[1] == ':'){
667 p += 2;
668 c = *p;
669 }
670 if(p && p[0] != c && h->offset == 0 && pathname){
671 /* on windows skip drive specifier in pathname */
672 if(systemtype(Windows) && pathname[1] == ':') {
673 op = p;
674 p = pathname+2;
675 c = *p;
676 } else if(pathname[0] == c){
677 op = p;
678 p = pathname;
679 }
680 }
681 while(p) {
682 q = strchr(p, c);
683 if(q) {
684 n = q-p;
685 if(n == 0){
686 n = 1; /* leading "/" */
687 *p = '/'; /* don't emit "\" on windows */
688 }
689 q++;
690 } else {
691 n = strlen(p);
692 q = 0;
693 }
694 if(n) {
695 Bputc(&obuf, ANAME);
696 Bputc(&obuf, D_FILE); /* type */
697 Bputc(&obuf, 1); /* sym */
698 Bputc(&obuf, '<');
699 Bwrite(&obuf, p, n);
700 Bputc(&obuf, 0);
701 }
702 p = q;
703 if(p == 0 && op) {
704 p = op;
705 op = 0;
706 }
707 }
708 g.offset = h->offset;
709
710 Bputc(&obuf, AHISTORY);
711 Bputc(&obuf, 0);
712 Bputc(&obuf, h->line);
713 Bputc(&obuf, h->line>>8);
714 Bputc(&obuf, h->line>>16);
715 Bputc(&obuf, h->line>>24);
716 zaddr(&nullgen, 0);
717 zaddr(&g, 0);
718 }
719 }
720
721 #include "../cc/lexbody"
722 #include "../cc/macbody"
723 #include "../cc/compat"
724