summaryrefslogtreecommitdiff
path: root/appl
diff options
context:
space:
mode:
authorCharles Forsyth <charles.forsyth@gmail.com>2015-04-25 19:46:27 +0100
committerCharles Forsyth <charles.forsyth@gmail.com>2015-04-25 19:46:27 +0100
commit70a234d0b5dd59660347742b2c5f3098522e5a80 (patch)
treeaa2ddd771078131065e987bb72a8517f14ced57e /appl
parent4ba871f66a3cfb31efe38493d249f6946092da9b (diff)
add Limbo version of asm(1)
Diffstat (limited to 'appl')
-rw-r--r--appl/cmd/asm/asm.b2369
-rw-r--r--appl/cmd/asm/asm.y1907
-rw-r--r--appl/cmd/asm/mkfile27
-rw-r--r--appl/cmd/asm/y.debug230
4 files changed, 4533 insertions, 0 deletions
diff --git a/appl/cmd/asm/asm.b b/appl/cmd/asm/asm.b
new file mode 100644
index 00000000..6ad007b0
--- /dev/null
+++ b/appl/cmd/asm/asm.b
@@ -0,0 +1,2369 @@
+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;
+}
diff --git a/appl/cmd/asm/asm.y b/appl/cmd/asm/asm.y
new file mode 100644
index 00000000..d1464002
--- /dev/null
+++ b/appl/cmd/asm/asm.y
@@ -0,0 +1,1907 @@
+%{
+
+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;
+};
+
+%}
+
+%module Asm {
+ init: fn(nil: ref Draw->Context, nil: list of string);
+}
+
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+
+%type<inst> label ilist inst
+%type<ival> con expr heapid
+%type<addr> addr raddr mem roff
+%type<listv> elist
+%type<str> ptrs
+%token<op> TOKI0 TOKI1 TOKI2 TOKI3
+%token <ival> TCONST
+%token TOKSB TOKFP TOKHEAP TOKDB TOKDW TOKDL TOKDF TOKDS TOKVAR
+%token TOKEXT TOKMOD TOKLINK TOKENTRY TOKARRAY TOKINDIR TOKAPOP TOKLDTS TOKEXCS TOKEXC TOKETAB TOKSRC
+%token<sym> TID
+%token<fval> TFCONST
+%token<str> TSTRING
+
+%%
+prog : ilist
+ {
+ assem($1);
+ }
+ ;
+
+ilist :
+ { $$ = nil; }
+ | ilist label
+ {
+ if($2 != nil) {
+ $2.link = $1;
+ $$ = $2;
+ }
+ else
+ $$ = $1;
+ }
+ ;
+
+label : TID ':' inst
+ {
+ $3.sym = $1;
+ $$ = $3;
+ }
+ | TOKHEAP heapid ',' expr ptrs
+ {
+ heap(int $2, int $4, $5);
+ $$ = nil;
+ }
+ | data
+ {
+ $$ = nil;
+ }
+ | inst
+ ;
+
+heapid : '$' expr
+ {
+ $$ = $2;
+ }
+ | TID
+ {
+ $1.value = heapid++;
+ $$ = big $1.value;
+ }
+ ;
+
+ptrs :
+ { $$ = nil; }
+ | ',' TSTRING
+ {
+ $$ = $2;
+ }
+ ;
+
+elist : expr
+ {
+ $$ = newi($1, nil);
+ }
+ | elist ',' expr
+ {
+ $$ = newi($3, $1);
+ }
+ ;
+
+inst : TOKI3 addr ',' addr
+ {
+ $$ = ai($1);
+ $$.src = $2;
+ $$.dst = $4;
+ }
+ | TOKI3 addr ',' raddr ',' addr
+ {
+ $$ = ai($1);
+ $$.src = $2;
+ $$.reg = $4;
+ $$.dst = $6;
+ }
+ | TOKI2 addr ',' addr
+ {
+ $$ = ai($1);
+ $$.src = $2;
+ $$.dst = $4;
+ }
+ | TOKI1 addr
+ {
+ $$ = ai($1);
+ $$.dst = $2;
+ }
+ | TOKI0
+ {
+ $$ = ai($1);
+ }
+ ;
+
+data : TOKDB expr ',' elist
+ {
+ data(DEFB, $2, $4);
+ }
+ | TOKDW expr ',' elist
+ {
+ data(DEFW, $2, $4);
+ }
+ | TOKDL expr ',' elist
+ {
+ data(DEFL, $2, $4);
+ }
+ | TOKDF expr ',' TCONST
+ {
+ data(DEFF, $2, newb(dtocanon(real $4), nil));
+ }
+ | TOKDF expr ',' TFCONST
+ {
+ data(DEFF, $2, newb(dtocanon($4), nil));
+ }
+ | TOKDF expr ',' TID
+ {
+ case $4.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, $2, 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, $2, newb(b, nil));
+ * =>
+ diag(sys->sprint("bad value for real: %s", $4.name));
+ }
+ }
+ | TOKDF expr ',' '-' TCONST
+ {
+ data(DEFF, $2, newb(dtocanon(-real $5), nil));
+ }
+ | TOKDF expr ',' '-' TFCONST
+ {
+ data(DEFF, $2, newb(dtocanon(-$5), nil));
+ }
+ | TOKDF expr ',' '-' TID
+ {
+ case $5.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, $2, newb(b, nil));
+ * =>
+ diag(sys->sprint("bad value for real: %s", $5.name));
+ }
+ }
+ | TOKDS expr ',' TSTRING
+ {
+ data(DEFS, $2, news($4, nil));
+ }
+ | TOKVAR TID ',' expr
+ {
+ if($2.ds != 0)
+ diag(sys->sprint("%s declared twice", $2.name));
+ $2.ds = int $4;
+ $2.value = dseg;
+ dseg += int $4;
+ }
+ | TOKEXT expr ',' expr ',' TSTRING
+ {
+ ext(int $2, int $4, $6);
+ }
+ | TOKLINK expr ',' expr ',' expr ',' TSTRING
+ {
+ mklink(int $2, int $4, int $6, $8);
+ }
+ | TOKMOD TID
+ {
+ if(amodule != nil)
+ diag(sys->sprint("this module already defined as %s", $2.name));
+ else
+ amodule = $2;
+ }
+ | TOKENTRY expr ',' expr
+ {
+ if(pcentry >= 0)
+ diag(sys->sprint("this module already has entry point %d, %d" , pcentry, dentry));
+ pcentry = int $2;
+ dentry = int $4;
+ }
+ | TOKARRAY expr ',' heapid ',' expr
+ {
+ data(DEFA, $2, newa(int $4, int $6));
+ }
+ | TOKINDIR expr ',' expr
+ {
+ data(DIND, $2, newa(int $4, 0));
+ }
+ | TOKAPOP
+ {
+ data(DAPOP, big 0, newa(0, 0));
+ }
+ | TOKLDTS TID ',' expr
+ {
+ ldts(int $4);
+ }
+ | TOKEXCS expr
+ {
+ excs(int $2);
+ }
+ | TOKEXC expr ',' expr ',' expr ',' expr ',' expr ',' expr
+ {
+ exc(int $2, int $4, int $6, int $8, int $10, int $12);
+ }
+ | TOKETAB TSTRING ',' expr
+ {
+ etab($2, int $4);
+ }
+ | TOKETAB '*' ',' expr
+ {
+ etab(nil, int $4);
+ }
+ | TOKSRC TSTRING
+ {
+ source($2);
+ }
+ ;
+
+raddr : '$' expr
+ {
+ $$ = aa($2);
+ $$.mode = AXIMM;
+ if($$.val > 16r7FFF || $$.val < -16r8000)
+ diag(sys->sprint("immediate %d too large for middle operand", $$.val));
+ }
+ | roff
+ {
+ if($1.mode == AMP)
+ $1.mode = AXINM;
+ else
+ $1.mode = AXINF;
+ if($1.mode == AXINM && isoff2big($1.val))
+ diag(sys->sprint("register offset %d(mp) too large", $1.val));
+ if($1.mode == AXINF && isoff2big($1.val))
+ diag(sys->sprint("register offset %d(fp) too large", $1.val));
+ $$ = $1;
+ }
+ ;
+
+addr : '$' expr
+ {
+ $$ = aa($2);
+ $$.mode = AIMM;
+ }
+ | TID
+ {
+ $$ = aa(big 0);
+ $$.sym = $1;
+ }
+ | mem
+ ;
+
+mem : '*' roff
+ {
+ $2.mode |= AIND;
+ $$ = $2;
+ }
+ | expr '(' roff ')'
+ {
+ $3.mode |= AIND;
+ if($3.val & 3)
+ diag("indirect offset must be word size");
+ if($3.mode == (AMP|AIND) && (isoff2big($3.val) || isoff2big(int $1)))
+ diag(sys->sprint("indirect offset %bd(%d(mp)) too large", $1, $3.val));
+ if($3.mode == (AFP|AIND) && (isoff2big($3.val) || isoff2big(int $1)))
+ diag(sys->sprint("indirect offset %bd(%d(fp)) too large", $1, $3.val));
+ $3.off = $3.val;
+ $3.val = int $1;
+ $$ = $3;
+ }
+ | roff
+ ;
+
+roff : expr '(' TOKSB ')'
+ {
+ $$ = aa($1);
+ $$.mode = AMP;
+ }
+ | expr '(' TOKFP ')'
+ {
+ $$ = aa($1);
+ $$.mode = AFP;
+ }
+ ;
+
+con : TCONST
+ | TID
+ {
+ $$ = big $1.value;
+ }
+ | '-' con
+ {
+ $$ = -$2;
+ }
+ | '+' con
+ {
+ $$ = $2;
+ }
+ | '~' con
+ {
+ $$ = ~$2;
+ }
+ | '(' expr ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+expr: con
+ | expr '+' expr
+ {
+ $$ = $1 + $3;
+ }
+ | expr '-' expr
+ {
+ $$ = $1 - $3;
+ }
+ | expr '*' expr
+ {
+ $$ = $1 * $3;
+ }
+ | expr '/' expr
+ {
+ $$ = $1 / $3;
+ }
+ | expr '%' expr
+ {
+ $$ = $1 % $3;
+ }
+ | expr '<' '<' expr
+ {
+ $$ = $1 << int $4;
+ }
+ | expr '>' '>' expr
+ {
+ $$ = $1 >> int $4;
+ }
+ | expr '&' expr
+ {
+ $$ = $1 & $3;
+ }
+ | expr '^' expr
+ {
+ $$ = $1 ^ $3;
+ }
+ | expr '|' expr
+ {
+ $$ = $1 | $3;
+ }
+ ;
+%%
+
+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),
+};
diff --git a/appl/cmd/asm/mkfile b/appl/cmd/asm/mkfile
new file mode 100644
index 00000000..32fc7041
--- /dev/null
+++ b/appl/cmd/asm/mkfile
@@ -0,0 +1,27 @@
+<../../../mkconfig
+
+TARG=asm.dis
+
+YFILES= asm.y
+
+MODULES=\
+ ../limbo/disoptab.m\
+ ../limbo/isa.m\
+ ../limbo/opname.m\
+ asm.b\
+
+SYSMODULES=\
+ arg.m\
+ bufio.m\
+ draw.m\
+ keyring.m\
+ math.m\
+ string.m\
+ sys.m\
+
+DISBIN=$ROOT/dis
+
+<$ROOT/mkfiles/mkdis
+
+#asm.b: asm.y
+# yacc -D1 -o asm.b asm.y
diff --git a/appl/cmd/asm/y.debug b/appl/cmd/asm/y.debug
new file mode 100644
index 00000000..7ff6fdaf
--- /dev/null
+++ b/appl/cmd/asm/y.debug
@@ -0,0 +1,230 @@
+yytoknames = array[] of {
+ "$end",
+ "error",
+ "$unk",
+ " |",
+ " ^",
+ " &",
+ " <",
+ " >",
+ " +",
+ " -",
+ " *",
+ " /",
+ " %",
+ "TOKI0",
+ "TOKI1",
+ "TOKI2",
+ "TOKI3",
+ "TCONST",
+ "TOKSB",
+ "TOKFP",
+ "TOKHEAP",
+ "TOKDB",
+ "TOKDW",
+ "TOKDL",
+ "TOKDF",
+ "TOKDS",
+ "TOKVAR",
+ "TOKEXT",
+ "TOKMOD",
+ "TOKLINK",
+ "TOKENTRY",
+ "TOKARRAY",
+ "TOKINDIR",
+ "TOKAPOP",
+ "TOKLDTS",
+ "TOKEXCS",
+ "TOKEXC",
+ "TOKETAB",
+ "TOKSRC",
+ "TID",
+ "TFCONST",
+ "TSTRING",
+ " :",
+ " ,",
+ " $",
+ " (",
+ " )",
+ " ~",
+};
+yystates = array [] of {
+ nil, #0
+ "$accept: prog.$end \n", #1/
+ nil, #2
+ nil, #3
+ "label: TID.: inst \n", #4/
+ "label: TOKHEAP.heapid , expr ptrs \n", #5/
+ nil, #6
+ nil, #7
+ "data: TOKDB.expr , elist \n", #8/
+ "data: TOKDW.expr , elist \n", #9/
+ "data: TOKDL.expr , elist \n", #10/
+ "data: TOKDF.expr , TCONST \ndata: TOKDF.expr , TFCONST \ndata: TOKDF.expr , TID \ndata: TOKDF.expr , - TCONST \ndata: TOKDF.expr , - TFCONST \ndata: TOKDF.expr , - TID \n", #11/
+ "data: TOKDS.expr , TSTRING \n", #12/
+ "data: TOKVAR.TID , expr \n", #13/
+ "data: TOKEXT.expr , expr , TSTRING \n", #14/
+ "data: TOKLINK.expr , expr , expr , TSTRING \n", #15/
+ "data: TOKMOD.TID \n", #16/
+ "data: TOKENTRY.expr , expr \n", #17/
+ "data: TOKARRAY.expr , heapid , expr \n", #18/
+ "data: TOKINDIR.expr , expr \n", #19/
+ nil, #20
+ "data: TOKLDTS.TID , expr \n", #21/
+ "data: TOKEXCS.expr \n", #22/
+ "data: TOKEXC.expr , expr , expr , expr , expr , expr \n", #23/
+ "data: TOKETAB.TSTRING , expr \ndata: TOKETAB.* , expr \n", #24/
+ "data: TOKSRC.TSTRING \n", #25/
+ "inst: TOKI3.addr , addr \ninst: TOKI3.addr , raddr , addr \n", #26/
+ "inst: TOKI2.addr , addr \n", #27/
+ "inst: TOKI1.addr \n", #28/
+ nil, #29
+ "label: TID :.inst \n", #30/
+ "label: TOKHEAP heapid., expr ptrs \n", #31/
+ "heapid: $.expr \n", #32/
+ nil, #33
+ "data: TOKDB expr., elist \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #34/
+ nil, #35
+ nil, #36
+ nil, #37
+ "con: -.con \n", #38/
+ "con: +.con \n", #39/
+ "con: ~.con \n", #40/
+ "con: (.expr ) \n", #41/
+ "data: TOKDW expr., elist \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #42/
+ "data: TOKDL expr., elist \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #43/
+ "data: TOKDF expr., TCONST \ndata: TOKDF expr., TFCONST \ndata: TOKDF expr., TID \ndata: TOKDF expr., - TCONST \ndata: TOKDF expr., - TFCONST \ndata: TOKDF expr., - TID \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #44/
+ "data: TOKDS expr., TSTRING \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #45/
+ "data: TOKVAR TID., expr \n", #46/
+ "data: TOKEXT expr., expr , TSTRING \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #47/
+ "data: TOKLINK expr., expr , expr , TSTRING \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #48/
+ nil, #49
+ "data: TOKENTRY expr., expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #50/
+ "data: TOKARRAY expr., heapid , expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #51/
+ "data: TOKINDIR expr., expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #52/
+ "data: TOKLDTS TID., expr \n", #53/
+ nil, #54
+ "data: TOKEXC expr., expr , expr , expr , expr , expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #55/
+ "data: TOKETAB TSTRING., expr \n", #56/
+ "data: TOKETAB *., expr \n", #57/
+ nil, #58
+ "inst: TOKI3 addr., addr \ninst: TOKI3 addr., raddr , addr \n", #59/
+ "addr: $.expr \n", #60/
+ nil, #61
+ nil, #62
+ "mem: *.roff \n", #63/
+ "mem: expr.( roff ) \nroff: expr.( TOKSB ) \nroff: expr.( TOKFP ) \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #64/
+ nil, #65
+ "inst: TOKI2 addr., addr \n", #66/
+ nil, #67
+ nil, #68
+ "label: TOKHEAP heapid ,.expr ptrs \n", #69/
+ nil, #70
+ "data: TOKDB expr ,.elist \n", #71/
+ "expr: expr +.expr \n", #72/
+ "expr: expr -.expr \n", #73/
+ "expr: expr *.expr \n", #74/
+ "expr: expr /.expr \n", #75/
+ "expr: expr %.expr \n", #76/
+ "expr: expr <.< expr \n", #77/
+ "expr: expr >.> expr \n", #78/
+ "expr: expr &.expr \n", #79/
+ "expr: expr ^.expr \n", #80/
+ "expr: expr |.expr \n", #81/
+ nil, #82
+ nil, #83
+ nil, #84
+ "con: ( expr.) \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #85/
+ "data: TOKDW expr ,.elist \n", #86/
+ "data: TOKDL expr ,.elist \n", #87/
+ "data: TOKDF expr ,.TCONST \ndata: TOKDF expr ,.TFCONST \ndata: TOKDF expr ,.TID \ndata: TOKDF expr ,.- TCONST \ndata: TOKDF expr ,.- TFCONST \ndata: TOKDF expr ,.- TID \n", #88/
+ "data: TOKDS expr ,.TSTRING \n", #89/
+ "data: TOKVAR TID ,.expr \n", #90/
+ "data: TOKEXT expr ,.expr , TSTRING \n", #91/
+ "data: TOKLINK expr ,.expr , expr , TSTRING \n", #92/
+ "data: TOKENTRY expr ,.expr \n", #93/
+ "data: TOKARRAY expr ,.heapid , expr \n", #94/
+ "data: TOKINDIR expr ,.expr \n", #95/
+ "data: TOKLDTS TID ,.expr \n", #96/
+ "data: TOKEXC expr ,.expr , expr , expr , expr , expr \n", #97/
+ "data: TOKETAB TSTRING ,.expr \n", #98/
+ "data: TOKETAB * ,.expr \n", #99/
+ "inst: TOKI3 addr ,.addr \ninst: TOKI3 addr ,.raddr , addr \n", #100/
+ nil, #101
+ nil, #102
+ "roff: expr.( TOKSB ) \nroff: expr.( TOKFP ) \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #103/
+ "mem: expr (.roff ) \nroff: expr (.TOKSB ) \nroff: expr (.TOKFP ) \n", #104/
+ "inst: TOKI2 addr ,.addr \n", #105/
+ nil, #106
+ nil, #107
+ nil, #108
+ nil, #109
+ nil, #110
+ nil, #111
+ nil, #112
+ nil, #113
+ "expr: expr < <.expr \n", #114/
+ "expr: expr > >.expr \n", #115/
+ nil, #116
+ nil, #117
+ nil, #118
+ nil, #119
+ nil, #120
+ nil, #121
+ nil, #122
+ nil, #123
+ nil, #124
+ "data: TOKDF expr , -.TCONST \ndata: TOKDF expr , -.TFCONST \ndata: TOKDF expr , -.TID \n", #125/
+ nil, #126
+ nil, #127
+ "data: TOKEXT expr , expr., TSTRING \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #128/
+ "data: TOKLINK expr , expr., expr , TSTRING \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #129/
+ nil, #130
+ "data: TOKARRAY expr , heapid., expr \n", #131/
+ nil, #132
+ nil, #133
+ "data: TOKEXC expr , expr., expr , expr , expr , expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #134/
+ nil, #135
+ nil, #136
+ nil, #137
+ "inst: TOKI3 addr , raddr., addr \n", #138/
+ "raddr: $.expr \naddr: $.expr \n", #139/
+ nil, #140
+ "roff: expr (.TOKSB ) \nroff: expr (.TOKFP ) \n", #141/
+ "mem: expr ( roff.) \n", #142/
+ "roff: expr ( TOKSB.) \n", #143/
+ "roff: expr ( TOKFP.) \n", #144/
+ nil, #145
+ nil, #146
+ "ptrs: ,.TSTRING \n", #147/
+ "elist: elist ,.expr \n", #148/
+ nil, #149
+ nil, #150
+ nil, #151
+ nil, #152
+ nil, #153
+ "data: TOKEXT expr , expr ,.TSTRING \n", #154/
+ "data: TOKLINK expr , expr ,.expr , TSTRING \n", #155/
+ "data: TOKARRAY expr , heapid ,.expr \n", #156/
+ "data: TOKEXC expr , expr ,.expr , expr , expr , expr \n", #157/
+ "inst: TOKI3 addr , raddr ,.addr \n", #158/
+ nil, #159
+ nil, #160
+ nil, #161
+ nil, #162
+ nil, #163
+ nil, #164
+ nil, #165
+ "data: TOKLINK expr , expr , expr., TSTRING \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #166/
+ nil, #167
+ "data: TOKEXC expr , expr , expr., expr , expr , expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #168/
+ nil, #169
+ "data: TOKLINK expr , expr , expr ,.TSTRING \n", #170/
+ "data: TOKEXC expr , expr , expr ,.expr , expr , expr \n", #171/
+ nil, #172
+ "data: TOKEXC expr , expr , expr , expr., expr , expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #173/
+ "data: TOKEXC expr , expr , expr , expr ,.expr , expr \n", #174/
+ "data: TOKEXC expr , expr , expr , expr , expr., expr \nexpr: expr.+ expr \nexpr: expr.- expr \nexpr: expr.* expr \nexpr: expr./ expr \nexpr: expr.% expr \nexpr: expr.< < expr \nexpr: expr.> > expr \nexpr: expr.& expr \nexpr: expr.^ expr \nexpr: expr.| expr \n", #175/
+ "data: TOKEXC expr , expr , expr , expr , expr ,.expr \n", #176/
+ nil, #177
+};