ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/limbo/dis.b/
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;
}