#include <ctype.h>
#define EXTERN
#include "a.h"
#include "y.tab.h"
void
main(int argc, char *argv[])
{
char *p;
int nout, nproc, status, i, c;
thechar = 'k';
thestring = "sparc";
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;
} 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[100], incfile[20], *p;
int i, of;
strcpy(ofile, file);
p = utfrrune(ofile, pathchar());
if(p) {
include[0] = ofile;
*p++ = 0;
} else
p = ofile;
if(outfile == 0) {
outfile = p;
if(outfile){
p = utfrrune(outfile, '.');
if(p)
if(p[1] == 's' && p[2] == 0)
p[0] = 0;
p = utfrune(outfile, 0);
p[0] = '.';
p[1] = thechar;
p[2] = 0;
} else
outfile = "/dev/null";
}
p = getenv("INCLUDE");
if(p) {
setinclude(p);
} else {
if(systemtype(Plan9)) {
sprint(incfile,"/%s/include", thestring);
setinclude(strdup(incfile));
}
}
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,
"FSR", LFSR, D_FSR,
"CSR", LFSR, D_CSR,
"FQ", LFPQ, D_FPQ,
"CQ", LFPQ, D_CPQ,
"Y", LPSR, D_Y,
"PSR", LPSR, D_PSR,
"WIM", LPSR, D_WIM,
"TBR", LPSR, D_TBR,
"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,
"C", LC, 0,
"C0", LCREG, 0,
"C1", LCREG, 1,
"C2", LCREG, 2,
"C3", LCREG, 3,
"C4", LCREG, 4,
"C5", LCREG, 5,
"C6", LCREG, 6,
"C7", LCREG, 7,
"C8", LCREG, 8,
"C9", LCREG, 9,
"C10", LCREG, 10,
"C11", LCREG, 11,
"C12", LCREG, 12,
"C13", LCREG, 13,
"C14", LCREG, 14,
"C15", LCREG, 15,
"C16", LCREG, 16,
"C17", LCREG, 17,
"C18", LCREG, 18,
"C19", LCREG, 19,
"C20", LCREG, 20,
"C21", LCREG, 21,
"C22", LCREG, 22,
"C23", LCREG, 23,
"C24", LCREG, 24,
"C25", LCREG, 25,
"C26", LCREG, 26,
"C27", LCREG, 27,
"C28", LCREG, 28,
"C29", LCREG, 29,
"C30", LCREG, 30,
"C31", LCREG, 31,
"F", LF, 0,
"F0", LFREG, 0,
"F2", LFREG, 2,
"F4", LFREG, 4,
"F6", LFREG, 6,
"F8", LFREG, 8,
"F10", LFREG, 10,
"F12", LFREG, 12,
"F14", LFREG, 14,
"F16", LFREG, 16,
"F18", LFREG, 18,
"F20", LFREG, 20,
"F22", LFREG, 22,
"F24", LFREG, 24,
"F26", LFREG, 26,
"F28", LFREG, 28,
"F30", LFREG, 30,
"F1", LFREG, 1,
"F3", LFREG, 3,
"F5", LFREG, 5,
"F7", LFREG, 7,
"F9", LFREG, 9,
"F11", LFREG, 11,
"F13", LFREG, 13,
"F15", LFREG, 15,
"F17", LFREG, 17,
"F19", LFREG, 19,
"F21", LFREG, 21,
"F23", LFREG, 23,
"F25", LFREG, 25,
"F27", LFREG, 27,
"F29", LFREG, 29,
"F31", LFREG, 31,
"ADD", LADDW, AADD,
"ADDCC", LADDW, AADDCC,
"ADDX", LADDW, AADDX,
"ADDXCC", LADDW, AADDXCC,
"AND", LADDW, AAND,
"ANDCC", LADDW, AANDCC,
"ANDN", LADDW, AANDN,
"ANDNCC", LADDW, AANDNCC,
"BA", LBRA, ABA,
"BCC", LBRA, ABCC,
"BCS", LBRA, ABCS,
"BE", LBRA, ABE,
"BG", LBRA, ABG,
"BGE", LBRA, ABGE,
"BGU", LBRA, ABGU,
"BL", LBRA, ABL,
"BLE", LBRA, ABLE,
"BLEU", LBRA, ABLEU,
"BN", LBRA, ABN,
"BNE", LBRA, ABNE,
"BNEG", LBRA, ABNEG,
"BPOS", LBRA, ABPOS,
"BVC", LBRA, ABVC,
"BVS", LBRA, ABVS,
"CB0", LBRA, ACB0,
"CB01", LBRA, ACB01,
"CB012", LBRA, ACB012,
"CB013", LBRA, ACB013,
"CB02", LBRA, ACB02,
"CB023", LBRA, ACB023,
"CB03", LBRA, ACB03,
"CB1", LBRA, ACB1,
"CB12", LBRA, ACB12,
"CB123", LBRA, ACB123,
"CB13", LBRA, ACB13,
"CB2", LBRA, ACB2,
"CB23", LBRA, ACB23,
"CB3", LBRA, ACB3,
"CBA", LBRA, ACBA,
"CBN", LBRA, ACBN,
"CMP", LCMP, ACMP,
"CPOP1", LCPOP, ACPOP1,
"CPOP2", LCPOP, ACPOP2,
"DATA", LDATA, ADATA,
"DIV", LADDW, ADIV,
"DIVL", LADDW, ADIVL,
"END", LEND, AEND,
"FABSD", LFCONV, AFABSD,
"FABSF", LFCONV, AFABSF,
"FABSX", LFCONV, AFABSX,
"FADDD", LFADD, AFADDD,
"FADDF", LFADD, AFADDF,
"FADDX", LFADD, AFADDX,
"FBA", LBRA, AFBA,
"FBE", LBRA, AFBE,
"FBG", LBRA, AFBG,
"FBGE", LBRA, AFBGE,
"FBL", LBRA, AFBL,
"FBLE", LBRA, AFBLE,
"FBLG", LBRA, AFBLG,
"FBN", LBRA, AFBN,
"FBNE", LBRA, AFBNE,
"FBO", LBRA, AFBO,
"FBU", LBRA, AFBU,
"FBUE", LBRA, AFBUE,
"FBUG", LBRA, AFBUG,
"FBUGE", LBRA, AFBUGE,
"FBUL", LBRA, AFBUL,
"FBULE", LBRA, AFBULE,
"FCMPD", LFADD, AFCMPD,
"FCMPED", LFADD, AFCMPED,
"FCMPEF", LFADD, AFCMPEF,
"FCMPEX", LFADD, AFCMPEX,
"FCMPF", LFADD, AFCMPF,
"FCMPX", LFADD, AFCMPX,
"FDIVD", LFADD, AFDIVD,
"FDIVF", LFADD, AFDIVF,
"FDIVX", LFADD, AFDIVX,
"FMOVD", LFMOV, AFMOVD,
"FMOVDF", LFCONV, AFMOVDF,
"FMOVDW", LFCONV, AFMOVDW,
"FMOVDX", LFCONV, AFMOVDX,
"FMOVF", LFMOV, AFMOVF,
"FMOVFD", LFCONV, AFMOVFD,
"FMOVFW", LFCONV, AFMOVFW,
"FMOVFX", LFCONV, AFMOVFX,
"FMOVWD", LFCONV, AFMOVWD,
"FMOVWF", LFCONV, AFMOVWF,
"FMOVWX", LFCONV, AFMOVWX,
"FMOVX", LFCONV, AFMOVX,
"FMOVXD", LFCONV, AFMOVXD,
"FMOVXF", LFCONV, AFMOVXF,
"FMOVXW", LFCONV, AFMOVXW,
"FMULD", LFADD, AFMULD,
"FMULF", LFADD, AFMULF,
"FMULX", LFADD, AFMULX,
"FNEGD", LFCONV, AFNEGD,
"FNEGF", LFCONV, AFNEGF,
"FNEGX", LFCONV, AFNEGX,
"FSQRTD", LFCONV, AFSQRTD,
"FSQRTF", LFCONV, AFSQRTF,
"FSQRTX", LFCONV, AFSQRTX,
"FSUBD", LFADD, AFSUBD,
"FSUBF", LFADD, AFSUBF,
"FSUBX", LFADD, AFSUBX,
"GLOBL", LTEXT, AGLOBL,
"IFLUSH", LFLUSH, AIFLUSH,
"JMPL", LJMPL, AJMPL,
"JMP", LJMPL, AJMP,
"MOD", LADDW, AMOD,
"MODL", LADDW, AMODL,
"MOVB", LMOVB, AMOVB,
"MOVBU", LMOVB, AMOVBU,
"MOVD", LMOVD, AMOVD,
"MOVH", LMOVB, AMOVH,
"MOVHU", LMOVB, AMOVHU,
"MOVW", LMOVW, AMOVW,
"MUL", LADDW, AMUL,
"MULSCC", LADDW, AMULSCC,
"NOP", LNOP, ANOP,
"OR", LADDW, AOR,
"ORCC", LADDW, AORCC,
"ORN", LADDW, AORN,
"ORNCC", LADDW, AORNCC,
"RESTORE", LADDW, ARESTORE,
"RETT", LRETT, ARETT,
"RETURN", LRETRN, ARETURN,
"SAVE", LADDW, ASAVE,
"SLL", LADDW, ASLL,
"SRA", LADDW, ASRA,
"SRL", LADDW, ASRL,
"SUB", LADDW, ASUB,
"SUBCC", LADDW, ASUBCC,
"SUBX", LADDW, ASUBX,
"SUBXCC", LADDW, ASUBXCC,
"SWAP", LSWAP, ASWAP,
"TA", LTRAP, ATA,
"TADDCC", LADDW, ATADDCC,
"TADDCCTV", LADDW, ATADDCCTV,
"TAS", LSWAP, ATAS,
"TCC", LTRAP, ATCC,
"TCS", LTRAP, ATCS,
"TE", LTRAP, ATE,
"TEXT", LTEXT, ATEXT,
"TG", LTRAP, ATG,
"TGE", LTRAP, ATGE,
"TGU", LTRAP, ATGU,
"TL", LTRAP, ATL,
"TLE", LTRAP, ATLE,
"TLEU", LTRAP, ATLEU,
"TN", LTRAP, ATN,
"TNE", LTRAP, ATNE,
"TNEG", LTRAP, ATNEG,
"TPOS", LTRAP, ATPOS,
"TSUBCC", LADDW, ATSUBCC,
"TSUBCCTV", LADDW, ATSUBCCTV,
"TVC", LTRAP, ATVC,
"TVS", LTRAP, ATVS,
"UNIMP", LUNIMP, AUNIMP,
"WORD", LUNIMP, AWORD,
"XNOR", LADDW, AXNOR,
"XNORCC", LADDW, AXNORCC,
"XOR", LXORW, AXOR,
"XORCC", LADDW, AXORCC,
"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;
nullgen.xreg = 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;
nhunk = 0;
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;
}
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_CREG:
case D_PREG:
break;
case D_OREG:
case D_ASI:
case D_CONST:
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;
if(g1->xreg != NREG) {
if(reg != NREG || g2->xreg != NREG)
yyerror("bad addressing modes");
reg = g1->xreg;
} else
if(g2->xreg != NREG) {
if(reg != NREG)
yyerror("bad addressing modes");
reg = g2->xreg;
}
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"
|