plan9fox/sys/src/cmd/va/lex.c
2020-05-12 23:18:48 +02:00

697 lines
12 KiB
C

#define EXTERN
#include "a.h"
#include "y.tab.h"
#include <ctype.h>
void
main(int argc, char *argv[])
{
char *p;
int nout, nproc, status, i, c;
thechar = 'v';
thestring = "mips";
memset(debug, 0, sizeof(debug));
cinit();
outfile = 0;
include[ninclude++] = ".";
ARGBEGIN {
default:
c = ARGC();
if(c >= 0 || c < sizeof(debug))
debug[c] = 1;
break;
case 'o':
outfile = ARGF();
break;
case 'D':
p = ARGF();
if(p)
Dlist[nDlist++] = p;
break;
case 'I':
p = ARGF();
setinclude(p);
break;
case 'L': /* for little-endian mips */
thechar = '0';
thestring = "spim";
break;
} ARGEND
if(*argv == 0) {
print("usage: %Ca [-options] file.s\n", thechar);
errorexit();
}
if(argc > 1 && systemtype(Windows)){
print("can't assemble multiple files on windows\n");
errorexit();
}
if(argc > 1 && !systemtype(Windows)) {
nproc = 1;
if(p = getenv("NPROC"))
nproc = atol(p); /* */
c = 0;
nout = 0;
for(;;) {
while(nout < nproc && argc > 0) {
i = myfork();
if(i < 0) {
i = mywait(&status);
if(i < 0)
errorexit();
if(status)
c++;
nout--;
continue;
}
if(i == 0) {
print("%s:\n", *argv);
if(assemble(*argv))
errorexit();
exits(0);
}
nout++;
argc--;
argv++;
}
i = mywait(&status);
if(i < 0) {
if(c)
errorexit();
exits(0);
}
if(status)
c++;
nout--;
}
}
if(assemble(argv[0]))
errorexit();
exits(0);
}
int
assemble(char *file)
{
char *ofile, *p;
int i, of;
ofile = strdup(file);
p = utfrrune(ofile, pathchar());
if(p) {
include[0] = ofile;
*p++ = 0;
} else
p = ofile;
if(outfile == 0) {
if(p){
outfile = p;
p = utfrrune(outfile, '.');
if(p)
if(p[1] == 's' && p[2] == 0)
p[0] = 0;
outfile = smprint("%s.%C", outfile, thechar);
} else
outfile = "/dev/null";
}
p = getenv("INCLUDE");
if(p) {
setinclude(p);
} else {
if(systemtype(Plan9))
setinclude(smprint("/%s/include", thestring));
}
of = mycreat(outfile, 0664);
if(of < 0) {
yyerror("%Ca: cannot create %s", thechar, outfile);
errorexit();
}
Binit(&obuf, of, OWRITE);
pass = 1;
pinit(file);
for(i=0; i<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
if(nerrors) {
cclean();
return nerrors;
}
pass = 2;
outhist();
pinit(file);
for(i=0; i<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
cclean();
return nerrors;
}
struct
{
char *name;
ushort type;
ushort value;
} itab[] =
{
"SP", LSP, D_AUTO,
"SB", LSB, D_EXTERN,
"FP", LFP, D_PARAM,
"PC", LPC, D_BRANCH,
"HI", LHI, D_HI,
"LO", LLO, D_LO,
"R", LR, 0,
"R0", LREG, 0,
"R1", LREG, 1,
"R2", LREG, 2,
"R3", LREG, 3,
"R4", LREG, 4,
"R5", LREG, 5,
"R6", LREG, 6,
"R7", LREG, 7,
"R8", LREG, 8,
"R9", LREG, 9,
"R10", LREG, 10,
"R11", LREG, 11,
"R12", LREG, 12,
"R13", LREG, 13,
"R14", LREG, 14,
"R15", LREG, 15,
"R16", LREG, 16,
"R17", LREG, 17,
"R18", LREG, 18,
"R19", LREG, 19,
"R20", LREG, 20,
"R21", LREG, 21,
"R22", LREG, 22,
"R23", LREG, 23,
"R24", LREG, 24,
"R25", LREG, 25,
"R26", LREG, 26,
"R27", LREG, 27,
"R28", LREG, 28,
"R29", LREG, 29,
"R30", LREG, 30,
"R31", LREG, 31,
"M", LM, 0,
"M0", LMREG, 0,
"M1", LMREG, 1,
"M2", LMREG, 2,
"M3", LMREG, 3,
"M4", LMREG, 4,
"M5", LMREG, 5,
"M6", LMREG, 6,
"M7", LMREG, 7,
"M8", LMREG, 8,
"M9", LMREG, 9,
"M10", LMREG, 10,
"M11", LMREG, 11,
"M12", LMREG, 12,
"M13", LMREG, 13,
"M14", LMREG, 14,
"M15", LMREG, 15,
"M16", LMREG, 16,
"M17", LMREG, 17,
"M18", LMREG, 18,
"M19", LMREG, 19,
"M20", LMREG, 20,
"M21", LMREG, 21,
"M22", LMREG, 22,
"M23", LMREG, 23,
"M24", LMREG, 24,
"M25", LMREG, 25,
"M26", LMREG, 26,
"M27", LMREG, 27,
"M28", LMREG, 28,
"M29", LMREG, 29,
"M30", LMREG, 30,
"M31", LMREG, 31,
"F", LF, 0,
"F0", LFREG, 0,
"F1", LFREG, 1,
"F2", LFREG, 2,
"F3", LFREG, 3,
"F4", LFREG, 4,
"F5", LFREG, 5,
"F6", LFREG, 6,
"F7", LFREG, 7,
"F8", LFREG, 8,
"F9", LFREG, 9,
"F10", LFREG, 10,
"F11", LFREG, 11,
"F12", LFREG, 12,
"F13", LFREG, 13,
"F14", LFREG, 14,
"F15", LFREG, 15,
"F16", LFREG, 16,
"F17", LFREG, 17,
"F18", LFREG, 18,
"F19", LFREG, 19,
"F20", LFREG, 20,
"F21", LFREG, 21,
"F22", LFREG, 22,
"F23", LFREG, 23,
"F24", LFREG, 24,
"F25", LFREG, 25,
"F26", LFREG, 26,
"F27", LFREG, 27,
"F28", LFREG, 28,
"F29", LFREG, 29,
"F30", LFREG, 30,
"F31", LFREG, 31,
"FCR", LFCR, 0,
"FCR0", LFCREG, 0,
"FCR1", LFCREG, 1,
"FCR2", LFCREG, 2,
"FCR3", LFCREG, 3,
"FCR4", LFCREG, 4,
"FCR5", LFCREG, 5,
"FCR6", LFCREG, 6,
"FCR7", LFCREG, 7,
"FCR8", LFCREG, 8,
"FCR9", LFCREG, 9,
"FCR10", LFCREG, 10,
"FCR11", LFCREG, 11,
"FCR12", LFCREG, 12,
"FCR13", LFCREG, 13,
"FCR14", LFCREG, 14,
"FCR15", LFCREG, 15,
"FCR16", LFCREG, 16,
"FCR17", LFCREG, 17,
"FCR18", LFCREG, 18,
"FCR19", LFCREG, 19,
"FCR20", LFCREG, 20,
"FCR21", LFCREG, 21,
"FCR22", LFCREG, 22,
"FCR23", LFCREG, 23,
"FCR24", LFCREG, 24,
"FCR25", LFCREG, 25,
"FCR26", LFCREG, 26,
"FCR27", LFCREG, 27,
"FCR28", LFCREG, 28,
"FCR29", LFCREG, 29,
"FCR30", LFCREG, 30,
"FCR31", LFCREG, 31,
"ADD", LTYPE1, AADD,
"ADDU", LTYPE1, AADDU,
"SUB", LTYPE1, ASUB, /* converted to ADD(-) in loader */
"SUBU", LTYPE1, ASUBU,
"SGT", LTYPE1, ASGT,
"SGTU", LTYPE1, ASGTU,
"AND", LTYPE1, AAND,
"OR", LTYPE1, AOR,
"XOR", LTYPE1, AXOR,
"SLL", LTYPE1, ASLL,
"SRL", LTYPE1, ASRL,
"SRA", LTYPE1, ASRA,
"ADDV", LTYPE1, AADDV,
"ADDVU", LTYPE1, AADDVU,
"SUBV", LTYPE1, ASUBV, /* converted to ADD(-) in loader */
"SUBVU", LTYPE1, ASUBVU,
"SLLV", LTYPE1, ASLLV,
"SRLV", LTYPE1, ASRLV,
"SRAV", LTYPE1, ASRAV,
"NOR", LTYPE2, ANOR,
"MOVB", LTYPE3, AMOVB,
"MOVBU", LTYPE3, AMOVBU,
"MOVH", LTYPE3, AMOVH,
"MOVHU", LTYPE3, AMOVHU,
"MOVWL", LTYPE3, AMOVWL,
"MOVWR", LTYPE3, AMOVWR,
"MOVVL", LTYPE3, AMOVVL,
"MOVVR", LTYPE3, AMOVVR,
"BREAK", LTYPEJ, ABREAK, /* overloaded CACHE opcode */
"END", LTYPE4, AEND,
"REM", LTYPE6, AREM,
"REMU", LTYPE6, AREMU,
"RET", LTYPE4, ARET,
"SYSCALL", LTYPE4, ASYSCALL,
"TLBP", LTYPE4, ATLBP,
"TLBR", LTYPE4, ATLBR,
"TLBWI", LTYPE4, ATLBWI,
"TLBWR", LTYPE4, ATLBWR,
"MOVW", LTYPE5, AMOVW,
"MOVV", LTYPE5, AMOVV,
"MOVD", LTYPE5, AMOVD,
"MOVF", LTYPE5, AMOVF,
"DIV", LTYPE6, ADIV,
"DIVU", LTYPE6, ADIVU,
"MUL", LTYPE6, AMUL,
"MULU", LTYPE6, AMULU,
"DIVV", LTYPE6, ADIVV,
"DIVVU", LTYPE6, ADIVVU,
"MULV", LTYPE6, AMULV,
"MULVU", LTYPE6, AMULVU,
"RFE", LTYPE7, ARFE,
"JMP", LTYPE7, AJMP,
"JAL", LTYPE8, AJAL,
"BEQ", LTYPE9, ABEQ,
"BNE", LTYPE9, ABNE,
"BGEZ", LTYPEA, ABGEZ,
"BGEZAL", LTYPEA, ABGEZAL,
"BGTZ", LTYPEA, ABGTZ,
"BLEZ", LTYPEA, ABLEZ,
"BLTZ", LTYPEA, ABLTZ,
"BLTZAL", LTYPEA, ABLTZAL,
"TEXT", LTYPEB, ATEXT,
"GLOBL", LTYPEB, AGLOBL,
"DATA", LTYPEC, ADATA,
"MOVDF", LTYPE5, AMOVDF,
"MOVDW", LTYPE5, AMOVDW,
"MOVFD", LTYPE5, AMOVFD,
"MOVFW", LTYPE5, AMOVFW,
"MOVWD", LTYPE5, AMOVWD,
"MOVWF", LTYPE5, AMOVWF,
"ABSD", LTYPED, AABSD,
"ABSF", LTYPED, AABSF,
"ABSW", LTYPED, AABSW,
"NEGD", LTYPED, ANEGD,
"NEGF", LTYPED, ANEGF,
"NEGW", LTYPED, ANEGW,
"CMPEQD", LTYPEF, ACMPEQD,
"CMPEQF", LTYPEF, ACMPEQF,
"CMPGED", LTYPEF, ACMPGED,
"CMPGEF", LTYPEF, ACMPGEF,
"CMPGTD", LTYPEF, ACMPGTD,
"CMPGTF", LTYPEF, ACMPGTF,
"ADDD", LTYPEE, AADDD,
"ADDF", LTYPEE, AADDF,
"ADDW", LTYPEE, AADDW,
"DIVD", LTYPEE, ADIVD,
"DIVF", LTYPEE, ADIVF,
"DIVW", LTYPEE, ADIVW,
"MULD", LTYPEE, AMULD,
"MULF", LTYPEE, AMULF,
"MULW", LTYPEE, AMULW,
"SUBD", LTYPEE, ASUBD,
"SUBF", LTYPEE, ASUBF,
"SUBW", LTYPEE, ASUBW,
"BFPT", LTYPEG, ABFPT,
"BFPF", LTYPEG, ABFPF,
"WORD", LTYPEH, AWORD,
"NOP", LTYPEI, ANOP,
"SCHED", LSCHED, 0,
"NOSCHED", LSCHED, 0x80,
0
};
void
cinit(void)
{
Sym *s;
int i;
nullgen.sym = S;
nullgen.offset = 0;
nullgen.type = D_NONE;
nullgen.name = D_NONE;
nullgen.reg = NREG;
if(FPCHIP)
nullgen.dval = 0;
for(i=0; i<sizeof(nullgen.sval); i++)
nullgen.sval[i] = 0;
nerrors = 0;
iostack = I;
iofree = I;
peekc = IGN;
for(i=0; i<NHASH; i++)
hash[i] = S;
for(i=0; itab[i].name; i++) {
s = slookup(itab[i].name);
s->type = itab[i].type;
s->value = itab[i].value;
}
pathname = allocn(pathname, 0, 100);
if(mygetwd(pathname, 99) == 0) {
pathname = allocn(pathname, 100, 900);
if(mygetwd(pathname, 999) == 0)
strcpy(pathname, "/???");
}
}
void
syminit(Sym *s)
{
s->type = LNAME;
s->value = 0;
}
int
isreg(Gen *g)
{
USED(g);
return 1;
}
void
cclean(void)
{
outcode(AEND, &nullgen, NREG, &nullgen);
Bflush(&obuf);
}
void
zname(char *n, int t, int s)
{
Bputc(&obuf, ANAME);
Bputc(&obuf, t); /* type */
Bputc(&obuf, s); /* sym */
while(*n) {
Bputc(&obuf, *n);
n++;
}
Bputc(&obuf, 0);
}
void
zaddr(Gen *a, int s)
{
long l;
int i;
char *n;
Ieee e;
Bputc(&obuf, a->type);
Bputc(&obuf, a->reg);
Bputc(&obuf, s);
Bputc(&obuf, a->name);
switch(a->type) {
default:
print("unknown type %d\n", a->type);
exits("arg");
case D_NONE:
case D_REG:
case D_FREG:
case D_MREG:
case D_FCREG:
case D_LO:
case D_HI:
break;
case D_OREG:
case D_CONST:
case D_OCONST:
case D_BRANCH:
l = a->offset;
Bputc(&obuf, l);
Bputc(&obuf, l>>8);
Bputc(&obuf, l>>16);
Bputc(&obuf, l>>24);
break;
case D_SCONST:
n = a->sval;
for(i=0; i<NSNAME; i++) {
Bputc(&obuf, *n);
n++;
}
break;
case D_FCONST:
ieeedtod(&e, a->dval);
Bputc(&obuf, e.l);
Bputc(&obuf, e.l>>8);
Bputc(&obuf, e.l>>16);
Bputc(&obuf, e.l>>24);
Bputc(&obuf, e.h);
Bputc(&obuf, e.h>>8);
Bputc(&obuf, e.h>>16);
Bputc(&obuf, e.h>>24);
break;
}
}
void
outcode(int a, Gen *g1, int reg, Gen *g2)
{
int sf, st, t;
Sym *s;
if(pass == 1)
goto out;
jackpot:
sf = 0;
s = g1->sym;
while(s != S) {
sf = s->sym;
if(sf < 0 || sf >= NSYM)
sf = 0;
t = g1->name;
if(h[sf].type == t)
if(h[sf].sym == s)
break;
zname(s->name, t, sym);
s->sym = sym;
h[sym].sym = s;
h[sym].type = t;
sf = sym;
sym++;
if(sym >= NSYM)
sym = 1;
break;
}
st = 0;
s = g2->sym;
while(s != S) {
st = s->sym;
if(st < 0 || st >= NSYM)
st = 0;
t = g2->name;
if(h[st].type == t)
if(h[st].sym == s)
break;
zname(s->name, t, sym);
s->sym = sym;
h[sym].sym = s;
h[sym].type = t;
st = sym;
sym++;
if(sym >= NSYM)
sym = 1;
if(st == sf)
goto jackpot;
break;
}
Bputc(&obuf, a);
Bputc(&obuf, reg|nosched);
Bputc(&obuf, lineno);
Bputc(&obuf, lineno>>8);
Bputc(&obuf, lineno>>16);
Bputc(&obuf, lineno>>24);
zaddr(g1, sf);
zaddr(g2, st);
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
void
outhist(void)
{
Gen g;
Hist *h;
char *p, *q, *op, c;
int n;
g = nullgen;
c = pathchar();
for(h = hist; h != H; h = h->link) {
p = h->name;
op = 0;
/* on windows skip drive specifier in pathname */
if(systemtype(Windows) && p && p[1] == ':'){
p += 2;
c = *p;
}
if(p && p[0] != c && h->offset == 0 && pathname){
/* on windows skip drive specifier in pathname */
if(systemtype(Windows) && pathname[1] == ':') {
op = p;
p = pathname+2;
c = *p;
} else if(pathname[0] == c){
op = p;
p = pathname;
}
}
while(p) {
q = strchr(p, c);
if(q) {
n = q-p;
if(n == 0){
n = 1; /* leading "/" */
*p = '/'; /* don't emit "\" on windows */
}
q++;
} else {
n = strlen(p);
q = 0;
}
if(n) {
Bputc(&obuf, ANAME);
Bputc(&obuf, D_FILE); /* type */
Bputc(&obuf, 1); /* sym */
Bputc(&obuf, '<');
Bwrite(&obuf, p, n);
Bputc(&obuf, 0);
}
p = q;
if(p == 0 && op) {
p = op;
op = 0;
}
}
g.offset = h->offset;
Bputc(&obuf, AHISTORY);
Bputc(&obuf, 0);
Bputc(&obuf, h->line);
Bputc(&obuf, h->line>>8);
Bputc(&obuf, h->line>>16);
Bputc(&obuf, h->line>>24);
zaddr(&nullgen, 0);
zaddr(&g, 0);
}
}
#include "../cc/lexbody"
#include "../cc/macbody"
#include "../cc/compat"