mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	arm_disasm: ARMv6 mul/div and abs media instructions
SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD, SMMLA, SMMUL, SMMLS USAD8, USADA8
This commit is contained in:
		
							parent
							
								
									4a1db13072
								
							
						
					
					
						commit
						38c87733d9
					
				
					 2 changed files with 119 additions and 1 deletions
				
			
		|  | @ -92,8 +92,17 @@ static const char *opcode_names[] = { | |||
|     "shsax", | ||||
|     "shsub16", | ||||
|     "shsub8", | ||||
|     "smlad", | ||||
|     "smlal", | ||||
|     "smlald", | ||||
|     "smlsd", | ||||
|     "smlsld", | ||||
|     "smmla", | ||||
|     "smmls", | ||||
|     "smmul", | ||||
|     "smuad", | ||||
|     "smull", | ||||
|     "smusd", | ||||
|     "ssat", | ||||
|     "ssat16", | ||||
|     "ssax", | ||||
|  | @ -139,6 +148,8 @@ static const char *opcode_names[] = { | |||
|     "uqsax", | ||||
|     "uqsub16", | ||||
|     "uqsub8", | ||||
|     "usad8", | ||||
|     "usada8", | ||||
|     "usat", | ||||
|     "usat16", | ||||
|     "usax", | ||||
|  | @ -341,6 +352,18 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
|             return DisassembleREV(opcode, insn); | ||||
|         case OP_SEL: | ||||
|             return DisassembleSEL(insn); | ||||
|         case OP_SMLAD: | ||||
|         case OP_SMLALD: | ||||
|         case OP_SMLSD: | ||||
|         case OP_SMLSLD: | ||||
|         case OP_SMMLA: | ||||
|         case OP_SMMLS: | ||||
|         case OP_SMMUL: | ||||
|         case OP_SMUAD: | ||||
|         case OP_SMUSD: | ||||
|         case OP_USAD8: | ||||
|         case OP_USADA8: | ||||
|             return DisassembleMediaMulDiv(opcode, insn); | ||||
|         case OP_SSAT: | ||||
|         case OP_SSAT16: | ||||
|         case OP_USAT: | ||||
|  | @ -503,6 +526,38 @@ std::string ARM_Disasm::DisassembleCLZ(uint32_t insn) | |||
|     return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm); | ||||
| } | ||||
| 
 | ||||
| std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, uint32_t insn) { | ||||
|     uint32_t cond = BITS(insn, 28, 31); | ||||
|     uint32_t rd = BITS(insn, 16, 19); | ||||
|     uint32_t ra = BITS(insn, 12, 15); | ||||
|     uint32_t rm = BITS(insn, 8, 11); | ||||
|     uint32_t m = BIT(insn, 5); | ||||
|     uint32_t rn = BITS(insn, 0, 3); | ||||
| 
 | ||||
|     std::string cross = ""; | ||||
|     if (m) { | ||||
|         if (opcode == OP_SMMLA || opcode == OP_SMMUL || opcode == OP_SMMLS) | ||||
|             cross = "r"; | ||||
|         else | ||||
|             cross = "x"; | ||||
|     } | ||||
| 
 | ||||
|     std::string ext_reg = ""; | ||||
|     std::unordered_set<Opcode, std::hash<int>> with_ext_reg = { | ||||
|             OP_SMLAD, OP_SMLSD, OP_SMMLA, OP_SMMLS, OP_USADA8 | ||||
|     }; | ||||
|     if (with_ext_reg.find(opcode) != with_ext_reg.end()) | ||||
|         ext_reg = Common::StringFromFormat(", r%u", ra); | ||||
| 
 | ||||
|     std::string rd_low = ""; | ||||
|     if (opcode == OP_SMLALD || opcode == OP_SMLSLD) | ||||
|         rd_low = Common::StringFromFormat("r%u, ", ra); | ||||
| 
 | ||||
|     return Common::StringFromFormat("%s%s%s\t%sr%u, r%u, r%u%s", opcode_names[opcode], | ||||
|                                     cross.c_str(), cond_to_str(cond), rd_low.c_str(), rd, rn, rm, | ||||
|                                     ext_reg.c_str()); | ||||
| } | ||||
| 
 | ||||
| std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) | ||||
| { | ||||
|     std::string tmp_list; | ||||
|  | @ -1339,11 +1394,52 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) { | |||
|     return OP_MSR; | ||||
| } | ||||
| 
 | ||||
