mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Disassembler: ARMv6K REX instructions
This commit is contained in:
		
							parent
							
								
									5d81a2fd48
								
							
						
					
					
						commit
						3425cfe54a
					
				
					 2 changed files with 97 additions and 6 deletions
				
			
		|  | @ -38,6 +38,7 @@ static const char *opcode_names[] = { | |||
|     "blx", | ||||
|     "bx", | ||||
|     "cdp", | ||||
|     "clrex", | ||||
|     "clz", | ||||
|     "cmn", | ||||
|     "cmp", | ||||
|  | @ -47,6 +48,10 @@ static const char *opcode_names[] = { | |||
|     "ldr", | ||||
|     "ldrb", | ||||
|     "ldrbt", | ||||
|     "ldrex", | ||||
|     "ldrexb", | ||||
|     "ldrexd", | ||||
|     "ldrexh", | ||||
|     "ldrh", | ||||
|     "ldrsb", | ||||
|     "ldrsh", | ||||
|  | @ -73,6 +78,10 @@ static const char *opcode_names[] = { | |||
|     "str", | ||||
|     "strb", | ||||
|     "strbt", | ||||
|     "strex", | ||||
|     "strexb", | ||||
|     "strexd", | ||||
|     "strexh", | ||||
|     "strh", | ||||
|     "strt", | ||||
|     "sub", | ||||
|  | @ -178,6 +187,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
|             return DisassembleBX(insn); | ||||
|         case OP_CDP: | ||||
|             return "cdp"; | ||||
|         case OP_CLREX: | ||||
|             return "clrex"; | ||||
|         case OP_CLZ: | ||||
|             return DisassembleCLZ(insn); | ||||
|         case OP_LDC: | ||||
|  | @ -194,6 +205,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
|         case OP_STRBT: | ||||
|         case OP_STRT: | ||||
|             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_LDRSB: | ||||
|         case OP_LDRSH: | ||||
|  | @ -687,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) | ||||
| { | ||||
|     uint8_t cond = (insn >> 28) & 0xf; | ||||
|  | @ -739,12 +789,9 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) { | |||
|         } | ||||
|         uint32_t bits7_4 = (insn >> 4) & 0xf; | ||||
|         if (bits7_4 == 0x9) { | ||||
|             if ((insn & 0x0ff00ff0) == 0x01000090) { | ||||
|                 // Swp instruction
 | ||||
|                 uint8_t bit22 = (insn >> 22) & 0x1; | ||||
|                 if (bit22) | ||||
|                     return OP_SWPB; | ||||
|                 return OP_SWP; | ||||
|             uint32_t bit24 = BIT(insn, 24); | ||||
|             if (bit24) { | ||||
|                 return DecodeSyncPrimitive(insn); | ||||
|             } | ||||
|             // One of the multiply instructions
 | ||||
|             return DecodeMUL(insn); | ||||
|  | @ -778,6 +825,10 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) { | |||
|         // Pre-load
 | ||||
|         return OP_PLD; | ||||
|     } | ||||
|     if (insn == 0xf57ff01f) { | ||||
|         // Clear-Exclusive
 | ||||
|         return OP_CLREX; | ||||
|     } | ||||
|     if (is_load) { | ||||
|         if (is_byte) { | ||||
|             // Load byte
 | ||||
|  | @ -868,6 +919,35 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) { | |||
|     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) { | ||||
|     uint8_t bit24 = (insn >> 24) & 0x1; | ||||
|     if (bit24 != 0) { | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ enum Opcode { | |||
|     OP_BLX, | ||||
|     OP_BX, | ||||
|     OP_CDP, | ||||
|     OP_CLREX, | ||||
|     OP_CLZ, | ||||
|     OP_CMN, | ||||
|     OP_CMP, | ||||
|  | @ -29,6 +30,10 @@ enum Opcode { | |||
|     OP_LDR, | ||||
|     OP_LDRB, | ||||
|     OP_LDRBT, | ||||
|     OP_LDREX, | ||||
|     OP_LDREXB, | ||||
|     OP_LDREXD, | ||||
|     OP_LDREXH, | ||||
|     OP_LDRH, | ||||
|     OP_LDRSB, | ||||
|     OP_LDRSH, | ||||
|  | @ -55,6 +60,10 @@ enum Opcode { | |||
|     OP_STR, | ||||
|     OP_STRB, | ||||
|     OP_STRBT, | ||||
|     OP_STREX, | ||||
|     OP_STREXB, | ||||
|     OP_STREXD, | ||||
|     OP_STREXH, | ||||
|     OP_STRH, | ||||
|     OP_STRT, | ||||
|     OP_SUB, | ||||
|  | @ -122,6 +131,7 @@ class ARM_Disasm { | |||
|   static Opcode Decode01(uint32_t insn); | ||||
|   static Opcode Decode10(uint32_t insn); | ||||
|   static Opcode Decode11(uint32_t insn); | ||||
|   static Opcode DecodeSyncPrimitive(uint32_t insn); | ||||
|   static Opcode DecodeMUL(uint32_t insn); | ||||
|   static Opcode DecodeMSRImmAndHints(uint32_t insn); | ||||
|   static Opcode DecodeLDRH(uint32_t insn); | ||||
|  | @ -143,6 +153,7 @@ class ARM_Disasm { | |||
|   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 DisassembleREX(Opcode opcode, uint32_t insn); | ||||
|   static std::string DisassembleSWI(uint32_t insn); | ||||
|   static std::string DisassembleSWP(Opcode opcode, uint32_t insn); | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue