diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libmach/7db.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libmach/7db.c')
-rwxr-xr-x | sys/src/libmach/7db.c | 925 |
1 files changed, 925 insertions, 0 deletions
diff --git a/sys/src/libmach/7db.c b/sys/src/libmach/7db.c new file mode 100755 index 000000000..bf101dd27 --- /dev/null +++ b/sys/src/libmach/7db.c @@ -0,0 +1,925 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +/* + * Alpha-specific debugger interface + */ + +static char *alphaexcep(Map*, Rgetter); +static int alphafoll(Map*, uvlong, Rgetter, uvlong*); +static int alphainst(Map*, uvlong, char, char*, int); +static int alphadas(Map*, uvlong, char*, int); +static int alphainstlen(Map*, uvlong); +/* + * Debugger interface + */ +Machdata alphamach = +{ + {0x80, 0, 0, 0}, /* break point */ + 4, /* break point size */ + + leswab, /* short to local byte order */ + leswal, /* long to local byte order */ + leswav, /* vlong to local byte order */ + risctrace, /* C traceback */ + riscframe, /* Frame finder */ + alphaexcep, /* print exception */ + 0, /* breakpoint fixup */ + leieeesftos, /* single precision float printer */ + leieeedftos, /* double precisioin float printer */ + alphafoll, /* following addresses */ + alphainst, /* print instruction */ + alphadas, /* dissembler */ + alphainstlen, /* instruction size */ +}; + +static char *illegaltype[] = { + "breakpoint", + "bugchk", + "gentrap", + "fen", + "illegal instruction", +}; + +static char * +alphaexcep(Map *map, Rgetter rget) +{ + ulong type, a0, a1; + static char buf[256]; + + type = (*rget)(map, "TYPE"); + a0 = (*rget)(map, "A0"); + a1 = (*rget)(map, "A1"); +/* a2 = (*rget)(map, "A2"); */ + + switch (type) { + case 1: /* arith */ + sprint(buf, "trap: arithmetic trap 0x%lux", a0); + break; + case 2: /* bad instr or FEN */ + if (a0 <= 4) + return illegaltype[a0]; + else + sprint(buf, "illegal instr trap, unknown type %lud", a0); + break; + case 3: /* intr */ + sprint(buf, "interrupt type %lud", a0); + break; + case 4: /* memory fault */ + sprint(buf, "fault %s addr=0x%lux", (a1&1)?"write":"read", a0); + break; + case 5: /* syscall() */ + return "system call"; + case 6: /* alignment fault */ + sprint(buf, "unaligned op 0x%lux addr 0x%lux", a1, a0); + break; + default: /* cannot happen */ + sprint(buf, "unknown exception type %lud", type); + break; + } + return buf; +} + + /* alpha disassembler and related functions */ + +static char FRAMENAME[] = ".frame"; + +typedef struct { + uvlong addr; + uchar op; /* bits 31-26 */ + uchar ra; /* bits 25-21 */ + uchar rb; /* bits 20-16 */ + uchar rc; /* bits 4-0 */ + long mem; /* bits 15-0 */ + long branch; /* bits 20-0 */ + uchar function; /* bits 11-5 */ + uchar literal; /* bits 20-13 */ + uchar islit; /* bit 12 */ + uchar fpfn; /* bits 10-5 */ + uchar fpmode; /* bits 15-11 */ + long w0; + long w1; + int size; /* instruction size */ + char *curr; /* fill point in buffer */ + char *end; /* end of buffer */ + char *err; /* error message */ +} Instr; + +static Map *mymap; + +static int +decode(uvlong pc, Instr *i) +{ + ulong w; + + if (get4(mymap, pc, &w) < 0) { + werrstr("can't read instruction: %r"); + return -1; + } + i->addr = pc; + i->size = 1; + i->op = (w >> 26) & 0x3F; + i->ra = (w >> 21) & 0x1F; + i->rb = (w >> 16) & 0x1F; + i->rc = w & 0x1F; + i->function = (w >> 5) & 0x7F; + i->mem = w & 0xFFFF; + if (i->mem & 0x8000) + i->mem -= 0x10000; + i->branch = w & 0x1FFFFF; + if (i->branch & 0x100000) + i->branch -= 0x200000; + i->function = (w >> 5) & 0x7F; + i->literal = (w >> 13) & 0xFF; + i->islit = (w >> 12) & 0x01; + i->fpfn = (w >> 5) & 0x3F; + i->fpmode = (w >> 11) & 0x1F; + i->w0 = w; + return 1; +} + +static int +mkinstr(uvlong pc, Instr *i) +{ +/* Instr x; */ + + if (decode(pc, i) < 0) + return -1; + +#ifdef frommips +/* we probably want to do something like this for alpha... */ + /* + * if it's a LUI followed by an ORI, + * it's an immediate load of a large constant. + * fix the LUI immediate in any case. + */ + if (i->op == 0x0F) { + if (decode(pc+4, &x) < 0) + return 0; + i->immediate <<= 16; + if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) { + i->immediate |= (x.immediate & 0xFFFF); + i->w1 = x.w0; + i->size++; + return 1; + } + } +#endif + return 1; +} + +#pragma varargck argpos bprint 2 + +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); +} + +typedef struct Opcode Opcode; + +struct Opcode { + char *mnemonic; + void (*f)(Opcode *, Instr *); + char *ken; +}; + +static void format(char *, Instr *, char *); + +static int +plocal(Instr *i, char *m, char r, int store) +{ + int offset; + char *reg; + Symbol s; + + if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) + return 0; + if (s.value > i->mem) { + if(!getauto(&s, s.value-i->mem, CAUTO, &s)) + return 0; + reg = "(SP)"; + offset = i->mem; + } else { + offset = i->mem-s.value-8; + if (!getauto(&s, offset, CPARAM, &s)) + return 0; + reg = "(FP)"; + } + if (store) + bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->ra, s.name, offset, reg); + else + bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->ra); + return 1; +} + +static void +_load(Opcode *o, Instr *i, char r) +{ + char *m; + + m = o->mnemonic; + if (i->rb == 30 && plocal(i, m, r, 0)) + return; + if (i->rb == 29 && mach->sb) { + bprint(i, "%s\t", m); + i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY); + bprint(i, "(SB),%c%d", r, i->ra); + return; + } + format(m, i, o->ken); +} + +static void +load(Opcode *o, Instr *i) +{ + _load(o, i, 'R'); +} + +static void +loadf(Opcode *o, Instr *i) +{ + _load(o, i, 'F'); +} + +static void +_store(Opcode *o, Instr *i, char r) +{ + char *m; + + m = o->mnemonic; + if (i->rb == 30 && plocal(i, m, r, 1)) + return; + if (i->rb == 29 && mach->sb) { + bprint(i, "%s\t%c%d,", m, r, i->ra); + i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY); + bprint(i, "(SB)"); + return; + } + format(o->mnemonic, i, o->ken); +} + +static void +store(Opcode *o, Instr *i) +{ + _store(o, i, 'R'); +} + +static void +storef(Opcode *o, Instr *i) +{ + _store(o, i, 'F'); +} + +static void +misc(Opcode *o, Instr *i) +{ + char *f; + + USED(o); + switch (i->mem&0xFFFF) { + case 0x0000: + f = "TRAPB"; + break; + case 0x4000: + f = "MB"; + break; + case 0x8000: + f = "FETCH\t0(R%b)"; + break; + case 0xA000: + f = "FETCH_M\t0(R%b)"; + break; + case 0xC000: + f = "RPCC\tR%a"; + break; + case 0xE000: + f = "RC\tR%a"; + break; + case 0xF000: + f = "RS\tR%a"; + break; + default: + f = "%w"; + } + format(0, i, f); +} + +static char *jmpcode[4] = { "JMP", "JSR", "RET", "JSR_COROUTINE" }; + +static void +jmp(Opcode *o, Instr *i) +{ + int hint; + char *m; + + USED(o); + hint = (i->mem >> 14) & 3; + m = jmpcode[hint]; + if (i->ra == 31) { + if (hint == 2 && i->rb == 29) + bprint(i, m); + else + format(m, i, "(R%b)"); + } + else + format(m, i, "R%a,(R%b)"); +} + +static void +br(Opcode *o, Instr *i) +{ + if (i->ra == 31) + format(o->mnemonic, i, "%B"); + else + format(o->mnemonic, i, o->ken); +} + +static void +bsr(Opcode *o, Instr *i) +{ + if (i->ra == 26) + format(o->mnemonic, i, "%B"); + else + format(o->mnemonic, i, o->ken); +} + +static void +mult(Opcode *o, Instr *i) +{ + char *m; + + switch (i->function) { + case 0x00: + m = "MULL"; + break; + case 0x20: + m = "MULQ"; + break; + case 0x40: + m = "MULL/V"; + break; + case 0x60: + m = "MULQ/V"; + break; + case 0x30: + m = "UMULH"; + break; + default: + format("???", i, "%w"); + return; + } + format(m, i, o->ken); +} + +static char alphaload[] = "%l,R%a"; +static char alphafload[] = "%l,F%a"; +static char alphastore[] = "R%a,%l"; +static char alphafstore[] = "F%a,%l"; +static char alphabranch[] = "R%a,%B"; +static char alphafbranch[] = "F%a,%B"; +static char alphaint[] = "%v,R%a,R%c"; +static char alphafp[] = "F%b,F%a,F%c"; +static char alphafp2[] = "F%b,F%c"; +static char alphaxxx[] = "%w"; + +static Opcode opcodes[64] = { + "PAL", 0, alphaxxx, + "OPC01", 0, alphaxxx, + "OPC02", 0, alphaxxx, + "OPC03", 0, alphaxxx, + "OPC04", 0, alphaxxx, + "OPC05", 0, alphaxxx, + "OPC06", 0, alphaxxx, + "OPC07", 0, alphaxxx, + "MOVQA", load, alphaload, + "MOVQAH", load, alphaload, + "MOVBU", load, alphaload, /* v 3 */ + "MOVQU", load, alphaload, + "MOVWU", load, alphaload, /* v 3 */ + "MOVWU", store, alphastore, /* v 3 */ + "MOVBU", store, alphastore, /* v 3 */ + "MOVQU", store, alphastore, + 0, 0, 0, /* int arith */ + 0, 0, 0, /* logical */ + 0, 0, 0, /* shift */ + 0, mult, alphaint, + "OPC14", 0, alphaxxx, + "vax", 0, alphafp, /* vax */ + 0, 0, 0, /* ieee */ + 0, 0, 0, /* fp */ + 0, misc, alphaxxx, + "PAL19 [HW_MFPR]",0, alphaxxx, + "JSR", jmp, 0, + "PAL1B [HW_LD]",0, alphaxxx, + "OPC1C", 0, alphaxxx, + "PAL1D [HW_MTPR]",0, alphaxxx, + "PAL1E [HW_REI]",0, alphaxxx, + "PAL1F [HW_ST]",0, alphaxxx, + "MOVF", loadf, alphafload, + "MOVG", loadf, alphafload, + "MOVS", loadf, alphafload, + "MOVT", loadf, alphafload, + "MOVF", storef, alphafstore, + "MOVG", storef, alphafstore, + "MOVS", storef, alphafstore, + "MOVT", storef, alphafstore, + "MOVL", load, alphaload, + "MOVQ", load, alphaload, + "MOVLL", load, alphaload, + "MOVQL", load, alphaload, + "MOVL", store, alphastore, + "MOVQ", store, alphastore, + "MOVLC", store, alphastore, + "MOVQC", store, alphastore, + "JMP", br, alphabranch, + "FBEQ", 0, alphafbranch, + "FBLT", 0, alphafbranch, + "FBLE", 0, alphafbranch, + "JSR", bsr, alphabranch, + "FBNE", 0, alphafbranch, + "FBGE", 0, alphafbranch, + "FBGT", 0, alphafbranch, + "BLBC", 0, alphafbranch, + "BEQ", 0, alphabranch, + "BLT", 0, alphabranch, + "BLE", 0, alphabranch, + "BLBS", 0, alphabranch, + "BNE", 0, alphabranch, + "BGE", 0, alphabranch, + "BGT", 0, alphabranch, +}; + +static Opcode fpopcodes[64] = { + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + + "CVTLQ", 0, alphafp2, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + + "CPYS", 0, alphafp, + "CPYSN", 0, alphafp, + "CPYSE", 0, alphafp, + "???", 0, alphaxxx, + "MOVT", 0, "FPCR,F%a", + "MOVT", 0, "F%a,FPCR", + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "FCMOVEQ", 0, alphafp, + "FCMOVNE", 0, alphafp, + "FCMOVLT", 0, alphafp, + "FCMOVGE", 0, alphafp, + "FCMOVLE", 0, alphafp, + "FCMOVGT", 0, alphafp, + + "CVTQL", 0, alphafp2, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, +}; + +static Opcode ieeeopcodes[64] = { + "ADDS", 0, alphafp, + "SUBS", 0, alphafp, + "MULS", 0, alphafp, + "DIVS", 0, alphafp, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + + "ADDT", 0, alphafp, + "SUBT", 0, alphafp, + "MULT", 0, alphafp, + "DIVT", 0, alphafp, + "CMPTUN", 0, alphafp, + "CMPTEQ", 0, alphafp, + "CMPTLT", 0, alphafp, + "CMPTLE", 0, alphafp, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "CVTTS", 0, alphafp2, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "CVTTQ", 0, alphafp2, + + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "???", 0, alphaxxx, + "CVTQS", 0, alphafp2, + "???", 0, alphaxxx, + "CVTQT", 0, alphafp2, + "???", 0, alphaxxx, +}; + +static uchar amap[128] = { + [0x00] 1, + [0x40] 2, + [0x20] 3, + [0x60] 4, + [0x09] 5, + [0x49] 6, + [0x29] 7, + [0x69] 8, + [0x2D] 9, + [0x4D] 10, + [0x6D] 11, + [0x1D] 12, + [0x3D] 13, + [0x0F] 14, + [0x02] 15, + [0x0B] 16, + [0x12] 17, + [0x1B] 18, + [0x22] 19, + [0x2B] 20, + [0x32] 21, + [0x3B] 22, +}; + +static Opcode arithopcodes[64] = { + "???", 0, alphaxxx, + "ADDL", 0, alphaint, + "ADDL/V", 0, alphaint, + "ADDQ", 0, alphaint, + "ADDQ/V", 0, alphaint, + "SUBL", 0, alphaint, + "SUBL/V", 0, alphaint, + "SUBQ", 0, alphaint, + "SUBQ/V", 0, alphaint, + "CMPEQ", 0, alphaint, + "CMPLT", 0, alphaint, + "CMPLE", 0, alphaint, + "CMPULT", 0, alphaint, + "CMPULE", 0, alphaint, + "CMPBGE", 0, alphaint, + "S4ADDL", 0, alphaint, + "S4SUBL", 0, alphaint, + "S8ADDL", 0, alphaint, + "S8SUBL", 0, alphaint, + "S4ADDQ", 0, alphaint, + "S4SUBQ", 0, alphaint, + "S8ADDQ", 0, alphaint, + "S8SUBQ", 0, alphaint, +}; + +static uchar lmap[128] = { + [0x00] 1, + [0x20] 2, + [0x40] 3, + [0x08] 4, + [0x28] 5, + [0x48] 6, + [0x24] 7, + [0x44] 8, + [0x64] 9, + [0x26] 7, + [0x46] 8, + [0x66] 9, + [0x14] 10, + [0x16] 11, +}; + +static Opcode logicalopcodes[64] = { + "???", 0, alphaxxx, + "AND", 0, alphaint, + "OR", 0, alphaint, + "XOR", 0, alphaint, + "ANDNOT", 0, alphaint, + "ORNOT", 0, alphaint, + "XORNOT", 0, alphaint, + "CMOVEQ", 0, alphaint, + "CMOVLT", 0, alphaint, + "CMOVLE", 0, alphaint, + "CMOVNE", 0, alphaint, + "CMOVGE", 0, alphaint, + "CMOVGT", 0, alphaint, + "CMOVLBS", 0, alphaint, + "CMOVLBC", 0, alphaint, +}; + +static uchar smap[128] = { + [0x39] 1, + [0x3C] 2, + [0x34] 3, + [0x06] 4, + [0x16] 5, + [0x26] 6, + [0x36] 7, + [0x5A] 8, + [0x6A] 9, + [0x7A] 10, + [0x0B] 11, + [0x1B] 12, + [0x2B] 13, + [0x3B] 14, + [0x57] 15, + [0x67] 16, + [0x77] 17, + [0x02] 18, + [0x12] 19, + [0x22] 20, + [0x32] 21, + [0x52] 22, + [0x62] 23, + [0x72] 24, + [0x30] 25, + [0x31] 26, +}; + +static Opcode shiftopcodes[64] = { + "???", 0, alphaxxx, + "SLLQ", 0, alphaint, + "SRAQ", 0, alphaint, + "SRLQ", 0, alphaint, + "EXTBL", 0, alphaint, + "EXTWL", 0, alphaint, + "EXTLL", 0, alphaint, + "EXTQL", 0, alphaint, + "EXTWH", 0, alphaint, + "EXTLH", 0, alphaint, + "EXTQH", 0, alphaint, + "INSBL", 0, alphaint, + "INSWL", 0, alphaint, + "INSLL", 0, alphaint, + "INSQL", 0, alphaint, + "INSWH", 0, alphaint, + "INSLH", 0, alphaint, + "INSQH", 0, alphaint, + "MSKBL", 0, alphaint, + "MSKWL", 0, alphaint, + "MSKLL", 0, alphaint, + "MSKQL", 0, alphaint, + "MSKWH", 0, alphaint, + "MSKLH", 0, alphaint, + "MSKQH", 0, alphaint, + "ZAP", 0, alphaint, + "ZAPNOT", 0, alphaint, +}; + +static void +format(char *mnemonic, Instr *i, char *f) +{ + 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 'a': + bprint(i, "%d", i->ra); + break; + + case 'b': + bprint(i, "%d", i->rb); + break; + + case 'c': + bprint(i, "%d", i->rc); + break; + + case 'v': + if (i->islit) + bprint(i, "$%ux", i->literal); + else + bprint(i, "R%d", i->rb); + break; + + case 'l': + bprint(i, "%lx(R%d)", i->mem, i->rb); + break; + + case 'i': + bprint(i, "$%lx", i->mem); + break; + + case 'B': + i->curr += symoff(i->curr, i->end-i->curr, + (i->branch<<2)+i->addr+4, CANY); + break; + + case 'w': + bprint(i, "[%lux]", i->w0); + break; + + case '\0': + *i->curr++ = '%'; + return; + + default: + bprint(i, "%%%c", *f); + break; + } + } + *i->curr = 0; +} + +static int +printins(Map *map, uvlong pc, char *buf, int n) +{ + Instr i; + Opcode *o; + uchar op; + + i.curr = buf; + i.end = buf+n-1; + mymap = map; + if (mkinstr(pc, &i) < 0) + return -1; + switch (i.op) { + + case 0x10: /* INTA */ + o = arithopcodes; + op = amap[i.function]; + break; + + case 0x11: /* INTL */ + o = logicalopcodes; + op = lmap[i.function]; + break; + + case 0x12: /* INTS */ + o = shiftopcodes; + op = smap[i.function]; + break; + + case 0x16: /* FLTI */ + o = ieeeopcodes; + op = i.fpfn; + break; + + case 0x17: /* FLTL */ + o = fpopcodes; + op = i.fpfn; + break; + + default: + o = opcodes; + op = i.op; + break; + } + if (o[op].f) + (*o[op].f)(&o[op], &i); + else + format(o[op].mnemonic, &i, o[op].ken); + return i.size*4; +} + +static int +alphainst(Map *map, uvlong pc, char modifier, char *buf, int n) +{ + USED(modifier); + return printins(map, pc, buf, n); +} + +static int +alphadas(Map *map, uvlong pc, char *buf, int n) +{ + Instr i; + + i.curr = buf; + i.end = buf+n; + mymap = map; + if (mkinstr(pc, &i) < 0) + return -1; + if (i.end-i.curr > 8) + i.curr = _hexify(buf, i.w0, 7); + if (i.size == 2 && i.end-i.curr > 9) { + *i.curr++ = ' '; + i.curr = _hexify(i.curr, i.w1, 7); + } + *i.curr = 0; + return i.size*4; +} + +static int +alphainstlen(Map *map, uvlong pc) +{ + Instr i; + + mymap = map; + if (mkinstr(pc, &i) < 0) + return -1; + return i.size*4; +} + +static int +alphafoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) +{ + char buf[8]; + Instr i; + + mymap = map; + if (mkinstr(pc, &i) < 0) + return -1; + + switch(i.op) { + case 0x1A: /* JMP/JSR/RET */ + sprint(buf, "R%d", i.rb); + foll[0] = (*rget)(map, buf); + return 1; + case 0x30: /* BR */ + case 0x34: /* BSR */ + foll[0] = pc+4 + (i.branch<<2); + return 1; + default: + if (i.op > 0x30) { /* cond */ + foll[0] = pc+4; + foll[1] = pc+4 + (i.branch<<2); + return 2; + } + foll[0] = pc+i.size*4; + return 1; + } +} |