| Opcode ARM_Disasm::DecodeMediaMulDiv(uint32_t insn) { | ||||
|     uint32_t op1 = BITS(insn, 20, 22); | ||||
|     uint32_t op2_h = BITS(insn, 6, 7); | ||||
|     uint32_t a = BITS(insn, 12, 15); | ||||
| 
 | ||||
|     switch (op1) { | ||||
|         case 0x0: | ||||
|             if (op2_h == 0x0) { | ||||
|                 if (a != 0xf) | ||||
|                     return OP_SMLAD; | ||||
|                 else | ||||
|                     return OP_SMUAD; | ||||
|             } else if (op2_h == 0x1) { | ||||
|                 if (a != 0xf) | ||||
|                     return OP_SMLSD; | ||||
|                 else | ||||
|                     return OP_SMUSD; | ||||
|             } | ||||
|             break; | ||||
|         case 0x4: | ||||
|             if (op2_h == 0x0) | ||||
|                 return OP_SMLALD; | ||||
|             else if (op2_h == 0x1) | ||||
|                 return OP_SMLSLD; | ||||
|             break; | ||||
|         case 0x5: | ||||
|             if (op2_h == 0x0) { | ||||
|                 if (a != 0xf) | ||||
|                     return OP_SMMLA; | ||||
|                 else | ||||
|                     return OP_SMMUL; | ||||
|             } else if (op2_h == 0x3) { | ||||
|                 return OP_SMMLS; | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     return OP_UNDEFINED; | ||||
| } | ||||
| 
 | ||||
| Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { | ||||
|     uint32_t op1 = BITS(insn, 20, 24); | ||||
|     uint32_t rd = BITS(insn, 12, 15); | ||||
|     uint32_t op2 = BITS(insn, 5, 7); | ||||
|     uint32_t rn = BITS(insn, 0, 3); | ||||
| 
 | ||||
|     switch (BITS(op1, 3, 4)) { | ||||
|         case 0x0: | ||||
|  | @ -1352,6 +1448,15 @@ Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { | |||
|         case 0x1: | ||||
|             // Packing, unpacking, saturation, and reversal
 | ||||
|             return DecodePackingSaturationReversal(insn); | ||||
|         case 0x2: | ||||
|             // Signed multiply, signed and unsigned divide
 | ||||
|             return DecodeMediaMulDiv(insn); | ||||
|         case 0x3: | ||||
|             if (op2 == 0 && rd == 0xf) | ||||
|                 return OP_USAD8; | ||||
|             if (op2 == 0 && rd != 0xf) | ||||
|                 return OP_USADA8; | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|  |  | |||
|  | @ -73,8 +73,17 @@ enum Opcode { | |||
|     OP_SHSAX, | ||||
|     OP_SHSUB16, | ||||
|     OP_SHSUB8, | ||||
|     OP_SMLAD, | ||||
|     OP_SMLAL, | ||||
|     OP_SMLALD, | ||||
|     OP_SMLSD, | ||||
|     OP_SMLSLD, | ||||
|     OP_SMMLA, | ||||
|     OP_SMMLS, | ||||
|     OP_SMMUL, | ||||
|     OP_SMUAD, | ||||
|     OP_SMULL, | ||||
|     OP_SMUSD, | ||||
|     OP_SSAT, | ||||
|     OP_SSAT16, | ||||
|     OP_SSAX, | ||||
|  | @ -120,6 +129,8 @@ enum Opcode { | |||
|     OP_UQSAX, | ||||
|     OP_UQSUB16, | ||||
|     OP_UQSUB8, | ||||
|     OP_USAD8, | ||||
|     OP_USADA8, | ||||
|     OP_USAT, | ||||
|     OP_USAT16, | ||||
|     OP_USAX, | ||||
|  | @ -193,6 +204,7 @@ class ARM_Disasm { | |||
|   static Opcode DecodePackingSaturationReversal(uint32_t insn); | ||||
|   static Opcode DecodeMUL(uint32_t insn); | ||||
|   static Opcode DecodeMSRImmAndHints(uint32_t insn); | ||||
|   static Opcode DecodeMediaMulDiv(uint32_t insn); | ||||
|   static Opcode DecodeMedia(uint32_t insn); | ||||
|   static Opcode DecodeLDRH(uint32_t insn); | ||||
|   static Opcode DecodeALU(uint32_t insn); | ||||
|  | @ -202,6 +214,7 @@ class ARM_Disasm { | |||
|   static std::string DisassembleBX(uint32_t insn); | ||||
|   static std::string DisassembleBKPT(uint32_t insn); | ||||
|   static std::string DisassembleCLZ(uint32_t insn); | ||||
|   static std::string DisassembleMediaMulDiv(Opcode opcode, uint32_t insn); | ||||
|   static std::string DisassembleMemblock(Opcode opcode, uint32_t insn); | ||||
|   static std::string DisassembleMem(uint32_t insn); | ||||
|   static std::string DisassembleMemHalf(uint32_t insn); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue