mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #1022 from aroulin/disas-missing-v6k-instructions
Disassembler: ARMv6K instructions
This commit is contained in:
		
						commit
						4821652241
					
				
					 2 changed files with 153 additions and 6 deletions
				
			
		|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/arm/disassembler/arm_disasm.h" | #include "core/arm/disassembler/arm_disasm.h" | ||||||
|  | #include "core/arm/skyeye_common/armsupp.h" | ||||||
| 
 | 
 | ||||||
| static const char *cond_names[] = { | static const char *cond_names[] = { | ||||||
|     "eq", |     "eq", | ||||||
|  | @ -37,6 +38,7 @@ static const char *opcode_names[] = { | ||||||
|     "blx", |     "blx", | ||||||
|     "bx", |     "bx", | ||||||
|     "cdp", |     "cdp", | ||||||
|  |     "clrex", | ||||||
|     "clz", |     "clz", | ||||||
|     "cmn", |     "cmn", | ||||||
|     "cmp", |     "cmp", | ||||||
|  | @ -46,6 +48,10 @@ static const char *opcode_names[] = { | ||||||
|     "ldr", |     "ldr", | ||||||
|     "ldrb", |     "ldrb", | ||||||
|     "ldrbt", |     "ldrbt", | ||||||
|  |     "ldrex", | ||||||
|  |     "ldrexb", | ||||||
|  |     "ldrexd", | ||||||
|  |     "ldrexh", | ||||||
|     "ldrh", |     "ldrh", | ||||||
|     "ldrsb", |     "ldrsb", | ||||||
|     "ldrsh", |     "ldrsh", | ||||||
|  | @ -58,11 +64,13 @@ static const char *opcode_names[] = { | ||||||
|     "msr", |     "msr", | ||||||
|     "mul", |     "mul", | ||||||
|     "mvn", |     "mvn", | ||||||
|  |     "nop", | ||||||
|     "orr", |     "orr", | ||||||
|     "pld", |     "pld", | ||||||
|     "rsb", |     "rsb", | ||||||
|     "rsc", |     "rsc", | ||||||
|     "sbc", |     "sbc", | ||||||
|  |     "sev", | ||||||
|     "smlal", |     "smlal", | ||||||
|     "smull", |     "smull", | ||||||
|     "stc", |     "stc", | ||||||
|  | @ -70,6 +78,10 @@ static const char *opcode_names[] = { | ||||||
|     "str", |     "str", | ||||||
|     "strb", |     "strb", | ||||||
|     "strbt", |     "strbt", | ||||||
|  |     "strex", | ||||||
|  |     "strexb", | ||||||
|  |     "strexd", | ||||||
|  |     "strexh", | ||||||
|     "strh", |     "strh", | ||||||
|     "strt", |     "strt", | ||||||
|     "sub", |     "sub", | ||||||
|  | @ -80,6 +92,9 @@ static const char *opcode_names[] = { | ||||||
|     "tst", |     "tst", | ||||||
|     "umlal", |     "umlal", | ||||||
|     "umull", |     "umull", | ||||||
|  |     "wfe", | ||||||
|  |     "wfi", | ||||||
|  |     "yield", | ||||||
| 
 | 
 | ||||||
|     "undefined", |     "undefined", | ||||||
|     "adc", |     "adc", | ||||||
|  | @ -172,6 +187,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | ||||||
|             return DisassembleBX(insn); |             return DisassembleBX(insn); | ||||||
|         case OP_CDP: |         case OP_CDP: | ||||||
|             return "cdp"; |             return "cdp"; | ||||||
|  |         case OP_CLREX: | ||||||
|  |             return "clrex"; | ||||||
|         case OP_CLZ: |         case OP_CLZ: | ||||||
|             return DisassembleCLZ(insn); |             return DisassembleCLZ(insn); | ||||||
|         case OP_LDC: |         case OP_LDC: | ||||||
|  | @ -188,6 +205,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | ||||||
|         case OP_STRBT: |         case OP_STRBT: | ||||||
|         case OP_STRT: |         case OP_STRT: | ||||||
|             return DisassembleMem(insn); |             return DisassembleMem(insn); | ||||||
|  |         case OP_LDREX: | ||||||
|  |         case OP_LDREXB: | ||||||
|  |         case OP_LDREXD: | ||||||
|  |         case OP_LDREXH: | ||||||
|  |         case OP_STREX: | ||||||
|  |         case OP_STREXB: | ||||||
|  |         case OP_STREXD: | ||||||
|  |         case OP_STREXH: | ||||||
|  |             return DisassembleREX(opcode, insn); | ||||||
|         case OP_LDRH: |         case OP_LDRH: | ||||||
|         case OP_LDRSB: |         case OP_LDRSB: | ||||||
|         case OP_LDRSH: |         case OP_LDRSH: | ||||||
|  | @ -204,6 +230,12 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | ||||||
|             return DisassembleMSR(insn); |             return DisassembleMSR(insn); | ||||||
|         case OP_MUL: |         case OP_MUL: | ||||||
|             return DisassembleMUL(opcode, insn); |             return DisassembleMUL(opcode, insn); | ||||||
|  |         case OP_NOP: | ||||||
|  |         case OP_SEV: | ||||||
|  |         case OP_WFE: | ||||||
|  |         case OP_WFI: | ||||||
|  |         case OP_YIELD: | ||||||
|  |             return DisassembleNoOperands(opcode, insn); | ||||||
|         case OP_PLD: |         case OP_PLD: | ||||||
|             return DisassemblePLD(insn); |             return DisassemblePLD(insn); | ||||||
|         case OP_STC: |         case OP_STC: | ||||||
|  | @ -646,6 +678,12 @@ std::string ARM_Disasm::DisassembleMSR(uint32_t insn) | ||||||
|             cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm); |             cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, uint32_t insn) | ||||||
|  | { | ||||||
|  |     uint32_t cond = BITS(insn, 28, 31); | ||||||
|  |     return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | ||||||
| { | { | ||||||
|     uint8_t is_reg = (insn >> 25) & 0x1; |     uint8_t is_reg = (insn >> 25) & 0x1; | ||||||
|  | @ -669,6 +707,36 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) { | ||||||
|  |     uint32_t rn = BITS(insn, 16, 19); | ||||||
|  |     uint32_t rd = BITS(insn, 12, 15); | ||||||
|  |     uint32_t rt = BITS(insn, 0, 3); | ||||||
|  |     uint32_t cond = BITS(insn, 28, 31); | ||||||
|  | 
 | ||||||
|  |     switch (opcode) { | ||||||
|  |         case OP_STREX: | ||||||
|  |         case OP_STREXB: | ||||||
|  |         case OP_STREXH: | ||||||
|  |             return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | ||||||
|  |                                             cond_to_str(cond), rd, rt, rn); | ||||||
|  |         case OP_STREXD: | ||||||
|  |             return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode], | ||||||
|  |                                             cond_to_str(cond), rd, rt, rt + 1, rn); | ||||||
|  | 
 | ||||||
|  |         // for LDREX instructions, rd corresponds to Rt from reference manual
 | ||||||
|  |         case OP_LDREX: | ||||||
|  |         case OP_LDREXB: | ||||||
|  |         case OP_LDREXH: | ||||||
|  |             return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], | ||||||
|  |                                             cond_to_str(cond), rd, rn); | ||||||
|  |         case OP_LDREXD: | ||||||
|  |             return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | ||||||
|  |                                             cond_to_str(cond), rd, rd + 1, rn); | ||||||
|  |         default: | ||||||
|  |             return opcode_names[OP_UNDEFINED]; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::string ARM_Disasm::DisassembleSWI(uint32_t insn) | std::string ARM_Disasm::DisassembleSWI(uint32_t insn) | ||||||
| { | { | ||||||
|     uint8_t cond = (insn >> 28) & 0xf; |     uint8_t cond = (insn >> 28) & 0xf; | ||||||
|  | @ -721,12 +789,9 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) { | ||||||
|         } |         } | ||||||
|         uint32_t bits7_4 = (insn >> 4) & 0xf; |         uint32_t bits7_4 = (insn >> 4) & 0xf; | ||||||
|         if (bits7_4 == 0x9) { |         if (bits7_4 == 0x9) { | ||||||
|             if ((insn & 0x0ff00ff0) == 0x01000090) { |             uint32_t bit24 = BIT(insn, 24); | ||||||
|                 // Swp instruction
 |             if (bit24) { | ||||||
|                 uint8_t bit22 = (insn >> 22) & 0x1; |                 return DecodeSyncPrimitive(insn); | ||||||
|                 if (bit22) |  | ||||||
|                     return OP_SWPB; |  | ||||||
|                 return OP_SWP; |  | ||||||
|             } |             } | ||||||
|             // One of the multiply instructions
 |             // One of the multiply instructions
 | ||||||
|             return DecodeMUL(insn); |             return DecodeMUL(insn); | ||||||
|  | @ -739,6 +804,12 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     uint32_t op1 = BITS(insn, 20, 24); | ||||||
|  |     if (bit25 && (op1 == 0x12 || op1 == 0x16)) { | ||||||
|  |         // One of the MSR (immediate) and hints instructions
 | ||||||
|  |         return DecodeMSRImmAndHints(insn); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // One of the data processing instructions
 |     // One of the data processing instructions
 | ||||||
|     return DecodeALU(insn); |     return DecodeALU(insn); | ||||||
| } | } | ||||||
|  | @ -754,6 +825,10 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) { | ||||||
|         // Pre-load
 |         // Pre-load
 | ||||||
|         return OP_PLD; |         return OP_PLD; | ||||||
|     } |     } | ||||||
|  |     if (insn == 0xf57ff01f) { | ||||||
|  |         // Clear-Exclusive
 | ||||||
|  |         return OP_CLREX; | ||||||
|  |     } | ||||||
|     if (is_load) { |     if (is_load) { | ||||||
|         if (is_byte) { |         if (is_byte) { | ||||||
|             // Load byte
 |             // Load byte
 | ||||||
|  | @ -844,6 +919,35 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) { | ||||||
|     return OP_MCR; |     return OP_MCR; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) { | ||||||
|  |     uint32_t op = BITS(insn, 20, 23); | ||||||
|  |     uint32_t bit22 = BIT(insn, 22); | ||||||
|  |     switch (op) { | ||||||
|  |         case 0x0: | ||||||
|  |             if (bit22) | ||||||
|  |                 return OP_SWPB; | ||||||
|  |             return OP_SWP; | ||||||
|  |         case 0x8: | ||||||
|  |             return OP_STREX; | ||||||
|  |         case 0x9: | ||||||
|  |             return OP_LDREX; | ||||||
|  |         case 0xA: | ||||||
|  |             return OP_STREXD; | ||||||
|  |         case 0xB: | ||||||
|  |             return OP_LDREXD; | ||||||
|  |         case 0xC: | ||||||
|  |             return OP_STREXB; | ||||||
|  |         case 0xD: | ||||||
|  |             return OP_LDREXB; | ||||||
|  |         case 0xE: | ||||||
|  |             return OP_STREXH; | ||||||
|  |         case 0xF: | ||||||
|  |             return OP_LDREXH; | ||||||
|  |         default: | ||||||
|  |             return OP_UNDEFINED; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { | Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { | ||||||
|     uint8_t bit24 = (insn >> 24) & 0x1; |     uint8_t bit24 = (insn >> 24) & 0x1; | ||||||
|     if (bit24 != 0) { |     if (bit24 != 0) { | ||||||
|  | @ -878,6 +982,31 @@ Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { | ||||||
|     return OP_SMLAL; |     return OP_SMLAL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) { | ||||||
|  |     uint32_t op = BIT(insn, 22); | ||||||
|  |     uint32_t op1 = BITS(insn, 16, 19); | ||||||
|  |     uint32_t op2 = BITS(insn, 0, 7); | ||||||
|  | 
 | ||||||
|  |     if (op == 0 && op1 == 0) { | ||||||
|  |         switch (op2) { | ||||||
|  |             case 0x0: | ||||||
|  |                 return OP_NOP; | ||||||
|  |             case 0x1: | ||||||
|  |                 return OP_YIELD; | ||||||
|  |             case 0x2: | ||||||
|  |                 return OP_WFE; | ||||||
|  |             case 0x3: | ||||||
|  |                 return OP_WFI; | ||||||
|  |             case 0x4: | ||||||
|  |                 return OP_SEV; | ||||||
|  |             default: | ||||||
|  |                 return OP_UNDEFINED; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return OP_MSR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { | Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { | ||||||
|     uint8_t is_load = (insn >> 20) & 0x1; |     uint8_t is_load = (insn >> 20) & 0x1; | ||||||
|     uint8_t bits_65 = (insn >> 5) & 0x3; |     uint8_t bits_65 = (insn >> 5) & 0x3; | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ enum Opcode { | ||||||
|     OP_BLX, |     OP_BLX, | ||||||
|     OP_BX, |     OP_BX, | ||||||
|     OP_CDP, |     OP_CDP, | ||||||
|  |     OP_CLREX, | ||||||
|     OP_CLZ, |     OP_CLZ, | ||||||
|     OP_CMN, |     OP_CMN, | ||||||
|     OP_CMP, |     OP_CMP, | ||||||
|  | @ -29,6 +30,10 @@ enum Opcode { | ||||||
|     OP_LDR, |     OP_LDR, | ||||||
|     OP_LDRB, |     OP_LDRB, | ||||||
|     OP_LDRBT, |     OP_LDRBT, | ||||||
|  |     OP_LDREX, | ||||||
|  |     OP_LDREXB, | ||||||
|  |     OP_LDREXD, | ||||||
|  |     OP_LDREXH, | ||||||
|     OP_LDRH, |     OP_LDRH, | ||||||
|     OP_LDRSB, |     OP_LDRSB, | ||||||
|     OP_LDRSH, |     OP_LDRSH, | ||||||
|  | @ -41,11 +46,13 @@ enum Opcode { | ||||||
|     OP_MSR, |     OP_MSR, | ||||||
|     OP_MUL, |     OP_MUL, | ||||||
|     OP_MVN, |     OP_MVN, | ||||||
|  |     OP_NOP, | ||||||
|     OP_ORR, |     OP_ORR, | ||||||
|     OP_PLD, |     OP_PLD, | ||||||
|     OP_RSB, |     OP_RSB, | ||||||
|     OP_RSC, |     OP_RSC, | ||||||
|     OP_SBC, |     OP_SBC, | ||||||
|  |     OP_SEV, | ||||||
|     OP_SMLAL, |     OP_SMLAL, | ||||||
|     OP_SMULL, |     OP_SMULL, | ||||||
|     OP_STC, |     OP_STC, | ||||||
|  | @ -53,6 +60,10 @@ enum Opcode { | ||||||
|     OP_STR, |     OP_STR, | ||||||
|     OP_STRB, |     OP_STRB, | ||||||
|     OP_STRBT, |     OP_STRBT, | ||||||
|  |     OP_STREX, | ||||||
|  |     OP_STREXB, | ||||||
|  |     OP_STREXD, | ||||||
|  |     OP_STREXH, | ||||||
|     OP_STRH, |     OP_STRH, | ||||||
|     OP_STRT, |     OP_STRT, | ||||||
|     OP_SUB, |     OP_SUB, | ||||||
|  | @ -63,6 +74,9 @@ enum Opcode { | ||||||
|     OP_TST, |     OP_TST, | ||||||
|     OP_UMLAL, |     OP_UMLAL, | ||||||
|     OP_UMULL, |     OP_UMULL, | ||||||
|  |     OP_WFE, | ||||||
|  |     OP_WFI, | ||||||
|  |     OP_YIELD, | ||||||
| 
 | 
 | ||||||
|     // Define thumb opcodes
 |     // Define thumb opcodes
 | ||||||
|     OP_THUMB_UNDEFINED, |     OP_THUMB_UNDEFINED, | ||||||
|  | @ -117,7 +131,9 @@ class ARM_Disasm { | ||||||
|   static Opcode Decode01(uint32_t insn); |   static Opcode Decode01(uint32_t insn); | ||||||
|   static Opcode Decode10(uint32_t insn); |   static Opcode Decode10(uint32_t insn); | ||||||
|   static Opcode Decode11(uint32_t insn); |   static Opcode Decode11(uint32_t insn); | ||||||
|  |   static Opcode DecodeSyncPrimitive(uint32_t insn); | ||||||
|   static Opcode DecodeMUL(uint32_t insn); |   static Opcode DecodeMUL(uint32_t insn); | ||||||
|  |   static Opcode DecodeMSRImmAndHints(uint32_t insn); | ||||||
|   static Opcode DecodeLDRH(uint32_t insn); |   static Opcode DecodeLDRH(uint32_t insn); | ||||||
|   static Opcode DecodeALU(uint32_t insn); |   static Opcode DecodeALU(uint32_t insn); | ||||||
| 
 | 
 | ||||||
|  | @ -135,7 +151,9 @@ class ARM_Disasm { | ||||||
|   static std::string DisassembleMUL(Opcode opcode, uint32_t insn); |   static std::string DisassembleMUL(Opcode opcode, uint32_t insn); | ||||||
|   static std::string DisassembleMRS(uint32_t insn); |   static std::string DisassembleMRS(uint32_t insn); | ||||||
|   static std::string DisassembleMSR(uint32_t insn); |   static std::string DisassembleMSR(uint32_t insn); | ||||||
|  |   static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); | ||||||
|   static std::string DisassemblePLD(uint32_t insn); |   static std::string DisassemblePLD(uint32_t insn); | ||||||
|  |   static std::string DisassembleREX(Opcode opcode, uint32_t insn); | ||||||
|   static std::string DisassembleSWI(uint32_t insn); |   static std::string DisassembleSWI(uint32_t insn); | ||||||
|   static std::string DisassembleSWP(Opcode opcode, uint32_t insn); |   static std::string DisassembleSWP(Opcode opcode, uint32_t insn); | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue