ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/asm/asm.b/
implement Asm;
#line 2 "asm.y"
include "sys.m";
sys: Sys;
include "draw.m";
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "math.m";
math: Math;
export_real: import math;
include "string.m";
str: String;
include "arg.m";
include "../limbo/isa.m";
YYSTYPE: adt {
inst: ref Inst;
addr: ref Addr;
op: int;
ival: big;
fval: real;
str: string;
sym: ref Sym;
listv: ref List;
};
YYLEX: adt {
lval: YYSTYPE;
EOF: con -1;
lex: fn(l: self ref YYLEX): int;
error: fn(l: self ref YYLEX, msg: string);
numsym: fn(l: self ref YYLEX, first: int): int;
eatstring: fn(l: self ref YYLEX);
};
Eof: con -1;
False: con 0;
True: con 1;
Strsize: con 1024;
Hashsize: con 128;
Addr: adt
{
mode: int;
off: int;
val: int;
sym: ref Sym;
text: fn(a: self ref Addr): string;
};
List: adt
{
link: cyclic ref List;
addr: int;
typ: int;
pick{
Int => ival: big; # DEFB, DEFW, DEFL
Bytes => b: array of byte; # DEFF, DEFS
Array => a: ref Array; # DEFA
}
};
Inst: adt
{
op: int;
typ: int;
size: int;
reg: ref Addr;
src: ref Addr;
dst: ref Addr;
pc: int;
sym: ref Sym;
link: cyclic ref Inst;
text: fn(i: self ref Inst): string;
};
Sym: adt
{
name: string;
lexval: int;
value: int;
ds: int;
};
Desc: adt
{
id: int;
size: int;
np: int;
map: array of byte;
link: cyclic ref Desc;
};
Array: adt
{
i: int;
size: int;
};
Link: adt
{
desc: int;
addr: int;
typ: int;
name: string;
link: cyclic ref Link;
};
Keywd: adt
{
name: string;
op: int;
terminal: int;
};
Ldts: adt
{
n: int;
ldt: list of ref Ldt;
};
Ldt: adt
{
sign: int;
name: string;
};
Exc: adt
{
n1, n2, n3, n4, n5, n6: int;
etab: list of ref Etab;
};
Etab: adt
{
n: int;
name: string;
};
Asm: module {
init: fn(nil: ref Draw->Context, nil: list of string);
TOKI0: con 57346;
TOKI1: con 57347;
TOKI2: con 57348;
TOKI3: con 57349;
TCONST: con 57350;
TOKSB: con 57351;
TOKFP: con 57352;
TOKHEAP: con 57353;
TOKDB: con 57354;
TOKDW: con 57355;
TOKDL: con 57356;
TOKDF: con 57357;
TOKDS: con 57358;
TOKVAR: con 57359;
TOKEXT: con 57360;
TOKMOD: con 57361;
TOKLINK: con 57362;
TOKENTRY: con 57363;
TOKARRAY: con 57364;
TOKINDIR: con 57365;
TOKAPOP: con 57366;
TOKLDTS: con 57367;
TOKEXCS: con 57368;
TOKEXC: con 57369;
TOKETAB: con 57370;
TOKSRC: con 57371;
TID: con 57372;
TFCONST: con 57373;
TSTRING: con 57374;
};
YYEOFCODE: con 1;
YYERRCODE: con 2;
YYMAXDEPTH: con 200;
#line 527 "asm.y"
kinit()
{
for(i := 0; keywds[i].name != nil; i++) {
s := enter(keywds[i].name, keywds[i].terminal);
s.value = keywds[i].op;
}
enter("desc", TOKHEAP);
enter("mp", TOKSB);
enter("fp", TOKFP);
enter("byte", TOKDB);
enter("word", TOKDW);
enter("long", TOKDL);
enter("real", TOKDF);
enter("string", TOKDS);
enter("var", TOKVAR);
enter("ext", TOKEXT);
enter("module", TOKMOD);
enter("link", TOKLINK);
enter("entry", TOKENTRY);
enter("array", TOKARRAY);
enter("indir", TOKINDIR);
enter("apop", TOKAPOP);
enter("ldts", TOKLDTS);
enter("exceptions", TOKEXCS);
enter("exception", TOKEXC);
enter("exctab", TOKETAB);
enter("source", TOKSRC);
cmap['0'] = '\0'+1;
cmap['z'] = '\0'+1;
cmap['n'] = '\n'+1;
cmap['r'] = '\r'+1;
cmap['t'] = '\t'+1;
cmap['b'] = '\b'+1;
cmap['f'] = '\f'+1;
cmap['a'] = '\a'+1;
cmap['v'] = '\v'+1;
cmap['\\'] = '\\'+1;
cmap['"'] = '"'+1;
}
Bgetc(b: ref Iobuf): int
{
return b.getb();
}
Bungetc(b: ref Iobuf)
{
b.ungetb();
}
Bgetrune(b: ref Iobuf): int
{
return b.getc();
}
Bputc(b: ref Iobuf, c: int)
{
b.putb(byte c);
}
strchr(s: string, c: int): string
{
for(i := 0; i < len s; i++)
if(s[i] == c)
return s[i:];
return nil;
}
escchar(c: int): int
{
buf := array[32] of byte;
if(c >= '0' && c <= '9') {
n := 1;
buf[0] = byte c;
for(;;) {
c = Bgetc(bin);
if(c == Eof)
fatal(sys->sprint("%d: <eof> in escape sequence", line));
if(strchr("0123456789xX", c) == nil) {
Bungetc(bin);
break;
}
buf[n++] = byte c;
}
return int string buf[0:n];
}
n := cmap[c];
if(n == 0)
return c;
return n-1;
}
strbuf := array[Strsize] of byte;
resizebuf()
{
t := array[len strbuf+Strsize] of byte;
t[0:] = strbuf;
strbuf = t;
}
YYLEX.eatstring(l: self ref YYLEX)
{
esc := 0;
Scan:
for(cnt := 0;;) {
c := Bgetc(bin);
case c {
Eof =>
fatal(sys->sprint("%d: <eof> in string constant", line));
'\n' =>
line++;
diag("newline in string constant");
break Scan;
'\\' =>
if(esc) {
if(cnt >= len strbuf)
resizebuf();
strbuf[cnt++] = byte c;
esc = 0;
break;
}
esc = 1;
'"' =>
if(esc == 0)
break Scan;
c = escchar(c);
esc = 0;
if(cnt >= len strbuf)
resizebuf();
strbuf[cnt++] = byte c;
* =>
if(esc) {
c = escchar(c);
esc = 0;
}
if(cnt >= len strbuf)
resizebuf();
strbuf[cnt++] = byte c;
}
}
l.lval.str = string strbuf[0: cnt];
}
eatnl()
{
line++;
for(;;) {
c := Bgetc(bin);
if(c == Eof)
diag("eof in comment");
if(c == '\n')
return;
}
}
YYLEX.lex(l: self ref YYLEX): int
{
for(;;){
c := Bgetc(bin);
case c {
Eof =>
return Eof;
'"' =>
l.eatstring();
return TSTRING;
' ' or
'\t' or
'\r' =>
continue;
'\n' =>
line++;
'.' =>
c = Bgetc(bin);
Bungetc(bin);
if(isdigit(c))
return l.numsym('.');
return '.';
'#' =>
eatnl();
'(' or
')' or
';' or
',' or
'~' or
'$' or
'+' or
'/' or
'%' or
'^' or
'*' or
'&' or
'=' or
'|' or
'<' or
'>' or
'-' or
':' =>
return c;
'\'' =>
c = Bgetrune(bin);
if(c == '\\')
l.lval.ival = big escchar(Bgetc(bin));
else
l.lval.ival = big c;
c = Bgetc(bin);
if(c != '\'') {
diag("missing '");
Bungetc(bin);
}
return TCONST;
* =>
return l.numsym(c);
}
}
}
isdigit(c: int): int
{
return c >= '0' && c <= '9';
}
isxdigit(c: int): int
{
return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F';
}
isalnum(c: int): int
{
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || isdigit(c);
}
YYLEX.numsym(l: self ref YYLEX, first: int): int
{
Int, Hex, Frac, Expsign, Exp: con iota;
state: int;
symbol[0] = byte first;
p := 0;
if(first == '.')
state = Frac;
else
state = Int;
c: int;
if(isdigit(int symbol[p++]) || state == Frac) {
Collect:
for(;;) {
c = Bgetc(bin);
if(c < 0)
fatal(sys->sprint("%d: <eof> eating numeric", line));
case state {
Int =>
if(isdigit(c))
break;
case c {
'x' or
'X' =>
c = 'x';
state = Hex;
'.' =>
state = Frac;
'e' or
'E' =>
c = 'e';
state = Expsign;
* =>
break Collect;
}
Hex =>
if(!isxdigit(c))
break Collect;
Frac =>
if(isdigit(c))
break;
if(c != 'e' && c != 'E')
break Collect;
c = 'e';
state = Expsign;
Expsign =>
state = Exp;
if(c == '-' || c == '+')
break;
if(!isdigit(c))
break Collect;
Exp =>
if(!isdigit(c))
break Collect;
}
symbol[p++] = byte c;
}
# break Collect
lastsym = string symbol[0:p];
Bungetc(bin);
case state {
Frac or
Expsign or
Exp =>
l.lval.fval = real lastsym;
return TFCONST;
* =>
if(len lastsym >= 3 && lastsym[0:2] == "0x")
(l.lval.ival, nil) = str->tobig(lastsym[2:], 16);
else
(l.lval.ival, nil) = str->tobig(lastsym, 10);
return TCONST;
}
}
for(;;) {
c = Bgetc(bin);
if(c < 0)
fatal(sys->sprint("%d <eof> eating symbols", line));
# '$' and '/' can occur in fully-qualified Java class names
if(c != '_' && c != '.' && c != '/' && c != '$' && !isalnum(c)) {
Bungetc(bin);
break;
}
symbol[p++] = byte c;
}
lastsym = string symbol[0:p];
s := enter(lastsym,TID);
case s.lexval {
TOKI0 or
TOKI1 or
TOKI2 or
TOKI3 =>
l.lval.op = s.value;
* =>
l.lval.sym = s;
}
return s.lexval;
}
hash := array[Hashsize] of list of ref Sym;
enter(name: string, stype: int): ref Sym
{
s := lookup(name);
if(s != nil)
return s;
h := 0;
for(p := 0; p < len name; p++)
h = h*3 + name[p];
if(h < 0)
h = ~h;
h %= Hashsize;
s = ref Sym(name, stype, 0, 0);
hash[h] = s :: hash[h];
return s;
}
lookup(name: string): ref Sym
{
h := 0;
for(p := 0; p < len name; p++)
h = h*3 + name[p];
if(h < 0)
h = ~h;
h %= Hashsize;
for(l := hash[h]; l != nil; l = tl l)
if((s := hd l).name == name)
return s;
return nil;
}
YYLEX.error(l: self ref YYLEX, s: string)
{
if(s == "syntax error") {
l.error(sys->sprint("syntax error, near symbol '%s'", lastsym));
return;
}
sys->print("%s %d: %s\n", file, line, s);
if(nerr++ > 10) {
sys->fprint(sys->fildes(2), "%s:%d: too many errors, giving up\n", file, line);
sys->remove(ofile);
raise "fail: yyerror";
}
}
fatal(s: string)
{
sys->fprint(sys->fildes(2), "asm: %d (fatal compiler problem) %s\n", line, s);
raise "fail:"+s;
}
diag(s: string)
{
srcline := line;
sys->fprint(sys->fildes(2), "%s:%d: %s\n", file, srcline, s);
if(nerr++ > 10) {
sys->fprint(sys->fildes(2), "%s:%d: too many errors, giving up\n", file, line);
sys->remove(ofile);
raise "fail: error";
}
}
zinst: Inst;
ai(op: int): ref Inst
{
i := ref zinst;
i.op = op;
return i;
}
aa(val: big): ref Addr
{
if(val <= big -1073741824 && val > big 1073741823)
diag("offset out of range");
return ref Addr(0, 0, int val, nil);
}
isoff2big(o: int): int
{
return o < 0 || o > 16rFFFF;
}
inldt := 0;
nldts := 0;
aldts: list of ref Ldts;
curl: ref Ldts;
nexcs := 0;
aexcs: list of ref Exc;
cure: ref Exc;
srcpath: string;
bin: ref Iobuf;
bout: ref Iobuf;
line := 0;
heapid := 0;
symbol := array[1024] of byte;
lastsym: string;
nerr := 0;
cmap := array[256] of int;
file: string;
dlist: ref Desc;
dcout := 0;
dseg := 0;
dcount := 0;
mdata: ref List;
amodule: ref Sym;
links: ref Link;
linkt: ref Link;
nlink := 0;
listing := 0;
mustcompile := 0;
dontcompile := 0;
ofile: string;
dentry := 0;
pcentry := 0;
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
math = load Math Math->PATH;
bufio = load Bufio Bufio->PATH;
str = load String String->PATH;
arg := load Arg Arg->PATH;
arg->setusage("asm [-l] file.s");
arg->init(args);
while((c := arg->opt()) != 0){
case c {
'C' => dontcompile++;
'c' => mustcompile++;
'l' => listing++;
* => arg->usage();
}
}
args = arg->argv();
if(len args != 1)
arg->usage();
arg = nil;
kinit();
pcentry = -1;
dentry = -1;
file = hd args;
bin = bufio->open(file, Bufio->OREAD);
if(bin == nil) {
sys->fprint(sys->fildes(2), "asm: can't open %s: %r\n", file);
raise "fail: errors";
}
p := strrchr(file, '/');
if(p == nil)
p = file;
else
p = p[1:];
ofile = mkfile(p, ".s", ".dis");
bout = bufio->create(ofile, Bufio->OWRITE, 8r666);
if(bout == nil){
sys->fprint(sys->fildes(2), "asm: can't create: %s: %r\n", ofile);
raise "fail: errors";
}
line = 1;
yyparse(ref YYLEX);
bout.close();
if(nerr != 0){
sys->remove(ofile);
raise "fail: errors";
}
}
strrchr(s: string, c: int): string
{
for(i := len s; --i >= 0;)
if(s[i] == c)
return s[i:];
return nil;
}
mkfile(file: string, oldext: string, ext: string): string
{
n := len file;
n2 := len oldext;
if(n >= n2 && file[n-n2:] == oldext)
n -= n2;
return file[0:n] + ext;
}
opcode(i: ref Inst): int
{
if(i.op < 0 || i.op >= len keywds)
fatal(sys->sprint("internal error: invalid op %d (%#x)", i.op, i.op));
return keywds[i.op].op;
}
Inst.text(i: self ref Inst): string
{
if(i == nil)
return "IZ";
case keywds[i.op].terminal {
TOKI0 =>
return sys->sprint("%s", keywds[i.op].name);
TOKI1 =>
return sys->sprint("%s\t%s", keywds[i.op].name, i.dst.text());
TOKI3 =>
if(i.reg != nil) {
pre := "";
post := "";
case i.reg.mode {
AXIMM =>
pre = "$";
break;
AXINF =>
post = "(fp)";
break;
AXINM =>
post = "(mp)";
break;
}
return sys->sprint("%s\t%s, %s%d%s, %s", keywds[i.op].name, i.src.text(), pre, i.reg.val, post, i.dst.text());
}
return sys->sprint("%s\t%s, %s", keywds[i.op].name, i.src.text(), i.dst.text());
TOKI2 =>
return sys->sprint("%s\t%s, %s", keywds[i.op].name, i.src.text(), i.dst.text());
* =>
return "IGOK";
}
}
Addr.text(a: self ref Addr): string
{
if(a == nil)
return "AZ";
if(a.mode & AIND) {
case a.mode & ~AIND {
AFP =>
return sys->sprint("%d(%d(fp))", a.val, a.off);
AMP =>
return sys->sprint("%d(%d(mp))", a.val, a.off);
}
}
else {
case a.mode {
AFP =>
return sys->sprint("%d(fp)", a.val);
AMP =>
return sys->sprint("%d(mp)", a.val);
AIMM =>
return sys->sprint("$%d", a.val);
}
}
return "AGOK";
}
append[T](l: list of T, v: T): list of T
{
if(l == nil)
return v :: nil;
return hd l :: append(tl l, v);
}
newa(i: int, size: int): ref List
{
a := ref Array(i, size);
l := ref List.Array(nil, -1, 0, a);
return l;
}
# does order matter?
newi(v: big, l: ref List): ref List
{
n := ref List.Int(nil, -1, 0, v);
if(l == nil)
return n;
for(t := l; t.link != nil; t = t.link)
;
t.link = n;
return l;
}
news(s: string, l: ref List): ref List
{
return ref List.Bytes(l, -1, 0, array of byte s);
}
newb(a: array of byte, l: ref List): ref List
{
return ref List.Bytes(l, -1, 0, a);
}
digit(x: int): int
{
if(x >= 'A' && x <= 'F')
return x - 'A' + 10;
if(x >= 'a' && x <= 'f')
return x - 'a' + 10;
if(x >= '0' && x <= '9')
return x - '0';
diag("bad hex value in pointers");
return 0;
}
heap(id: int, size: int, ptr: string)
{
d := ref Desc;
d.id = id;
d.size = size;
size /= IBY2WD;
d.map = array[size] of {* => byte 0};
d.np = 0;
if(dlist == nil)
dlist = d;
else {
f: ref Desc;
for(f = dlist; f.link != nil; f = f.link)
;
f.link = d;
}
d.link = nil;
dcount++;
if(ptr == nil)
return;
if(len ptr & 1) {
diag("pointer descriptor has odd length");
return;
}
k := 0;
l := len ptr;
for(i := 0; i < l; i += 2) {
d.map[k++] = byte ((digit(ptr[i])<<4)|digit(ptr[i+1]));
if(k > size) {
diag("pointer descriptor too long");
break;
}
}
d.np = k;
}
conout(val: int)
{
if(val >= -64 && val <= 63) {
Bputc(bout, val & ~16r80);
return;
}
if(val >= -8192 && val <= 8191) {
Bputc(bout, ((val>>8) & ~16rC0) | 16r80);
Bputc(bout, val);
return;
}
if(val < 0 && ((val >> 29) & 7) != 7
|| val > 0 && (val >> 29) != 0)
diag(sys->sprint("overflow in constant 0x%ux\n", val));
Bputc(bout, (val>>24) | 16rC0);
Bputc(bout, val>>16);
Bputc(bout, val>>8);
Bputc(bout, val);
}
aout(a: ref Addr)
{
if(a == nil)
return;
if(a.mode & AIND)
conout(a.off);
conout(a.val);
}
Bputs(b: ref Iobuf, s: string)
{
for(i := 0; i < len s; i++)
Bputc(b, s[i]);
Bputc(b, '\0');
}
lout()
{
if(amodule == nil)
amodule = enter("main", 0);
Bputs(bout, amodule.name);
for(l := links; l != nil; l = l.link) {
conout(l.addr);
conout(l.desc);
Bputc(bout, l.typ>>24);
Bputc(bout, l.typ>>16);
Bputc(bout, l.typ>>8);
Bputc(bout, l.typ);
Bputs(bout, l.name);
}
}
ldtout()
{
conout(nldts);
for(la := aldts; la != nil; la = tl la){
ls := hd la;
conout(ls.n);
for(l := ls.ldt; l != nil; l = tl l){
t := hd l;
Bputc(bout, t.sign>>24);
Bputc(bout, t.sign>>16);
Bputc(bout, t.sign>>8);
Bputc(bout, t.sign);
Bputs(bout, t.name);
}
}
conout(0);
}
excout()
{
if(nexcs == 0)
return;
conout(nexcs);
for(es := aexcs; es != nil; es = tl es){
e := hd es;
conout(e.n3);
conout(e.n1);
conout(e.n2);
conout(e.n4);
conout(e.n5|(e.n6<<16));
for(ets := e.etab; ets != nil; ets = tl ets){
et := hd ets;
if(et.name != nil)
Bputs(bout, et.name);
conout(et.n);
}
}
conout(0);
}
srcout()
{
if(srcpath == nil)
return;
Bputs(bout, srcpath);
}
assem(i: ref Inst)
{
f: ref Inst;
while(i != nil){
link := i.link;
i.link = f;
f = i;
i = link;
}
i = f;
pc := 0;
for(f = i; f != nil; f = f.link) {
f.pc = pc++;
if(f.sym != nil)
f.sym.value = f.pc;
}
if(pcentry >= pc)
diag("entry pc out of range");
if(dentry >= dcount)
diag("entry descriptor out of range");
conout(XMAGIC);
hints := 0;
if(mustcompile)
hints |= MUSTCOMPILE;
if(dontcompile)
hints |= DONTCOMPILE;
hints |= HASLDT;
if(nexcs > 0)
hints |= HASEXCEPT;
conout(hints); # Runtime flags
conout(1024); # default stack size
conout(pc);
conout(dseg);
conout(dcount);
conout(nlink);
conout(pcentry);
conout(dentry);
for(f = i; f != nil; f = f.link) {
if(f.dst != nil && f.dst.sym != nil) {
f.dst.mode = AIMM;
f.dst.val = f.dst.sym.value;
}
o := opcode(f);
if(o == IRAISE){
f.src = f.dst;
f.dst = nil;
}
Bputc(bout, o);
n := 0;
if(f.src != nil)
n |= src(f.src.mode);
else
n |= src(AXXX);
if(f.dst != nil)
n |= dst(f.dst.mode);
else
n |= dst(AXXX);
if(f.reg != nil)
n |= f.reg.mode;
else
n |= AXNON;
Bputc(bout, n);
aout(f.reg);
aout(f.src);
aout(f.dst);
if(listing)
sys->print("%4d %s\n", f.pc, f.text());
}
for(d := dlist; d != nil; d = d.link) {
conout(d.id);
conout(d.size);
conout(d.np);
for(n := 0; n < d.np; n++)
Bputc(bout, int d.map[n]);
}
dout();
lout();
ldtout();
excout();
srcout();
}
data(typ: int, addr: big, l: ref List)
{
if(inldt){
ldtw(int intof(l));
return;
}
l.typ = typ;
l.addr = int addr;
if(mdata == nil)
mdata = l;
else {
for(f := mdata; f.link != nil; f = f.link)
;
f.link = l;
}
}
ext(addr: int, typ: int, s: string)
{
if(inldt){
ldte(typ, s);
return;
}
data(DEFW, big addr, newi(big typ, nil));
n: ref List;
for(i := 0; i < len s; i++)
n = newi(big s[i], n);
data(DEFB, big(addr+IBY2WD), n);
if(addr+len s > dseg)
diag("ext beyond mp");
}
mklink(desc: int, addr: int, typ: int, s: string)
{
for(ls := links; ls != nil; ls = ls.link)
if(ls.name == s)
diag(sys->sprint("%s already defined", s));
nlink++;
l := ref Link;
l.desc = desc;
l.addr = addr;
l.typ = typ;
l.name = s;
l.link = nil;
if(links == nil)
links = l;
else
linkt.link = l;
linkt = l;
}
intof(l: ref List): big
{
pick rl := l {
Int =>
return rl.ival;
* =>
raise "list botch";
}
}
arrayof(l: ref List): ref Array
{
pick rl := l {
Array =>
return rl.a;
* =>
raise "list botch";
}
}
bytesof(l: ref List): array of byte
{
pick rl := l {
Bytes =>
return rl.b;
* =>
raise "list botch";
}
}
nel(l: ref List): (int, ref List)
{
n := 1;
for(e := l.link; e != nil && e.addr == -1; e = e.link)
n++;
return (n, e);
}
dout()
{
e: ref List;
n: int;
for(l := mdata; l != nil; l = e) {
case l.typ {
DEFB =>
(n, e) = nel(l);
if(n < DMAX)
Bputc(bout, dbyte(DEFB, n));
else {
Bputc(bout, dbyte(DEFB, 0));
conout(n);
}
conout(l.addr);
while(l != e) {
Bputc(bout, int intof(l));
l = l.link;
}
break;
DEFW =>
(n, e) = nel(l);
if(n < DMAX)
Bputc(bout, dbyte(DEFW, n));
else {
Bputc(bout, dbyte(DEFW, 0));
conout(n);
}
conout(l.addr);
while(l != e) {
n = int intof(l);
Bputc(bout, n>>24);
Bputc(bout, n>>16);
Bputc(bout, n>>8);
Bputc(bout, n);
l = l.link;
}
break;
DEFL =>
(n, e) = nel(l);
if(n < DMAX)
Bputc(bout, dbyte(DEFL, n));
else {
Bputc(bout, dbyte(DEFL, 0));
conout(n);
}
conout(l.addr);
while(l != e) {
b := intof(l);
Bputc(bout, int (b>>56));
Bputc(bout, int (b>>48));
Bputc(bout, int (b>>40));
Bputc(bout, int (b>>32));
Bputc(bout, int (b>>24));
Bputc(bout, int (b>>16));
Bputc(bout, int (b>>8));
Bputc(bout, int b);
l = l.link;
}
break;
DEFF =>
(n, e) = nel(l);
if(n < DMAX)
Bputc(bout, dbyte(DEFF, n));
else {
Bputc(bout, dbyte(DEFF, 0));
conout(n);
}
conout(l.addr);
while(l != e) {
b := bytesof(l);
Bputc(bout, int b[0]);
Bputc(bout, int b[1]);
Bputc(bout, int b[2]);
Bputc(bout, int b[3]);
Bputc(bout, int b[4]);
Bputc(bout, int b[5]);
Bputc(bout, int b[6]);
Bputc(bout, int b[7]);
l = l.link;
}
break;
DEFS =>
a := bytesof(l);
n = len a;
if(n < DMAX && n != 0)
Bputc(bout, dbyte(DEFS, n));
else {
Bputc(bout, dbyte(DEFS, 0));
conout(n);
}
conout(l.addr);
for(i := 0; i < n; i++)
Bputc(bout, int a[i]);
e = l.link;
break;
DEFA =>
Bputc(bout, dbyte(DEFA, 1));
conout(l.addr);
ar := arrayof(l);
Bputc(bout, ar.i>>24);
Bputc(bout, ar.i>>16);
Bputc(bout, ar.i>>8);
Bputc(bout, ar.i);
Bputc(bout, ar.size>>24);
Bputc(bout, ar.size>>16);
Bputc(bout, ar.size>>8);
Bputc(bout, ar.size);
e = l.link;
break;
DIND =>
Bputc(bout, dbyte(DIND, 1));
conout(l.addr);
Bputc(bout, 0);
Bputc(bout, 0);
Bputc(bout, 0);
Bputc(bout, 0);
e = l.link;
break;
DAPOP =>
Bputc(bout, dbyte(DAPOP, 1));
conout(0);
e = l.link;
break;
}
}
Bputc(bout, dbyte(DEFZ, 0));
}
ldts(n: int)
{
nldts = n;
inldt = 1;
}
ldtw(n: int)
{
ls := ref Ldts(n, nil);
aldts = append(aldts, ls);
curl = ls;
}
ldte(n: int, s: string)
{
l := ref Ldt(n, s);
curl.ldt = append(curl.ldt, l);
}
excs(n: int)
{
nexcs = n;
}
exc(n1: int, n2: int, n3: int, n4: int, n5: int, n6: int)
{
e := ref Exc;
e.n1 = n1;
e.n2 = n2;
e.n3 = n3;
e.n4 = n4;
e.n5 = n5;
e.n6 = n6;
e.etab = nil;
aexcs = append(aexcs, e);
cure = e;
}
etab(s: string, n: int)
{
et := ref Etab;
et.n = n;
et.name = s;
cure.etab = append(cure.etab, et);
}
source(s: string)
{
srcpath = s;
}
dtype(x: int): int
{
return (x>>4)&16rF;
}
dbyte(x: int, l: int): int
{
return (x<<4) | l;
}
dlen(x: int): int
{
return x & (DMAX-1);
}
src(x: int): int
{
return x<<3;
}
dst(x: int): int
{
return x<<0;
}
dtocanon(d: real): array of byte
{
b := array[8] of byte;
export_real(b, array[] of {d});
return b;
}
keywds: array of Keywd = array[] of
{
("nop", INOP, TOKI0),
("alt", IALT, TOKI3),
("nbalt", INBALT, TOKI3),
("goto", IGOTO, TOKI2),
("call", ICALL, TOKI2),
("frame", IFRAME, TOKI2),
("spawn", ISPAWN, TOKI2),
("runt", IRUNT, TOKI2),
("load", ILOAD, TOKI3),
("mcall", IMCALL, TOKI3),
("mspawn", IMSPAWN, TOKI3),
("mframe", IMFRAME, TOKI3),
("ret", IRET, TOKI0),
("jmp", IJMP, TOKI1),
("case", ICASE, TOKI2),
("exit", IEXIT, TOKI0),
("new", INEW, TOKI2),
("newa", INEWA, TOKI3),
("newcb", INEWCB, TOKI1),
("newcw", INEWCW, TOKI1),
("newcf", INEWCF, TOKI1),
("newcp", INEWCP, TOKI1),
("newcm", INEWCM, TOKI2),
("newcmp", INEWCMP, TOKI2),
("send", ISEND, TOKI2),
("recv", IRECV, TOKI2),
("consb", ICONSB, TOKI2),
("consw", ICONSW, TOKI2),
("consp", ICONSP, TOKI2),
("consf", ICONSF, TOKI2),
("consm", ICONSM, TOKI3),
("consmp", ICONSMP, TOKI3),
("headb", IHEADB, TOKI2),
("headw", IHEADW, TOKI2),
("headp", IHEADP, TOKI2),
("headf", IHEADF, TOKI2),
("headm", IHEADM, TOKI3),
("headmp", IHEADMP, TOKI3),
("tail", ITAIL, TOKI2),
("lea", ILEA, TOKI2),
("indx", IINDX, TOKI3),
("movp", IMOVP, TOKI2),
("movm", IMOVM, TOKI3),
("movmp", IMOVMP, TOKI3),
("movb", IMOVB, TOKI2),
("movw", IMOVW, TOKI2),
("movf", IMOVF, TOKI2),
("cvtbw", ICVTBW, TOKI2),
("cvtwb", ICVTWB, TOKI2),
("cvtfw", ICVTFW, TOKI2),
("cvtwf", ICVTWF, TOKI2),
("cvtca", ICVTCA, TOKI2),
("cvtac", ICVTAC, TOKI2),
("cvtwc", ICVTWC, TOKI2),
("cvtcw", ICVTCW, TOKI2),
("cvtfc", ICVTFC, TOKI2),
("cvtcf", ICVTCF, TOKI2),
("addb", IADDB, TOKI3),
("addw", IADDW, TOKI3),
("addf", IADDF, TOKI3),
("subb", ISUBB, TOKI3),
("subw", ISUBW, TOKI3),
("subf", ISUBF, TOKI3),
("mulb", IMULB, TOKI3),
("mulw", IMULW, TOKI3),
("mulf", IMULF, TOKI3),
("divb", IDIVB, TOKI3),
("divw", IDIVW, TOKI3),
("divf", IDIVF, TOKI3),
("modw", IMODW, TOKI3),
("modb", IMODB, TOKI3),
("andb", IANDB, TOKI3),
("andw", IANDW, TOKI3),
("orb", IORB, TOKI3),
("orw", IORW, TOKI3),
("xorb", IXORB, TOKI3),
("xorw", IXORW, TOKI3),
("shlb", ISHLB, TOKI3),
("shlw", ISHLW, TOKI3),
("shrb", ISHRB, TOKI3),
("shrw", ISHRW, TOKI3),
("insc", IINSC, TOKI3),
("indc", IINDC, TOKI3),
("addc", IADDC, TOKI3),
("lenc", ILENC, TOKI2),
("lena", ILENA, TOKI2),
("lenl", ILENL, TOKI2),
("beqb", IBEQB, TOKI3),
("bneb", IBNEB, TOKI3),
("bltb", IBLTB, TOKI3),
("bleb", IBLEB, TOKI3),
("bgtb", IBGTB, TOKI3),
("bgeb", IBGEB, TOKI3),
("beqw", IBEQW, TOKI3),
("bnew", IBNEW, TOKI3),
("bltw", IBLTW, TOKI3),
("blew", IBLEW, TOKI3),
("bgtw", IBGTW, TOKI3),
("bgew", IBGEW, TOKI3),
("beqf", IBEQF, TOKI3),
("bnef", IBNEF, TOKI3),
("bltf", IBLTF, TOKI3),
("blef", IBLEF, TOKI3),
("bgtf", IBGTF, TOKI3),
("bgef", IBGEF, TOKI3),
("beqc", IBEQC, TOKI3),
("bnec", IBNEC, TOKI3),
("bltc", IBLTC, TOKI3),
("blec", IBLEC, TOKI3),
("bgtc", IBGTC, TOKI3),
("bgec", IBGEC, TOKI3),
("slicea", ISLICEA, TOKI3),
("slicela", ISLICELA, TOKI3),
("slicec", ISLICEC, TOKI3),
("indw", IINDW, TOKI3),
("indf", IINDF, TOKI3),
("indb", IINDB, TOKI3),
("negf", INEGF, TOKI2),
("movl", IMOVL, TOKI2),
("addl", IADDL, TOKI3),
("subl", ISUBL, TOKI3),
("divl", IDIVL, TOKI3),
("modl", IMODL, TOKI3),
("mull", IMULL, TOKI3),
("andl", IANDL, TOKI3),
("orl", IORL, TOKI3),
("xorl", IXORL, TOKI3),
("shll", ISHLL, TOKI3),
("shrl", ISHRL, TOKI3),
("bnel", IBNEL, TOKI3),
("bltl", IBLTL, TOKI3),
("blel", IBLEL, TOKI3),
("bgtl", IBGTL, TOKI3),
("bgel", IBGEL, TOKI3),
("beql", IBEQL, TOKI3),
("cvtlf", ICVTLF, TOKI2),
("cvtfl", ICVTFL, TOKI2),
("cvtlw", ICVTLW, TOKI2),
("cvtwl", ICVTWL, TOKI2),
("cvtlc", ICVTLC, TOKI2),
("cvtcl", ICVTCL, TOKI2),
("headl", IHEADL, TOKI2),
("consl", ICONSL, TOKI2),
("newcl", INEWCL, TOKI1),
("casec", ICASEC, TOKI2),
("indl", IINDL, TOKI3),
("movpc", IMOVPC, TOKI2),
("tcmp", ITCMP, TOKI2),
("mnewz", IMNEWZ, TOKI3),
("cvtrf", ICVTRF, TOKI2),
("cvtfr", ICVTFR, TOKI2),
("cvtws", ICVTWS, TOKI2),
("cvtsw", ICVTSW, TOKI2),
("lsrw", ILSRW, TOKI3),
("lsrl", ILSRL, TOKI3),
("eclr", IECLR, TOKI0),
("newz", INEWZ, TOKI2),
("newaz", INEWAZ, TOKI3),
("raise", IRAISE, TOKI1),
("casel", ICASEL, TOKI2),
("mulx", IMULX, TOKI3),
("divx", IDIVX, TOKI3),
("cvtxx", ICVTXX, TOKI3),
("mulx0", IMULX0, TOKI3),
("divx0", IDIVX0, TOKI3),
("cvtxx0", ICVTXX0, TOKI3),
("mulx1", IMULX1, TOKI3),
("divx1", IDIVX1, TOKI3),
("cvtxx1", ICVTXX1, TOKI3),
("cvtfx", ICVTFX, TOKI3),
("cvtxf", ICVTXF, TOKI3),
("expw", IEXPW, TOKI3),
("expl", IEXPL, TOKI3),
("expf", IEXPF, TOKI3),
("self", ISELF, TOKI1),
(nil, 0, 0),
};
yyexca := array[] of {-1, 1,
1, -1,
-2, 0,
-1, 61,
4, 54,
5, 54,
6, 54,
7, 54,
8, 54,
9, 54,
10, 54,
11, 54,
12, 54,
13, 54,
46, 54,
-2, 46,
-1, 140,
44, 44,
-2, 50,
-1, 159,
44, 43,
-2, 45,
};
YYNPROD: con 70;
YYPRIVATE: con 57344;
yytoknames: array of string;
yystates: array of string;
include "y.debug";
yydebug: con 1;
YYLAST: con 561;
yyact := array[] of {
64, 59, 107, 65, 162, 161, 31, 160, 158, 34,
42, 43, 44, 45, 156, 47, 48, 33, 50, 51,
52, 30, 32, 54, 55, 148, 39, 38, 63, 66,
67, 105, 100, 70, 99, 36, 98, 96, 90, 69,
57, 172, 85, 81, 80, 79, 77, 78, 72, 73,
74, 75, 76, 165, 163, 126, 151, 61, 58, 53,
49, 101, 60, 41, 103, 40, 46, 102, 143, 144,
106, 56, 108, 109, 110, 111, 112, 113, 153, 152,
116, 117, 118, 7, 115, 114, 119, 108, 108, 120,
121, 127, 128, 129, 130, 6, 132, 133, 134, 135,
136, 131, 137, 1, 140, 103, 35, 145, 142, 146,
29, 28, 27, 26, 68, 149, 150, 5, 8, 9,
10, 11, 12, 13, 14, 16, 15, 17, 18, 19,
20, 21, 22, 23, 24, 25, 4, 74, 75, 76,
159, 62, 138, 125, 2, 82, 83, 84, 3, 164,
0, 122, 29, 28, 27, 26, 166, 167, 168, 0,
169, 81, 80, 79, 77, 78, 72, 73, 74, 75,
76, 0, 173, 124, 123, 175, 0, 177, 81, 80,
79, 77, 78, 72, 73, 74, 75, 76, 39, 38,
0, 0, 39, 38, 63, 0, 0, 36, 143, 144,
0, 36, 0, 141, 81, 80, 79, 77, 78, 72,
73, 74, 75, 76, 72, 73, 74, 75, 76, 37,
104, 0, 0, 61, 0, 41, 0, 40, 139, 41,
0, 40, 81, 80, 79, 77, 78, 72, 73, 74,
75, 76, 0, 0, 176, 81, 80, 79, 77, 78,
72, 73, 74, 75, 76, 81, 80, 79, 77, 78,
72, 73, 74, 75, 76, 77, 78, 72, 73, 74,
75, 76, 174, 81, 80, 79, 77, 78, 72, 73,
74, 75, 76, 0, 0, 171, 80, 79, 77, 78,
72, 73, 74, 75, 76, 170, 81, 80, 79, 77,
78, 72, 73, 74, 75, 76, 0, 0, 0, 0,
0, 0, 0, 157, 81, 80, 79, 77, 78, 72,
73, 74, 75, 76, 81, 80, 79, 77, 78, 72,
73, 74, 75, 76, 0, 0, 155, 81, 80, 79,
77, 78, 72, 73, 74, 75, 76, 0, 0, 0,
0, 0, 0, 0, 154, 79, 77, 78, 72, 73,
74, 75, 76, 0, 147, 81, 80, 79, 77, 78,
72, 73, 74, 75, 76, 0, 0, 97, 81, 80,
79, 77, 78, 72, 73, 74, 75, 76, 81, 80,
79, 77, 78, 72, 73, 74, 75, 76, 0, 0,
0, 0, 0, 0, 0, 95, 81, 80, 79, 77,
78, 72, 73, 74, 75, 76, 0, 0, 94, 0,
0, 0, 0, 0, 0, 0, 0, 0, 93, 81,
80, 79, 77, 78, 72, 73, 74, 75, 76, 0,
0, 0, 0, 0, 0, 0, 92, 81, 80, 79,
77, 78, 72, 73, 74, 75, 76, 81, 80, 79,
77, 78, 72, 73, 74, 75, 76, 0, 0, 91,
81, 80, 79, 77, 78, 72, 73, 74, 75, 76,
0, 0, 0, 0, 0, 0, 0, 89, 0, 0,
0, 0, 0, 0, 0, 0, 0, 88, 81, 80,
79, 77, 78, 72, 73, 74, 75, 76, 0, 0,
87, 81, 80, 79, 77, 78, 72, 73, 74, 75,
76, 39, 38, 0, 0, 0, 0, 0, 0, 0,
36, 0, 0, 0, 0, 0, 0, 0, 86, 81,
80, 79, 77, 78, 72, 73, 74, 75, 76, 0,
0, 71, 37, 0, 0, 0, 0, 0, 41, 0,
40,
};
yypact := array[] of {
-1000,-1000, 96,-1000, -22, -23,-1000,-1000, 512, 512,
512, 512, 512, 26, 512, 512, 20, 512, 512, 512,
-1000, 19, 512, 512, 29, 16, 17, 17, 17,-1000,
138, -5, 512,-1000, 507,-1000,-1000,-1000, 512, 512,
512, 512, 494, 466, 453, 443, -6, 425, 402,-1000,
384, 374, 361, -7, 535, 333, -8, -10,-1000, -12,
512,-1000,-1000, 512, 174,-1000, -13,-1000,-1000, 512,
535, 512, 512, 512, 512, 512, 512, 78, 76, 512,
512, 512,-1000,-1000,-1000, 39, 512, 512, 133, 13,
512, 512, 512, 512, -23, 512, 512, 512, 512, 512,
183, 535,-1000, 157, 179, 17, 320, -19, 535, 126,
126,-1000,-1000,-1000, 512, 512, 258, 349, 281,-1000,
-19, -19,-1000,-1000,-1000, 38,-1000, 535, 310, 292,
535, -30, 535, 535, 269, 535, 535,-1000, -36, 512,
-1000, 49, -40, -42, -43,-1000,-1000, 12, 512, 205,
205,-1000,-1000,-1000, 11, 512, 512, 512, 17, 535,
-1000,-1000,-1000,-1000, 535,-1000, 251, 535, 241,-1000,
-1, 512,-1000, 228, 512, 200, 512, 535,
};
yypgo := array[] of {
0, 148, 144, 83, 106, 0, 6, 1, 142, 141,
3, 2, 109, 103, 95,
};
yyr1 := array[] of {
0, 13, 2, 2, 1, 1, 1, 1, 6, 6,
12, 12, 11, 11, 3, 3, 3, 3, 3, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 8, 8, 7, 7, 7, 9, 9,
9, 10, 10, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
};
yyr2 := array[] of {
0, 1, 0, 2, 3, 5, 1, 1, 2, 1,
0, 2, 1, 3, 4, 6, 4, 2, 1, 4,
4, 4, 4, 4, 4, 5, 5, 5, 4, 4,
6, 8, 2, 4, 6, 4, 1, 4, 2, 12,
4, 4, 2, 2, 1, 2, 1, 1, 2, 4,
1, 4, 4, 1, 1, 2, 2, 2, 3, 1,
3, 3, 3, 3, 3, 4, 4, 3, 3, 3,
};
yychk := array[] of {
-1000, -13, -2, -1, 40, 21, -14, -3, 22, 23,
24, 25, 26, 27, 28, 30, 29, 31, 32, 33,
34, 35, 36, 37, 38, 39, 17, 16, 15, 14,
43, -6, 45, 40, -5, -4, 18, 40, 10, 9,
48, 46, -5, -5, -5, -5, 40, -5, -5, 40,
-5, -5, -5, 40, -5, -5, 42, 11, 42, -7,
45, 40, -9, 11, -5, -10, -7, -7, -3, 44,
-5, 44, 9, 10, 11, 12, 13, 7, 8, 6,
5, 4, -4, -4, -4, -5, 44, 44, 44, 44,
44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
44, -5, -10, -5, 46, 44, -5, -11, -5, -5,
-5, -5, -5, -5, 7, 8, -5, -5, -5, 47,
-11, -11, 18, 41, 40, 10, 42, -5, -5, -5,
-5, -6, -5, -5, -5, -5, -5, -7, -8, 45,
-10, 46, -10, 19, 20, -7, -12, 44, 44, -5,
-5, 18, 41, 40, 44, 44, 44, 44, 44, -5,
47, 47, 47, 42, -5, 42, -5, -5, -5, -7,
44, 44, 42, -5, 44, -5, 44, -5,
};
yydef := array[] of {
2, -2, 1, 3, 0, 0, 6, 7, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36, 0, 0, 0, 0, 0, 0, 0, 0, 18,
0, 0, 0, 9, 0, 59, 53, 54, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
0, 0, 0, 0, 38, 0, 0, 0, 42, 0,
0, -2, 47, 0, 0, 50, 0, 17, 4, 0,
8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 55, 56, 57, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 45, 48, 0, 0, 0, 10, 19, 12, 60,
61, 62, 63, 64, 0, 0, 67, 68, 69, 58,
20, 21, 22, 23, 24, 0, 28, 29, 0, 0,
33, 0, 35, 37, 0, 40, 41, 14, 0, 0,
-2, 0, 0, 0, 0, 16, 5, 0, 0, 65,
66, 25, 26, 27, 0, 0, 0, 0, 0, -2,
49, 51, 52, 11, 13, 30, 0, 34, 0, 15,
0, 0, 31, 0, 0, 0, 0, 39,
};
yytok1 := array[] of {
1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 45, 13, 6, 3,
46, 47, 11, 9, 44, 10, 3, 12, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 43, 3,
7, 3, 8, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 5, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 4, 3, 48,
};
yytok2 := array[] of {
2, 3, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42,
};
yytok3 := array[] of {
0
};
YYSys: module
{
FD: adt
{
fd: int;
};
fildes: fn(fd: int): ref FD;
fprint: fn(fd: ref FD, s: string, *): int;
};
yysys: YYSys;
yystderr: ref YYSys->FD;
YYFLAG: con -1000;
# parser for yacc output
yytokname(yyc: int): string
{
if(yyc > 0 && yyc <= len yytoknames && yytoknames[yyc-1] != nil)
return yytoknames[yyc-1];
return "<"+string yyc+">";
}
yystatname(yys: int): string
{
if(yys >= 0 && yys < len yystates && yystates[yys] != nil)
return yystates[yys];
return "<"+string yys+">\n";
}
yylex1(yylex: ref YYLEX): int
{
c : int;
yychar := yylex.lex();
if(yychar <= 0)
c = yytok1[0];
else if(yychar < len yytok1)
c = yytok1[yychar];
else if(yychar >= YYPRIVATE && yychar < YYPRIVATE+len yytok2)
c = yytok2[yychar-YYPRIVATE];
else{
n := len yytok3;
c = 0;
for(i := 0; i < n; i+=2) {
if(yytok3[i+0] == yychar) {
c = yytok3[i+1];
break;
}
}
if(c == 0)
c = yytok2[1]; # unknown char
}
if(yydebug >= 3)
yysys->fprint(yystderr, "lex %.4ux %s\n", yychar, yytokname(c));
return c;
}
YYS: adt
{
yyv: YYSTYPE;
yys: int;
};
yyparse(yylex: ref YYLEX): int
{
if(yydebug >= 1 && yysys == nil) {
yysys = load YYSys "$Sys";
yystderr = yysys->fildes(2);
}
yys := array[YYMAXDEPTH] of YYS;
yyval: YYSTYPE;
yystate := 0;
yychar := -1;
yynerrs := 0; # number of errors
yyerrflag := 0; # error recovery flag
yyp := -1;
yyn := 0;
yystack:
for(;;){
# put a state and value onto the stack
if(yydebug >= 4)
yysys->fprint(yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
yyp++;
if(yyp >= len yys)
yys = (array[len yys * 2] of YYS)[0:] = yys;
yys[yyp].yys = yystate;
yys[yyp].yyv = yyval;
for(;;){
yyn = yypact[yystate];
if(yyn > YYFLAG) { # simple state
if(yychar < 0)
yychar = yylex1(yylex);
yyn += yychar;
if(yyn >= 0 && yyn < YYLAST) {
yyn = yyact[yyn];
if(yychk[yyn] == yychar) { # valid shift
yychar = -1;
yyp++;
if(yyp >= len yys)
yys = (array[len yys * 2] of YYS)[0:] = yys;
yystate = yyn;
yys[yyp].yys = yystate;
yys[yyp].yyv = yylex.lval;
if(yyerrflag > 0)
yyerrflag--;
if(yydebug >= 4)
yysys->fprint(yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
continue;
}
}
}
# default state action
yyn = yydef[yystate];
if(yyn == -2) {
if(yychar < 0)
yychar = yylex1(yylex);
# look through exception table
for(yyxi:=0;; yyxi+=2)
if(yyexca[yyxi] == -1 && yyexca[yyxi+1] == yystate)
break;
for(yyxi += 2;; yyxi += 2) {
yyn = yyexca[yyxi];
if(yyn < 0 || yyn == yychar)
break;
}
yyn = yyexca[yyxi+1];
if(yyn < 0){
yyn = 0;
break yystack;
}
}
if(yyn != 0)
break;
# error ... attempt to resume parsing
if(yyerrflag == 0) { # brand new error
yylex.error("syntax error");
yynerrs++;
if(yydebug >= 1) {
yysys->fprint(yystderr, "%s", yystatname(yystate));
yysys->fprint(yystderr, "saw %s\n", yytokname(yychar));
}
}
if(yyerrflag != 3) { # incompletely recovered error ... try again
yyerrflag = 3;
# find a state where "error" is a legal shift action
while(yyp >= 0) {
yyn = yypact[yys[yyp].yys] + YYERRCODE;
if(yyn >= 0 && yyn < YYLAST) {
yystate = yyact[yyn]; # simulate a shift of "error"
if(yychk[yystate] == YYERRCODE)
continue yystack;
}
# the current yyp has no shift onn "error", pop stack
if(yydebug >= 2)
yysys->fprint(yystderr, "error recovery pops state %d, uncovers %d\n",
yys[yyp].yys, yys[yyp-1].yys );
yyp--;
}
# there is no state on the stack with an error shift ... abort
yyn = 1;
break yystack;
}
# no shift yet; clobber input char
if(yydebug >= 2)
yysys->fprint(yystderr, "error recovery discards %s\n", yytokname(yychar));
if(yychar == YYEOFCODE) {
yyn = 1;
break yystack;
}
yychar = -1;
# try again in the same state
}
# reduction by production yyn
if(yydebug >= 2)
yysys->fprint(yystderr, "reduce %d in:\n\t%s", yyn, yystatname(yystate));
yypt := yyp;
yyp -= yyr2[yyn];
# yyval = yys[yyp+1].yyv;
yym := yyn;
# consult goto table to find next state
yyn = yyr1[yyn];
yyg := yypgo[yyn];
yyj := yyg + yys[yyp].yys + 1;
if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn)
yystate = yyact[yyg];
case yym {
1=>
#line 178 "asm.y"
{
assem(yys[yypt-0].yyv.inst);
}
2=>
#line 184 "asm.y"
{ yyval.inst = nil; }
3=>
#line 186 "asm.y"
{
if(yys[yypt-0].yyv.inst != nil) {
yys[yypt-0].yyv.inst.link = yys[yypt-1].yyv.inst;
yyval.inst = yys[yypt-0].yyv.inst;
}
else
yyval.inst = yys[yypt-1].yyv.inst;
}
4=>
#line 197 "asm.y"
{
yys[yypt-0].yyv.inst.sym = yys[yypt-2].yyv.sym;
yyval.inst = yys[yypt-0].yyv.inst;
}
5=>
#line 202 "asm.y"
{
heap(int yys[yypt-3].yyv.ival, int yys[yypt-1].yyv.ival, yys[yypt-0].yyv.str);
yyval.inst = nil;
}
6=>
#line 207 "asm.y"
{
yyval.inst = nil;
}
7=>
yyval.inst = yys[yyp+1].yyv.inst;
8=>
#line 214 "asm.y"
{
yyval.ival = yys[yypt-0].yyv.ival;
}
9=>
#line 218 "asm.y"
{
yys[yypt-0].yyv.sym.value = heapid++;
yyval.ival = big yys[yypt-0].yyv.sym.value;
}
10=>
#line 225 "asm.y"
{ yyval.str = nil; }
11=>
#line 227 "asm.y"
{
yyval.str = yys[yypt-0].yyv.str;
}
12=>
#line 233 "asm.y"
{
yyval.listv = newi(yys[yypt-0].yyv.ival, nil);
}
13=>
#line 237 "asm.y"
{
yyval.listv = newi(yys[yypt-0].yyv.ival, yys[yypt-2].yyv.listv);
}
14=>
#line 243 "asm.y"
{
yyval.inst = ai(yys[yypt-3].yyv.op);
yyval.inst.src = yys[yypt-2].yyv.addr;
yyval.inst.dst = yys[yypt-0].yyv.addr;
}
15=>
#line 249 "asm.y"
{
yyval.inst = ai(yys[yypt-5].yyv.op);
yyval.inst.src = yys[yypt-4].yyv.addr;
yyval.inst.reg = yys[yypt-2].yyv.addr;
yyval.inst.dst = yys[yypt-0].yyv.addr;
}
16=>
#line 256 "asm.y"
{
yyval.inst = ai(yys[yypt-3].yyv.op);
yyval.inst.src = yys[yypt-2].yyv.addr;
yyval.inst.dst = yys[yypt-0].yyv.addr;
}
17=>
#line 262 "asm.y"
{
yyval.inst = ai(yys[yypt-1].yyv.op);
yyval.inst.dst = yys[yypt-0].yyv.addr;
}
18=>
#line 267 "asm.y"
{
yyval.inst = ai(yys[yypt-0].yyv.op);
}
19=>
#line 273 "asm.y"
{
data(DEFB, yys[yypt-2].yyv.ival, yys[yypt-0].yyv.listv);
}
20=>
#line 277 "asm.y"
{
data(DEFW, yys[yypt-2].yyv.ival, yys[yypt-0].yyv.listv);
}
21=>
#line 281 "asm.y"
{
data(DEFL, yys[yypt-2].yyv.ival, yys[yypt-0].yyv.listv);
}
22=>
#line 285 "asm.y"
{
data(DEFF, yys[yypt-2].yyv.ival, newb(dtocanon(real yys[yypt-0].yyv.ival), nil));
}
23=>
#line 289 "asm.y"
{
data(DEFF, yys[yypt-2].yyv.ival, newb(dtocanon(yys[yypt-0].yyv.fval), nil));
}
24=>
#line 293 "asm.y"
{
case yys[yypt-0].yyv.sym.name {
"Inf" or "Infinity" =>
b := array[] of {byte 16r7F, byte 16rF0, byte 0, byte 0, byte 0, byte 0, byte 0, byte 0};
data(DEFF, yys[yypt-2].yyv.ival, newb(b, nil));
"NaN" =>
b := array[] of {byte 16r7F, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF};
data(DEFF, yys[yypt-2].yyv.ival, newb(b, nil));
* =>
diag(sys->sprint("bad value for real: %s", yys[yypt-0].yyv.sym.name));
}
}
25=>
#line 306 "asm.y"
{
data(DEFF, yys[yypt-3].yyv.ival, newb(dtocanon(-real yys[yypt-0].yyv.ival), nil));
}
26=>
#line 310 "asm.y"
{
data(DEFF, yys[yypt-3].yyv.ival, newb(dtocanon(-yys[yypt-0].yyv.fval), nil));
}
27=>
#line 314 "asm.y"
{
case yys[yypt-0].yyv.sym.name {
"Inf" or "Infinity" =>
b := array[] of {byte 16rFF, byte 16rF0, byte 0, byte 0, byte 0, byte 0, byte 0, byte 0};
data(DEFF, yys[yypt-3].yyv.ival, newb(b, nil));
* =>
diag(sys->sprint("bad value for real: %s", yys[yypt-0].yyv.sym.name));
}
}
28=>
#line 324 "asm.y"
{
data(DEFS, yys[yypt-2].yyv.ival, news(yys[yypt-0].yyv.str, nil));
}
29=>
#line 328 "asm.y"
{
if(yys[yypt-2].yyv.sym.ds != 0)
diag(sys->sprint("%s declared twice", yys[yypt-2].yyv.sym.name));
yys[yypt-2].yyv.sym.ds = int yys[yypt-0].yyv.ival;
yys[yypt-2].yyv.sym.value = dseg;
dseg += int yys[yypt-0].yyv.ival;
}
30=>
#line 336 "asm.y"
{
ext(int yys[yypt-4].yyv.ival, int yys[yypt-2].yyv.ival, yys[yypt-0].yyv.str);
}
31=>
#line 340 "asm.y"
{
mklink(int yys[yypt-6].yyv.ival, int yys[yypt-4].yyv.ival, int yys[yypt-2].yyv.ival, yys[yypt-0].yyv.str);
}
32=>
#line 344 "asm.y"
{
if(amodule != nil)
diag(sys->sprint("this module already defined as %s", yys[yypt-0].yyv.sym.name));
else
amodule = yys[yypt-0].yyv.sym;
}
33=>
#line 351 "asm.y"
{
if(pcentry >= 0)
diag(sys->sprint("this module already has entry point %d, %d" , pcentry, dentry));
pcentry = int yys[yypt-2].yyv.ival;
dentry = int yys[yypt-0].yyv.ival;
}
34=>
#line 358 "asm.y"
{
data(DEFA, yys[yypt-4].yyv.ival, newa(int yys[yypt-2].yyv.ival, int yys[yypt-0].yyv.ival));
}
35=>
#line 362 "asm.y"
{
data(DIND, yys[yypt-2].yyv.ival, newa(int yys[yypt-0].yyv.ival, 0));
}
36=>
#line 366 "asm.y"
{
data(DAPOP, big 0, newa(0, 0));
}
37=>
#line 370 "asm.y"
{
ldts(int yys[yypt-0].yyv.ival);
}
38=>
#line 374 "asm.y"
{
excs(int yys[yypt-0].yyv.ival);
}
39=>
#line 378 "asm.y"
{
exc(int yys[yypt-10].yyv.ival, int yys[yypt-8].yyv.ival, int yys[yypt-6].yyv.ival, int yys[yypt-4].yyv.ival, int yys[yypt-2].yyv.ival, int yys[yypt-0].yyv.ival);
}
40=>
#line 382 "asm.y"
{
etab(yys[yypt-2].yyv.str, int yys[yypt-0].yyv.ival);
}
41=>
#line 386 "asm.y"
{
etab(nil, int yys[yypt-0].yyv.ival);
}
42=>
#line 390 "asm.y"
{
source(yys[yypt-0].yyv.str);
}
43=>
#line 396 "asm.y"
{
yyval.addr = aa(yys[yypt-0].yyv.ival);
yyval.addr.mode = AXIMM;
if(yyval.addr.val > 16r7FFF || yyval.addr.val < -16r8000)
diag(sys->sprint("immediate %d too large for middle operand", yyval.addr.val));
}
44=>
#line 403 "asm.y"
{
if(yys[yypt-0].yyv.addr.mode == AMP)
yys[yypt-0].yyv.addr.mode = AXINM;
else
yys[yypt-0].yyv.addr.mode = AXINF;
if(yys[yypt-0].yyv.addr.mode == AXINM && isoff2big(yys[yypt-0].yyv.addr.val))
diag(sys->sprint("register offset %d(mp) too large", yys[yypt-0].yyv.addr.val));
if(yys[yypt-0].yyv.addr.mode == AXINF && isoff2big(yys[yypt-0].yyv.addr.val))
diag(sys->sprint("register offset %d(fp) too large", yys[yypt-0].yyv.addr.val));
yyval.addr = yys[yypt-0].yyv.addr;
}
45=>
#line 417 "asm.y"
{
yyval.addr = aa(yys[yypt-0].yyv.ival);
yyval.addr.mode = AIMM;
}
46=>
#line 422 "asm.y"
{
yyval.addr = aa(big 0);
yyval.addr.sym = yys[yypt-0].yyv.sym;
}
47=>
yyval.addr = yys[yyp+1].yyv.addr;
48=>
#line 430 "asm.y"
{
yys[yypt-0].yyv.addr.mode |= AIND;
yyval.addr = yys[yypt-0].yyv.addr;
}
49=>
#line 435 "asm.y"
{
yys[yypt-1].yyv.addr.mode |= AIND;
if(yys[yypt-1].yyv.addr.val & 3)
diag("indirect offset must be word size");
if(yys[yypt-1].yyv.addr.mode == (AMP|AIND) && (isoff2big(yys[yypt-1].yyv.addr.val) || isoff2big(int yys[yypt-3].yyv.ival)))
diag(sys->sprint("indirect offset %bd(%d(mp)) too large", yys[yypt-3].yyv.ival, yys[yypt-1].yyv.addr.val));
if(yys[yypt-1].yyv.addr.mode == (AFP|AIND) && (isoff2big(yys[yypt-1].yyv.addr.val) || isoff2big(int yys[yypt-3].yyv.ival)))
diag(sys->sprint("indirect offset %bd(%d(fp)) too large", yys[yypt-3].yyv.ival, yys[yypt-1].yyv.addr.val));
yys[yypt-1].yyv.addr.off = yys[yypt-1].yyv.addr.val;
yys[yypt-1].yyv.addr.val = int yys[yypt-3].yyv.ival;
yyval.addr = yys[yypt-1].yyv.addr;
}
50=>
yyval.addr = yys[yyp+1].yyv.addr;
51=>
#line 451 "asm.y"
{
yyval.addr = aa(yys[yypt-3].yyv.ival);
yyval.addr.mode = AMP;
}
52=>
#line 456 "asm.y"
{
yyval.addr = aa(yys[yypt-3].yyv.ival);
yyval.addr.mode = AFP;
}
53=>
yyval.ival = yys[yyp+1].yyv.ival;
54=>
#line 464 "asm.y"
{
yyval.ival = big yys[yypt-0].yyv.sym.value;
}
55=>
#line 468 "asm.y"
{
yyval.ival = -yys[yypt-0].yyv.ival;
}
56=>
#line 472 "asm.y"
{
yyval.ival = yys[yypt-0].yyv.ival;
}
57=>
#line 476 "asm.y"
{
yyval.ival = ~yys[yypt-0].yyv.ival;
}
58=>
#line 480 "asm.y"
{
yyval.ival = yys[yypt-1].yyv.ival;
}
59=>
yyval.ival = yys[yyp+1].yyv.ival;
60=>
#line 487 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival + yys[yypt-0].yyv.ival;
}
61=>
#line 491 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival - yys[yypt-0].yyv.ival;
}
62=>
#line 495 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival * yys[yypt-0].yyv.ival;
}
63=>
#line 499 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival / yys[yypt-0].yyv.ival;
}
64=>
#line 503 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival % yys[yypt-0].yyv.ival;
}
65=>
#line 507 "asm.y"
{
yyval.ival = yys[yypt-3].yyv.ival << int yys[yypt-0].yyv.ival;
}
66=>
#line 511 "asm.y"
{
yyval.ival = yys[yypt-3].yyv.ival >> int yys[yypt-0].yyv.ival;
}
67=>
#line 515 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival & yys[yypt-0].yyv.ival;
}
68=>
#line 519 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival ^ yys[yypt-0].yyv.ival;
}
69=>
#line 523 "asm.y"
{
yyval.ival = yys[yypt-2].yyv.ival | yys[yypt-0].yyv.ival;
}
}
}
return yyn;
}