summaryrefslogtreecommitdiff
path: root/appl/cmd/limbo/dis.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/limbo/dis.b')
-rw-r--r--appl/cmd/limbo/dis.b560
1 files changed, 560 insertions, 0 deletions
diff --git a/appl/cmd/limbo/dis.b b/appl/cmd/limbo/dis.b
new file mode 100644
index 00000000..7d79553e
--- /dev/null
+++ b/appl/cmd/limbo/dis.b
@@ -0,0 +1,560 @@
+
+NAMELEN: con 28;
+
+cache: array of byte;
+ncached: int;
+ndatum: int;
+startoff: int;
+lastoff: int;
+lastkind: int;
+
+discon(val: int)
+{
+ if(val >= -64 && val <= 63){
+ bout.putb(byte (val & ~16r80));
+ return;
+ }
+ if(val >= -8192 && val <= 8191){
+ bout.putb(byte ((val>>8) & ~16rC0 | 16r80));
+ bout.putb(byte val);
+ return;
+ }
+ if(val < 0 && ((val >> 29) & 7) != 7
+ || val > 0 && (val >> 29) != 0)
+ fatal("overflow in constant 16r"+hex(val, 0));
+ bout.putb(byte(val>>24 | 16rC0));
+ bout.putb(byte(val>>16));
+ bout.putb(byte(val>>8));
+ bout.putb(byte val);
+}
+
+disword(w: int)
+{
+ bout.putb(byte(w >> 24));
+ bout.putb(byte(w >> 16));
+ bout.putb(byte(w >> 8));
+ bout.putb(byte w);
+}
+
+disdata(kind, n: int)
+{
+ if(n < DMAX && n != 0)
+ bout.putb(byte((kind << DBYTE) | n));
+ else{
+ bout.putb(byte kind << DBYTE);
+ discon(n);
+ }
+}
+
+dismod(m: ref Decl)
+{
+ fileoff := bout.seek(big 0, 1);
+ name := array of byte m.sym.name;
+ n := len name;
+ if(n > NAMELEN-1)
+ n = NAMELEN-1;
+ bout.write(name, n);
+ bout.putb(byte 0);
+ for(m = m.ty.tof.ids; m != nil; m = m.next){
+ case m.store{
+ Dglobal =>
+ discon(-1);
+ discon(-1);
+ disword(sign(m));
+ bout.puts(".mp");
+ bout.putb(byte 0);
+ Dfn =>
+ discon(m.pc.pc);
+ discon(m.desc.id);
+ disword(sign(m));
+ if(m.dot.ty.kind == Tadt){
+ bout.puts(m.dot.sym.name);
+ bout.putb(byte '.');
+ }
+ bout.puts(m.sym.name);
+ bout.putb(byte 0);
+ * =>
+ fatal("unknown kind in dismod: "+declconv(m));
+ }
+ }
+ if(debug['s'])
+ print("%bd linkage bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
+}
+
+dispath()
+{
+ sp := array of byte srcpath();
+ bout.write(sp, len sp);
+ bout.putb(byte 0);
+}
+
+disentry(e: ref Decl)
+{
+ if(e == nil){
+ discon(-1);
+ discon(-1);
+ return;
+ }
+ discon(e.pc.pc);
+ discon(e.desc.id);
+}
+
+disdesc(d: ref Desc)
+{
+ fileoff := bout.seek(big 0, 1);
+ for(; d != nil; d = d.next){
+ discon(d.id);
+ discon(d.size);
+ discon(d.nmap);
+ bout.write(d.map, d.nmap);
+ }
+ if(debug['s'])
+ print("%bd type descriptor bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
+}
+
+disvar(nil: int, ids: ref Decl)
+{
+ fileoff := bout.seek(big 0, 1);
+ lastkind = -1;
+ ncached = 0;
+ ndatum = 0;
+
+ for(d := ids; d != nil; d = d.next)
+ if(d.store == Dglobal && d.init != nil)
+ disdatum(d.offset, d.init);
+
+ disflush(-1, -1, 0);
+
+ bout.putb(byte 0);
+
+ if(debug['s'])
+ print("%bd data bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
+}
+
+disldt(size: int, ds: ref Decl)
+{
+ if(0){
+ discon(size);
+ disvar(size, ds);
+ return;
+ }
+
+ m := 0;
+ for(d := ds; d != nil; d = d.next)
+ if(d.store == Dglobal && d.init != nil)
+ m++;
+ discon(m);
+ n: ref Node;
+ for(d = ds; d != nil; d = d.next){
+ if(d.store == Dglobal && d.init != nil){
+ n = d.init;
+ if(n.ty.kind != Tiface)
+ nerror(n, "disldt: not Tiface");
+ discon(int n.c.val);
+ for(id := n.decl.ty.ids; id != nil; id = id.next){
+ disword(sign(id));
+ if(id.dot.ty.kind == Tadt){
+ s := array of byte id.dot.sym.name;
+ bout.write(s, len s);
+ bout.putb(byte '.');
+ }
+ s := array of byte id.sym.name;
+ bout.write(s, len s);
+ bout.putb(byte 0);
+ }
+ }
+ }
+ discon(0);
+}
+
+disdatum(offset: int, n: ref Node)
+{
+ c: ref Case;
+ lab: Label;
+ id: ref Decl;
+ wild: ref Node;
+ i, e: int;
+
+ case n.ty.kind{
+ Tbyte =>
+ disbyte(offset, byte n.c.val);
+ Tint or
+ Tfix =>
+ disint(offset, int n.c.val);
+ Tbig =>
+ disbig(offset, n.c.val);
+ Tstring =>
+ disstring(offset, n.decl.sym);
+ Treal =>
+ disreal(offset, n.c.rval);
+ Tadt or
+ Tadtpick or
+ Ttuple =>
+ id = n.ty.ids;
+ for(n = n.left; n != nil; n = n.right){
+ disdatum(offset + id.offset, n.left);
+ id = id.next;
+ }
+ Tany =>
+ break;
+ Tcase =>
+ c = n.ty.cse;
+ disint(offset, c.nlab);
+ offset += IBY2WD;
+ for(i = 0; i < c.nlab; i++){
+ lab = c.labs[i];
+ disint(offset, int lab.start.c.val);
+ offset += IBY2WD;
+ disint(offset, int lab.stop.c.val+1);
+ offset += IBY2WD;
+ disint(offset, lab.inst.pc);
+ offset += IBY2WD;
+ }
+ if(c.iwild != nil)
+ disint(offset, c.iwild.pc);
+ else
+ disint(offset, -1);
+ Tcasel =>
+ c = n.ty.cse;
+ disint(offset, c.nlab);
+ offset += 2*IBY2WD;
+ for(i = 0; i < c.nlab; i++){
+ lab = c.labs[i];
+ disbig(offset, lab.start.c.val);
+ offset += IBY2LG;
+ disbig(offset, lab.stop.c.val+big 1);
+ offset += IBY2LG;
+ disint(offset, lab.inst.pc);
+ offset += 2*IBY2WD;
+ }
+ if(c.iwild != nil)
+ disint(offset, c.iwild.pc);
+ else
+ disint(offset, -1);
+ Tcasec =>
+ c = n.ty.cse;
+ disint(offset, c.nlab);
+ offset += IBY2WD;
+ for(i = 0; i < c.nlab; i++){
+ lab = c.labs[i];
+ disstring(offset, lab.start.decl.sym);
+ offset += IBY2WD;
+ if(lab.stop != lab.start)
+ disstring(offset, lab.stop.decl.sym);
+ offset += IBY2WD;
+ disint(offset, lab.inst.pc);
+ offset += IBY2WD;
+ }
+ if(c.iwild != nil)
+ disint(offset, c.iwild.pc);
+ else
+ disint(offset, -1);
+ Tgoto =>
+ c = n.ty.cse;
+ disint(offset, n.ty.size/IBY2WD-1);
+ offset += IBY2WD;
+ for(i = 0; i < c.nlab; i++){
+ disint(offset, c.labs[i].inst.pc);
+ offset += IBY2WD;
+ }
+ if(c.iwild != nil)
+ disint(offset, c.iwild.pc);
+ Tarray =>
+ disflush(-1, -1, 0);
+ disdata(DEFA, 1); # 1 is ignored
+ discon(offset);
+ disword(n.ty.tof.decl.desc.id);
+ disword(int n.left.c.val);
+
+ if(n.right == nil)
+ break;
+
+ disdata(DIND, 1); # 1 is ignored
+ discon(offset);
+ disword(0);
+
+ c = n.right.ty.cse;
+ wild = nil;
+ if(c.wild != nil)
+ wild = c.wild.right;
+ last := 0;
+ esz := n.ty.tof.size;
+ for(i = 0; i < c.nlab; i++){
+ e = int c.labs[i].start.c.val;
+ if(wild != nil){
+ for(; last < e; last++)
+ disdatum(esz * last, wild);
+ }
+ last = e;
+ e = int c.labs[i].stop.c.val;
+ elem := c.labs[i].node.right;
+ for(; last <= e; last++)
+ disdatum(esz * last, elem);
+ }
+ if(wild != nil)
+ for(e = int n.left.c.val; last < e; last++)
+ disdatum(esz * last, wild);
+
+ disflush(-1, -1, 0);
+ disdata(DAPOP, 1); # 1 is ignored
+ discon(0);
+ Tiface =>
+ disint(offset, int n.c.val);
+ offset += IBY2WD;
+ for(id = n.decl.ty.ids; id != nil; id = id.next){
+ offset = align(offset, IBY2WD);
+ disint(offset, sign(id));
+ offset += IBY2WD;
+
+ name: array of byte;
+ if(id.dot.ty.kind == Tadt){
+ name = array of byte id.dot.sym.name;
+ disbytes(offset, name);
+ offset += len name;
+ disbyte(offset, byte '.');
+ offset++;
+ }
+ name = array of byte id.sym.name;
+ disbytes(offset, name);
+ offset += len name;
+ disbyte(offset, byte 0);
+ offset++;
+ }
+ * =>
+ fatal("can't gen global "+nodeconv(n));
+ }
+}
+
+disexc(es: ref Except)
+{
+ e: ref Except;
+
+ n := 0;
+ for(e = es; e != nil; e = e.next)
+ if(int e.p1.reach || int e.p2.reach)
+ n++;
+ discon(n);
+ for(e = es; e != nil; e = e.next){
+ if(!int e.p1.reach && !int e.p2.reach)
+ continue;
+ c := e.c;
+ discon(e.d.offset);
+ discon(getpc(e.p1));
+ discon(getpc(e.p2));
+ if(e.desc != nil)
+ discon(e.desc.id);
+ else
+ discon(-1);
+ discon(c.nlab|(e.ne<<16));
+ for(i := 0; i < c.nlab; i++){
+ lab := c.labs[i];
+ d := lab.start.decl;
+ if(lab.start.ty.kind == Texception)
+ d = d.init.decl;
+ bout.puts(d.sym.name);
+ bout.putb(byte 0);
+ discon(lab.inst.pc);
+ }
+ if(c.iwild == nil)
+ discon(-1);
+ else
+ discon(c.iwild.pc);
+ }
+ discon(0);
+}
+
+disbyte(off: int, v: byte)
+{
+ disflush(DEFB, off, 1);
+ cache[ncached++] = v;
+ ndatum++;
+}
+
+disbytes(off: int, v: array of byte)
+{
+ n := len v;
+ disflush(DEFB, off, n);
+ cache[ncached:] = v;
+ ncached += n;
+ ndatum += n;
+}
+
+disint(off, v: int)
+{
+ disflush(DEFW, off, IBY2WD);
+ cache[ncached++] = byte(v >> 24);
+ cache[ncached++] = byte(v >> 16);
+ cache[ncached++] = byte(v >> 8);
+ cache[ncached++] = byte(v);
+ ndatum++;
+}
+
+disbig(off: int, v: big)
+{
+ disflush(DEFL, off, IBY2LG);
+ iv := int(v >> 32);
+ cache[ncached++] = byte(iv >> 24);
+ cache[ncached++] = byte(iv >> 16);
+ cache[ncached++] = byte(iv >> 8);
+ cache[ncached++] = byte(iv);
+ iv = int v;
+ cache[ncached++] = byte(iv >> 24);
+ cache[ncached++] = byte(iv >> 16);
+ cache[ncached++] = byte(iv >> 8);
+ cache[ncached++] = byte(iv);
+ ndatum++;
+}
+
+disreal(off: int, v: real)
+{
+ disflush(DEFF, off, IBY2LG);
+ export_real(cache[ncached:ncached+8], array[] of {v});
+ ncached += IBY2LG;
+ ndatum++;
+}
+
+disstring(offset: int, sym: ref Sym)
+{
+ disflush(-1, -1, 0);
+ d := array of byte sym.name;
+ disdata(DEFS, len d);
+ discon(offset);
+ bout.write(d, len d);
+}
+
+disflush(kind, off, size: int)
+{
+ if(kind != lastkind || off != lastoff){
+ if(lastkind != -1 && ncached){
+ disdata(lastkind, ndatum);
+ discon(startoff);
+ bout.write(cache, ncached);
+ }
+ startoff = off;
+ lastkind = kind;
+ ncached = 0;
+ ndatum = 0;
+ }
+ lastoff = off + size;
+ while(kind >= 0 && ncached + size >= len cache){
+ c := array[ncached + 1024] of byte;
+ c[0:] = cache;
+ cache = c;
+ }
+}
+
+dismode := array[int Aend] of
+{
+ int Aimm => byte AIMM,
+ int Amp => byte AMP,
+ int Ampind => byte(AMP|AIND),
+ int Afp => byte AFP,
+ int Afpind => byte(AFP|AIND),
+ int Apc => byte AIMM,
+ int Adesc => byte AIMM,
+ int Aoff => byte AIMM,
+ int Anoff => byte AIMM,
+ int Aerr => byte AXXX,
+ int Anone => byte AXXX,
+ int Aldt => byte AIMM,
+};
+
+disregmode := array[int Aend] of
+{
+ int Aimm => byte AXIMM,
+ int Amp => byte AXINM,
+ int Ampind => byte AXNON,
+ int Afp => byte AXINF,
+ int Afpind => byte AXNON,
+ int Apc => byte AXIMM,
+ int Adesc => byte AXIMM,
+ int Aoff => byte AXIMM,
+ int Anoff => byte AXIMM,
+ int Aerr => byte AXNON,
+ int Anone => byte AXNON,
+ int Aldt => byte AXIMM,
+};
+
+MAXCON: con 4;
+MAXADDR: con 2*MAXCON;
+MAXINST: con 3*MAXADDR+2;
+NIBUF: con 1024;
+
+ibuf: array of byte;
+nibuf: int;
+
+disinst(in: ref Inst)
+{
+ fileoff := bout.seek(big 0, 1);
+ ibuf = array[NIBUF] of byte;
+ nibuf = 0;
+ for(; in != nil; in = in.next){
+ if(in.op == INOOP)
+ continue;
+ if(nibuf >= NIBUF-MAXINST){
+ bout.write(ibuf, nibuf);
+ nibuf = 0;
+ }
+ ibuf[nibuf++] = byte in.op;
+ o := dismode[int in.sm] << SRC;
+ o |= dismode[int in.dm] << DST;
+ o |= disregmode[int in.mm];
+ ibuf[nibuf++] = o;
+ if(in.mm != Anone)
+ disaddr(in.mm, in.m);
+ if(in.sm != Anone)
+ disaddr(in.sm, in.s);
+ if(in.dm != Anone)
+ disaddr(in.dm, in.d);
+ }
+ if(nibuf > 0)
+ bout.write(ibuf, nibuf);
+ ibuf = nil;
+
+ if(debug['s'])
+ print("%bd instruction bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
+}
+
+disaddr(m: byte, a: Addr)
+{
+ val := 0;
+ case int m{
+ int Aimm or
+ int Apc or
+ int Adesc =>
+ val = a.offset;
+ int Aoff =>
+ val = a.decl.iface.offset;
+ int Anoff =>
+ val = -(a.decl.iface.offset+1);
+ int Afp or
+ int Amp or
+ int Aldt =>
+ val = a.reg;
+ int Afpind or
+ int Ampind =>
+ disbcon(a.reg);
+ val = a.offset;
+ }
+ disbcon(val);
+}
+
+disbcon(val: int)
+{
+ if(val >= -64 && val <= 63){
+ ibuf[nibuf++] = byte(val & ~16r80);
+ return;
+ }
+ if(val >= -8192 && val <= 8191){
+ ibuf[nibuf++] = byte(val>>8 & ~16rC0 | 16r80);
+ ibuf[nibuf++] = byte val;
+ return;
+ }
+ if(val < 0 && ((val >> 29) & 7) != 7
+ || val > 0 && (val >> 29) != 0)
+ fatal("overflow in constant 16r"+hex(val, 0));
+ ibuf[nibuf++] = byte(val>>24 | 16rC0);
+ ibuf[nibuf++] = byte(val>>16);
+ ibuf[nibuf++] = byte(val>>8);
+ ibuf[nibuf++] = byte val;
+}