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: 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: 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: 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 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; }