mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #418 from lioncash/qd
dyncom: Implement QADD/QSUB/QDADD/QDSUB
This commit is contained in:
		
						commit
						8b1ec1a82a
					
				
					 4 changed files with 117 additions and 25 deletions
				
			
		|  | @ -2053,7 +2053,37 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) | |||
| 
 | ||||
|     return inst_base; | ||||
| } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index)     { UNIMPLEMENTED_INSTRUCTION("QADD"); } | ||||
| 
 | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) | ||||
| { | ||||
|     arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | ||||
|     generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||||
| 
 | ||||
|     inst_base->cond     = BITS(inst, 28, 31); | ||||
|     inst_base->idx      = index; | ||||
|     inst_base->br       = NON_BRANCH; | ||||
|     inst_base->load_r15 = 0; | ||||
| 
 | ||||
|     inst_cream->op1 = BITS(inst, 21, 22); | ||||
|     inst_cream->Rm  = BITS(inst, 0, 3); | ||||
|     inst_cream->Rn  = BITS(inst, 16, 19); | ||||
|     inst_cream->Rd  = BITS(inst, 12, 15); | ||||
| 
 | ||||
|     return inst_base; | ||||
| } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) | ||||
| { | ||||
|     return INTERPRETER_TRANSLATE(qadd)(inst, index); | ||||
| } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) | ||||
| { | ||||
|     return INTERPRETER_TRANSLATE(qadd)(inst, index); | ||||
| } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) | ||||
| { | ||||
|     return INTERPRETER_TRANSLATE(qadd)(inst, index); | ||||
| } | ||||
| 
 | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) | ||||
| { | ||||
|     arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | ||||
|  | @ -2080,9 +2110,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) | |||
| { | ||||
|     return INTERPRETER_TRANSLATE(qadd8)(inst, index); | ||||
| } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QDADD"); } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QDSUB"); } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index)     { UNIMPLEMENTED_INSTRUCTION("QSUB"); } | ||||
| ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) | ||||
| { | ||||
|     return INTERPRETER_TRANSLATE(qadd8)(inst, index); | ||||
|  | @ -5042,6 +5069,78 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
|     } | ||||
| 
 | ||||
|     QADD_INST: | ||||
|     QDADD_INST: | ||||
|     QDSUB_INST: | ||||
|     QSUB_INST: | ||||
|     { | ||||
|         if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||||
|             generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||||
|             const u8 op1 = inst_cream->op1; | ||||
|             const u32 rm_val = RM; | ||||
|             const u32 rn_val = RN; | ||||
| 
 | ||||
|             u32 result = 0; | ||||
| 
 | ||||
|             // QADD
 | ||||
|             if (op1 == 0x00) { | ||||
|                 result = rm_val + rn_val; | ||||
| 
 | ||||
|                 if (AddOverflow(rm_val, rn_val, result)) { | ||||
|                     result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | ||||
|                     cpu->Cpsr |= (1 << 27); | ||||
|                 } | ||||
|             } | ||||
|             // QSUB
 | ||||
|             else if (op1 == 0x01) { | ||||
|                 result = rm_val - rn_val; | ||||
| 
 | ||||
|                 if (SubOverflow(rm_val, rn_val, result)) { | ||||
|                     result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | ||||
|                     cpu->Cpsr |= (1 << 27); | ||||
|                 } | ||||
|             } | ||||
|             // QDADD
 | ||||
|             else if (op1 == 0x02) { | ||||
|                 u32 mul = (rn_val * 2); | ||||
| 
 | ||||
|                 if (AddOverflow(rn_val, rn_val, rn_val * 2)) { | ||||
|                     mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; | ||||
|                     cpu->Cpsr |= (1 << 27); | ||||
|                 } | ||||
| 
 | ||||
|                 result = mul + rm_val; | ||||
| 
 | ||||
|                 if (AddOverflow(rm_val, mul, result)) { | ||||
|                     result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | ||||
|                     cpu->Cpsr |= (1 << 27); | ||||
|                 } | ||||
|             } | ||||
|             // QDSUB
 | ||||
|             else if (op1 == 0x03) { | ||||
|                 u32 mul = (rn_val * 2); | ||||
| 
 | ||||
|                 if (AddOverflow(rn_val, rn_val, mul)) { | ||||
|                     mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; | ||||
|                     cpu->Cpsr |= (1 << 27); | ||||
|                 } | ||||
| 
 | ||||
|                 result = rm_val - mul; | ||||
| 
 | ||||
|                 if (SubOverflow(rm_val, mul, result)) { | ||||
|                     result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | ||||
|                     cpu->Cpsr |= (1 << 27); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             RD = result; | ||||
|         } | ||||
| 
 | ||||
|         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|         INC_PC(sizeof(generic_arm_inst)); | ||||
|         FETCH_INST; | ||||
|         GOTO_NEXT_INST; | ||||
|     } | ||||
| 
 | ||||
|     QADD8_INST: | ||||
|     QADD16_INST: | ||||
|     QADDSUBX_INST: | ||||
|  | @ -5104,10 +5203,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
|         GOTO_NEXT_INST; | ||||
|     } | ||||
| 
 | ||||
