summaryrefslogtreecommitdiff
path: root/appl/lib/dis.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/dis.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/lib/dis.b')
-rw-r--r--appl/lib/dis.b609
1 files changed, 609 insertions, 0 deletions
diff --git a/appl/lib/dis.b b/appl/lib/dis.b
new file mode 100644
index 00000000..f64fd162
--- /dev/null
+++ b/appl/lib/dis.b
@@ -0,0 +1,609 @@
+implement Dis;
+
+#
+# Derived by Vita Nuova Limited 1998 from /appl/wm/rt.b, which is
+# Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved.
+#
+
+include "sys.m";
+ sys: Sys;
+ sprint: import sys;
+
+include "math.m";
+ math: Math;
+
+include "dis.m";
+
+disptr: int;
+disobj: array of byte;
+
+optab := array[] of {
+ "nop",
+ "alt",
+ "nbalt",
+ "goto",
+ "call",
+ "frame",
+ "spawn",
+ "runt",
+ "load",
+ "mcall",
+ "mspawn",
+ "mframe",
+ "ret",
+ "jmp",
+ "case",
+ "exit",
+ "new",
+ "newa",
+ "newcb",
+ "newcw",
+ "newcf",
+ "newcp",
+ "newcm",
+ "newcmp",
+ "send",
+ "recv",
+ "consb",
+ "consw",
+ "consp",
+ "consf",
+ "consm",
+ "consmp",
+ "headb",
+ "headw",
+ "headp",
+ "headf",
+ "headm",
+ "headmp",
+ "tail",
+ "lea",
+ "indx",
+ "movp",
+ "movm",
+ "movmp",
+ "movb",
+ "movw",
+ "movf",
+ "cvtbw",
+ "cvtwb",
+ "cvtfw",
+ "cvtwf",
+ "cvtca",
+ "cvtac",
+ "cvtwc",
+ "cvtcw",
+ "cvtfc",
+ "cvtcf",
+ "addb",
+ "addw",
+ "addf",
+ "subb",
+ "subw",
+ "subf",
+ "mulb",
+ "mulw",
+ "mulf",
+ "divb",
+ "divw",
+ "divf",
+ "modw",
+ "modb",
+ "andb",
+ "andw",
+ "orb",
+ "orw",
+ "xorb",
+ "xorw",
+ "shlb",
+ "shlw",
+ "shrb",
+ "shrw",
+ "insc",
+ "indc",
+ "addc",
+ "lenc",
+ "lena",
+ "lenl",
+ "beqb",
+ "bneb",
+ "bltb",
+ "bleb",
+ "bgtb",
+ "bgeb",
+ "beqw",
+ "bnew",
+ "bltw",
+ "blew",
+ "bgtw",
+ "bgew",
+ "beqf",
+ "bnef",
+ "bltf",
+ "blef",
+ "bgtf",
+ "bgef",
+ "beqc",
+ "bnec",
+ "bltc",
+ "blec",
+ "bgtc",
+ "bgec",
+ "slicea",
+ "slicela",
+ "slicec",
+ "indw",
+ "indf",
+ "indb",
+ "negf",
+ "movl",
+ "addl",
+ "subl",
+ "divl",
+ "modl",
+ "mull",
+ "andl",
+ "orl",
+ "xorl",
+ "shll",
+ "shrl",
+ "bnel",
+ "bltl",
+ "blel",
+ "bgtl",
+ "bgel",
+ "beql",
+ "cvtlf",
+ "cvtfl",
+ "cvtlw",
+ "cvtwl",
+ "cvtlc",
+ "cvtcl",
+ "headl",
+ "consl",
+ "newcl",
+ "casec",
+ "indl",
+ "movpc",
+ "tcmp",
+ "mnewz",
+ "cvtrf",
+ "cvtfr",
+ "cvtws",
+ "cvtsw",
+ "lsrw",
+ "lsrl",
+ "eclr",
+ "newz",
+ "newaz",
+ "raise",
+ "casel",
+ "mulx",
+ "divx",
+ "cvtxx",
+ "mulx0",
+ "divx0",
+ "cvtxx0",
+ "mulx1",
+ "divx1",
+ "cvtxx1",
+ "cvtfx",
+ "cvtxf",
+ "expw",
+ "expl",
+ "expf",
+ "self",
+};
+
+init()
+{
+ sys = load Sys Sys->PATH;
+ math = load Math Math->PATH; # optional
+}
+
+loadobj(disfile: string): (ref Mod, string)
+{
+ fd := sys->open(disfile, sys->OREAD);
+ if(fd == nil)
+ return (nil, "open failed: "+sprint("%r"));
+
+ (ok, d) := sys->fstat(fd);
+ if(ok < 0)
+ return (nil, "stat failed: "+sprint("%r"));
+
+ objlen := int d.length;
+ disobj = array[objlen] of byte;
+
+ if(sys->read(fd, disobj, objlen) != objlen){
+ disobj = nil;
+ return (nil, "read failed: "+sprint("%r"));
+ }
+
+ disptr = 0;
+ m := ref Mod;
+ m.magic = operand();
+ if(m.magic == SMAGIC) {
+ n := operand();
+ m.sign = disobj[disptr:disptr+n];
+ disptr += n;
+ m.magic = operand();
+ }
+ if(m.magic != XMAGIC){
+ disobj = nil;
+ return (nil, "bad magic number");
+ }
+
+ m.rt = operand();
+ m.ssize = operand();
+ m.isize = operand();
+ m.dsize = operand();
+ m.tsize = operand();
+ m.lsize = operand();
+ m.entry = operand();
+ m.entryt = operand();
+
+ m.inst = array[m.isize] of ref Inst;
+ for(i := 0; i < m.isize; i++) {
+ o := ref Inst;
+ o.op = int disobj[disptr++];
+ o.addr = int disobj[disptr++];
+ case o.addr & ARM {
+ AXIMM or
+ AXINF or
+ AXINM =>
+ o.mid = operand();
+ }
+
+ case (o.addr>>3) & 7 {
+ AFP or
+ AMP or
+ AIMM =>
+ o.src = operand();
+ AIND|AFP or
+ AIND|AMP =>
+ o.src = operand()<<16;
+ o.src |= operand();
+ }
+
+ case o.addr & 7 {
+ AFP or
+ AMP or
+ AIMM =>
+ o.dst = operand();
+ AIND|AFP or
+ AIND|AMP =>
+ o.dst = operand()<<16;
+ o.dst |= operand();
+ }
+ m.inst[i] = o;
+ }
+
+ m.types = array[m.tsize] of ref Type;
+ for(i = 0; i < m.tsize; i++) {
+ h := ref Type;
+ id := operand();
+ h.size = operand();
+ h.np = operand();
+ h.map = disobj[disptr:disptr+h.np];
+ disptr += h.np;
+ m.types[i] = h;
+ }
+
+ for(;;) {
+ op := int disobj[disptr++];
+ if(op == 0)
+ break;
+
+ n := op & (DMAX-1);
+ if(n == 0)
+ n = operand();
+
+ offset := operand();
+
+ dat: ref Data;
+ case op>>4 {
+ DEFB =>
+ dat = ref Data.Bytes(op, n, offset, disobj[disptr:disptr+n]);
+ disptr += n;
+ DEFW =>
+ words := array[n] of int;
+ for(i = 0; i < n; i++)
+ words[i] = getw();
+ dat = ref Data.Words(op, n, offset, words);
+ DEFS =>
+ dat = ref Data.String(op, n, offset, string disobj[disptr:disptr+n]);
+ disptr += n;
+ DEFF =>
+ if(math != nil){
+ reals := array[n] of real;
+ for(i = 0; i < n; i++)
+ reals[i] = math->bits64real(getl());
+ dat = ref Data.Reals(op, n, offset, nil);
+ } else {
+ disptr += 8*n; # skip it
+ dat = ref Data.Reals(op, n, offset, nil);
+ }
+ break;
+ DEFA =>
+ typex := getw();
+ length := getw();
+ dat = ref Data.Array(op, n, offset, typex, length);
+ DIND =>
+ dat = ref Data.Aindex(op, n, offset, getw());
+ DAPOP =>
+ dat = ref Data.Arestore(op, n, offset);
+ DEFL =>
+ bigs := array[n] of big;
+ for(i = 0; i < n; i++)
+ bigs[i] = getl();
+ dat = ref Data.Bigs(op, n, offset, bigs);
+ * =>
+ dat = ref Data.Zero(op, n, offset);
+ }
+ m.data = dat :: m.data;
+ }
+
+ m.data = revdat(m.data);
+
+ m.name = gets();
+
+ m.links = array[m.lsize] of ref Link;
+ for(i = 0; i < m.lsize; i++) {
+ l := ref Link;
+ l.pc = operand();
+ l.desc = operand();
+ l.sig = getw();
+ l.name = gets();
+
+ m.links[i] = l;
+ }
+
+ if(m.rt & Dis->HASLDT0)
+ raise "obsolete dis";
+
+ if(m.rt & Dis->HASLDT){
+ nl := operand();
+ imps := array[nl] of array of ref Import;
+ for(i = 0; i < nl; i++){
+ n := operand();
+ imps[i] = array[n] of ref Import;
+ for(j := 0; j < n; j++){
+ imps[i][j] = im := ref Import;
+ im.sig = getw();
+ im.name = gets();
+ }
+ }
+ disptr++;
+ m.imports = imps;
+ }
+
+ if(m.rt & Dis->HASEXCEPT){
+ nh := operand(); # number of handlers
+ hs := array[nh] of ref Handler;
+ for(i = 0; i < nh; i++){
+ h := hs[i] = ref Handler;
+ h.eoff = operand();
+ h.pc1 = operand();
+ h.pc2 = operand();
+ t := operand();
+ if(t >= 0)
+ h.t = m.types[t];
+ n := operand();
+ h.ne = n>>16;
+ n &= 16rffff; # number of cases
+ h.etab = array[n+1] of ref Except;
+ for(j := 0; j < n; j++){
+ e := h.etab[j] = ref Except;
+ k := disptr;
+ while(int disobj[disptr++]) # pattern
+ ;
+ e.s = string disobj[k: disptr-1];
+ e.pc = operand();
+ }
+ e := h.etab[j] = ref Except;
+ e.pc = operand(); # * pc
+ }
+ disptr++; # 0 byte
+ m.handlers = hs;
+ }
+
+ m.srcpath = gets();
+
+ disobj = nil;
+ return (m, nil);
+}
+
+operand(): int
+{
+ if(disptr >= len disobj)
+ return -1;
+
+ b := int disobj[disptr++];
+
+ case b & 16rC0 {
+ 16r00 =>
+ return b;
+ 16r40 =>
+ return b | ~16r7F;
+ 16r80 =>
+ if(disptr >= len disobj)
+ return -1;
+ if(b & 16r20)
+ b |= ~16r3F;
+ else
+ b &= 16r3F;
+ return (b<<8) | int disobj[disptr++];
+ 16rC0 =>
+ if(disptr+2 >= len disobj)
+ return -1;
+ if(b & 16r20)
+ b |= ~16r3F;
+ else
+ b &= 16r3F;
+ b = b<<24 |
+ (int disobj[disptr]<<16) |
+ (int disobj[disptr+1]<<8)|
+ int disobj[disptr+2];
+ disptr += 3;
+ return b;
+ }
+ return 0;
+}
+
+get4(a: array of byte, i: int): int
+{
+ return (int a[i+0] << 24) | (int a[i+1] << 16) | (int a[i+2] << 8) | int a[i+3];
+}
+
+getw(): int
+{
+ if(disptr+3 >= len disobj)
+ return -1;
+ i := (int disobj[disptr+0]<<24) |
+ (int disobj[disptr+1]<<16) |
+ (int disobj[disptr+2]<<8) |
+ int disobj[disptr+3];
+
+ disptr += 4;
+ return i;
+}
+
+getl(): big
+{
+ if(disptr+7 >= len disobj)
+ return big -1;
+ i := (big disobj[disptr+0]<<56) |
+ (big disobj[disptr+1]<<48) |
+ (big disobj[disptr+2]<<40) |
+ (big disobj[disptr+3]<<32) |
+ (big disobj[disptr+4]<<24) |
+ (big disobj[disptr+5]<<16) |
+ (big disobj[disptr+6]<<8) |
+ big disobj[disptr+7];
+
+ disptr += 8;
+ return i;
+}
+
+gets(): string
+{
+ s := disptr;
+ while(disptr < len disobj && disobj[disptr] != byte 0)
+ disptr++;
+
+ v := string disobj[s:disptr];
+ disptr++;
+ return v;
+}
+
+revdat(d: list of ref Data): list of ref Data
+{
+ t: list of ref Data;
+
+ while(d != nil) {
+ t = hd d :: t;
+ d = tl d;
+ }
+ return t;
+}
+
+op2s(op: int): string
+{
+ if(op < 0 || op >= len optab)
+ return sys->sprint("OP%d", op);
+ return optab[op];
+}
+
+inst2s(o: ref Inst): string
+{
+ fi := 0;
+ si := 0;
+ s := sprint("%-10s", optab[o.op]);
+ src := "";
+ dst := "";
+ mid := "";
+ case (o.addr>>3) & 7 {
+ AFP =>
+ src = sprint("%d(fp)", o.src);
+ AMP =>
+ src = sprint("%d(mp)", o.src);
+ AIMM =>
+ src = sprint("$%d", o.src);
+ AIND|AFP =>
+ fi = (o.src>>16) & 16rFFFF;
+ si = o.src & 16rFFFF;
+ src = sprint("%d(%d(fp))", si, fi);
+ AIND|AMP =>
+ fi = (o.src>>16) & 16rFFFF;
+ si = o.src & 16rFFFF;
+ src = sprint("%d(%d(mp))", si, fi);
+ }
+
+ case o.addr & ARM {
+ AXIMM =>
+ mid = sprint("$%d", o.mid);
+ AXINF =>
+ mid = sprint("%d(fp)", o.mid);
+ AXINM =>
+ mid = sprint("%d(mp)", o.mid);
+ }
+
+ case o.addr & 7 {
+ AFP =>
+ dst = sprint("%d(fp)", o.dst);
+ AMP =>
+ dst = sprint("%d(mp)", o.dst);
+ AIMM =>
+ dst = sprint("$%d", o.dst);
+ AIND|AFP =>
+ fi = (o.dst>>16) & 16rFFFF;
+ si = o.dst & 16rFFFF;
+ dst = sprint("%d(%d(fp))", si, fi);
+ AIND|AMP =>
+ fi = (o.dst>>16) & 16rFFFF;
+ si = o.dst & 16rFFFF;
+ dst = sprint("%d(%d(mp))", si, fi);
+ }
+ if(mid == "") {
+ if(src == "")
+ s += sprint("%s", dst);
+ else if(dst == "")
+ s += sprint("%s", src);
+ else
+ s += sprint("%s, %s", src, dst);
+ }
+ else
+ s += sprint("%s, %s, %s", src, mid, dst);
+
+ return s;
+}
+
+getsb(fd: ref Sys->FD, o: int): (string, int)
+{
+ b := array[1] of byte;
+ buf := array[8192] of byte;
+ p := len buf;
+ for( ; ; o++){
+ sys->seek(fd, big -o, Sys->SEEKEND);
+ if(sys->read(fd, b, 1) != 1)
+ return (nil, 0);
+ if(b[0] == byte 0){
+ if(p < len buf)
+ break;
+ }
+ else if(p > 0)
+ buf[--p] = b[0];
+ }
+ return (string buf[p: ], o);
+}
+
+src(disf: string): string
+{
+ fd := sys->open(disf, sys->OREAD);
+ if(fd == nil)
+ return nil;
+ (s, nil) := getsb(fd, 1);
+ if(s != nil && s[0] == '/')
+ return s;
+ return nil;
+}