#include <lib9.h>#include <bio.h>#include "mach.h" /* * Sparc-specific debugger interface */ static char *sparcexcep(Map*, Rgetter);static int sparcfoll(Map*, ulong, Rgetter, ulong*);static int sparcinst(Map*, ulong, char, char*, int);static int sparcdas(Map*, ulong, char*, int);static int sparcinstlen(Map*, ulong); Machdata sparcmach ={ {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */ 4, /* break point size */ beswab, /* convert short to local byte order */ beswal, /* convert long to local byte order */ beswav, /* convert vlong to local byte order */ risctrace, /* C traceback */ riscframe, /* frame finder */ sparcexcep, /* print exception */ 0, /* breakpoint fixup */ beieeesftos, /* single precision float printer */ beieeedftos, /* double precision float printer */ sparcfoll, /* following addresses */ sparcinst, /* print instruction */ sparcdas, /* dissembler */ sparcinstlen, /* instruction size */}; static char *trapname[] ={ "reset", "instruction access exception", "illegal instruction", "privileged instruction", "fp disabled", "window overflow", "window underflow", "unaligned address", "fp exception", "data access exception", "tag overflow",}; static char*excname(ulong tbr){ static char buf[32]; if(tbr < sizeof trapname/sizeof(char*)) return trapname[tbr]; if(tbr >= 130) sprint(buf, "trap instruction %ld", tbr-128); else if(17<=tbr && tbr<=31) sprint(buf, "interrupt level %ld", tbr-16); else switch(tbr){ case 36: return "cp disabled"; case 40: return "cp exception"; case 128: return "syscall"; case 129: return "breakpoint"; default: sprint(buf, "unknown trap %ld", tbr); } return buf;} static char*sparcexcep(Map *map, Rgetter rget){ long tbr; tbr = (*rget)(map, "TBR"); tbr = (tbr&0xFFF)>>4; return excname(tbr);} /* Sparc disassembler and related functions */ typedef struct instr Instr; struct opcode { char *mnemonic; void (*f)(Instr*, char*); int flag;}; static char FRAMENAME[] = ".frame"; struct instr { uchar op; /* bits 31-30 */ uchar rd; /* bits 29-25 */ uchar op2; /* bits 24-22 */ uchar a; /* bit 29 */ uchar cond; /* bits 28-25 */ uchar op3; /* bits 24-19 */ uchar rs1; /* bits 18-14 */ uchar i; /* bit 13 */ uchar asi; /* bits 12-05 */ uchar rs2; /* bits 04-00 */ short simm13; /* bits 12-00, signed */ ushort opf; /* bits 13-05 */ ulong immdisp22; /* bits 21-00 */ ulong simmdisp22; /* bits 21-00, signed */ ulong disp30; /* bits 30-00 */ ulong imm32; /* SETHI+ADD constant */ int target; /* SETHI+ADD dest reg */ long w0; long w1; ulong addr; /* pc of instruction */ char *curr; /* current fill level in output buffer */ char *end; /* end of buffer */ int size; /* number of longs in instr */ char *err; /* errmsg */}; static Map *mymap; /* disassembler context */static int dascase; static int mkinstr(ulong, Instr*);static void bra1(Instr*, char*, char*[]);static void bra(Instr*, char*);static void fbra(Instr*, char*);static void cbra(Instr*, char*);static void unimp(Instr*, char*);static void fpop(Instr*, char*);static void shift(Instr*, char*);static void sethi(Instr*, char*);static void load(Instr*, char*);static void loada(Instr*, char*);static void store(Instr*, char*);static void storea(Instr*, char*);static void add(Instr*, char*);static void cmp(Instr*, char*);static void wr(Instr*, char*);static void jmpl(Instr*, char*);static void rd(Instr*, char*);static void loadf(Instr*, char*);static void storef(Instr*, char*);static void loadc(Instr*, char*);static void loadcsr(Instr*, char*);static void trap(Instr*, char*); static struct opcode sparcop0[8] = { "UNIMP", unimp, 0, /* page 137 */ /* 0 */ "", 0, 0, /* 1 */ "B", bra, 0, /* page 119 */ /* 2 */ "", 0, 0, /* 3 */ "SETHI", sethi, 0, /* page 104 */ /* 4 */ "", 0, 0, /* 5 */ "FB", fbra, 0, /* page 121 */ /* 6 */ "CB", cbra, 0, /* page 123 */ /* 7 */}; static struct opcode sparcop2[64] = { "ADD", add, 0, /* page 108 */ /* 0x00 */ "AND", add, 0, /* page 106 */ /* 0x01 */ "OR", add, 0, /* 0x02 */ "XOR", add, 0, /* 0x03 */ "SUB", add, 0, /* page 110 */ /* 0x04 */ "ANDN", add, 0, /* 0x05 */ "ORN", add, 0, /* 0x06 */ "XORN", add, 0, /* 0x07 */ "ADDX", add, 0, /* 0x08 */ "", 0, 0, /* 0x09 */ "UMUL", add, 0, /* page 113 */ /* 0x0a */ "SMUL", add, 0, /* 0x0b */ "SUBX", add, 0, /* 0x0c */ "", 0, 0, /* 0x0d */ "UDIV", add, 0, /* page 115 */ /* 0x0e */ "SDIV", add, 0, /* 0x0f */ "ADDCC", add, 0, /* 0x10 */ "ANDCC", add, 0, /* 0x11 */ "ORCC", add, 0, /* 0x12 */ "XORCC", add, 0, /* 0x13 */ "SUBCC", cmp, 0, /* 0x14 */ "ANDNCC", add, 0, /* 0x15 */ "ORNCC", add, 0, /* 0x16 */ "XORNCC", add, 0, /* 0x17 */ "ADDXCC", add, 0, /* 0x18 */ "", 0, 0, /* 0x19 */ "UMULCC", add, 0, /* 0x1a */ "SMULCC", add, 0, /* 0x1b */ "SUBXCC", add, 0, /* 0x1c */ "", 0, 0, /* 0x1d */ "UDIVCC", add, 0, /* 0x1e */ "SDIVCC", add, 0, /* 0x1f */ "TADD", add, 0, /* page 109 */ /* 0x20 */ "TSUB", add, 0, /* page 111 */ /* 0x21 */ "TADDCCTV", add, 0, /* 0x22 */ "TSUBCCTV", add, 0, /* 0x23 */ "MULSCC", add, 0, /* page 112 */ /* 0x24 */ "SLL", shift, 0, /* page 107 */ /* 0x25 */ "SRL", shift, 0, /* 0x26 */ "SRA", shift, 0, /* 0x27 */ "rdy", rd, 0, /* page 131 */ /* 0x28 */ "rdpsr", rd, 0, /* 0x29 */ "rdwim", rd, 0, /* 0x2a */ "rdtbr", rd, 0, /* 0x2b */ "", 0, 0, /* 0x2c */ "", 0, 0, /* 0x2d */ "", 0, 0, /* 0x2e */ "", 0, 0, /* 0x2f */ "wry", wr, 0, /* page 133 */ /* 0x30 */ "wrpsr", wr, 0, /* 0x31 */ "wrwim", wr, 0, /* 0x32 */ "wrtbr", wr, 0, /* 0x33 */ "FPOP", fpop, 0, /* page 140 */ /* 0x34 */ "FPOP", fpop, 0, /* 0x35 */ "", 0, 0, /* 0x36 */ "", 0, 0, /* 0x37 */ "JMPL", jmpl, 0, /* page 126 */ /* 0x38 */ "RETT", add, 0, /* page 127 */ /* 0x39 */ "T", trap, 0, /* page 129 */ /* 0x3a */ "flush", add, 0, /* page 138 */ /* 0x3b */ "SAVE", add, 0, /* page 117 */ /* 0x3c */ "RESTORE", add, 0, /* 0x3d */}; static struct opcode sparcop3[64]={ "ld", load, 0, /* 0x00 */ "ldub", load, 0, /* 0x01 */ "lduh", load, 0, /* 0x02 */ "ldd", load, 0, /* 0x03 */ "st", store, 0, /* 0x04 */ "stb", store, 0, /* page 95 */ /* 0x05 */ "sth", store, 0, /* 0x06 */ "std", store, 0, /* 0x07 */ "", 0, 0, /* 0x08 */ "ldsb", load, 0, /* page 90 */ /* 0x09 */ "ldsh", load, 0, /* 0x0a */ "", 0, 0, /* 0x0b */ "", 0, 0, /* 0x0c */ "ldstub", store, 0, /* page 101 */ /* 0x0d */ "", 0, 0, /* 0x0e */ "swap", load, 0, /* page 102 */ /* 0x0f */ "lda", loada, 0, /* 0x10 */ "lduba", loada, 0, /* 0x11 */ "lduha", loada, 0, /* 0x12 */ "ldda", loada, 0, /* 0x13 */ "sta", storea, 0, /* 0x14 */ "stba", storea, 0, /* 0x15 */ "stha", storea, 0, /* 0x16 */ "stda", storea, 0, /* 0x17 */ "", 0, 0, /* 0x18 */ "ldsba", loada, 0, /* 0x19 */ "ldsha", loada, 0, /* 0x1a */ "", 0, 0, /* 0x1b */ "", 0, 0, /* 0x1c */ "ldstuba", storea, 0, /* 0x1d */ "", 0, 0, /* 0x1e */ "swapa", loada, 0, /* 0x1f */ "ldf", loadf, 0, /* page 92 */ /* 0x20 */ "ldfsr", loadf,0, /* 0x21 */ "", 0, 0, /* 0x22 */ "lddf", loadf, 0, /* 0x23 */ "stf", storef, 0, /* page 97 */ /* 0x24 */ "stfsr", storef,0, /* 0x25 */ "stdfq", storef,0, /* 0x26 */ "stdf", storef, 0, /* 0x27 */ "", 0, 0, /* 0x28 */ "", 0, 0, /* 0x29 */ "", 0, 0, /* 0x2a */ "", 0, 0, /* 0x2b */ "", 0, 0, /* 0x2c */ "", 0, 0, /* 0x2d */ "", 0, 0, /* 0x2e */ "", 0, 0, /* 0x2f */ "ldc", loadc, 0, /* page 94 */ /* 0x30 */ "ldcsr", loadcsr,0, /* 0x31 */ "", 0, 0, /* 0x32 */ "lddc", loadc, 0, /* 0x33 */ "stc", loadc, 0, /* page 99 */ /* 0x34 */ "stcsr", loadcsr,0, /* 0x35 */ "stdcq", loadcsr,0, /* 0x36 */ "stdc", loadc, 0, /* 0x37 */}; static voidbprint(Instr *i, char *fmt, ...){ va_list arg; va_start(arg, fmt); i->curr = vseprint(i->curr, i->end, fmt, arg); va_end(arg);} static intdecode(ulong pc, Instr *i){ long w; if (get4(mymap, pc, &w) < 0) { werrstr("can't read instruction: %r"); return -1; } i->op = (w >> 30) & 0x03; i->rd = (w >> 25) & 0x1F; i->op2 = (w >> 22) & 0x07; i->a = (w >> 29) & 0x01; i->cond = (w >> 25) & 0x0F; i->op3 = (w >> 19) & 0x3F; i->rs1 = (w >> 14) & 0x1F; i->i = (w >> 13) & 0x01; i->asi = (w >> 5) & 0xFF; i->rs2 = (w >> 0) & 0x1F; i->simm13 = (w >> 0) & 0x1FFF; if(i->simm13 & (1<<12)) i->simm13 |= ~((1<<13)-1); i->opf = (w >> 5) & 0x1FF; i->immdisp22 = (w >> 0) & 0x3FFFFF; i->simmdisp22 = i->immdisp22; if(i->simmdisp22 & (1<<21)) i->simmdisp22 |= ~((1<<22)-1); i->disp30 = (w >> 0) & 0x3FFFFFFF; i->w0 = w; i->target = -1; i->addr = pc; i->size = 1; return 1;} static intmkinstr(ulong pc, Instr *i){ Instr xi; if (decode(pc, i) < 0) return -1; if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */ if (decode(pc+4, &xi) < 0) return -1; if(xi.op==2 && xi.op3==0) /* ADD */ if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */ i->imm32 = xi.simm13 + (i->immdisp22<<10); i->target = xi.rd; i->w1 = xi.w0; i->size++; return 1; } } if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */ if (decode(pc+4, &xi) < 0) return -1; if(i->op==2 && i->opf==1) /* FMOVS */ if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */ i->w1 = xi.w0; i->size++; } } return 1;} static intprintins(Map *map, ulong pc, char *buf, int n){ Instr instr; void (*f)(Instr*, char*); mymap = map; memset(&instr, 0, sizeof(instr)); instr.curr = buf; instr.end = buf+n-1; if (mkinstr(pc, &instr) < 0) return -1; switch(instr.op){ case 0: f = sparcop0[instr.op2].f; if(f) (*f)(&instr, sparcop0[instr.op2].mnemonic); else bprint(&instr, "unknown %lux", instr.w0); break; case 1: bprint(&instr, "%X", "CALL\t"); instr.curr += symoff(instr.curr, instr.end-instr.curr, pc+instr.disp30*4, CTEXT); if (!dascase) bprint(&instr, "(SB)"); break; case 2: f = sparcop2[instr.op3].f; if(f) (*f)(&instr, sparcop2[instr.op3].mnemonic); else bprint(&instr, "unknown %lux", instr.w0); break; case 3: f = sparcop3[instr.op3].f; if(f) (*f)(&instr, sparcop3[instr.op3].mnemonic); else bprint(&instr, "unknown %lux", instr.w0); break; } if (instr.err) { if (instr.curr != buf) bprint(&instr, "\t\t;"); bprint(&instr, instr.err); } return instr.size*4;} /* convert to lower case from upper, according to dascase */static intXconv(Fmt *f){ char buf[128]; char *s, *t, *oa; oa = va_arg(f->args, char*); if(dascase){ for(s=oa,t=buf; *t = *s; s++,t++) if('A'<=*t && *t<='Z') *t += 'a'-'A'; return fmtstrcpy(f, buf); } return fmtstrcpy(f, oa);} static intsparcinst(Map *map, ulong pc, char modifier, char *buf, int n){ static int fmtinstalled = 0; /* a modifier of 'I' toggles the dissassembler type */ if (!fmtinstalled) { fmtinstalled = 1; fmtinstall('X', Xconv); } if ((asstype == ASUNSPARC && modifier == 'i') || (asstype == ASPARC && modifier == 'I')) dascase = 'a'-'A'; else dascase = 0; return printins(map, pc, buf, n);} static intsparcdas(Map *map, ulong pc, char *buf, int n){ Instr instr; mymap = map; memset(&instr, 0, sizeof(instr)); instr.curr = buf; instr.end = buf+n-1; if (mkinstr(pc, &instr) < 0) return -1; if (instr.end-instr.curr > 8) instr.curr = _hexify(instr.curr, instr.w0, 7); if (instr.end-instr.curr > 9 && instr.size == 2) { *instr.curr++ = ' '; instr.curr = _hexify(instr.curr, instr.w1, 7); } *instr.curr = 0; return instr.size*4;} static intsparcinstlen(Map *map, ulong pc){ Instr i; mymap = map; if (mkinstr(pc, &i) < 0) return -1; return i.size*4;} static intplocal(Instr *i){ int offset; Symbol s; if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) return -1; if (s.value > i->simm13) { if(getauto(&s, s.value-i->simm13, CAUTO, &s)) { bprint(i, "%s+%d(SP)", s.name, s.value); return 1; } } else { offset = i->simm13-s.value; if (getauto(&s, offset-4, CPARAM, &s)) { bprint(i, "%s+%d(FP)", s.name, offset); return 1;Lines 1–500 of 1055. Load more
#include <lib9.h> #include <bio.h> #include "mach.h" /* * Sparc-specific debugger interface */ static char *sparcexcep(Map*, Rgetter); static int sparcfoll(Map*, ulong, Rgetter, ulong*); static int sparcinst(Map*, ulong, char, char*, int); static int sparcdas(Map*, ulong, char*, int); static int sparcinstlen(Map*, ulong); Machdata sparcmach = { {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */ 4, /* break point size */ beswab, /* convert short to local byte order */ beswal, /* convert long to local byte order */ beswav, /* convert vlong to local byte order */ risctrace, /* C traceback */ riscframe, /* frame finder */ sparcexcep, /* print exception */ 0, /* breakpoint fixup */ beieeesftos, /* single precision float printer */ beieeedftos, /* double precision float printer */ sparcfoll, /* following addresses */ sparcinst, /* print instruction */ sparcdas, /* dissembler */ sparcinstlen, /* instruction size */ }; static char *trapname[] = { "reset", "instruction access exception", "illegal instruction", "privileged instruction", "fp disabled", "window overflow", "window underflow", "unaligned address", "fp exception", "data access exception", "tag overflow", }; static char* excname(ulong tbr) { static char buf[32]; if(tbr < sizeof trapname/sizeof(char*)) return trapname[tbr]; if(tbr >= 130) sprint(buf, "trap instruction %ld", tbr-128); else if(17<=tbr && tbr<=31) sprint(buf, "interrupt level %ld", tbr-16); else switch(tbr){ case 36: return "cp disabled"; case 40: return "cp exception"; case 128: return "syscall"; case 129: return "breakpoint"; default: sprint(buf, "unknown trap %ld", tbr); } return buf; } static char* sparcexcep(Map *map, Rgetter rget) { long tbr; tbr = (*rget)(map, "TBR"); tbr = (tbr&0xFFF)>>4; return excname(tbr); } /* Sparc disassembler and related functions */ typedef struct instr Instr; struct opcode { char *mnemonic; void (*f)(Instr*, char*); int flag; }; static char FRAMENAME[] = ".frame"; struct instr { uchar op; /* bits 31-30 */ uchar rd; /* bits 29-25 */ uchar op2; /* bits 24-22 */ uchar a; /* bit 29 */ uchar cond; /* bits 28-25 */ uchar op3; /* bits 24-19 */ uchar rs1; /* bits 18-14 */ uchar i; /* bit 13 */ uchar asi; /* bits 12-05 */ uchar rs2; /* bits 04-00 */ short simm13; /* bits 12-00, signed */ ushort opf; /* bits 13-05 */ ulong immdisp22; /* bits 21-00 */ ulong simmdisp22; /* bits 21-00, signed */ ulong disp30; /* bits 30-00 */ ulong imm32; /* SETHI+ADD constant */ int target; /* SETHI+ADD dest reg */ long w0; long w1; ulong addr; /* pc of instruction */ char *curr; /* current fill level in output buffer */ char *end; /* end of buffer */ int size; /* number of longs in instr */ char *err; /* errmsg */ }; static Map *mymap; /* disassembler context */ static int dascase; static int mkinstr(ulong, Instr*); static void bra1(Instr*, char*, char*[]); static void bra(Instr*, char*); static void fbra(Instr*, char*); static void cbra(Instr*, char*); static void unimp(Instr*, char*); static void fpop(Instr*, char*); static void shift(Instr*, char*); static void sethi(Instr*, char*); static void load(Instr*, char*); static void loada(Instr*, char*); static void store(Instr*, char*); static void storea(Instr*, char*); static void add(Instr*, char*); static void cmp(Instr*, char*); static void wr(Instr*, char*); static void jmpl(Instr*, char*); static void rd(Instr*, char*); static void loadf(Instr*, char*); static void storef(Instr*, char*); static void loadc(Instr*, char*); static void loadcsr(Instr*, char*); static void trap(Instr*, char*); static struct opcode sparcop0[8] = { "UNIMP", unimp, 0, /* page 137 */ /* 0 */ "", 0, 0, /* 1 */ "B", bra, 0, /* page 119 */ /* 2 */ "", 0, 0, /* 3 */ "SETHI", sethi, 0, /* page 104 */ /* 4 */ "", 0, 0, /* 5 */ "FB", fbra, 0, /* page 121 */ /* 6 */ "CB", cbra, 0, /* page 123 */ /* 7 */ }; static struct opcode sparcop2[64] = { "ADD", add, 0, /* page 108 */ /* 0x00 */ "AND", add, 0, /* page 106 */ /* 0x01 */ "OR", add, 0, /* 0x02 */ "XOR", add, 0, /* 0x03 */ "SUB", add, 0, /* page 110 */ /* 0x04 */ "ANDN", add, 0, /* 0x05 */ "ORN", add, 0, /* 0x06 */ "XORN", add, 0, /* 0x07 */ "ADDX", add, 0, /* 0x08 */ "", 0, 0, /* 0x09 */ "UMUL", add, 0, /* page 113 */ /* 0x0a */ "SMUL", add, 0, /* 0x0b */ "SUBX", add, 0, /* 0x0c */ "", 0, 0, /* 0x0d */ "UDIV", add, 0, /* page 115 */ /* 0x0e */ "SDIV", add, 0, /* 0x0f */ "ADDCC", add, 0, /* 0x10 */ "ANDCC", add, 0, /* 0x11 */ "ORCC", add, 0, /* 0x12 */ "XORCC", add, 0, /* 0x13 */ "SUBCC", cmp, 0, /* 0x14 */ "ANDNCC", add, 0, /* 0x15 */ "ORNCC", add, 0, /* 0x16 */ "XORNCC", add, 0, /* 0x17 */ "ADDXCC", add, 0, /* 0x18 */ "", 0, 0, /* 0x19 */ "UMULCC", add, 0, /* 0x1a */ "SMULCC", add, 0, /* 0x1b */ "SUBXCC", add, 0, /* 0x1c */ "", 0, 0, /* 0x1d */ "UDIVCC", add, 0, /* 0x1e */ "SDIVCC", add, 0, /* 0x1f */ "TADD", add, 0, /* page 109 */ /* 0x20 */ "TSUB", add, 0, /* page 111 */ /* 0x21 */ "TADDCCTV", add, 0, /* 0x22 */ "TSUBCCTV", add, 0, /* 0x23 */ "MULSCC", add, 0, /* page 112 */ /* 0x24 */ "SLL", shift, 0, /* page 107 */ /* 0x25 */ "SRL", shift, 0, /* 0x26 */ "SRA", shift, 0, /* 0x27 */ "rdy", rd, 0, /* page 131 */ /* 0x28 */ "rdpsr", rd, 0, /* 0x29 */ "rdwim", rd, 0, /* 0x2a */ "rdtbr", rd, 0, /* 0x2b */ "", 0, 0, /* 0x2c */ "", 0, 0, /* 0x2d */ "", 0, 0, /* 0x2e */ "", 0, 0, /* 0x2f */ "wry", wr, 0, /* page 133 */ /* 0x30 */ "wrpsr", wr, 0, /* 0x31 */ "wrwim", wr, 0, /* 0x32 */ "wrtbr", wr, 0, /* 0x33 */ "FPOP", fpop, 0, /* page 140 */ /* 0x34 */ "FPOP", fpop, 0, /* 0x35 */ "", 0, 0, /* 0x36 */ "", 0, 0, /* 0x37 */ "JMPL", jmpl, 0, /* page 126 */ /* 0x38 */ "RETT", add, 0, /* page 127 */ /* 0x39 */ "T", trap, 0, /* page 129 */ /* 0x3a */ "flush", add, 0, /* page 138 */ /* 0x3b */ "SAVE", add, 0, /* page 117 */ /* 0x3c */ "RESTORE", add, 0, /* 0x3d */ }; static struct opcode sparcop3[64]={ "ld", load, 0, /* 0x00 */ "ldub", load, 0, /* 0x01 */ "lduh", load, 0, /* 0x02 */ "ldd", load, 0, /* 0x03 */ "st", store, 0, /* 0x04 */ "stb", store, 0, /* page 95 */ /* 0x05 */ "sth", store, 0, /* 0x06 */ "std", store, 0, /* 0x07 */ "", 0, 0, /* 0x08 */ "ldsb", load, 0, /* page 90 */ /* 0x09 */ "ldsh", load, 0, /* 0x0a */ "", 0, 0, /* 0x0b */ "", 0, 0, /* 0x0c */ "ldstub", store, 0, /* page 101 */ /* 0x0d */ "", 0, 0, /* 0x0e */ "swap", load, 0, /* page 102 */ /* 0x0f */ "lda", loada, 0, /* 0x10 */ "lduba", loada, 0, /* 0x11 */ "lduha", loada, 0, /* 0x12 */ "ldda", loada, 0, /* 0x13 */ "sta", storea, 0, /* 0x14 */ "stba", storea, 0, /* 0x15 */ "stha", storea, 0, /* 0x16 */ "stda", storea, 0, /* 0x17 */ "", 0, 0, /* 0x18 */ "ldsba", loada, 0, /* 0x19 */ "ldsha", loada, 0, /* 0x1a */ "", 0, 0, /* 0x1b */ "", 0, 0, /* 0x1c */ "ldstuba", storea, 0, /* 0x1d */ "", 0, 0, /* 0x1e */ "swapa", loada, 0, /* 0x1f */ "ldf", loadf, 0, /* page 92 */ /* 0x20 */ "ldfsr", loadf,0, /* 0x21 */ "", 0, 0, /* 0x22 */ "lddf", loadf, 0, /* 0x23 */ "stf", storef, 0, /* page 97 */ /* 0x24 */ "stfsr", storef,0, /* 0x25 */ "stdfq", storef,0, /* 0x26 */ "stdf", storef, 0, /* 0x27 */ "", 0, 0, /* 0x28 */ "", 0, 0, /* 0x29 */ "", 0, 0, /* 0x2a */ "", 0, 0, /* 0x2b */ "", 0, 0, /* 0x2c */ "", 0, 0, /* 0x2d */ "", 0, 0, /* 0x2e */ "", 0, 0, /* 0x2f */ "ldc", loadc, 0, /* page 94 */ /* 0x30 */ "ldcsr", loadcsr,0, /* 0x31 */ "", 0, 0, /* 0x32 */ "lddc", loadc, 0, /* 0x33 */ "stc", loadc, 0, /* page 99 */ /* 0x34 */ "stcsr", loadcsr,0, /* 0x35 */ "stdcq", loadcsr,0, /* 0x36 */ "stdc", loadc, 0, /* 0x37 */ }; 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 decode(ulong pc, Instr *i) { long w; if (get4(mymap, pc, &w) < 0) { werrstr("can't read instruction: %r"); return -1; } i->op = (w >> 30) & 0x03; i->rd = (w >> 25) & 0x1F; i->op2 = (w >> 22) & 0x07; i->a = (w >> 29) & 0x01; i->cond = (w >> 25) & 0x0F; i->op3 = (w >> 19) & 0x3F; i->rs1 = (w >> 14) & 0x1F; i->i = (w >> 13) & 0x01; i->asi = (w >> 5) & 0xFF; i->rs2 = (w >> 0) & 0x1F; i->simm13 = (w >> 0) & 0x1FFF; if(i->simm13 & (1<<12)) i->simm13 |= ~((1<<13)-1); i->opf = (w >> 5) & 0x1FF; i->immdisp22 = (w >> 0) & 0x3FFFFF; i->simmdisp22 = i->immdisp22; if(i->simmdisp22 & (1<<21)) i->simmdisp22 |= ~((1<<22)-1); i->disp30 = (w >> 0) & 0x3FFFFFFF; i->w0 = w; i->target = -1; i->addr = pc; i->size = 1; return 1; } static int mkinstr(ulong pc, Instr *i) { Instr xi; if (decode(pc, i) < 0) return -1; if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */ if (decode(pc+4, &xi) < 0) return -1; if(xi.op==2 && xi.op3==0) /* ADD */ if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */ i->imm32 = xi.simm13 + (i->immdisp22<<10); i->target = xi.rd; i->w1 = xi.w0; i->size++; return 1; } } if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */ if (decode(pc+4, &xi) < 0) return -1; if(i->op==2 && i->opf==1) /* FMOVS */ if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */ i->w1 = xi.w0; i->size++; } } return 1; } static int printins(Map *map, ulong pc, char *buf, int n) { Instr instr; void (*f)(Instr*, char*); mymap = map; memset(&instr, 0, sizeof(instr)); instr.curr = buf; instr.end = buf+n-1; if (mkinstr(pc, &instr) < 0) return -1; switch(instr.op){ case 0: f = sparcop0[instr.op2].f; if(f) (*f)(&instr, sparcop0[instr.op2].mnemonic); else bprint(&instr, "unknown %lux", instr.w0); break; case 1: bprint(&instr, "%X", "CALL\t"); instr.curr += symoff(instr.curr, instr.end-instr.curr, pc+instr.disp30*4, CTEXT); if (!dascase) bprint(&instr, "(SB)"); break; case 2: f = sparcop2[instr.op3].f; if(f) (*f)(&instr, sparcop2[instr.op3].mnemonic); else bprint(&instr, "unknown %lux", instr.w0); break; case 3: f = sparcop3[instr.op3].f; if(f) (*f)(&instr, sparcop3[instr.op3].mnemonic); else bprint(&instr, "unknown %lux", instr.w0); break; } if (instr.err) { if (instr.curr != buf) bprint(&instr, "\t\t;"); bprint(&instr, instr.err); } return instr.size*4; } /* convert to lower case from upper, according to dascase */ static int Xconv(Fmt *f) { char buf[128]; char *s, *t, *oa; oa = va_arg(f->args, char*); if(dascase){ for(s=oa,t=buf; *t = *s; s++,t++) if('A'<=*t && *t<='Z') *t += 'a'-'A'; return fmtstrcpy(f, buf); } return fmtstrcpy(f, oa); } static int sparcinst(Map *map, ulong pc, char modifier, char *buf, int n) { static int fmtinstalled = 0; /* a modifier of 'I' toggles the dissassembler type */ if (!fmtinstalled) { fmtinstalled = 1; fmtinstall('X', Xconv); } if ((asstype == ASUNSPARC && modifier == 'i') || (asstype == ASPARC && modifier == 'I')) dascase = 'a'-'A'; else dascase = 0; return printins(map, pc, buf, n); } static int sparcdas(Map *map, ulong pc, char *buf, int n) { Instr instr; mymap = map; memset(&instr, 0, sizeof(instr)); instr.curr = buf; instr.end = buf+n-1; if (mkinstr(pc, &instr) < 0) return -1; if (instr.end-instr.curr > 8) instr.curr = _hexify(instr.curr, instr.w0, 7); if (instr.end-instr.curr > 9 && instr.size == 2) { *instr.curr++ = ' '; instr.curr = _hexify(instr.curr, instr.w1, 7); } *instr.curr = 0; return instr.size*4; } static int sparcinstlen(Map *map, ulong pc) { Instr i; mymap = map; if (mkinstr(pc, &i) < 0) return -1; return i.size*4; } static int plocal(Instr *i) { int offset; Symbol s; if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) return -1; if (s.value > i->simm13) { if(getauto(&s, s.value-i->simm13, CAUTO, &s)) { bprint(i, "%s+%d(SP)", s.name, s.value); return 1; } } else { offset = i->simm13-s.value; if (getauto(&s, offset-4, CPARAM, &s)) { bprint(i, "%s+%d(FP)", s.name, offset); return 1;