|     QDADD_INST: | ||||
|     QDSUB_INST: | ||||
|     QSUB_INST: | ||||
| 
 | ||||
|     REV_INST: | ||||
|     REV16_INST: | ||||
|     REVSH_INST: | ||||
|  |  | |||
|  | @ -418,22 +418,18 @@ ARMul_NegZero (ARMul_State * state, ARMword result) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Compute whether an addition of A and B, giving RESULT, overflowed.  */ | ||||
| 
 | ||||
| int | ||||
| AddOverflow (ARMword a, ARMword b, ARMword result) | ||||
| // Compute whether an addition of A and B, giving RESULT, overflowed.
 | ||||
| bool AddOverflow(ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
|     return ((NEG (a) && NEG (b) && POS (result)) | ||||
|             || (POS (a) && POS (b) && NEG (result))); | ||||
|     return ((NEG(a) && NEG(b) && POS(result)) || | ||||
|             (POS(a) && POS(b) && NEG(result))); | ||||
| } | ||||
| 
 | ||||
| /* Compute whether a subtraction of A and B, giving RESULT, overflowed.  */ | ||||
| 
 | ||||
| int | ||||
| SubOverflow (ARMword a, ARMword b, ARMword result) | ||||
| // Compute whether a subtraction of A and B, giving RESULT, overflowed.
 | ||||
| bool SubOverflow(ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
|     return ((NEG (a) && POS (b) && POS (result)) | ||||
|             || (POS (a) && NEG (b) && NEG (result))); | ||||
|     return ((NEG(a) && POS(b) && POS(result)) || | ||||
|             (POS(a) && NEG(b) && NEG(result))); | ||||
| } | ||||
| 
 | ||||
| /* Assigns the C flag after an addition of a and b to give result.  */ | ||||
|  |  | |||
|  | @ -70,6 +70,9 @@ | |||
| #define DATACACHE  1 | ||||
| #define INSTCACHE  2 | ||||
| 
 | ||||
| #define POS(i) ( (~(i)) >> 31 ) | ||||
| #define NEG(i) ( (i) >> 31 ) | ||||
| 
 | ||||
| #ifndef __STDC__ | ||||
| typedef char *VoidStar; | ||||
| #endif | ||||
|  | @ -783,6 +786,8 @@ RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\ | |||
| //#define PXA250      0x69052903
 | ||||
| // 0x69052903;  //PXA250 B1 from intel 278522-001.pdf
 | ||||
| 
 | ||||
| extern bool AddOverflow(ARMword, ARMword, ARMword); | ||||
| extern bool SubOverflow(ARMword, ARMword, ARMword); | ||||
| 
 | ||||
| extern void ARMul_UndefInstr(ARMul_State*, ARMword); | ||||
| extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword); | ||||
|  |  | |||
|  | @ -42,9 +42,6 @@ | |||
| #define R15FBIT (1L << 26) | ||||
| #define R15IFBITS (3L << 26) | ||||
| 
 | ||||
| #define POS(i) ( (~(i)) >> 31 ) | ||||
| #define NEG(i) ( (i) >> 31 ) | ||||
| 
 | ||||
| #ifdef MODET			/* Thumb support.  */ | ||||
| /* ??? This bit is actually in the low order bit of the PC in the hardware.
 | ||||
|    It isn't clear if the simulator needs to model that or not.  */ | ||||
|  | @ -561,8 +558,7 @@ tdstate; | |||
| 
 | ||||
| /* Prototypes for exported functions.  */ | ||||
| extern unsigned ARMul_NthReg (ARMword, unsigned); | ||||
| extern int AddOverflow (ARMword, ARMword, ARMword); | ||||
| extern int SubOverflow (ARMword, ARMword, ARMword); | ||||
| 
 | ||||
| /* Prototypes for exported functions.  */ | ||||
| #ifdef __cplusplus | ||||
|  extern "C" { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue