Path: blob/master/libsnes/bsnes/snes/chip/armdsp/disassembler.cpp
2 views
#ifdef ARMDSP_CPP12string ArmDSP::disassemble_opcode(uint32 pc) {3static string conditions[] = { "eq", "ne", "cs", "cc", "mi" ,"pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "" /*al*/, "nv" };4static string opcodes[] = { "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc", "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn" };5static string registers[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" };6static string indices[] = { "da", "ia", "db", "ib" };78static auto is_move = [](uint4 opcode) { return opcode == 13 || opcode == 15; };9static auto is_comp = [](uint4 opcode) { return opcode >= 8 && opcode <= 11; };10static auto is_math = [](uint4 opcode) { return opcode < 8 || opcode == 12 || opcode == 14; };1112string output{hex<8>(pc), " "};1314uint32 instruction = bus_readword(pc);15output.append(hex<8>(instruction), " ");1617//multiply18//(mul,mla){condition}{s} rd,rm,rs,rn19if((instruction & 0x0fc000f0) == 0x00000090) {20uint4 condition = instruction >> 28;21uint1 accumulate = instruction >> 21;22uint1 save = instruction >> 20;23uint4 rd = instruction >> 16;24uint4 rn = instruction >> 12;25uint4 rs = instruction >> 8;26uint4 rm = instruction >> 0;2728output.append(accumulate ? "mla" : "mul", condition[conditions], save ? "s " : " ");29output.append(registers[rd], ",", registers[rm], ",", registers[rs]);30if(accumulate) output.append(",", registers[rn]);3132return output;33}3435//move to register from status register36//mrs{condition} rd,(c,s)psr37if((instruction & 0x0fb000f0) == 0x01000000) {38uint4 condition = instruction >> 28;39uint1 psr = instruction >> 22;40uint4 rd = instruction >> 12;4142output.append("mrs", condition[conditions], " ");43output.append(registers[rd], ",", psr ? "spsr" : "cpsr");4445return output;46}4748//move to status register from register49//msr{condition} (c,s)psr:{fields},rm50if((instruction & 0x0fb000f0) == 0x01200000) {51uint4 condition = instruction >> 28;52uint1 psr = instruction >> 22;53uint4 field = instruction >> 16;5455output.append("msr", conditions[condition], " ");56output.append(psr ? "spsr:" : "cpsr:",57field & 1 ? "c" : "",58field & 2 ? "x" : "",59field & 4 ? "s" : "",60field & 8 ? "f" : "",61",", registers[(uint4)instruction]);6263return output;64}6566//data immediate shift67//{opcode}{condition}{s} rd,rm {shift} #immediate68//{opcode}{condition} rn,rm {shift} #immediate69//{opcode}{condition}{s} rd,rn,rm {shift} #immediate70if((instruction & 0x0e000010) == 0x00000000) {71uint4 condition = instruction >> 28;72uint4 opcode = instruction >> 21;73uint1 save = instruction >> 20;74uint4 rn = instruction >> 16;75uint4 rd = instruction >> 12;76uint5 shift = instruction >> 7;77uint2 op = instruction >> 5;78uint4 rm = instruction;7980output.append(opcodes[opcode], conditions[condition]);81if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd]);82if(is_comp(opcode)) output.append(" ", registers[rn]);83if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn]);84output.append(",", registers[rm]);85if(op == 0 && shift != 0) output.append(" lsl #", shift);86if(op == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift);87if(op == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift);88if(op == 3 && shift != 0) output.append(" ror #", shift);89if(op == 3 && shift == 0) output.append(" rrx");9091return output;92}9394//data register shift95//{opcode}{condition}{s} rd,rm {shift} rs96//{opcode}{condition} rn,rm {shift} rs97//{opcode}{condition}{s} rd,rn,rm {shift} rs98if((instruction & 0x0e000090) == 0x00000010) {99uint4 condition = instruction >> 28;100uint4 opcode = instruction >> 21;101uint1 save = instruction >> 20;102uint4 rn = instruction >> 16;103uint4 rd = instruction >> 12;104uint4 rs = instruction >> 8;105uint2 mode = instruction >> 5;106uint4 rm = instruction;107108output.append(opcodes[opcode], conditions[condition]);109if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd], ",");110if(is_comp(opcode)) output.append(registers[rn], ",");111if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn], ",");112output.append(registers[rm]);113if(mode == 0) output.append(" lsl ");114if(mode == 1) output.append(" lsr ");115if(mode == 2) output.append(" asr ");116if(mode == 3) output.append(" ror ");117output.append(registers[rs]);118119return output;120}121122//data immediate123//{opcode}{condition}{s} rd,#immediate124//{opcode}{condition} rn,#immediate125//{opcode}{condition}{s} rd,rn,#immediate126if((instruction & 0x0e000000) == 0x02000000) {127uint4 condition = instruction >> 28;128uint4 opcode = instruction >> 21;129uint1 save = instruction >> 20;130uint4 rn = instruction >> 16;131uint4 rd = instruction >> 12;132uint4 rotate = instruction >> 8;133uint8 immediate = instruction;134135uint32 shifter = (immediate >> (rotate << 1)) | (immediate << (32 - (rotate << 1)));136output.append(opcodes[opcode], conditions[condition]);137if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd]);138if(is_comp(opcode)) output.append(" ", registers[rn]);139if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn]);140output.append(",#0x", hex<8>(shifter));141142return output;143}144145//move immediate offset146//(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!}147//(ldr,str){condition}{b} rd,[rn]{,+/-offset}148if((instruction & 0x0e000000) == 0x04000000) {149uint4 condition = instruction >> 28;150uint1 p = instruction >> 24;151uint1 u = instruction >> 23;152uint1 b = instruction >> 22;153uint1 w = instruction >> 21;154uint1 load = instruction >> 20;155uint4 rn = instruction >> 16;156uint4 rd = instruction >> 12;157uint12 immediate = instruction;158159output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " ");160output.append(registers[rd], ",[", registers[rn]);161if(p == 0) output.append("]");162if(immediate) output.append(",", u ? "+" : "-", "0x", hex<3>(immediate));163if(p == 1) output.append("]");164if(p == 1 && w == 1) output.append("!");165166if(rn == 15) output.append(" =0x", hex<8>(bus_readword(pc + 8 + (u ? +immediate : -immediate))));167168return output;169}170171//move register offset172//(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!}173//(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate174if((instruction & 0x0e000010) == 0x06000000) {175uint4 condition = instruction >> 28;176uint1 p = instruction >> 24;177uint1 u = instruction >> 23;178uint1 b = instruction >> 22;179uint1 w = instruction >> 21;180uint1 load = instruction >> 20;181uint4 rn = instruction >> 16;182uint4 rd = instruction >> 12;183uint5 shift = instruction >> 7;184uint2 mode = instruction >> 5;185uint4 rm = instruction;186187output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " ");188output.append(registers[rd], ",[", registers[rn]);189if(p == 0) output.append("]");190output.append(",", u ? "+" : "-", registers[rm]);191if(mode == 0 && shift != 0) output.append(" lsl #", shift);192if(mode == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift);193if(mode == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift);194if(mode == 3 && shift != 0) output.append(" ror #", shift);195if(mode == 3 && shift == 0) output.append(" rrx");196if(p == 1) output.append("]");197if(p == 1 && w == 1) output.append("!");198199return output;200}201202//move multiple203//(ldm,stm){condition}{mode} rn{!},{r...}204if((instruction & 0x0e000000) == 0x08000000) {205uint4 condition = instruction >> 28;206uint4 rn = instruction >> 16;207208output.append(instruction & 0x00100000 ? "ldm" : "stm", conditions[condition], indices[(uint2)(instruction >> 23)]);209output.append(" ", registers[rn], instruction & 0x00200000 ? "!" : "", ",{");210for(unsigned n = 0; n < 16; n++) if(instruction & (1 << n)) output.append(registers[n], ",");211output.rtrim<1>(",");212output.append("}");213214return output;215}216217//branch218//b{l}{condition} address219if((instruction & 0x0e000000) == 0x0a000000) {220uint4 condition = instruction >> 28;221uint1 l = instruction >> 24;222223output.append("b", l ? "l" : "", conditions[condition]);224output.append(" 0x", hex<8>(pc + 8 + (int24)instruction * 4));225226return output;227}228229output.append("???");230return output;231}232233string ArmDSP::disassemble_registers() {234return {235"r0:", hex<8>(r[ 0]), " r1:", hex<8>(r[ 1]), " r2:", hex<8>(r[ 2]), " r3:", hex<8>(r[ 3]),236" r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), " ",237"cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v", "\n",238"r8:", hex<8>(r[ 8]), " r9:", hex<8>(r[ 9]), " r10:", hex<8>(r[10]), " r11:", hex<8>(r[11]),239" r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), " ",240"spsr:", spsr.n ? "N" : "n", spsr.z ? "Z" : "z", spsr.c ? "C" : "c", spsr.v ? "V" : "v"241242};243}244245#endif246247248