mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +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", |     "shsax", | ||||||
|     "shsub16", |     "shsub16", | ||||||
|     "shsub8", |     "shsub8", | ||||||
|  |     "smlad", | ||||||
|     "smlal", |     "smlal", | ||||||
|  |     "smlald", | ||||||
|  |     "smlsd", | ||||||
|  |     "smlsld", | ||||||
|  |     "smmla", | ||||||
|  |     "smmls", | ||||||
|  |     "smmul", | ||||||
|  |     "smuad", | ||||||
|     "smull", |     "smull", | ||||||
|  |     "smusd", | ||||||
|     "ssat", |     "ssat", | ||||||
|     "ssat16", |     "ssat16", | ||||||
|     "ssax", |     "ssax", | ||||||
|  | @ -139,6 +148,8 @@ static const char *opcode_names[] = { | ||||||
|     "uqsax", |     "uqsax", | ||||||
|     "uqsub16", |     "uqsub16", | ||||||
|     "uqsub8", |     "uqsub8", | ||||||
|  |     "usad8", | ||||||
|  |     "usada8", | ||||||
|     "usat", |     "usat", | ||||||
|     "usat16", |     "usat16", | ||||||
|     "usax", |     "usax", | ||||||
|  | @ -341,6 +352,18 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | ||||||
|             return DisassembleREV(opcode, insn); |             return DisassembleREV(opcode, insn); | ||||||
|         case OP_SEL: |         case OP_SEL: | ||||||
|             return DisassembleSEL(insn); |             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_SSAT: | ||||||
|         case OP_SSAT16: |         case OP_SSAT16: | ||||||
|         case OP_USAT: |         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); |     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 ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) | ||||||
| { | { | ||||||
|     std::string tmp_list; |     std::string tmp_list; | ||||||
|  | @ -1339,11 +1394,52 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) { | ||||||
|     return OP_MSR; |     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) { | Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { | ||||||
|     uint32_t op1 = BITS(insn, 20, 24); |     uint32_t op1 = BITS(insn, 20, 24); | ||||||
|     uint32_t rd = BITS(insn, 12, 15); |     uint32_t rd = BITS(insn, 12, 15); | ||||||
|     uint32_t op2 = BITS(insn, 5, 7); |     uint32_t op2 = BITS(insn, 5, 7); | ||||||
|     uint32_t rn = BITS(insn, 0, 3); |  | ||||||
| 
 | 
 | ||||||
|     switch (BITS(op1, 3, 4)) { |     switch (BITS(op1, 3, 4)) { | ||||||
|         case 0x0: |         case 0x0: | ||||||
|  | @ -1352,6 +1448,15 @@ Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { | ||||||
|         case 0x1: |         case 0x1: | ||||||
|             // Packing, unpacking, saturation, and reversal
 |             // Packing, unpacking, saturation, and reversal
 | ||||||
|             return DecodePackingSaturationReversal(insn); |             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: |         default: | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -73,8 +73,17 @@ enum Opcode { | ||||||
|     OP_SHSAX, |     OP_SHSAX, | ||||||
|     OP_SHSUB16, |     OP_SHSUB16, | ||||||
|     OP_SHSUB8, |     OP_SHSUB8, | ||||||
|  |     OP_SMLAD, | ||||||
|     OP_SMLAL, |     OP_SMLAL, | ||||||
|  |     OP_SMLALD, | ||||||
|  |     OP_SMLSD, | ||||||
|  |     OP_SMLSLD, | ||||||
|  |     OP_SMMLA, | ||||||
|  |     OP_SMMLS, | ||||||
|  |     OP_SMMUL, | ||||||
|  |     OP_SMUAD, | ||||||
|     OP_SMULL, |     OP_SMULL, | ||||||
|  |     OP_SMUSD, | ||||||
|     OP_SSAT, |     OP_SSAT, | ||||||
|     OP_SSAT16, |     OP_SSAT16, | ||||||
|     OP_SSAX, |     OP_SSAX, | ||||||
|  | @ -120,6 +129,8 @@ enum Opcode { | ||||||
|     OP_UQSAX, |     OP_UQSAX, | ||||||
|     OP_UQSUB16, |     OP_UQSUB16, | ||||||
|     OP_UQSUB8, |     OP_UQSUB8, | ||||||
|  |     OP_USAD8, | ||||||
|  |     OP_USADA8, | ||||||
|     OP_USAT, |     OP_USAT, | ||||||
|     OP_USAT16, |     OP_USAT16, | ||||||
|     OP_USAX, |     OP_USAX, | ||||||
|  | @ -193,6 +204,7 @@ class ARM_Disasm { | ||||||
|   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); | ||||||
|  |   static Opcode DecodeMediaMulDiv(uint32_t insn); | ||||||
|   static Opcode DecodeMedia(uint32_t insn); |   static Opcode DecodeMedia(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); | ||||||
|  | @ -202,6 +214,7 @@ class ARM_Disasm { | ||||||
|   static std::string DisassembleBX(uint32_t insn); |   static std::string DisassembleBX(uint32_t insn); | ||||||
|   static std::string DisassembleBKPT(uint32_t insn); |   static std::string DisassembleBKPT(uint32_t insn); | ||||||
|   static std::string DisassembleCLZ(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 DisassembleMemblock(Opcode opcode, uint32_t insn); | ||||||
|   static std::string DisassembleMem(uint32_t insn); |   static std::string DisassembleMem(uint32_t insn); | ||||||
|   static std::string DisassembleMemHalf(uint32_t insn); |   static std::string DisassembleMemHalf(uint32_t insn); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue