1219b2ee8SDavid du Colombier #include <u.h> 2219b2ee8SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <bio.h> 4219b2ee8SDavid du Colombier #include <mach.h> 5219b2ee8SDavid du Colombier 6219b2ee8SDavid du Colombier /* 7219b2ee8SDavid du Colombier * Sparc-specific debugger interface 8219b2ee8SDavid du Colombier */ 9219b2ee8SDavid du Colombier 10219b2ee8SDavid du Colombier static char *sparcexcep(Map*, Rgetter); 11219b2ee8SDavid du Colombier static int sparcfoll(Map*, ulong, Rgetter, ulong*); 12219b2ee8SDavid du Colombier static int sparcinst(Map*, ulong, char, char*, int); 13219b2ee8SDavid du Colombier static int sparcdas(Map*, ulong, char*, int); 14219b2ee8SDavid du Colombier static int sparcinstlen(Map*, ulong); 15219b2ee8SDavid du Colombier 16219b2ee8SDavid du Colombier Machdata sparcmach = 17219b2ee8SDavid du Colombier { 18219b2ee8SDavid du Colombier {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */ 19219b2ee8SDavid du Colombier 4, /* break point size */ 20219b2ee8SDavid du Colombier 21219b2ee8SDavid du Colombier beswab, /* convert short to local byte order */ 22219b2ee8SDavid du Colombier beswal, /* convert long to local byte order */ 237dd7cddfSDavid du Colombier beswav, /* convert vlong to local byte order */ 24219b2ee8SDavid du Colombier risctrace, /* C traceback */ 25219b2ee8SDavid du Colombier riscframe, /* frame finder */ 26219b2ee8SDavid du Colombier sparcexcep, /* print exception */ 27219b2ee8SDavid du Colombier 0, /* breakpoint fixup */ 28219b2ee8SDavid du Colombier beieeesftos, /* single precision float printer */ 29219b2ee8SDavid du Colombier beieeedftos, /* double precision float printer */ 30219b2ee8SDavid du Colombier sparcfoll, /* following addresses */ 31219b2ee8SDavid du Colombier sparcinst, /* print instruction */ 32219b2ee8SDavid du Colombier sparcdas, /* dissembler */ 33219b2ee8SDavid du Colombier sparcinstlen, /* instruction size */ 34219b2ee8SDavid du Colombier }; 35219b2ee8SDavid du Colombier 36219b2ee8SDavid du Colombier static char *trapname[] = 37219b2ee8SDavid du Colombier { 38219b2ee8SDavid du Colombier "reset", 39219b2ee8SDavid du Colombier "instruction access exception", 40219b2ee8SDavid du Colombier "illegal instruction", 41219b2ee8SDavid du Colombier "privileged instruction", 42219b2ee8SDavid du Colombier "fp disabled", 43219b2ee8SDavid du Colombier "window overflow", 44219b2ee8SDavid du Colombier "window underflow", 45219b2ee8SDavid du Colombier "unaligned address", 46219b2ee8SDavid du Colombier "fp exception", 47219b2ee8SDavid du Colombier "data access exception", 48219b2ee8SDavid du Colombier "tag overflow", 49219b2ee8SDavid du Colombier }; 50219b2ee8SDavid du Colombier 51219b2ee8SDavid du Colombier static char* 52219b2ee8SDavid du Colombier excname(ulong tbr) 53219b2ee8SDavid du Colombier { 54219b2ee8SDavid du Colombier static char buf[32]; 55219b2ee8SDavid du Colombier 56219b2ee8SDavid du Colombier if(tbr < sizeof trapname/sizeof(char*)) 57219b2ee8SDavid du Colombier return trapname[tbr]; 58219b2ee8SDavid du Colombier if(tbr >= 130) 597dd7cddfSDavid du Colombier sprint(buf, "trap instruction %ld", tbr-128); 60219b2ee8SDavid du Colombier else if(17<=tbr && tbr<=31) 617dd7cddfSDavid du Colombier sprint(buf, "interrupt level %ld", tbr-16); 62219b2ee8SDavid du Colombier else switch(tbr){ 63219b2ee8SDavid du Colombier case 36: 64219b2ee8SDavid du Colombier return "cp disabled"; 65219b2ee8SDavid du Colombier case 40: 66219b2ee8SDavid du Colombier return "cp exception"; 67219b2ee8SDavid du Colombier case 128: 68219b2ee8SDavid du Colombier return "syscall"; 69219b2ee8SDavid du Colombier case 129: 70219b2ee8SDavid du Colombier return "breakpoint"; 71219b2ee8SDavid du Colombier default: 727dd7cddfSDavid du Colombier sprint(buf, "unknown trap %ld", tbr); 73219b2ee8SDavid du Colombier } 74219b2ee8SDavid du Colombier return buf; 75219b2ee8SDavid du Colombier } 76219b2ee8SDavid du Colombier 77219b2ee8SDavid du Colombier static char* 78219b2ee8SDavid du Colombier sparcexcep(Map *map, Rgetter rget) 79219b2ee8SDavid du Colombier { 80219b2ee8SDavid du Colombier long tbr; 81219b2ee8SDavid du Colombier 82219b2ee8SDavid du Colombier tbr = (*rget)(map, "TBR"); 83219b2ee8SDavid du Colombier tbr = (tbr&0xFFF)>>4; 84219b2ee8SDavid du Colombier return excname(tbr); 85219b2ee8SDavid du Colombier } 86219b2ee8SDavid du Colombier 87219b2ee8SDavid du Colombier /* Sparc disassembler and related functions */ 88219b2ee8SDavid du Colombier 89219b2ee8SDavid du Colombier struct opcode { 90219b2ee8SDavid du Colombier char *mnemonic; 91219b2ee8SDavid du Colombier void (*f)(struct instr*, char*); 92219b2ee8SDavid du Colombier int flag; 93219b2ee8SDavid du Colombier }; 94219b2ee8SDavid du Colombier 95219b2ee8SDavid du Colombier static char FRAMENAME[] = ".frame"; 96219b2ee8SDavid du Colombier 97219b2ee8SDavid du Colombier typedef struct instr Instr; 98219b2ee8SDavid du Colombier 99219b2ee8SDavid du Colombier struct instr { 100219b2ee8SDavid du Colombier uchar op; /* bits 31-30 */ 101219b2ee8SDavid du Colombier uchar rd; /* bits 29-25 */ 102219b2ee8SDavid du Colombier uchar op2; /* bits 24-22 */ 103219b2ee8SDavid du Colombier uchar a; /* bit 29 */ 104219b2ee8SDavid du Colombier uchar cond; /* bits 28-25 */ 105219b2ee8SDavid du Colombier uchar op3; /* bits 24-19 */ 106219b2ee8SDavid du Colombier uchar rs1; /* bits 18-14 */ 107219b2ee8SDavid du Colombier uchar i; /* bit 13 */ 108219b2ee8SDavid du Colombier uchar asi; /* bits 12-05 */ 109219b2ee8SDavid du Colombier uchar rs2; /* bits 04-00 */ 110219b2ee8SDavid du Colombier short simm13; /* bits 12-00, signed */ 111219b2ee8SDavid du Colombier ushort opf; /* bits 13-05 */ 112219b2ee8SDavid du Colombier ulong immdisp22; /* bits 21-00 */ 113219b2ee8SDavid du Colombier ulong simmdisp22; /* bits 21-00, signed */ 114219b2ee8SDavid du Colombier ulong disp30; /* bits 30-00 */ 115219b2ee8SDavid du Colombier ulong imm32; /* SETHI+ADD constant */ 116219b2ee8SDavid du Colombier int target; /* SETHI+ADD dest reg */ 117219b2ee8SDavid du Colombier long w0; 118219b2ee8SDavid du Colombier long w1; 119219b2ee8SDavid du Colombier ulong addr; /* pc of instruction */ 120219b2ee8SDavid du Colombier char *curr; /* current fill level in output buffer */ 121219b2ee8SDavid du Colombier char *end; /* end of buffer */ 122219b2ee8SDavid du Colombier int size; /* number of longs in instr */ 123219b2ee8SDavid du Colombier char *err; /* errmsg */ 124219b2ee8SDavid du Colombier }; 125219b2ee8SDavid du Colombier 126219b2ee8SDavid du Colombier static Map *mymap; /* disassembler context */ 127219b2ee8SDavid du Colombier static int dascase; 128219b2ee8SDavid du Colombier 129219b2ee8SDavid du Colombier static int mkinstr(ulong, Instr*); 130219b2ee8SDavid du Colombier static void bra1(Instr*, char*, char*[]); 131219b2ee8SDavid du Colombier static void bra(Instr*, char*); 132219b2ee8SDavid du Colombier static void fbra(Instr*, char*); 133219b2ee8SDavid du Colombier static void cbra(Instr*, char*); 134219b2ee8SDavid du Colombier static void unimp(Instr*, char*); 135219b2ee8SDavid du Colombier static void fpop(Instr*, char*); 136219b2ee8SDavid du Colombier static void shift(Instr*, char*); 137219b2ee8SDavid du Colombier static void sethi(Instr*, char*); 138219b2ee8SDavid du Colombier static void load(Instr*, char*); 139219b2ee8SDavid du Colombier static void loada(Instr*, char*); 140219b2ee8SDavid du Colombier static void store(Instr*, char*); 141219b2ee8SDavid du Colombier static void storea(Instr*, char*); 142219b2ee8SDavid du Colombier static void add(Instr*, char*); 143219b2ee8SDavid du Colombier static void cmp(Instr*, char*); 144219b2ee8SDavid du Colombier static void wr(Instr*, char*); 145219b2ee8SDavid du Colombier static void jmpl(Instr*, char*); 146219b2ee8SDavid du Colombier static void rd(Instr*, char*); 147219b2ee8SDavid du Colombier static void loadf(Instr*, char*); 148219b2ee8SDavid du Colombier static void storef(Instr*, char*); 149219b2ee8SDavid du Colombier static void loadc(Instr*, char*); 150219b2ee8SDavid du Colombier static void loadcsr(Instr*, char*); 151219b2ee8SDavid du Colombier static void trap(Instr*, char*); 152219b2ee8SDavid du Colombier 153219b2ee8SDavid du Colombier static struct opcode sparcop0[8] = { 154219b2ee8SDavid du Colombier [0] "UNIMP", unimp, 0, /* page 137 */ 155219b2ee8SDavid du Colombier [2] "B", bra, 0, /* page 119 */ 156219b2ee8SDavid du Colombier [4] "SETHI", sethi, 0, /* page 104 */ 157219b2ee8SDavid du Colombier [6] "FB", fbra, 0, /* page 121 */ 158219b2ee8SDavid du Colombier [7] "CB", cbra, 0, /* page 123 */ 159219b2ee8SDavid du Colombier }; 160219b2ee8SDavid du Colombier 161219b2ee8SDavid du Colombier static struct opcode sparcop2[64] = { 162219b2ee8SDavid du Colombier [0x00] "ADD", add, 0, /* page 108 */ 163219b2ee8SDavid du Colombier [0x10] "ADDCC", add, 0, 164219b2ee8SDavid du Colombier [0x08] "ADDX", add, 0, 165219b2ee8SDavid du Colombier [0x18] "ADDXCC", add, 0, 166219b2ee8SDavid du Colombier 167219b2ee8SDavid du Colombier [0x20] "TADD", add, 0, /* page 109 */ 168219b2ee8SDavid du Colombier [0x22] "TADDCCTV", add, 0, 169219b2ee8SDavid du Colombier 170219b2ee8SDavid du Colombier [0x04] "SUB", add, 0, /* page 110 */ 171219b2ee8SDavid du Colombier [0x14] "SUBCC", cmp, 0, 172219b2ee8SDavid du Colombier [0x0C] "SUBX", add, 0, 173219b2ee8SDavid du Colombier [0x1C] "SUBXCC", add, 0, 174219b2ee8SDavid du Colombier 175219b2ee8SDavid du Colombier [0x21] "TSUB", add, 0, /* page 111 */ 176219b2ee8SDavid du Colombier [0x23] "TSUBCCTV", add, 0, 177219b2ee8SDavid du Colombier 178219b2ee8SDavid du Colombier [0x24] "MULSCC", add, 0, /* page 112 */ 179219b2ee8SDavid du Colombier 180219b2ee8SDavid du Colombier [0x0A] "UMUL", add, 0, /* page 113 */ 181219b2ee8SDavid du Colombier [0x0B] "SMUL", add, 0, 182219b2ee8SDavid du Colombier [0x1A] "UMULCC", add, 0, 183219b2ee8SDavid du Colombier [0x1B] "SMULCC", add, 0, 184219b2ee8SDavid du Colombier 185219b2ee8SDavid du Colombier [0x0E] "UDIV", add, 0, /* page 115 */ 186219b2ee8SDavid du Colombier [0x0F] "SDIV", add, 0, 187219b2ee8SDavid du Colombier [0x1E] "UDIVCC", add, 0, 188219b2ee8SDavid du Colombier [0x1F] "SDIVCC", add, 0, 189219b2ee8SDavid du Colombier 190219b2ee8SDavid du Colombier [0x01] "AND", add, 0, /* page 106 */ 191219b2ee8SDavid du Colombier [0x11] "ANDCC", add, 0, 192219b2ee8SDavid du Colombier [0x05] "ANDN", add, 0, 193219b2ee8SDavid du Colombier [0x15] "ANDNCC", add, 0, 194219b2ee8SDavid du Colombier [0x02] "OR", add, 0, 195219b2ee8SDavid du Colombier [0x12] "ORCC", add, 0, 196219b2ee8SDavid du Colombier [0x06] "ORN", add, 0, 197219b2ee8SDavid du Colombier [0x16] "ORNCC", add, 0, 198219b2ee8SDavid du Colombier [0x03] "XOR", add, 0, 199219b2ee8SDavid du Colombier [0x13] "XORCC", add, 0, 200219b2ee8SDavid du Colombier [0x07] "XORN", add, 0, 201219b2ee8SDavid du Colombier [0x17] "XORNCC", add, 0, 202219b2ee8SDavid du Colombier 203219b2ee8SDavid du Colombier [0x25] "SLL", shift, 0, /* page 107 */ 204219b2ee8SDavid du Colombier [0x26] "SRL", shift, 0, 205219b2ee8SDavid du Colombier [0x27] "SRA", shift, 0, 206219b2ee8SDavid du Colombier 207219b2ee8SDavid du Colombier [0x3C] "SAVE", add, 0, /* page 117 */ 208219b2ee8SDavid du Colombier [0x3D] "RESTORE", add, 0, 209219b2ee8SDavid du Colombier 210219b2ee8SDavid du Colombier [0x38] "JMPL", jmpl, 0, /* page 126 */ 211219b2ee8SDavid du Colombier 212219b2ee8SDavid du Colombier [0x39] "RETT", add, 0, /* page 127 */ 213219b2ee8SDavid du Colombier 214219b2ee8SDavid du Colombier [0x3A] "T", trap, 0, /* page 129 */ 215219b2ee8SDavid du Colombier 216219b2ee8SDavid du Colombier [0x28] "rdy", rd, 0, /* page 131 */ 217219b2ee8SDavid du Colombier [0x29] "rdpsr", rd, 0, 218219b2ee8SDavid du Colombier [0x2A] "rdwim", rd, 0, 219219b2ee8SDavid du Colombier [0x2B] "rdtbr", rd, 0, 220219b2ee8SDavid du Colombier 221219b2ee8SDavid du Colombier [0x30] "wry", wr, 0, /* page 133 */ 222219b2ee8SDavid du Colombier [0x31] "wrpsr", wr, 0, 223219b2ee8SDavid du Colombier [0x32] "wrwim", wr, 0, 224219b2ee8SDavid du Colombier [0x33] "wrtbr", wr, 0, 225219b2ee8SDavid du Colombier 226219b2ee8SDavid du Colombier [0x3B] "flush", add, 0, /* page 138 */ 227219b2ee8SDavid du Colombier 228219b2ee8SDavid du Colombier [0x34] "FPOP", fpop, 0, /* page 140 */ 229219b2ee8SDavid du Colombier [0x35] "FPOP", fpop, 0, 230219b2ee8SDavid du Colombier }; 231219b2ee8SDavid du Colombier 232219b2ee8SDavid du Colombier static struct opcode sparcop3[64]={ 233219b2ee8SDavid du Colombier [0x09] "ldsb", load, 0, /* page 90 */ 234219b2ee8SDavid du Colombier [0x19] "ldsba", loada, 0, 235219b2ee8SDavid du Colombier [0x0A] "ldsh", load, 0, 236219b2ee8SDavid du Colombier [0x1A] "ldsha", loada, 0, 237219b2ee8SDavid du Colombier [0x01] "ldub", load, 0, 238219b2ee8SDavid du Colombier [0x11] "lduba", loada, 0, 239219b2ee8SDavid du Colombier [0x02] "lduh", load, 0, 240219b2ee8SDavid du Colombier [0x12] "lduha", loada, 0, 241219b2ee8SDavid du Colombier [0x00] "ld", load, 0, 242219b2ee8SDavid du Colombier [0x10] "lda", loada, 0, 243219b2ee8SDavid du Colombier [0x03] "ldd", load, 0, 244219b2ee8SDavid du Colombier [0x13] "ldda", loada, 0, 245219b2ee8SDavid du Colombier 246219b2ee8SDavid du Colombier [0x20] "ldf", loadf, 0, /* page 92 */ 247219b2ee8SDavid du Colombier [0x23] "lddf", loadf, 0, 248219b2ee8SDavid du Colombier [0x21] "ldfsr", loadf,0, 249219b2ee8SDavid du Colombier 250219b2ee8SDavid du Colombier [0x30] "ldc", loadc, 0, /* page 94 */ 251219b2ee8SDavid du Colombier [0x33] "lddc", loadc, 0, 252219b2ee8SDavid du Colombier [0x31] "ldcsr", loadcsr,0, 253219b2ee8SDavid du Colombier 254219b2ee8SDavid du Colombier [0x05] "stb", store, 0, /* page 95 */ 255219b2ee8SDavid du Colombier [0x15] "stba", storea, 0, 256219b2ee8SDavid du Colombier [0x06] "sth", store, 0, 257219b2ee8SDavid du Colombier [0x16] "stha", storea, 0, 258219b2ee8SDavid du Colombier [0x04] "st", store, 0, 259219b2ee8SDavid du Colombier [0x14] "sta", storea, 0, 260219b2ee8SDavid du Colombier [0x07] "std", store, 0, 261219b2ee8SDavid du Colombier [0x17] "stda", storea, 0, 262219b2ee8SDavid du Colombier 263219b2ee8SDavid du Colombier [0x24] "stf", storef, 0, /* page 97 */ 264219b2ee8SDavid du Colombier [0x27] "stdf", storef, 0, 265219b2ee8SDavid du Colombier [0x25] "stfsr", storef,0, 266219b2ee8SDavid du Colombier [0x26] "stdfq", storef,0, 267219b2ee8SDavid du Colombier 268219b2ee8SDavid du Colombier [0x34] "stc", loadc, 0, /* page 99 */ 269219b2ee8SDavid du Colombier [0x37] "stdc", loadc, 0, 270219b2ee8SDavid du Colombier [0x35] "stcsr", loadcsr,0, 271219b2ee8SDavid du Colombier [0x36] "stdcq", loadcsr,0, 272219b2ee8SDavid du Colombier 273219b2ee8SDavid du Colombier [0x0D] "ldstub", store, 0, /* page 101 */ 274219b2ee8SDavid du Colombier [0x1D] "ldstuba", storea, 0, 275219b2ee8SDavid du Colombier 276219b2ee8SDavid du Colombier [0x0F] "swap", load, 0, /* page 102 */ 277219b2ee8SDavid du Colombier [0x1F] "swapa", loada, 0, 278219b2ee8SDavid du Colombier }; 279219b2ee8SDavid du Colombier 280219b2ee8SDavid du Colombier static void 281219b2ee8SDavid du Colombier bprint(Instr *i, char *fmt, ...) 282219b2ee8SDavid du Colombier { 2837dd7cddfSDavid du Colombier va_list arg; 2847dd7cddfSDavid du Colombier 2857dd7cddfSDavid du Colombier va_start(arg, fmt); 286*9a747e4fSDavid du Colombier i->curr = vseprint(i->curr, i->end, fmt, arg); 2877dd7cddfSDavid du Colombier va_end(arg); 288219b2ee8SDavid du Colombier } 289219b2ee8SDavid du Colombier 290219b2ee8SDavid du Colombier static int 291219b2ee8SDavid du Colombier decode(ulong pc, Instr *i) 292219b2ee8SDavid du Colombier { 293219b2ee8SDavid du Colombier long w; 294219b2ee8SDavid du Colombier 295219b2ee8SDavid du Colombier if (get4(mymap, pc, &w) < 0) { 296219b2ee8SDavid du Colombier werrstr("can't read instruction: %r"); 297219b2ee8SDavid du Colombier return -1; 298219b2ee8SDavid du Colombier } 299219b2ee8SDavid du Colombier i->op = (w >> 30) & 0x03; 300219b2ee8SDavid du Colombier i->rd = (w >> 25) & 0x1F; 301219b2ee8SDavid du Colombier i->op2 = (w >> 22) & 0x07; 302219b2ee8SDavid du Colombier i->a = (w >> 29) & 0x01; 303219b2ee8SDavid du Colombier i->cond = (w >> 25) & 0x0F; 304219b2ee8SDavid du Colombier i->op3 = (w >> 19) & 0x3F; 305219b2ee8SDavid du Colombier i->rs1 = (w >> 14) & 0x1F; 306219b2ee8SDavid du Colombier i->i = (w >> 13) & 0x01; 307219b2ee8SDavid du Colombier i->asi = (w >> 5) & 0xFF; 308219b2ee8SDavid du Colombier i->rs2 = (w >> 0) & 0x1F; 309219b2ee8SDavid du Colombier i->simm13 = (w >> 0) & 0x1FFF; 310219b2ee8SDavid du Colombier if(i->simm13 & (1<<12)) 311219b2ee8SDavid du Colombier i->simm13 |= ~((1<<13)-1); 312219b2ee8SDavid du Colombier i->opf = (w >> 5) & 0x1FF; 313219b2ee8SDavid du Colombier i->immdisp22 = (w >> 0) & 0x3FFFFF; 314219b2ee8SDavid du Colombier i->simmdisp22 = i->immdisp22; 315219b2ee8SDavid du Colombier if(i->simmdisp22 & (1<<21)) 316219b2ee8SDavid du Colombier i->simmdisp22 |= ~((1<<22)-1); 317219b2ee8SDavid du Colombier i->disp30 = (w >> 0) & 0x3FFFFFFF; 318219b2ee8SDavid du Colombier i->w0 = w; 319219b2ee8SDavid du Colombier i->target = -1; 320219b2ee8SDavid du Colombier i->addr = pc; 321219b2ee8SDavid du Colombier i->size = 1; 322219b2ee8SDavid du Colombier return 1; 323219b2ee8SDavid du Colombier } 324219b2ee8SDavid du Colombier 325219b2ee8SDavid du Colombier static int 326219b2ee8SDavid du Colombier mkinstr(ulong pc, Instr *i) 327219b2ee8SDavid du Colombier { 328219b2ee8SDavid du Colombier Instr xi; 329219b2ee8SDavid du Colombier 330219b2ee8SDavid du Colombier if (decode(pc, i) < 0) 331219b2ee8SDavid du Colombier return -1; 332219b2ee8SDavid du Colombier if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */ 333219b2ee8SDavid du Colombier if (decode(pc+4, &xi) < 0) 334219b2ee8SDavid du Colombier return -1; 335219b2ee8SDavid du Colombier if(xi.op==2 && xi.op3==0) /* ADD */ 336219b2ee8SDavid du Colombier if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */ 337219b2ee8SDavid du Colombier i->imm32 = xi.simm13 + (i->immdisp22<<10); 338219b2ee8SDavid du Colombier i->target = xi.rd; 339219b2ee8SDavid du Colombier i->w1 = xi.w0; 340219b2ee8SDavid du Colombier i->size++; 341219b2ee8SDavid du Colombier return 1; 342219b2ee8SDavid du Colombier } 343219b2ee8SDavid du Colombier } 344219b2ee8SDavid du Colombier if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */ 345219b2ee8SDavid du Colombier if (decode(pc+4, &xi) < 0) 346219b2ee8SDavid du Colombier return -1; 347219b2ee8SDavid du Colombier if(i->op==2 && i->opf==1) /* FMOVS */ 348219b2ee8SDavid du Colombier if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */ 349219b2ee8SDavid du Colombier i->w1 = xi.w0; 350219b2ee8SDavid du Colombier i->size++; 351219b2ee8SDavid du Colombier } 352219b2ee8SDavid du Colombier } 353219b2ee8SDavid du Colombier return 1; 354219b2ee8SDavid du Colombier } 355219b2ee8SDavid du Colombier 356219b2ee8SDavid du Colombier static int 357219b2ee8SDavid du Colombier printins(Map *map, ulong pc, char *buf, int n) 358219b2ee8SDavid du Colombier { 359219b2ee8SDavid du Colombier Instr instr; 360219b2ee8SDavid du Colombier void (*f)(Instr*, char*); 361219b2ee8SDavid du Colombier 362219b2ee8SDavid du Colombier mymap = map; 363219b2ee8SDavid du Colombier memset(&instr, 0, sizeof(instr)); 364219b2ee8SDavid du Colombier instr.curr = buf; 365219b2ee8SDavid du Colombier instr.end = buf+n-1; 366219b2ee8SDavid du Colombier if (mkinstr(pc, &instr) < 0) 367219b2ee8SDavid du Colombier return -1; 368219b2ee8SDavid du Colombier switch(instr.op){ 369219b2ee8SDavid du Colombier case 0: 370219b2ee8SDavid du Colombier f = sparcop0[instr.op2].f; 371219b2ee8SDavid du Colombier if(f) 372219b2ee8SDavid du Colombier (*f)(&instr, sparcop0[instr.op2].mnemonic); 373219b2ee8SDavid du Colombier else 374219b2ee8SDavid du Colombier bprint(&instr, "unknown %lux", instr.w0); 375219b2ee8SDavid du Colombier break; 376219b2ee8SDavid du Colombier 377219b2ee8SDavid du Colombier case 1: 378219b2ee8SDavid du Colombier bprint(&instr, "%X", "CALL\t"); 379219b2ee8SDavid du Colombier instr.curr += symoff(instr.curr, instr.end-instr.curr, 380219b2ee8SDavid du Colombier pc+instr.disp30*4, CTEXT); 381219b2ee8SDavid du Colombier if (!dascase) 382219b2ee8SDavid du Colombier bprint(&instr, "(SB)"); 383219b2ee8SDavid du Colombier break; 384219b2ee8SDavid du Colombier 385219b2ee8SDavid du Colombier case 2: 386219b2ee8SDavid du Colombier f = sparcop2[instr.op3].f; 387219b2ee8SDavid du Colombier if(f) 388219b2ee8SDavid du Colombier (*f)(&instr, sparcop2[instr.op3].mnemonic); 389219b2ee8SDavid du Colombier else 390219b2ee8SDavid du Colombier bprint(&instr, "unknown %lux", instr.w0); 391219b2ee8SDavid du Colombier break; 392219b2ee8SDavid du Colombier 393219b2ee8SDavid du Colombier case 3: 394219b2ee8SDavid du Colombier f = sparcop3[instr.op3].f; 395219b2ee8SDavid du Colombier if(f) 396219b2ee8SDavid du Colombier (*f)(&instr, sparcop3[instr.op3].mnemonic); 397219b2ee8SDavid du Colombier else 398219b2ee8SDavid du Colombier bprint(&instr, "unknown %lux", instr.w0); 399219b2ee8SDavid du Colombier break; 400219b2ee8SDavid du Colombier } 401219b2ee8SDavid du Colombier if (instr.err) { 402219b2ee8SDavid du Colombier if (instr.curr != buf) 403219b2ee8SDavid du Colombier bprint(&instr, "\t\t;"); 404219b2ee8SDavid du Colombier bprint(&instr, instr.err); 405219b2ee8SDavid du Colombier } 406219b2ee8SDavid du Colombier return instr.size*4; 407219b2ee8SDavid du Colombier } 408219b2ee8SDavid du Colombier 409219b2ee8SDavid du Colombier /* convert to lower case from upper, according to dascase */ 410219b2ee8SDavid du Colombier static int 411*9a747e4fSDavid du Colombier Xfmt(Fmt *f) 412219b2ee8SDavid du Colombier { 413219b2ee8SDavid du Colombier char buf[128]; 4147dd7cddfSDavid du Colombier char *s, *t, *oa; 415219b2ee8SDavid du Colombier 416*9a747e4fSDavid du Colombier oa = va_arg(f->args, char*); 417219b2ee8SDavid du Colombier if(dascase){ 4187dd7cddfSDavid du Colombier for(s=oa,t=buf; *t = *s; s++,t++) 419219b2ee8SDavid du Colombier if('A'<=*t && *t<='Z') 420219b2ee8SDavid du Colombier *t += 'a'-'A'; 421*9a747e4fSDavid du Colombier return fmtstrcpy(f, buf); 422*9a747e4fSDavid du Colombier } 423*9a747e4fSDavid du Colombier return fmtstrcpy(f, oa); 424219b2ee8SDavid du Colombier } 425219b2ee8SDavid du Colombier 426219b2ee8SDavid du Colombier static int 427219b2ee8SDavid du Colombier sparcinst(Map *map, ulong pc, char modifier, char *buf, int n) 428219b2ee8SDavid du Colombier { 429219b2ee8SDavid du Colombier static int fmtinstalled = 0; 430219b2ee8SDavid du Colombier 431219b2ee8SDavid du Colombier /* a modifier of 'I' toggles the dissassembler type */ 432219b2ee8SDavid du Colombier if (!fmtinstalled) { 433219b2ee8SDavid du Colombier fmtinstalled = 1; 434*9a747e4fSDavid du Colombier fmtinstall('X', Xfmt); 435219b2ee8SDavid du Colombier } 436219b2ee8SDavid du Colombier if ((asstype == ASUNSPARC && modifier == 'i') 437219b2ee8SDavid du Colombier || (asstype == ASPARC && modifier == 'I')) 438219b2ee8SDavid du Colombier dascase = 'a'-'A'; 439219b2ee8SDavid du Colombier else 440219b2ee8SDavid du Colombier dascase = 0; 441219b2ee8SDavid du Colombier return printins(map, pc, buf, n); 442219b2ee8SDavid du Colombier } 443219b2ee8SDavid du Colombier 444219b2ee8SDavid du Colombier static int 445219b2ee8SDavid du Colombier sparcdas(Map *map, ulong pc, char *buf, int n) 446219b2ee8SDavid du Colombier { 447219b2ee8SDavid du Colombier Instr instr; 448219b2ee8SDavid du Colombier 449219b2ee8SDavid du Colombier mymap = map; 450219b2ee8SDavid du Colombier memset(&instr, 0, sizeof(instr)); 451219b2ee8SDavid du Colombier instr.curr = buf; 452219b2ee8SDavid du Colombier instr.end = buf+n-1; 453219b2ee8SDavid du Colombier if (mkinstr(pc, &instr) < 0) 454219b2ee8SDavid du Colombier return -1; 455219b2ee8SDavid du Colombier if (instr.end-instr.curr > 8) 456219b2ee8SDavid du Colombier instr.curr = _hexify(instr.curr, instr.w0, 7); 457219b2ee8SDavid du Colombier if (instr.end-instr.curr > 9 && instr.size == 2) { 458219b2ee8SDavid du Colombier *instr.curr++ = ' '; 459219b2ee8SDavid du Colombier instr.curr = _hexify(instr.curr, instr.w1, 7); 460219b2ee8SDavid du Colombier } 461219b2ee8SDavid du Colombier *instr.curr = 0; 462219b2ee8SDavid du Colombier return instr.size*4; 463219b2ee8SDavid du Colombier } 464219b2ee8SDavid du Colombier 465219b2ee8SDavid du Colombier static int 466219b2ee8SDavid du Colombier sparcinstlen(Map *map, ulong pc) 467219b2ee8SDavid du Colombier { 468219b2ee8SDavid du Colombier Instr i; 469219b2ee8SDavid du Colombier 470219b2ee8SDavid du Colombier mymap = map; 471219b2ee8SDavid du Colombier if (mkinstr(pc, &i) < 0) 472219b2ee8SDavid du Colombier return -1; 473219b2ee8SDavid du Colombier return i.size*4; 474219b2ee8SDavid du Colombier } 475219b2ee8SDavid du Colombier 476219b2ee8SDavid du Colombier static int 477219b2ee8SDavid du Colombier plocal(Instr *i) 478219b2ee8SDavid du Colombier { 479219b2ee8SDavid du Colombier int offset; 480219b2ee8SDavid du Colombier Symbol s; 481219b2ee8SDavid du Colombier 482219b2ee8SDavid du Colombier if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) 483219b2ee8SDavid du Colombier return -1; 484219b2ee8SDavid du Colombier if (s.value > i->simm13) { 485219b2ee8SDavid du Colombier if(getauto(&s, s.value-i->simm13, CAUTO, &s)) { 486219b2ee8SDavid du Colombier bprint(i, "%s+%d(SP)", s.name, s.value); 487219b2ee8SDavid du Colombier return 1; 488219b2ee8SDavid du Colombier } 489219b2ee8SDavid du Colombier } else { 490219b2ee8SDavid du Colombier offset = i->simm13-s.value; 491219b2ee8SDavid du Colombier if (getauto(&s, offset-4, CPARAM, &s)) { 492219b2ee8SDavid du Colombier bprint(i, "%s+%d(FP)", s.name, offset); 493219b2ee8SDavid du Colombier return 1; 494219b2ee8SDavid du Colombier } 495219b2ee8SDavid du Colombier } 496219b2ee8SDavid du Colombier return -1; 497219b2ee8SDavid du Colombier } 498219b2ee8SDavid du Colombier 499219b2ee8SDavid du Colombier static void 500219b2ee8SDavid du Colombier address(Instr *i) 501219b2ee8SDavid du Colombier { 502219b2ee8SDavid du Colombier Symbol s, s2; 503219b2ee8SDavid du Colombier long off, off1; 504219b2ee8SDavid du Colombier 505219b2ee8SDavid du Colombier if (i->rs1 == 1 && plocal(i) >= 0) 506219b2ee8SDavid du Colombier return; 507219b2ee8SDavid du Colombier off = mach->sb+i->simm13; 508219b2ee8SDavid du Colombier if(i->rs1 == 2 && findsym(off, CANY, &s) 509219b2ee8SDavid du Colombier && s.value-off < 4096 510219b2ee8SDavid du Colombier && (s.class == CDATA || s.class == CTEXT)) { 511219b2ee8SDavid du Colombier if(off==s.value && s.name[0]=='$'){ 512219b2ee8SDavid du Colombier off1 = 0; 513219b2ee8SDavid du Colombier get4(mymap, s.value, &off1); 514219b2ee8SDavid du Colombier if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){ 515219b2ee8SDavid du Colombier bprint(i, "$%s(SB)", s2.name); 516219b2ee8SDavid du Colombier return; 517219b2ee8SDavid du Colombier } 518219b2ee8SDavid du Colombier } 519219b2ee8SDavid du Colombier bprint(i, "%s", s.name); 520219b2ee8SDavid du Colombier if (s.value != off) 521219b2ee8SDavid du Colombier bprint(i, "+%lux", s.value-off); 522219b2ee8SDavid du Colombier bprint(i, "(SB)"); 523219b2ee8SDavid du Colombier return; 524219b2ee8SDavid du Colombier } 525219b2ee8SDavid du Colombier bprint(i, "%lux(R%d)", i->simm13, i->rs1); 526219b2ee8SDavid du Colombier } 527219b2ee8SDavid du Colombier 528219b2ee8SDavid du Colombier static void 529219b2ee8SDavid du Colombier unimp(Instr *i, char *m) 530219b2ee8SDavid du Colombier { 531219b2ee8SDavid du Colombier bprint(i, "%X", m); 532219b2ee8SDavid du Colombier } 533219b2ee8SDavid du Colombier 534219b2ee8SDavid du Colombier static char *bratab[16] = { /* page 91 */ 535219b2ee8SDavid du Colombier [0X8] "A", 536219b2ee8SDavid du Colombier [0X0] "N", 537219b2ee8SDavid du Colombier [0X9] "NE", 538219b2ee8SDavid du Colombier [0X1] "E", 539219b2ee8SDavid du Colombier [0XA] "G", 540219b2ee8SDavid du Colombier [0X2] "LE", 541219b2ee8SDavid du Colombier [0XB] "GE", 542219b2ee8SDavid du Colombier [0X3] "L", 543219b2ee8SDavid du Colombier [0XC] "GU", 544219b2ee8SDavid du Colombier [0X4] "LEU", 545219b2ee8SDavid du Colombier [0XD] "CC", 546219b2ee8SDavid du Colombier [0X5] "CS", 547219b2ee8SDavid du Colombier [0XE] "POS", 548219b2ee8SDavid du Colombier [0X6] "NEG", 549219b2ee8SDavid du Colombier [0XF] "VC", 550219b2ee8SDavid du Colombier [0X7] "VS", 551219b2ee8SDavid du Colombier }; 552219b2ee8SDavid du Colombier 553219b2ee8SDavid du Colombier static char *fbratab[16] = { /* page 91 */ 554219b2ee8SDavid du Colombier [0X8] "A", 555219b2ee8SDavid du Colombier [0X0] "N", 556219b2ee8SDavid du Colombier [0X7] "U", 557219b2ee8SDavid du Colombier [0X6] "G", 558219b2ee8SDavid du Colombier [0X5] "UG", 559219b2ee8SDavid du Colombier [0X4] "L", 560219b2ee8SDavid du Colombier [0X3] "UL", 561219b2ee8SDavid du Colombier [0X2] "LG", 562219b2ee8SDavid du Colombier [0X1] "NE", 563219b2ee8SDavid du Colombier [0X9] "E", 564219b2ee8SDavid du Colombier [0XA] "UE", 565219b2ee8SDavid du Colombier [0XB] "GE", 566219b2ee8SDavid du Colombier [0XC] "UGE", 567219b2ee8SDavid du Colombier [0XD] "LE", 568219b2ee8SDavid du Colombier [0XE] "ULE", 569219b2ee8SDavid du Colombier [0XF] "O", 570219b2ee8SDavid du Colombier }; 571219b2ee8SDavid du Colombier 572219b2ee8SDavid du Colombier static char *cbratab[16] = { /* page 91 */ 573219b2ee8SDavid du Colombier [0X8] "A", 574219b2ee8SDavid du Colombier [0X0] "N", 575219b2ee8SDavid du Colombier [0X7] "3", 576219b2ee8SDavid du Colombier [0X6] "2", 577219b2ee8SDavid du Colombier [0X5] "23", 578219b2ee8SDavid du Colombier [0X4] "1", 579219b2ee8SDavid du Colombier [0X3] "13", 580219b2ee8SDavid du Colombier [0X2] "12", 581219b2ee8SDavid du Colombier [0X1] "123", 582219b2ee8SDavid du Colombier [0X9] "0", 583219b2ee8SDavid du Colombier [0XA] "03", 584219b2ee8SDavid du Colombier [0XB] "02", 585219b2ee8SDavid du Colombier [0XC] "023", 586219b2ee8SDavid du Colombier [0XD] "01", 587219b2ee8SDavid du Colombier [0XE] "013", 588219b2ee8SDavid du Colombier [0XF] "012", 589219b2ee8SDavid du Colombier }; 590219b2ee8SDavid du Colombier 591219b2ee8SDavid du Colombier static void 592219b2ee8SDavid du Colombier bra1(Instr *i, char *m, char *tab[]) 593219b2ee8SDavid du Colombier { 594219b2ee8SDavid du Colombier long imm; 595219b2ee8SDavid du Colombier 596219b2ee8SDavid du Colombier imm = i->simmdisp22; 597219b2ee8SDavid du Colombier if(i->a) 598219b2ee8SDavid du Colombier bprint(i, "%X%X.%c\t", m, tab[i->cond], 'A'+dascase); 599219b2ee8SDavid du Colombier else 600219b2ee8SDavid du Colombier bprint(i, "%X%X\t", m, tab[i->cond]); 601219b2ee8SDavid du Colombier i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT); 602219b2ee8SDavid du Colombier if (!dascase) 603219b2ee8SDavid du Colombier bprint(i, "(SB)"); 604219b2ee8SDavid du Colombier } 605219b2ee8SDavid du Colombier 606219b2ee8SDavid du Colombier static void 607219b2ee8SDavid du Colombier bra(Instr *i, char *m) /* page 91 */ 608219b2ee8SDavid du Colombier { 609219b2ee8SDavid du Colombier bra1(i, m, bratab); 610219b2ee8SDavid du Colombier } 611219b2ee8SDavid du Colombier 612219b2ee8SDavid du Colombier static void 613219b2ee8SDavid du Colombier fbra(Instr *i, char *m) /* page 93 */ 614219b2ee8SDavid du Colombier { 615219b2ee8SDavid du Colombier bra1(i, m, fbratab); 616219b2ee8SDavid du Colombier } 617219b2ee8SDavid du Colombier 618219b2ee8SDavid du Colombier static void 619219b2ee8SDavid du Colombier cbra(Instr *i, char *m) /* page 95 */ 620219b2ee8SDavid du Colombier { 621219b2ee8SDavid du Colombier bra1(i, m, cbratab); 622219b2ee8SDavid du Colombier } 623219b2ee8SDavid du Colombier 624219b2ee8SDavid du Colombier static void 625219b2ee8SDavid du Colombier trap(Instr *i, char *m) /* page 101 */ 626219b2ee8SDavid du Colombier { 627219b2ee8SDavid du Colombier if(i->i == 0) 628219b2ee8SDavid du Colombier bprint(i, "%X%X\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1); 629219b2ee8SDavid du Colombier else 630219b2ee8SDavid du Colombier bprint(i, "%X%X\t$%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1); 631219b2ee8SDavid du Colombier } 632219b2ee8SDavid du Colombier 633219b2ee8SDavid du Colombier static void 634219b2ee8SDavid du Colombier sethi(Instr *i, char *m) /* page 89 */ 635219b2ee8SDavid du Colombier { 636219b2ee8SDavid du Colombier ulong imm; 637219b2ee8SDavid du Colombier 638219b2ee8SDavid du Colombier imm = i->immdisp22<<10; 639219b2ee8SDavid du Colombier if(dascase){ 640219b2ee8SDavid du Colombier bprint(i, "%X\t%lux, R%d", m, imm, i->rd); 641219b2ee8SDavid du Colombier return; 642219b2ee8SDavid du Colombier } 643219b2ee8SDavid du Colombier if(imm==0 && i->rd==0){ 644219b2ee8SDavid du Colombier bprint(i, "NOP"); 645219b2ee8SDavid du Colombier return; 646219b2ee8SDavid du Colombier } 647219b2ee8SDavid du Colombier if(i->target < 0){ 648219b2ee8SDavid du Colombier bprint(i, "MOVW\t$%lux, R%d", imm, i->rd); 649219b2ee8SDavid du Colombier return; 650219b2ee8SDavid du Colombier } 651219b2ee8SDavid du Colombier bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target); 652219b2ee8SDavid du Colombier } 653219b2ee8SDavid du Colombier 654219b2ee8SDavid du Colombier static char ldtab[] = { 655219b2ee8SDavid du Colombier 'W', 656219b2ee8SDavid du Colombier 'B', 657219b2ee8SDavid du Colombier 'H', 658219b2ee8SDavid du Colombier 'D', 659219b2ee8SDavid du Colombier }; 660219b2ee8SDavid du Colombier 661219b2ee8SDavid du Colombier static char* 662219b2ee8SDavid du Colombier moveinstr(int op3, char *m) 663219b2ee8SDavid du Colombier { 664219b2ee8SDavid du Colombier char *s; 665219b2ee8SDavid du Colombier int c; 666219b2ee8SDavid du Colombier static char buf[8]; 667219b2ee8SDavid du Colombier 668219b2ee8SDavid du Colombier if(!dascase){ 669219b2ee8SDavid du Colombier /* batshit cases */ 670219b2ee8SDavid du Colombier if(op3 == 0xF || op3 == 0x1F) 671219b2ee8SDavid du Colombier return "SWAP"; 672219b2ee8SDavid du Colombier if(op3 == 0xD || op3 == 0x1D) 673219b2ee8SDavid du Colombier return "TAS"; /* really LDSTUB */ 674219b2ee8SDavid du Colombier c = ldtab[op3&3]; 675219b2ee8SDavid du Colombier s = ""; 676219b2ee8SDavid du Colombier if((op3&11)==1 || (op3&11)==2) 677219b2ee8SDavid du Colombier s="U"; 678219b2ee8SDavid du Colombier sprint(buf, "MOV%c%s", c, s); 679219b2ee8SDavid du Colombier return buf; 680219b2ee8SDavid du Colombier } 681219b2ee8SDavid du Colombier return m; 682219b2ee8SDavid du Colombier } 683219b2ee8SDavid du Colombier 684219b2ee8SDavid du Colombier static void 685219b2ee8SDavid du Colombier load(Instr *i, char *m) /* page 68 */ 686219b2ee8SDavid du Colombier { 687219b2ee8SDavid du Colombier m = moveinstr(i->op3, m); 688219b2ee8SDavid du Colombier if(i->i == 0) 689219b2ee8SDavid du Colombier bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd); 690219b2ee8SDavid du Colombier else{ 691219b2ee8SDavid du Colombier bprint(i, "%s\t", m); 692219b2ee8SDavid du Colombier address(i); 693219b2ee8SDavid du Colombier bprint(i, ", R%d", i->rd); 694219b2ee8SDavid du Colombier } 695219b2ee8SDavid du Colombier } 696219b2ee8SDavid du Colombier 697219b2ee8SDavid du Colombier static void 698219b2ee8SDavid du Colombier loada(Instr *i, char *m) /* page 68 */ 699219b2ee8SDavid du Colombier { 700219b2ee8SDavid du Colombier m = moveinstr(i->op3, m); 701219b2ee8SDavid du Colombier if(i->i == 0) 702219b2ee8SDavid du Colombier bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd); 703219b2ee8SDavid du Colombier else 704219b2ee8SDavid du Colombier bprint(i, "unknown ld asi %lux", i->w0); 705219b2ee8SDavid du Colombier } 706219b2ee8SDavid du Colombier 707219b2ee8SDavid du Colombier static void 708219b2ee8SDavid du Colombier store(Instr *i, char *m) /* page 74 */ 709219b2ee8SDavid du Colombier { 710219b2ee8SDavid du Colombier m = moveinstr(i->op3, m); 711219b2ee8SDavid du Colombier if(i->i == 0) 712219b2ee8SDavid du Colombier bprint(i, "%s\tR%d, (R%d+R%d)", 713219b2ee8SDavid du Colombier m, i->rd, i->rs1, i->rs2); 714219b2ee8SDavid du Colombier else{ 715219b2ee8SDavid du Colombier bprint(i, "%s\tR%d, ", m, i->rd); 716219b2ee8SDavid du Colombier address(i); 717219b2ee8SDavid du Colombier } 718219b2ee8SDavid du Colombier } 719219b2ee8SDavid du Colombier 720219b2ee8SDavid du Colombier static void 721219b2ee8SDavid du Colombier storea(Instr *i, char *m) /* page 74 */ 722219b2ee8SDavid du Colombier { 723219b2ee8SDavid du Colombier m = moveinstr(i->op3, m); 724219b2ee8SDavid du Colombier if(i->i == 0) 725219b2ee8SDavid du Colombier bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi); 726219b2ee8SDavid du Colombier else 727219b2ee8SDavid du Colombier bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi); 728219b2ee8SDavid du Colombier } 729219b2ee8SDavid du Colombier 7307dd7cddfSDavid du Colombier static void 731219b2ee8SDavid du Colombier shift(Instr *i, char *m) /* page 88 */ 732219b2ee8SDavid du Colombier { 733219b2ee8SDavid du Colombier if(i->i == 0){ 734219b2ee8SDavid du Colombier if(i->rs1 == i->rd) 735219b2ee8SDavid du Colombier if(dascase) 736219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); 737219b2ee8SDavid du Colombier else 738219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); 739219b2ee8SDavid du Colombier else 740219b2ee8SDavid du Colombier if(dascase) 741219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd); 742219b2ee8SDavid du Colombier else 743219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd); 744219b2ee8SDavid du Colombier }else{ 745219b2ee8SDavid du Colombier if(i->rs1 == i->rd) 746219b2ee8SDavid du Colombier if(dascase) 747219b2ee8SDavid du Colombier bprint(i, "%X\t$%d,R%d", m, i->simm13&0x1F, i->rs1); 748219b2ee8SDavid du Colombier else 749219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, $%d", m, i->rs1, i->simm13&0x1F); 750219b2ee8SDavid du Colombier else 751219b2ee8SDavid du Colombier if(dascase) 752219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd); 753219b2ee8SDavid du Colombier else 754219b2ee8SDavid du Colombier bprint(i, "%X\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd); 755219b2ee8SDavid du Colombier } 756219b2ee8SDavid du Colombier } 757219b2ee8SDavid du Colombier 758219b2ee8SDavid du Colombier static void 759219b2ee8SDavid du Colombier add(Instr *i, char *m) /* page 82 */ 760219b2ee8SDavid du Colombier { 761219b2ee8SDavid du Colombier if(i->i == 0){ 762219b2ee8SDavid du Colombier if(dascase) 763219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); 764219b2ee8SDavid du Colombier else 765219b2ee8SDavid du Colombier if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */ 766219b2ee8SDavid du Colombier bprint(i, "MOVW\tR%d", i->rs2); 767219b2ee8SDavid du Colombier else 768219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); 769219b2ee8SDavid du Colombier }else{ 770219b2ee8SDavid du Colombier if(dascase) 771219b2ee8SDavid du Colombier bprint(i, "%X\tR%d, $%lux", m, i->rs1, i->simm13); 772219b2ee8SDavid du Colombier else 773219b2ee8SDavid du Colombier if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */ 774219b2ee8SDavid du Colombier bprint(i, "MOVW\t$%lux", i->simm13); 775219b2ee8SDavid du Colombier else if(i->op3==0 && i->rd && i->rs1==2){ 776219b2ee8SDavid du Colombier /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */ 777219b2ee8SDavid du Colombier bprint(i, "MOVW\t$"); 778219b2ee8SDavid du Colombier address(i); 779219b2ee8SDavid du Colombier } else 780219b2ee8SDavid du Colombier bprint(i, "%X\t$%lux, R%d", m, i->simm13, i->rs1); 781219b2ee8SDavid du Colombier } 782219b2ee8SDavid du Colombier if(i->rs1 != i->rd) 783219b2ee8SDavid du Colombier bprint(i, ", R%d", i->rd); 784219b2ee8SDavid du Colombier } 785219b2ee8SDavid du Colombier 786219b2ee8SDavid du Colombier static void 787219b2ee8SDavid du Colombier cmp(Instr *i, char *m) 788219b2ee8SDavid du Colombier { 789219b2ee8SDavid du Colombier if(dascase || i->rd){ 790219b2ee8SDavid du Colombier add(i, m); 791219b2ee8SDavid du Colombier return; 792219b2ee8SDavid du Colombier } 793219b2ee8SDavid du Colombier if(i->i == 0) 794219b2ee8SDavid du Colombier bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2); 795219b2ee8SDavid du Colombier else 796219b2ee8SDavid du Colombier bprint(i, "CMP\tR%d, $%lux", i->rs1, i->simm13); 797219b2ee8SDavid du Colombier } 798219b2ee8SDavid du Colombier 799219b2ee8SDavid du Colombier static char *regtab[4] = { 800219b2ee8SDavid du Colombier "Y", 801219b2ee8SDavid du Colombier "PSR", 802219b2ee8SDavid du Colombier "WIM", 803219b2ee8SDavid du Colombier "TBR", 804219b2ee8SDavid du Colombier }; 805219b2ee8SDavid du Colombier 806219b2ee8SDavid du Colombier static void 807219b2ee8SDavid du Colombier wr(Instr *i, char *m) /* page 82 */ 808219b2ee8SDavid du Colombier { 809219b2ee8SDavid du Colombier if(dascase){ 810219b2ee8SDavid du Colombier if(i->i == 0) 811219b2ee8SDavid du Colombier bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2); 812219b2ee8SDavid du Colombier else 813219b2ee8SDavid du Colombier bprint(i, "%s\tR%d, $%lux", m, i->rs1, i->simm13); 814219b2ee8SDavid du Colombier }else{ 815219b2ee8SDavid du Colombier if(i->i && i->simm13==0) 816219b2ee8SDavid du Colombier bprint(i, "MOVW\tR%d", i->rs1); 817219b2ee8SDavid du Colombier else if(i->i == 0) 818219b2ee8SDavid du Colombier bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1); 819219b2ee8SDavid du Colombier else 820219b2ee8SDavid du Colombier bprint(i, "wr\t$%lux, R%d", i->simm13, i->rs1); 821219b2ee8SDavid du Colombier } 822219b2ee8SDavid du Colombier bprint(i, ", %s", regtab[i->op3&3]); 823219b2ee8SDavid du Colombier } 824219b2ee8SDavid du Colombier 825219b2ee8SDavid du Colombier static void 826219b2ee8SDavid du Colombier rd(Instr *i, char *m) /* page 103 */ 827219b2ee8SDavid du Colombier { 828219b2ee8SDavid du Colombier if(i->rs1==15 && i->rd==0){ 829219b2ee8SDavid du Colombier m = "stbar"; 830219b2ee8SDavid du Colombier if(!dascase) 831219b2ee8SDavid du Colombier m = "STBAR"; 832219b2ee8SDavid du Colombier bprint(i, "%s", m); 833219b2ee8SDavid du Colombier }else{ 834219b2ee8SDavid du Colombier if(!dascase) 835219b2ee8SDavid du Colombier m = "MOVW"; 836219b2ee8SDavid du Colombier bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd); 837219b2ee8SDavid du Colombier } 838219b2ee8SDavid du Colombier } 839219b2ee8SDavid du Colombier 840219b2ee8SDavid du Colombier static void 841219b2ee8SDavid du Colombier jmpl(Instr *i, char *m) /* page 82 */ 842219b2ee8SDavid du Colombier { 843219b2ee8SDavid du Colombier if(i->i == 0){ 844219b2ee8SDavid du Colombier if(i->rd == 15) 845219b2ee8SDavid du Colombier bprint(i, "%X\t(R%d+R%d)", "CALL", i->rs2, i->rs1); 846219b2ee8SDavid du Colombier else 847219b2ee8SDavid du Colombier bprint(i, "%X\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd); 848219b2ee8SDavid du Colombier }else{ 849219b2ee8SDavid du Colombier if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0) 850219b2ee8SDavid du Colombier bprint(i, "RETURN"); 851219b2ee8SDavid du Colombier else{ 852219b2ee8SDavid du Colombier bprint(i, "%X\t", m); 853219b2ee8SDavid du Colombier address(i); 854219b2ee8SDavid du Colombier bprint(i, ", R%d", i->rd); 855219b2ee8SDavid du Colombier } 856219b2ee8SDavid du Colombier } 857219b2ee8SDavid du Colombier } 858219b2ee8SDavid du Colombier 859219b2ee8SDavid du Colombier static void 860219b2ee8SDavid du Colombier loadf(Instr *i, char *m) /* page 70 */ 861219b2ee8SDavid du Colombier { 862219b2ee8SDavid du Colombier if(!dascase){ 863219b2ee8SDavid du Colombier m = "FMOVD"; 864219b2ee8SDavid du Colombier if(i->op3 == 0x20) 865219b2ee8SDavid du Colombier m = "FMOVF"; 866219b2ee8SDavid du Colombier else if(i->op3 == 0x21) 867219b2ee8SDavid du Colombier m = "MOVW"; 868219b2ee8SDavid du Colombier } 869219b2ee8SDavid du Colombier if(i->i == 0) 870219b2ee8SDavid du Colombier bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2); 871219b2ee8SDavid du Colombier else{ 872219b2ee8SDavid du Colombier bprint(i, "%s\t", m); 873219b2ee8SDavid du Colombier address(i); 874219b2ee8SDavid du Colombier } 875219b2ee8SDavid du Colombier if(i->op3 == 0x21) 876219b2ee8SDavid du Colombier bprint(i, ", FSR"); 877219b2ee8SDavid du Colombier else 878219b2ee8SDavid du Colombier bprint(i, ", R%d", i->rd); 879219b2ee8SDavid du Colombier } 880219b2ee8SDavid du Colombier 881219b2ee8SDavid du Colombier static 882219b2ee8SDavid du Colombier void storef(Instr *i, char *m) /* page 70 */ 883219b2ee8SDavid du Colombier { 884219b2ee8SDavid du Colombier if(!dascase){ 885219b2ee8SDavid du Colombier m = "FMOVD"; 886219b2ee8SDavid du Colombier if(i->op3 == 0x25 || i->op3 == 0x26) 887219b2ee8SDavid du Colombier m = "MOVW"; 888219b2ee8SDavid du Colombier else if(i->op3 == 0x20) 889219b2ee8SDavid du Colombier m = "FMOVF"; 890219b2ee8SDavid du Colombier } 891219b2ee8SDavid du Colombier bprint(i, "%s\t", m); 892219b2ee8SDavid du Colombier if(i->op3 == 0x25) 893219b2ee8SDavid du Colombier bprint(i, "FSR, "); 894219b2ee8SDavid du Colombier else if(i->op3 == 0x26) 895219b2ee8SDavid du Colombier bprint(i, "FQ, "); 896219b2ee8SDavid du Colombier else 897219b2ee8SDavid du Colombier bprint(i, "R%d, ", i->rd); 898219b2ee8SDavid du Colombier if(i->i == 0) 899219b2ee8SDavid du Colombier bprint(i, "(R%d+R%d)", i->rs1, i->rs2); 900219b2ee8SDavid du Colombier else 901219b2ee8SDavid du Colombier address(i); 902219b2ee8SDavid du Colombier } 903219b2ee8SDavid du Colombier 904219b2ee8SDavid du Colombier static 905219b2ee8SDavid du Colombier void loadc(Instr *i, char *m) /* page 72 */ 906219b2ee8SDavid du Colombier { 907219b2ee8SDavid du Colombier if(i->i == 0) 908219b2ee8SDavid du Colombier bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd); 909219b2ee8SDavid du Colombier else{ 910219b2ee8SDavid du Colombier bprint(i, "%s\t", m); 911219b2ee8SDavid du Colombier address(i); 912219b2ee8SDavid du Colombier bprint(i, ", C%d", i->rd); 913219b2ee8SDavid du Colombier } 914219b2ee8SDavid du Colombier } 915219b2ee8SDavid du Colombier 916219b2ee8SDavid du Colombier static 917219b2ee8SDavid du Colombier void loadcsr(Instr *i, char *m) /* page 72 */ 918219b2ee8SDavid du Colombier { 919219b2ee8SDavid du Colombier if(i->i == 0) 920219b2ee8SDavid du Colombier bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2); 921219b2ee8SDavid du Colombier else{ 922219b2ee8SDavid du Colombier bprint(i, "%s\t", m); 923219b2ee8SDavid du Colombier address(i); 924219b2ee8SDavid du Colombier bprint(i, ", CSR"); 925219b2ee8SDavid du Colombier } 926219b2ee8SDavid du Colombier } 927219b2ee8SDavid du Colombier 928219b2ee8SDavid du Colombier static struct{ 929219b2ee8SDavid du Colombier int opf; 930219b2ee8SDavid du Colombier char *name; 931219b2ee8SDavid du Colombier } fptab1[] = { /* ignores rs1 */ 932219b2ee8SDavid du Colombier 0xC4, "FITOS", /* page 109 */ 933219b2ee8SDavid du Colombier 0xC8, "FITOD", 934219b2ee8SDavid du Colombier 0xCC, "FITOX", 935219b2ee8SDavid du Colombier 936219b2ee8SDavid du Colombier 0xD1, "FSTOI", /* page 110 */ 937219b2ee8SDavid du Colombier 0xD2, "FDTOI", 938219b2ee8SDavid du Colombier 0xD3, "FXTOI", 939219b2ee8SDavid du Colombier 940219b2ee8SDavid du Colombier 0xC9, "FSTOD", /* page 111 */ 941219b2ee8SDavid du Colombier 0xCD, "FSTOX", 942219b2ee8SDavid du Colombier 0xC6, "FDTOS", 943219b2ee8SDavid du Colombier 0xCE, "FDTOX", 944219b2ee8SDavid du Colombier 0xC7, "FXTOS", 945219b2ee8SDavid du Colombier 0xCB, "FXTOD", 946219b2ee8SDavid du Colombier 947219b2ee8SDavid du Colombier 0x01, "FMOVS", /* page 112 */ 948219b2ee8SDavid du Colombier 0x05, "FNEGS", 949219b2ee8SDavid du Colombier 0x09, "FABSS", 950219b2ee8SDavid du Colombier 951219b2ee8SDavid du Colombier 0x29, "FSQRTS", /* page 113 */ 952219b2ee8SDavid du Colombier 0x2A, "FSQRTD", 953219b2ee8SDavid du Colombier 0x2B, "FSQRTX", 954219b2ee8SDavid du Colombier 955219b2ee8SDavid du Colombier 0, 0, 956219b2ee8SDavid du Colombier }; 957219b2ee8SDavid du Colombier 958219b2ee8SDavid du Colombier static struct{ 959219b2ee8SDavid du Colombier int opf; 960219b2ee8SDavid du Colombier char *name; 961219b2ee8SDavid du Colombier } fptab2[] = { /* uses rs1 */ 962219b2ee8SDavid du Colombier 963219b2ee8SDavid du Colombier 0x41, "FADDS", /* page 114 */ 964219b2ee8SDavid du Colombier 0x42, "FADDD", 965219b2ee8SDavid du Colombier 0x43, "FADDX", 966219b2ee8SDavid du Colombier 0x45, "FSUBS", 967219b2ee8SDavid du Colombier 0x46, "FSUBD", 968219b2ee8SDavid du Colombier 0x47, "FSUBX", 969219b2ee8SDavid du Colombier 970219b2ee8SDavid du Colombier 0x49, "FMULS", /* page 115 */ 971219b2ee8SDavid du Colombier 0x4A, "FMULD", 972219b2ee8SDavid du Colombier 0x4B, "FMULX", 973219b2ee8SDavid du Colombier 0x4D, "FDIVS", 974219b2ee8SDavid du Colombier 0x4E, "FDIVD", 975219b2ee8SDavid du Colombier 0x4F, "FDIVX", 976219b2ee8SDavid du Colombier 977219b2ee8SDavid du Colombier 0x51, "FCMPS", /* page 116 */ 978219b2ee8SDavid du Colombier 0x52, "FCMPD", 979219b2ee8SDavid du Colombier 0x53, "FCMPX", 980219b2ee8SDavid du Colombier 0x55, "FCMPES", 981219b2ee8SDavid du Colombier 0x56, "FCMPED", 982219b2ee8SDavid du Colombier 0x57, "FCMPEX", 983219b2ee8SDavid du Colombier 984219b2ee8SDavid du Colombier 0, 0 985219b2ee8SDavid du Colombier }; 986219b2ee8SDavid du Colombier 987219b2ee8SDavid du Colombier static void 988219b2ee8SDavid du Colombier fpop(Instr *i, char *m) /* page 108-116 */ 989219b2ee8SDavid du Colombier { 990219b2ee8SDavid du Colombier int j; 991219b2ee8SDavid du Colombier 992219b2ee8SDavid du Colombier if(dascase==0 && i->size==2){ 993219b2ee8SDavid du Colombier bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd); 994219b2ee8SDavid du Colombier return; 995219b2ee8SDavid du Colombier } 996219b2ee8SDavid du Colombier for(j=0; fptab1[j].name; j++) 997219b2ee8SDavid du Colombier if(fptab1[j].opf == i->opf){ 998219b2ee8SDavid du Colombier bprint(i, "%X\tF%d, F%d", fptab1[j].name, i->rs2, i->rd); 999219b2ee8SDavid du Colombier return; 1000219b2ee8SDavid du Colombier } 1001219b2ee8SDavid du Colombier for(j=0; fptab2[j].name; j++) 1002219b2ee8SDavid du Colombier if(fptab2[j].opf == i->opf){ 1003219b2ee8SDavid du Colombier bprint(i, "%X\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd); 1004219b2ee8SDavid du Colombier return; 1005219b2ee8SDavid du Colombier } 1006219b2ee8SDavid du Colombier bprint(i, "%X%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd); 1007219b2ee8SDavid du Colombier } 1008219b2ee8SDavid du Colombier 1009219b2ee8SDavid du Colombier static int 1010219b2ee8SDavid du Colombier sparcfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) 1011219b2ee8SDavid du Colombier { 1012219b2ee8SDavid du Colombier ulong w, r1, r2; 1013219b2ee8SDavid du Colombier char buf[8]; 1014219b2ee8SDavid du Colombier Instr i; 1015219b2ee8SDavid du Colombier 1016219b2ee8SDavid du Colombier mymap = map; 1017219b2ee8SDavid du Colombier if (mkinstr(pc, &i) < 0) 1018219b2ee8SDavid du Colombier return -1; 1019219b2ee8SDavid du Colombier w = i.w0; 1020219b2ee8SDavid du Colombier switch(w & 0xC1C00000){ 1021219b2ee8SDavid du Colombier case 0x00800000: /* branch on int cond */ 1022219b2ee8SDavid du Colombier case 0x01800000: /* branch on fp cond */ 1023219b2ee8SDavid du Colombier case 0x01C00000: /* branch on copr cond */ 1024219b2ee8SDavid du Colombier foll[0] = pc+8; 1025219b2ee8SDavid du Colombier foll[1] = pc + (i.simmdisp22<<2); 1026219b2ee8SDavid du Colombier return 2; 1027219b2ee8SDavid du Colombier } 1028219b2ee8SDavid du Colombier 1029219b2ee8SDavid du Colombier if((w&0xC0000000) == 0x40000000){ /* CALL */ 1030219b2ee8SDavid du Colombier foll[0] = pc + (i.disp30<<2); 1031219b2ee8SDavid du Colombier return 1; 1032219b2ee8SDavid du Colombier } 1033219b2ee8SDavid du Colombier 1034219b2ee8SDavid du Colombier if((w&0xC1F80000) == 0x81C00000){ /* JMPL */ 10357dd7cddfSDavid du Colombier sprint(buf, "R%ld", (w>>14)&0xF); 1036219b2ee8SDavid du Colombier r1 = (*rget)(map, buf); 1037219b2ee8SDavid du Colombier if(w & 0x2000) /* JMPL R1+simm13 */ 1038219b2ee8SDavid du Colombier r2 = i.simm13; 1039219b2ee8SDavid du Colombier else{ /* JMPL R1+R2 */ 10407dd7cddfSDavid du Colombier sprint(buf, "R%ld", w&0xF); 1041219b2ee8SDavid du Colombier r2 = (*rget)(map, buf); 1042219b2ee8SDavid du Colombier } 1043219b2ee8SDavid du Colombier foll[0] = r1 + r2; 1044219b2ee8SDavid du Colombier return 1; 1045219b2ee8SDavid du Colombier } 1046219b2ee8SDavid du Colombier foll[0] = pc+i.size*4; 1047219b2ee8SDavid du Colombier return 1; 1048219b2ee8SDavid du Colombier } 1049