mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	arm_disasm: ARMv6 parallel add/sub media instructions
{S, U, Q, UQ, SH, UH}{ADD16, ASX, SAX, SUB16, ADD8, SUB8}
			
			
This commit is contained in:
		
							parent
							
								
									0be8e1bfb6
								
							
						
					
					
						commit
						4a1db13072
					
				
					 2 changed files with 167 additions and 0 deletions
				
			
		|  | @ -69,18 +69,36 @@ static const char *opcode_names[] = { | ||||||
|     "orr", |     "orr", | ||||||
|     "pkh", |     "pkh", | ||||||
|     "pld", |     "pld", | ||||||
|  |     "qadd16", | ||||||
|  |     "qadd8", | ||||||
|  |     "qasx", | ||||||
|  |     "qsax", | ||||||
|  |     "qsub16", | ||||||
|  |     "qsub8", | ||||||
|     "rev", |     "rev", | ||||||
|     "rev16", |     "rev16", | ||||||
|     "revsh", |     "revsh", | ||||||
|     "rsb", |     "rsb", | ||||||
|     "rsc", |     "rsc", | ||||||
|  |     "sadd16", | ||||||
|  |     "sadd8", | ||||||
|  |     "sasx", | ||||||
|     "sbc", |     "sbc", | ||||||
|     "sel", |     "sel", | ||||||
|     "sev", |     "sev", | ||||||
|  |     "shadd16", | ||||||
|  |     "shadd8", | ||||||
|  |     "shasx", | ||||||
|  |     "shsax", | ||||||
|  |     "shsub16", | ||||||
|  |     "shsub8", | ||||||
|     "smlal", |     "smlal", | ||||||
|     "smull", |     "smull", | ||||||
|     "ssat", |     "ssat", | ||||||
|     "ssat16", |     "ssat16", | ||||||
|  |     "ssax", | ||||||
|  |     "ssub16", | ||||||
|  |     "ssub8", | ||||||
|     "stc", |     "stc", | ||||||
|     "stm", |     "stm", | ||||||
|     "str", |     "str", | ||||||
|  | @ -104,10 +122,28 @@ static const char *opcode_names[] = { | ||||||
|     "sxth", |     "sxth", | ||||||
|     "teq", |     "teq", | ||||||
|     "tst", |     "tst", | ||||||
|  |     "uadd16", | ||||||
|  |     "uadd8", | ||||||
|  |     "uasx", | ||||||
|  |     "uhadd16", | ||||||
|  |     "uhadd8", | ||||||
|  |     "uhasx", | ||||||
|  |     "uhsax", | ||||||
|  |     "uhsub16", | ||||||
|  |     "uhsub8", | ||||||
|     "umlal", |     "umlal", | ||||||
|     "umull", |     "umull", | ||||||
|  |     "uqadd16", | ||||||
|  |     "uqadd8", | ||||||
|  |     "uqasx", | ||||||
|  |     "uqsax", | ||||||
|  |     "uqsub16", | ||||||
|  |     "uqsub8", | ||||||
|     "usat", |     "usat", | ||||||
|     "usat16", |     "usat16", | ||||||
|  |     "usax", | ||||||
|  |     "usub16", | ||||||
|  |     "usub8", | ||||||
|     "uxtab", |     "uxtab", | ||||||
|     "uxtab16", |     "uxtab16", | ||||||
|     "uxtah", |     "uxtah", | ||||||
|  | @ -262,6 +298,43 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | ||||||
|             return DisassemblePKH(insn); |             return DisassemblePKH(insn); | ||||||
|         case OP_PLD: |         case OP_PLD: | ||||||
|             return DisassemblePLD(insn); |             return DisassemblePLD(insn); | ||||||
|  |         case OP_QADD16: | ||||||
|  |         case OP_QADD8: | ||||||
|  |         case OP_QASX: | ||||||
|  |         case OP_QSAX: | ||||||
|  |         case OP_QSUB16: | ||||||
|  |         case OP_QSUB8: | ||||||
|  |         case OP_SADD16: | ||||||
|  |         case OP_SADD8: | ||||||
|  |         case OP_SASX: | ||||||
|  |         case OP_SHADD16: | ||||||
|  |         case OP_SHADD8: | ||||||
|  |         case OP_SHASX: | ||||||
|  |         case OP_SHSAX: | ||||||
|  |         case OP_SHSUB16: | ||||||
|  |         case OP_SHSUB8: | ||||||
|  |         case OP_SSAX: | ||||||
|  |         case OP_SSUB16: | ||||||
|  |         case OP_SSUB8: | ||||||
|  |         case OP_UADD16: | ||||||
|  |         case OP_UADD8: | ||||||
|  |         case OP_UASX: | ||||||
|  |         case OP_UHADD16: | ||||||
|  |         case OP_UHADD8: | ||||||
|  |         case OP_UHASX: | ||||||
|  |         case OP_UHSAX: | ||||||
|  |         case OP_UHSUB16: | ||||||
|  |         case OP_UHSUB8: | ||||||
|  |         case OP_UQADD16: | ||||||
|  |         case OP_UQADD8: | ||||||
|  |         case OP_UQASX: | ||||||
|  |         case OP_UQSAX: | ||||||
|  |         case OP_UQSUB16: | ||||||
|  |         case OP_UQSUB8: | ||||||
|  |         case OP_USAX: | ||||||
|  |         case OP_USUB16: | ||||||
|  |         case OP_USUB8: | ||||||
|  |             return DisassembleParallelAddSub(opcode, insn); | ||||||
|         case OP_REV: |         case OP_REV: | ||||||
|         case OP_REV16: |         case OP_REV16: | ||||||
|         case OP_REVSH: |         case OP_REVSH: | ||||||
|  | @ -732,6 +805,16 @@ std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, uint32_t insn) | ||||||
|     return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); |     return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, uint32_t insn) { | ||||||
|  |     uint32_t cond = BITS(insn, 28, 31); | ||||||
|  |     uint32_t rn = BITS(insn, 16, 19); | ||||||
|  |     uint32_t rd = BITS(insn, 12, 15); | ||||||
|  |     uint32_t rm = BITS(insn, 0, 3); | ||||||
|  | 
 | ||||||
|  |     return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[opcode], cond_to_str(cond), | ||||||
|  |                                     rd, rn, rm); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::string ARM_Disasm::DisassemblePKH(uint32_t insn) | std::string ARM_Disasm::DisassemblePKH(uint32_t insn) | ||||||
| { | { | ||||||
|     uint32_t cond = BITS(insn, 28, 31); |     uint32_t cond = BITS(insn, 28, 31); | ||||||
|  | @ -1083,6 +1166,49 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Opcode ARM_Disasm::DecodeParallelAddSub(uint32_t insn) { | ||||||
|  |     uint32_t op1 = BITS(insn, 20, 21); | ||||||
|  |     uint32_t op2 = BITS(insn, 5, 7); | ||||||
|  |     uint32_t is_unsigned = BIT(insn, 22); | ||||||
|  | 
 | ||||||
|  |     if (op1 == 0x0 || op2 == 0x5 || op2 == 0x6) | ||||||
|  |         return OP_UNDEFINED; | ||||||
|  | 
 | ||||||
|  |     // change op1 range from [1, 3] to range [0, 2]
 | ||||||
|  |     op1--; | ||||||
|  | 
 | ||||||
|  |     // change op2 range from [0, 4] U {7} to range [0, 5]
 | ||||||
|  |     if (op2 == 0x7) | ||||||
|  |         op2 = 0x5; | ||||||
|  | 
 | ||||||
|  |     static std::vector<Opcode> opcodes = { | ||||||
|  |         // op1 = 0
 | ||||||
|  |         OP_SADD16, OP_UADD16, | ||||||
|  |         OP_SASX, OP_UASX, | ||||||
|  |         OP_SSAX, OP_USAX, | ||||||
|  |         OP_SSUB16, OP_USUB16, | ||||||
|  |         OP_SADD8, OP_UADD8, | ||||||
|  |         OP_SSUB8, OP_USUB8, | ||||||
|  |         // op1 = 1
 | ||||||
|  |         OP_QADD16, OP_UQADD16, | ||||||
|  |         OP_QASX, OP_UQASX, | ||||||
|  |         OP_QSAX, OP_UQSAX, | ||||||
|  |         OP_QSUB16, OP_UQSUB16, | ||||||
|  |         OP_QADD8, OP_UQADD8, | ||||||
|  |         OP_QSUB8, OP_UQSUB8, | ||||||
|  |         // op1 = 2
 | ||||||
|  |         OP_SHADD16, OP_UHADD16, | ||||||
|  |         OP_SHASX, OP_UHASX, | ||||||
|  |         OP_SHSAX, OP_UHSAX, | ||||||
|  |         OP_SHSUB16, OP_UHSUB16, | ||||||
|  |         OP_SHADD8, OP_UHADD8, | ||||||
|  |         OP_SHSUB8, OP_UHSUB8 | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     uint32_t opcode_index = op1 * 12 + op2 * 2 + is_unsigned; | ||||||
|  |     return opcodes[opcode_index]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { | Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { | ||||||
|     uint32_t op1 = BITS(insn, 20, 22); |     uint32_t op1 = BITS(insn, 20, 22); | ||||||
|     uint32_t a = BITS(insn, 16, 19); |     uint32_t a = BITS(insn, 16, 19); | ||||||
|  | @ -1220,6 +1346,9 @@ Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { | ||||||
|     uint32_t rn = BITS(insn, 0, 3); |     uint32_t rn = BITS(insn, 0, 3); | ||||||
| 
 | 
 | ||||||
|     switch (BITS(op1, 3, 4)) { |     switch (BITS(op1, 3, 4)) { | ||||||
|  |         case 0x0: | ||||||
|  |             // unsigned and signed parallel addition and subtraction
 | ||||||
|  |             return DecodeParallelAddSub(insn); | ||||||
|         case 0x1: |         case 0x1: | ||||||
|             // Packing, unpacking, saturation, and reversal
 |             // Packing, unpacking, saturation, and reversal
 | ||||||
|             return DecodePackingSaturationReversal(insn); |             return DecodePackingSaturationReversal(insn); | ||||||
|  |  | ||||||
|  | @ -50,18 +50,36 @@ enum Opcode { | ||||||
|     OP_ORR, |     OP_ORR, | ||||||
|     OP_PKH, |     OP_PKH, | ||||||
|     OP_PLD, |     OP_PLD, | ||||||
|  |     OP_QADD16, | ||||||
|  |     OP_QADD8, | ||||||
|  |     OP_QASX, | ||||||
|  |     OP_QSAX, | ||||||
|  |     OP_QSUB16, | ||||||
|  |     OP_QSUB8, | ||||||
|     OP_REV, |     OP_REV, | ||||||
|     OP_REV16, |     OP_REV16, | ||||||
|     OP_REVSH, |     OP_REVSH, | ||||||
|     OP_RSB, |     OP_RSB, | ||||||
|     OP_RSC, |     OP_RSC, | ||||||
|  |     OP_SADD16, | ||||||
|  |     OP_SADD8, | ||||||
|  |     OP_SASX, | ||||||
|     OP_SBC, |     OP_SBC, | ||||||
|     OP_SEL, |     OP_SEL, | ||||||
|     OP_SEV, |     OP_SEV, | ||||||
|  |     OP_SHADD16, | ||||||
|  |     OP_SHADD8, | ||||||
|  |     OP_SHASX, | ||||||
|  |     OP_SHSAX, | ||||||
|  |     OP_SHSUB16, | ||||||
|  |     OP_SHSUB8, | ||||||
|     OP_SMLAL, |     OP_SMLAL, | ||||||
|     OP_SMULL, |     OP_SMULL, | ||||||
|     OP_SSAT, |     OP_SSAT, | ||||||
|     OP_SSAT16, |     OP_SSAT16, | ||||||
|  |     OP_SSAX, | ||||||
|  |     OP_SSUB16, | ||||||
|  |     OP_SSUB8, | ||||||
|     OP_STC, |     OP_STC, | ||||||
|     OP_STM, |     OP_STM, | ||||||
|     OP_STR, |     OP_STR, | ||||||
|  | @ -85,10 +103,28 @@ enum Opcode { | ||||||
|     OP_SXTH, |     OP_SXTH, | ||||||
|     OP_TEQ, |     OP_TEQ, | ||||||
|     OP_TST, |     OP_TST, | ||||||
|  |     OP_UADD16, | ||||||
|  |     OP_UADD8, | ||||||
|  |     OP_UASX, | ||||||
|  |     OP_UHADD16, | ||||||
|  |     OP_UHADD8, | ||||||
|  |     OP_UHASX, | ||||||
|  |     OP_UHSAX, | ||||||
|  |     OP_UHSUB16, | ||||||
|  |     OP_UHSUB8, | ||||||
|     OP_UMLAL, |     OP_UMLAL, | ||||||
|     OP_UMULL, |     OP_UMULL, | ||||||
|  |     OP_UQADD16, | ||||||
|  |     OP_UQADD8, | ||||||
|  |     OP_UQASX, | ||||||
|  |     OP_UQSAX, | ||||||
|  |     OP_UQSUB16, | ||||||
|  |     OP_UQSUB8, | ||||||
|     OP_USAT, |     OP_USAT, | ||||||
|     OP_USAT16, |     OP_USAT16, | ||||||
|  |     OP_USAX, | ||||||
|  |     OP_USUB16, | ||||||
|  |     OP_USUB8, | ||||||
|     OP_UXTAB, |     OP_UXTAB, | ||||||
|     OP_UXTAB16, |     OP_UXTAB16, | ||||||
|     OP_UXTAH, |     OP_UXTAH, | ||||||
|  | @ -153,6 +189,7 @@ class ARM_Disasm { | ||||||
|   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 DecodeSyncPrimitive(uint32_t insn); | ||||||
|  |   static Opcode DecodeParallelAddSub(uint32_t insn); | ||||||
|   static Opcode DecodePackingSaturationReversal(uint32_t insn); |   static Opcode DecodePackingSaturationReversal(uint32_t insn); | ||||||
|   static Opcode DecodeMUL(uint32_t insn); |   static Opcode DecodeMUL(uint32_t insn); | ||||||
|   static Opcode DecodeMSRImmAndHints(uint32_t insn); |   static Opcode DecodeMSRImmAndHints(uint32_t insn); | ||||||
|  | @ -175,6 +212,7 @@ class ARM_Disasm { | ||||||
|   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 DisassembleNoOperands(Opcode opcode, uint32_t insn); | ||||||
|  |   static std::string DisassembleParallelAddSub(Opcode opcode, uint32_t insn); | ||||||
|   static std::string DisassemblePKH(uint32_t insn); |   static std::string DisassemblePKH(uint32_t insn); | ||||||
|   static std::string DisassemblePLD(uint32_t insn); |   static std::string DisassemblePLD(uint32_t insn); | ||||||
|   static std::string DisassembleREV(Opcode opcode, uint32_t insn); |   static std::string DisassembleREV(Opcode opcode, uint32_t insn); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue