summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-10-19 22:33:56 -0700
committerRuss Cox <rsc@golang.org>2009-10-19 22:33:56 -0700
commite760a551366b0602b1919e2389763634cad76332 (patch)
treef9a83c705f6af9ebb4a45863b47a0289b377675d
parent4ab24cf45c6fd58f83f0ee179c801b850692eb48 (diff)
downloadgolang-e760a551366b0602b1919e2389763634cad76332.tar.gz
support for 5.out files
R=kaib DELTA=1262 (1247 added, 7 deleted, 8 changed) OCL=35907 CL=35909
-rw-r--r--include/ureg_arm.h49
-rw-r--r--src/cmd/5l/asm.c5
-rw-r--r--src/libmach/5.c92
-rw-r--r--src/libmach/5db.c1095
-rw-r--r--src/libmach/Makefile2
-rw-r--r--src/libmach/executable.c1
-rw-r--r--src/libmach/setmach.c26
7 files changed, 1255 insertions, 15 deletions
diff --git a/include/ureg_arm.h b/include/ureg_arm.h
new file mode 100644
index 000000000..c740b0302
--- /dev/null
+++ b/include/ureg_arm.h
@@ -0,0 +1,49 @@
+// Inferno utils/libmach/ureg5.h
+// http://code.google.com/p/inferno-os/source/browse/utils/libmach/ureg5.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc.
+// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
+// Portions Copyright © 1997-1999 Vita Nuova Limited.
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
+// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+struct Ureg {
+ uint r0;
+ uint r1;
+ uint r2;
+ uint r3;
+ uint r4;
+ uint r5;
+ uint r6;
+ uint r7;
+ uint r8;
+ uint r9;
+ uint r10;
+ uint r11;
+ uint r12;
+ uint r13;
+ uint r14;
+ uint link;
+ uint type;
+ uint psr;
+ uint pc;
+};
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 6cd4b2390..a375b8bf8 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -671,7 +671,10 @@ putsymb(char *s, int t, int32 v, int ver)
cput(s[i]);
cput(0);
}
- symsize += 4 + 1 + i + 1;
+ // TODO(rsc): handle go parameter
+ lput(0);
+
+ symsize += 4 + 1 + i + 1 + 4;
if(debug['n']) {
if(t == 'z' || t == 'Z') {
diff --git a/src/libmach/5.c b/src/libmach/5.c
new file mode 100644
index 000000000..67bd88db4
--- /dev/null
+++ b/src/libmach/5.c
@@ -0,0 +1,92 @@
+// Inferno libmach/5.c
+// http://code.google.com/p/inferno-os/source/browse/utils/libmach/5.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc.
+// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
+// Portions Copyright © 1997-1999 Vita Nuova Limited.
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
+// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/*
+ * arm definition
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "ureg_arm.h"
+#include <mach.h>
+
+#define REGOFF(x) (ulong) (&((struct Ureg *) 0)->x)
+
+#define SP REGOFF(r13)
+#define PC REGOFF(pc)
+
+#define REGSIZE sizeof(struct Ureg)
+
+Reglist armreglist[] =
+{
+ {"LINK", REGOFF(link), RINT|RRDONLY, 'X'},
+ {"TYPE", REGOFF(type), RINT|RRDONLY, 'X'},
+ {"PSR", REGOFF(psr), RINT|RRDONLY, 'X'},
+ {"PC", PC, RINT, 'X'},
+ {"SP", SP, RINT, 'X'},
+ {"R15", PC, RINT, 'X'},
+ {"R14", REGOFF(r14), RINT, 'X'},
+ {"R13", REGOFF(r13), RINT, 'X'},
+ {"R12", REGOFF(r12), RINT, 'X'},
+ {"R11", REGOFF(r11), RINT, 'X'},
+ {"R10", REGOFF(r10), RINT, 'X'},
+ {"R9", REGOFF(r9), RINT, 'X'},
+ {"R8", REGOFF(r8), RINT, 'X'},
+ {"R7", REGOFF(r7), RINT, 'X'},
+ {"R6", REGOFF(r6), RINT, 'X'},
+ {"R5", REGOFF(r5), RINT, 'X'},
+ {"R4", REGOFF(r4), RINT, 'X'},
+ {"R3", REGOFF(r3), RINT, 'X'},
+ {"R2", REGOFF(r2), RINT, 'X'},
+ {"R1", REGOFF(r1), RINT, 'X'},
+ {"R0", REGOFF(r0), RINT, 'X'},
+ { 0 }
+};
+
+ /* the machine description */
+Mach marm =
+{
+ "arm",
+ MARM, /* machine type */
+ armreglist, /* register set */
+ REGSIZE, /* register set size */
+ 0, /* fp register set size */
+ "PC", /* name of PC */
+ "SP", /* name of SP */
+ "R15", /* name of link register */
+ "setR12", /* static base register name */
+ 0, /* static base register value */
+ 0x1000, /* page size */
+ 0xC0000000, /* kernel base */
+ 0, /* kernel text mask */
+ 4, /* quantization of pc */
+ 4, /* szaddr */
+ 4, /* szreg */
+ 4, /* szfloat */
+ 8, /* szdouble */
+};
diff --git a/src/libmach/5db.c b/src/libmach/5db.c
new file mode 100644
index 000000000..aea391edf
--- /dev/null
+++ b/src/libmach/5db.c
@@ -0,0 +1,1095 @@
+// Inferno libmach/5db.c
+// http://code.google.com/p/inferno-os/source/browse/utils/libmach/5db.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc.
+// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
+// Portions Copyright © 1997-1999 Vita Nuova Limited.
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
+// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "ureg_arm.h"
+#include <mach.h>
+
+static int debug = 0;
+
+#define BITS(a, b) ((1<<(b+1))-(1<<a))
+
+#define LSR(v, s) ((ulong)(v) >> (s))
+#define ASR(v, s) ((long)(v) >> (s))
+#define ROR(v, s) (LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
+
+
+
+typedef struct Instr Instr;
+struct Instr
+{
+ Map *map;
+ ulong w;
+ ulong addr;
+ uchar op; /* super opcode */
+
+ uchar cond; /* bits 28-31 */
+ uchar store; /* bit 20 */
+
+ uchar rd; /* bits 12-15 */
+ uchar rn; /* bits 16-19 */
+ uchar rs; /* bits 0-11 (shifter operand) */
+
+ long imm; /* rotated imm */
+ char* curr; /* fill point in buffer */
+ char* end; /* end of buffer */
+ char* err; /* error message */
+};
+
+typedef struct Opcode Opcode;
+struct Opcode
+{
+ char* o;
+ void (*fmt)(Opcode*, Instr*);
+ ulong (*foll)(Map*, Rgetter, Instr*, ulong);
+ char* a;
+};
+
+static void format(char*, Instr*, char*);
+static char FRAMENAME[] = ".frame";
+
+/*
+ * Arm-specific debugger interface
+ */
+
+extern char *armexcep(Map*, Rgetter);
+static int armfoll(Map*, uvlong, Rgetter, uvlong*);
+static int arminst(Map*, uvlong, char, char*, int);
+static int armdas(Map*, uvlong, char*, int);
+static int arminstlen(Map*, uvlong);
+
+/*
+ * Debugger interface
+ */
+Machdata armmach =
+{
+ {0, 0, 0, 0xD}, /* break point */
+ 4, /* break point size */
+
+ leswab, /* short to local byte order */
+ leswal, /* long to local byte order */
+ leswav, /* long to local byte order */
+ risctrace, /* C traceback */
+ riscframe, /* Frame finder */
+ armexcep, /* print exception */
+ 0, /* breakpoint fixup */
+ 0, /* single precision float printer */
+ 0, /* double precision float printer */
+ armfoll, /* following addresses */
+ arminst, /* print instruction */
+ armdas, /* dissembler */
+ arminstlen, /* instruction size */
+};
+
+char*
+armexcep(Map *map, Rgetter rget)
+{
+ long c;
+
+ c = (*rget)(map, "TYPE");
+ switch (c&0x1f) {
+ case 0x11:
+ return "Fiq interrupt";
+ case 0x12:
+ return "Mirq interrupt";
+ case 0x13:
+ return "SVC/SWI Exception";
+ case 0x17:
+ return "Prefetch Abort/Data Abort";
+ case 0x18:
+ return "Data Abort";
+ case 0x1b:
+ return "Undefined instruction/Breakpoint";
+ case 0x1f:
+ return "Sys trap";
+ default:
+ return "Undefined trap";
+ }
+}
+
+static
+char* cond[16] =
+{
+ "EQ", "NE", "CS", "CC",
+ "MI", "PL", "VS", "VC",
+ "HI", "LS", "GE", "LT",
+ "GT", "LE", 0, "NV"
+};
+
+static
+char* shtype[4] =
+{
+ "<<", ">>", "->", "@>"
+};
+
+static
+char *hb[4] =
+{
+ "???", "HU", "B", "H"
+};
+
+static
+char* addsub[2] =
+{
+ "-", "+",
+};
+
+int
+armclass(long w)
+{
+ int op;
+
+ op = (w >> 25) & 0x7;
+ switch(op) {
+ case 0: /* data processing r,r,r */
+ op = ((w >> 4) & 0xf);
+ if(op == 0x9) {
+ op = 48+16; /* mul */
+ if(w & (1<<24)) {
+ op += 2;
+ if(w & (1<<22))
+ op++; /* swap */
+ break;
+ }
+ if(w & (1<<21))
+ op++; /* mla */
+ break;
+ }
+ if ((op & 0x9) == 0x9) /* ld/st byte/half s/u */
+ {
+ op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
+ break;
+ }
+ op = (w >> 21) & 0xf;
+ if(w & (1<<4))
+ op += 32;
+ else
+ if(w & (31<<7))
+ op += 16;
+ break;
+ case 1: /* data processing i,r,r */
+ op = (48) + ((w >> 21) & 0xf);
+ break;
+ case 2: /* load/store byte/word i(r) */
+ op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
+ break;
+ case 3: /* load/store byte/word (r)(r) */
+ op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
+ break;
+ case 4: /* block data transfer (r)(r) */
+ op = (48+24+4+4) + ((w >> 20) & 0x1);
+ break;
+ case 5: /* branch / branch link */
+ op = (48+24+4+4+2) + ((w >> 24) & 0x1);
+ break;
+ case 7: /* coprocessor crap */
+ op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
+ break;
+ default:
+ op = (48+24+4+4+2+2+4);
+ break;
+ }
+ return op;
+}
+
+static int
+decode(Map *map, ulong pc, Instr *i)
+{
+ uint32 w;
+
+ if(get4(map, pc, &w) < 0) {
+ werrstr("can't read instruction: %r");
+ return -1;
+ }
+ i->w = w;
+ i->addr = pc;
+ i->cond = (w >> 28) & 0xF;
+ i->op = armclass(w);
+ i->map = map;
+ return 1;
+}
+
+static void
+bprint(Instr *i, char *fmt, ...)
+{
+ va_list arg;
+
+ va_start(arg, fmt);
+ i->curr = vseprint(i->curr, i->end, fmt, arg);
+ va_end(arg);
+}
+
+static int
+plocal(Instr *i)
+{
+ char *reg;
+ Symbol s;
+ char *fn;
+ int class;
+ int offset;
+
+ if(!findsym(i->addr, CTEXT, &s)) {
+ if(debug)fprint(2,"fn not found @%lux: %r\n", i->addr);
+ return 0;
+ }
+ fn = s.name;
+ if (!findlocal(&s, FRAMENAME, &s)) {
+ if(debug)fprint(2,"%s.%s not found @%s: %r\n", fn, FRAMENAME, s.name);
+ return 0;
+ }
+ if(s.value > i->imm) {
+ class = CAUTO;
+ offset = s.value-i->imm;
+ reg = "(SP)";
+ } else {
+ class = CPARAM;
+ offset = i->imm-s.value-4;
+ reg = "(FP)";
+ }
+ if(!getauto(&s, offset, class, &s)) {
+ if(debug)fprint(2,"%s %s not found @%ux: %r\n", fn,
+ class == CAUTO ? " auto" : "param", offset);
+ return 0;
+ }
+ bprint(i, "%s%c%d%s", s.name, class == CPARAM ? '+' : '-', s.value, reg);
+ return 1;
+}
+
+/*
+ * Print value v as name[+offset]
+ */
+int
+gsymoff(char *buf, int n, long v, int space)
+{
+ Symbol s;
+ int r;
+ long delta;
+
+ r = delta = 0; /* to shut compiler up */
+ if (v) {
+ r = findsym(v, space, &s);
+ if (r)
+ delta = v-s.value;
+ if (delta < 0)
+ delta = -delta;
+ }
+ if (v == 0 || r == 0 || delta >= 4096)
+ return snprint(buf, n, "#%lux", v);
+ if (strcmp(s.name, ".string") == 0)
+ return snprint(buf, n, "#%lux", v);
+ if (!delta)
+ return snprint(buf, n, "%s", s.name);
+ if (s.type != 't' && s.type != 'T')
+ return snprint(buf, n, "%s+%lux", s.name, v-s.value);
+ else
+ return snprint(buf, n, "#%lux", v);
+}
+
+static void
+armdps(Opcode *o, Instr *i)
+{
+ i->store = (i->w >> 20) & 1;
+ i->rn = (i->w >> 16) & 0xf;
+ i->rd = (i->w >> 12) & 0xf;
+ i->rs = (i->w >> 0) & 0xf;
+ if(i->rn == 15 && i->rs == 0) {
+ if(i->op == 8) {
+ format("MOVW", i,"CPSR, R%d");
+ return;
+ } else
+ if(i->op == 10) {
+ format("MOVW", i,"SPSR, R%d");
+ return;
+ }
+ } else
+ if(i->rn == 9 && i->rd == 15) {
+ if(i->op == 9) {
+ format("MOVW", i, "R%s, CPSR");
+ return;
+ } else
+ if(i->op == 11) {
+ format("MOVW", i, "R%s, SPSR");
+ return;
+ }
+ }
+ format(o->o, i, o->a);
+}
+
+static void
+armdpi(Opcode *o, Instr *i)
+{
+ ulong v;
+ int c;
+
+ v = (i->w >> 0) & 0xff;
+ c = (i->w >> 8) & 0xf;
+ while(c) {
+ v = (v<<30) | (v>>2);
+ c--;
+ }
+ i->imm = v;
+ i->store = (i->w >> 20) & 1;
+ i->rn = (i->w >> 16) & 0xf;
+ i->rd = (i->w >> 12) & 0xf;
+ i->rs = i->w&0x0f;
+
+ /* RET is encoded as ADD #0,R14,R15 */
+ if((i->w & 0x0fffffff) == 0x028ef000){
+ format("RET%C", i, "");
+ return;
+ }
+ if((i->w & 0x0ff0ffff) == 0x0280f000){
+ format("B%C", i, "0(R%n)");
+ return;
+ }
+ format(o->o, i, o->a);
+}
+
+static void
+armsdti(Opcode *o, Instr *i)
+{
+ ulong v;
+
+ v = i->w & 0xfff;
+ if(!(i->w & (1<<23)))
+ v = -v;
+ i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
+ i->imm = v;
+ i->rn = (i->w >> 16) & 0xf;
+ i->rd = (i->w >> 12) & 0xf;
+ /* RET is encoded as LW.P x,R13,R15 */
+ if ((i->w & 0x0ffff000) == 0x049df000)
+ {
+ format("RET%C%p", i, "%I");
+ return;
+ }
+ format(o->o, i, o->a);
+}
+
+/* arm V4 ld/st halfword, signed byte */
+static void
+armhwby(Opcode *o, Instr *i)
+{
+ i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
+ i->imm = (i->w & 0xf) | ((i->w >> 8) & 0xf);
+ if (!(i->w & (1 << 23)))
+ i->imm = - i->imm;
+ i->rn = (i->w >> 16) & 0xf;
+ i->rd = (i->w >> 12) & 0xf;
+ i->rs = (i->w >> 0) & 0xf;
+ format(o->o, i, o->a);
+}
+
+static void
+armsdts(Opcode *o, Instr *i)
+{
+ i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
+ i->rs = (i->w >> 0) & 0xf;
+ i->rn = (i->w >> 16) & 0xf;
+ i->rd = (i->w >> 12) & 0xf;
+ format(o->o, i, o->a);
+}
+
+static void
+armbdt(Opcode *o, Instr *i)
+{
+ i->store = (i->w >> 21) & 0x3; /* S & W bits */
+ i->rn = (i->w >> 16) & 0xf;
+ i->imm = i->w & 0xffff;
+ if(i->w == 0xe8fd8000)
+ format("RFE", i, "");
+ else
+ format(o->o, i, o->a);
+}
+
+/*
+static void
+armund(Opcode *o, Instr *i)
+{
+ format(o->o, i, o->a);
+}
+
+static void
+armcdt(Opcode *o, Instr *i)
+{
+ format(o->o, i, o->a);
+}
+*/
+
+static void
+armunk(Opcode *o, Instr *i)
+{
+ format(o->o, i, o->a);
+}
+
+static void
+armb(Opcode *o, Instr *i)
+{
+ ulong v;
+
+ v = i->w & 0xffffff;
+ if(v & 0x800000)
+ v |= ~0xffffff;
+ i->imm = (v<<2) + i->addr + 8;
+ format(o->o, i, o->a);
+}
+
+static void
+armco(Opcode *o, Instr *i) /* coprocessor instructions */
+{
+ int op, p, cp;
+
+ char buf[1024];
+
+ i->rn = (i->w >> 16) & 0xf;
+ i->rd = (i->w >> 12) & 0xf;
+ i->rs = i->w&0xf;
+ cp = (i->w >> 8) & 0xf;
+ p = (i->w >> 5) & 0x7;
+ if(i->w&(1<<4)) {
+ op = (i->w >> 21) & 0x07;
+ snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
+ } else {
+ op = (i->w >> 20) & 0x0f;
+ snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
+ }
+ format(o->o, i, buf);
+}
+
+static int
+armcondpass(Map *map, Rgetter rget, uchar cond)
+{
+ ulong psr;
+ uchar n;
+ uchar z;
+ uchar c;
+ uchar v;
+
+ psr = rget(map, "PSR");
+ n = (psr >> 31) & 1;
+ z = (psr >> 30) & 1;
+ c = (psr >> 29) & 1;
+ v = (psr >> 28) & 1;
+
+ switch(cond) {
+ case 0: return z;
+ case 1: return !z;
+ case 2: return c;
+ case 3: return !c;
+ case 4: return n;
+ case 5: return !n;
+ case 6: return v;
+ case 7: return !v;
+ case 8: return c && !z;
+ case 9: return !c || z;
+ case 10: return n == v;
+ case 11: return n != v;
+ case 12: return !z && (n == v);
+ case 13: return z && (n != v);
+ case 14: return 1;
+ case 15: return 0;
+ }
+ return 0;
+}
+
+static ulong
+armshiftval(Map *map, Rgetter rget, Instr *i)
+{
+ if(i->w & (1 << 25)) { /* immediate */
+ ulong imm = i->w & BITS(0, 7);
+ ulong s = (i->w & BITS(8, 11)) >> 7; /* this contains the *2 */
+ return ROR(imm, s);
+ } else {
+ char buf[8];
+ ulong v;
+ ulong s = (i->w & BITS(7,11)) >> 7;
+
+ sprint(buf, "R%ld", i->w & 0xf);
+ v = rget(map, buf);
+
+ switch((i->w & BITS(4, 6)) >> 4) {
+ case 0: /* LSLIMM */
+ return v << s;
+ case 1: /* LSLREG */
+ sprint(buf, "R%lud", s >> 1);
+ s = rget(map, buf) & 0xFF;
+ if(s >= 32) return 0;
+ return v << s;
+ case 2: /* LSRIMM */
+ return LSR(v, s);
+ case 3: /* LSRREG */
+ sprint(buf, "R%ld", s >> 1);
+ s = rget(map, buf) & 0xFF;
+ if(s >= 32) return 0;
+ return LSR(v, s);
+ case 4: /* ASRIMM */
+ if(s == 0) {
+ if((v & (1U<<31)) == 0)
+ return 0;
+ return 0xFFFFFFFF;
+ }
+ return ASR(v, s);
+ case 5: /* ASRREG */
+ sprint(buf, "R%ld", s >> 1);
+ s = rget(map, buf) & 0xFF;
+ if(s >= 32) {
+ if((v & (1U<<31)) == 0)
+ return 0;
+ return 0xFFFFFFFF;
+ }
+ return ASR(v, s);
+ case 6: /* RORIMM */
+ if(s == 0) {
+ ulong c = (rget(map, "PSR") >> 29) & 1;
+
+ return (c << 31) | LSR(v, 1);
+ }
+ return ROR(v, s);
+ case 7: /* RORREG */
+ sprint(buf, "R%ld", (s>>1)&0xF);
+ s = rget(map, buf);
+ if(s == 0 || (s & 0xF) == 0)
+ return v;
+ return ROR(v, s & 0xF);
+ }
+ }
+ return 0;
+}
+
+static int
+nbits(ulong v)
+{
+ int n = 0;
+ int i;
+
+ for(i=0; i < 32 ; i++) {
+ if(v & 1) ++n;
+ v >>= 1;
+ }
+
+ return n;
+}
+
+static ulong
+armmaddr(Map *map, Rgetter rget, Instr *i)
+{
+ ulong v;
+ ulong nb;
+ char buf[8];
+ ulong rn;
+
+ rn = (i->w >> 16) & 0xf;
+ sprint(buf,"R%ld", rn);
+
+ v = rget(map, buf);
+ nb = nbits(i->w & ((1 << 15) - 1));
+
+ switch((i->w >> 23) & 3) {
+ case 0: return (v - (nb*4)) + 4;
+ case 1: return v;
+ case 2: return v - (nb*4);
+ case 3: return v + 4;
+ }
+ return 0;
+}
+
+static ulong
+armaddr(Map *map, Rgetter rget, Instr *i)
+{
+ char buf[8];
+ ulong rn;
+
+ sprint(buf, "R%ld", (i->w >> 16) & 0xf);
+ rn = rget(map, buf);
+
+ if((i->w & (1<<24)) == 0) { /* POSTIDX */
+ sprint(buf, "R%ld", rn);
+ return rget(map, buf);
+ }
+
+ if((i->w & (1<<25)) == 0) { /* OFFSET */
+ sprint(buf, "R%ld", rn);
+ if(i->w & (1U<<23))
+ return rget(map, buf) + (i->w & BITS(0,11));
+ return rget(map, buf) - (i->w & BITS(0,11));
+ } else { /* REGOFF */
+ ulong index = 0;
+ uchar c;
+ uchar rm;
+
+ sprint(buf, "R%ld", i->w & 0xf);
+ rm = rget(map, buf);
+
+ switch((i->w & BITS(5,6)) >> 5) {
+ case 0: index = rm << ((i->w & BITS(7,11)) >> 7); break;
+ case 1: index = LSR(rm, ((i->w & BITS(7,11)) >> 7)); break;
+ case 2: index = ASR(rm, ((i->w & BITS(7,11)) >> 7)); break;
+ case 3:
+ if((i->w & BITS(7,11)) == 0) {
+ c = (rget(map, "PSR") >> 29) & 1;
+ index = c << 31 | LSR(rm, 1);
+ } else {
+ index = ROR(rm, ((i->w & BITS(7,11)) >> 7));
+ }
+ break;
+ }
+ if(i->w & (1<<23))
+ return rn + index;
+ return rn - index;
+ }
+}
+
+static ulong
+armfadd(Map *map, Rgetter rget, Instr *i, ulong pc)
+{
+ char buf[8];
+ int r;
+
+ r = (i->w >> 12) & 0xf;
+ if(r != 15 || !armcondpass(map, rget, (i->w >> 28) & 0xf))
+ return pc+4;
+
+ r = (i->w >> 16) & 0xf;
+ sprint(buf, "R%d", r);
+
+ return rget(map, buf) + armshiftval(map, rget, i);
+}
+
+static ulong
+armfmovm(Map *map, Rgetter rget, Instr *i, ulong pc)
+{
+ uint32 v;
+ ulong addr;
+
+ v = i->w & 1<<15;
+ if(!v || !armcondpass(map, rget, (i->w>>28)&0xf))
+ return pc+4;
+
+ addr = armmaddr(map, rget, i) + nbits(i->w & BITS(0,15));
+ if(get4(map, addr, &v) < 0) {
+ werrstr("can't read addr: %r");
+ return -1;
+ }
+ return v;
+}
+
+static ulong
+armfbranch(Map *map, Rgetter rget, Instr *i, ulong pc)
+{
+ if(!armcondpass(map, rget, (i->w >> 28) & 0xf))
+ return pc+4;
+
+ return pc + (((signed long)i->w << 8) >> 6) + 8;
+}
+
+static ulong
+armfmov(Map *map, Rgetter rget, Instr *i, ulong pc)
+{
+ ulong rd;
+ uint32 v;
+
+ rd = (i->w >> 12) & 0xf;
+ if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf))
+ return pc+4;
+
+ /* LDR */
+ /* BUG: Needs LDH/B, too */
+ if(((i->w>>26)&0x3) == 1) {
+ if(get4(map, armaddr(map, rget, i), &v) < 0) {
+ werrstr("can't read instruction: %r");
+ return pc+4;
+ }
+ return v;
+ }
+
+ /* MOV */
+ return armshiftval(map, rget, i);
+}
+
+static Opcode opcodes[] =
+{
+ "AND%C%S", armdps, 0, "R%s,R%n,R%d",
+ "EOR%C%S", armdps, 0, "R%s,R%n,R%d",
+ "SUB%C%S", armdps, 0, "R%s,R%n,R%d",
+ "RSB%C%S", armdps, 0, "R%s,R%n,R%d",
+ "ADD%C%S", armdps, armfadd, "R%s,R%n,R%d",
+ "ADC%C%S", armdps, 0, "R%s,R%n,R%d",
+ "SBC%C%S", armdps, 0, "R%s,R%n,R%d",
+ "RSC%C%S", armdps, 0, "R%s,R%n,R%d",
+ "TST%C%S", armdps, 0, "R%s,R%n",
+ "TEQ%C%S", armdps, 0, "R%s,R%n",
+ "CMP%C%S", armdps, 0, "R%s,R%n",
+ "CMN%C%S", armdps, 0, "R%s,R%n",
+ "ORR%C%S", armdps, 0, "R%s,R%n,R%d",
+ "MOVW%C%S", armdps, armfmov, "R%s,R%d",
+ "BIC%C%S", armdps, 0, "R%s,R%n,R%d",
+ "MVN%C%S", armdps, 0, "R%s,R%d",
+
+/* 16 */
+ "AND%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "EOR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "SUB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "RSB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "ADD%C%S", armdps, armfadd, "(R%s%h%m),R%n,R%d",
+ "ADC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "SBC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "RSC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "TST%C%S", armdps, 0, "(R%s%h%m),R%n",
+ "TEQ%C%S", armdps, 0, "(R%s%h%m),R%n",
+ "CMP%C%S", armdps, 0, "(R%s%h%m),R%n",
+ "CMN%C%S", armdps, 0, "(R%s%h%m),R%n",
+ "ORR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "MOVW%C%S", armdps, armfmov, "(R%s%h%m),R%d",
+ "BIC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
+ "MVN%C%S", armdps, 0, "(R%s%h%m),R%d",
+
+/* 32 */
+ "AND%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "EOR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "SUB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "RSB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "ADD%C%S", armdps, armfadd, "(R%s%hR%M),R%n,R%d",
+ "ADC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "SBC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "RSC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "TST%C%S", armdps, 0, "(R%s%hR%M),R%n",
+ "TEQ%C%S", armdps, 0, "(R%s%hR%M),R%n",
+ "CMP%C%S", armdps, 0, "(R%s%hR%M),R%n",
+ "CMN%C%S", armdps, 0, "(R%s%hR%M),R%n",
+ "ORR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "MOVW%C%S", armdps, armfmov, "(R%s%hR%M),R%d",
+ "BIC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
+ "MVN%C%S", armdps, 0, "(R%s%hR%M),R%d",
+
+/* 48 */
+ "AND%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "EOR%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "SUB%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "RSB%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "ADD%C%S", armdpi, armfadd, "$#%i,R%n,R%d",
+ "ADC%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "SBC%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "RSC%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "TST%C%S", armdpi, 0, "$#%i,R%n",
+ "TEQ%C%S", armdpi, 0, "$#%i,R%n",
+ "CMP%C%S", armdpi, 0, "$#%i,R%n",
+ "CMN%C%S", armdpi, 0, "$#%i,R%n",
+ "ORR%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "MOVW%C%S", armdpi, armfmov, "$#%i,R%d",
+ "BIC%C%S", armdpi, 0, "$#%i,R%n,R%d",
+ "MVN%C%S", armdpi, 0, "$#%i,R%d",
+
+/* 48+16 */
+ "MUL%C%S", armdpi, 0, "R%s,R%M,R%n",
+ "MULA%C%S", armdpi, 0, "R%s,R%M,R%n,R%d",
+ "SWPW", armdpi, 0, "R%s,(R%n),R%d",
+ "SWPB", armdpi, 0, "R%s,(R%n),R%d",
+
+/* 48+16+4 */
+ "MOV%u%C%p", armhwby, 0, "R%d,(R%n%UR%M)",
+ "MOV%u%C%p", armhwby, 0, "R%d,%I",
+ "MOV%u%C%p", armhwby, armfmov, "(R%n%UR%M),R%d",
+ "MOV%u%C%p", armhwby, armfmov, "%I,R%d",
+
+/* 48+24 */
+ "MOVW%C%p", armsdti, 0, "R%d,%I",
+ "MOVB%C%p", armsdti, 0, "R%d,%I",
+ "MOVW%C%p", armsdti, armfmov, "%I,R%d",
+ "MOVBU%C%p", armsdti, armfmov, "%I,R%d",
+
+ "MOVW%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
+ "MOVB%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
+ "MOVW%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
+ "MOVBU%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
+
+ "MOVM%C%P%a", armbdt, armfmovm, "[%r],(R%n)",
+ "MOVM%C%P%a", armbdt, armfmovm, "(R%n),[%r]",
+
+ "B%C", armb, armfbranch, "%b",
+ "BL%C", armb, armfbranch, "%b",
+
+ "CDP%C", armco, 0, "",
+ "CDP%C", armco, 0, "",
+ "MCR%C", armco, 0, "",
+ "MRC%C", armco, 0, "",
+
+ "UNK", armunk, 0, "",
+};
+
+static void
+gaddr(Instr *i)
+{
+ *i->curr++ = '$';
+ i->curr += gsymoff(i->curr, i->end-i->curr, i->imm, CANY);
+}
+
+static char *mode[] = { 0, "IA", "DB", "IB" };
+static char *pw[] = { "P", "PW", 0, "W" };
+static char *sw[] = { 0, "W", "S", "SW" };
+
+static void
+format(char *mnemonic, Instr *i, char *f)
+{
+ int j, k, m, n;
+ int g;
+ char *fmt;
+
+ if(mnemonic)
+ format(0, i, mnemonic);
+ if(f == 0)
+ return;
+ if(mnemonic)
+ if(i->curr < i->end)
+ *i->curr++ = '\t';
+ for ( ; *f && i->curr < i->end; f++) {
+ if(*f != '%') {
+ *i->curr++ = *f;
+ continue;
+ }
+ switch (*++f) {
+
+ case 'C': /* .CONDITION */
+ if(cond[i->cond])
+ bprint(i, ".%s", cond[i->cond]);
+ break;
+
+ case 'S': /* .STORE */
+ if(i->store)
+ bprint(i, ".S");
+ break;
+
+ case 'P': /* P & U bits for block move */
+ n = (i->w >>23) & 0x3;
+ if (mode[n])
+ bprint(i, ".%s", mode[n]);
+ break;
+
+ case 'p': /* P & W bits for single data xfer*/
+ if (pw[i->store])
+ bprint(i, ".%s", pw[i->store]);
+ break;
+
+ case 'a': /* S & W bits for single data xfer*/
+ if (sw[i->store])
+ bprint(i, ".%s", sw[i->store]);
+ break;
+
+ case 's':
+ bprint(i, "%d", i->rs & 0xf);
+ break;
+
+ case 'M':
+ bprint(i, "%d", (i->w>>8) & 0xf);
+ break;
+
+ case 'm':
+ bprint(i, "%d", (i->w>>7) & 0x1f);
+ break;
+
+ case 'h':
+ bprint(i, shtype[(i->w>>5) & 0x3]);
+ break;
+
+ case 'u': /* Signed/unsigned Byte/Halfword */
+ bprint(i, hb[(i->w>>5) & 0x3]);
+ break;
+
+ case 'I':
+ if (i->rn == 13) {
+ if (plocal(i))
+ break;
+ }
+ g = 0;
+ fmt = "#%lx(R%d)";
+ if (i->rn == 15) {
+ /* convert load of offset(PC) to a load immediate */
+ uint32 x;
+ if (get4(i->map, i->addr+i->imm+8, &x) > 0)
+ {
+ i->imm = (int32)x;
+ g = 1;
+ fmt = "";
+ }
+ }
+ if (mach->sb)
+ {
+ if (i->rd == 11) {
+ uint32 nxti;
+
+ if (get4(i->map, i->addr+4, &nxti) > 0) {
+ if ((nxti & 0x0e0f0fff) == 0x060c000b) {
+ i->imm += mach->sb;
+ g = 1;
+ fmt = "-SB";
+ }
+ }
+ }
+ if (i->rn == 12)
+ {
+ i->imm += mach->sb;
+ g = 1;
+ fmt = "-SB(SB)";
+ }
+ }
+ if (g)
+ {
+ gaddr(i);
+ bprint(i, fmt, i->rn);
+ }
+ else
+ bprint(i, fmt, i->imm, i->rn);
+ break;
+ case 'U': /* Add/subtract from base */
+ bprint(i, addsub[(i->w >> 23) & 1]);
+ break;
+
+ case 'n':
+ bprint(i, "%d", i->rn);
+ break;
+
+ case 'd':
+ bprint(i, "%d", i->rd);
+ break;
+
+ case 'i':
+ bprint(i, "%lux", i->imm);
+ break;
+
+ case 'b':
+ i->curr += symoff(i->curr, i->end-i->curr,
+ i->imm, CTEXT);
+ break;
+
+ case 'g':
+ i->curr += gsymoff(i->curr, i->end-i->curr,
+ i->imm, CANY);
+ break;
+
+ case 'r':
+ n = i->imm&0xffff;
+ j = 0;
+ k = 0;
+ while(n) {
+ m = j;
+ while(n&0x1) {
+ j++;
+ n >>= 1;
+ }
+ if(j != m) {
+ if(k)
+ bprint(i, ",");
+ if(j == m+1)
+ bprint(i, "R%d", m);
+ else
+ bprint(i, "R%d-R%d", m, j-1);
+ k = 1;
+ }
+ j++;
+ n >>= 1;
+ }
+ break;
+
+ case '\0':
+ *i->curr++ = '%';
+ return;
+
+ default:
+ bprint(i, "%%%c", *f);
+ break;
+ }
+ }
+ *i->curr = 0;
+}
+
+static int
+printins(Map *map, ulong pc, char *buf, int n)
+{
+ Instr i;
+
+ i.curr = buf;
+ i.end = buf+n-1;
+ if(decode(map, pc, &i) < 0)
+ return -1;
+
+ (*opcodes[i.op].fmt)(&opcodes[i.op], &i);
+ return 4;
+}
+
+static int
+arminst(Map *map, uvlong pc, char modifier, char *buf, int n)
+{
+ USED(modifier);
+ return printins(map, pc, buf, n);
+}
+
+static int
+armdas(Map *map, uvlong pc, char *buf, int n)
+{
+ Instr i;
+
+ i.curr = buf;
+ i.end = buf+n;
+ if(decode(map, pc, &i) < 0)
+ return -1;
+ if(i.end-i.curr > 8)
+ i.curr = _hexify(buf, i.w, 7);
+ *i.curr = 0;
+ return 4;
+}
+
+static int
+arminstlen(Map *map, uvlong pc)
+{
+ Instr i;
+
+ if(decode(map, pc, &i) < 0)
+ return -1;
+ return 4;
+}
+
+static int
+armfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
+{
+ ulong d;
+ Instr i;
+
+ if(decode(map, pc, &i) < 0)
+ return -1;
+
+ if(opcodes[i.op].foll) {
+ d = (*opcodes[i.op].foll)(map, rget, &i, pc);
+ if(d == -1)
+ return -1;
+ } else
+ d = pc+4;
+
+ foll[0] = d;
+ return 1;
+}
diff --git a/src/libmach/Makefile b/src/libmach/Makefile
index b0031486a..cde2cdf66 100644
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -39,8 +39,10 @@ OFILES=\
access.$O\
machdata.$O\
setmach.$O\
+ 5.$O\
6.$O\
8.$O\
+ 5db.$O\
8db.$O\
5obj.$O\
6obj.$O\
diff --git a/src/libmach/executable.c b/src/libmach/executable.c
index 075738e9c..6bde5b5a4 100644
--- a/src/libmach/executable.c
+++ b/src/libmach/executable.c
@@ -108,7 +108,6 @@ Mach mmips2be;
Mach msparc;
Mach msparc64;
Mach m68020;
-Mach marm;
Mach mpower;
Mach mpower64;
Mach malpha;
diff --git a/src/libmach/setmach.c b/src/libmach/setmach.c
index b88778186..0fa4d3192 100644
--- a/src/libmach/setmach.c
+++ b/src/libmach/setmach.c
@@ -1,11 +1,11 @@
// Inferno libmach/setmach.c
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/setmach.c
//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
+// Copyright © 1994-1999 Lucent Technologies Inc.
+// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
+// Portions Copyright © 1997-1999 Vita Nuova Limited.
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
+// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -50,8 +50,8 @@ extern Mach mmips, msparc, m68020, mi386, mamd64,
extern Machdata mipsmach, sparcmach, m68020mach, i386mach,
armmach, mipsmach2le, powermach, alphamach, sparc64mach;
*/
-extern Mach mi386, mamd64;
-extern Machdata i386mach;
+extern Mach mi386, mamd64, marm;
+extern Machdata i386mach, armmach;
/*
* machine selection table. machines with native disassemblers should
@@ -72,6 +72,12 @@ Machtab machines[] =
AAMD64,
&mamd64,
&i386mach, },
+ { "arm", /*ARM*/
+ FARM,
+ FARMB,
+ AARM,
+ &marm,
+ &armmach, },
#ifdef unused
{ "68020", /*68020*/
F68020,
@@ -127,12 +133,6 @@ Machtab machines[] =
AI8086,
&mi386,
&i386mach, },
- { "arm", /*ARM*/
- FARM,
- FARMB,
- AARM,
- &marm,
- &armmach, },
{ "power", /*PowerPC*/
FPOWER,
FPOWERB,