diff options
| author | Charles Forsyth <charles.forsyth@gmail.com> | 2015-04-25 19:46:27 +0100 |
|---|---|---|
| committer | Charles Forsyth <charles.forsyth@gmail.com> | 2015-04-25 19:46:27 +0100 |
| commit | 70a234d0b5dd59660347742b2c5f3098522e5a80 (patch) | |
| tree | aa2ddd771078131065e987bb72a8517f14ced57e | |
| parent | 4ba871f66a3cfb31efe38493d249f6946092da9b (diff) | |
add Limbo version of asm(1)
| -rw-r--r-- | appl/cmd/asm/asm.b | 2369 | ||||
| -rw-r--r-- | appl/cmd/asm/asm.y | 1907 | ||||
| -rw-r--r-- | appl/cmd/asm/mkfile | 27 | ||||
| -rw-r--r-- | appl/cmd/asm/y.debug | 230 | ||||
| -rw-r--r-- | dis/asm.dis | bin | 0 -> 39904 bytes |
5 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 +}; diff --git a/dis/asm.dis b/dis/asm.dis Binary files differnew file mode 100644 index 00000000..533cb223 --- /dev/null +++ b/dis/asm.dis |
