diff options
Diffstat (limited to 'src/libmach/5db.c')
-rw-r--r-- | src/libmach/5db.c | 1095 |
1 files changed, 0 insertions, 1095 deletions
diff --git a/src/libmach/5db.c b/src/libmach/5db.c deleted file mode 100644 index ae71dd90d..000000000 --- a/src/libmach/5db.c +++ /dev/null @@ -1,1095 +0,0 @@ -// 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+%llux", 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; -} |