forked from eden-emu/eden
		
	dyncom: Implement QADD/QSUB/QDADD/QDSUB
This commit is contained in:
		
							parent
							
								
									b058ce6feb
								
							
						
					
					
						commit
						d00c22c706
					
				
					 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; |     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_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) | ||||||
| { | { | ||||||
|     arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |     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); |     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) | ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) | ||||||
| { | { | ||||||
|     return INTERPRETER_TRANSLATE(qadd8)(inst, index); |     return INTERPRETER_TRANSLATE(qadd8)(inst, index); | ||||||
|  | @ -5042,6 +5069,78 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     QADD_INST: |     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: |     QADD8_INST: | ||||||
|     QADD16_INST: |     QADD16_INST: | ||||||
|     QADDSUBX_INST: |     QADDSUBX_INST: | ||||||
|  | @ -5104,10 +5203,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|         GOTO_NEXT_INST; |         GOTO_NEXT_INST; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     QDADD_INST: |  | ||||||
|     QDSUB_INST: |  | ||||||
|     QSUB_INST: |  | ||||||
| 
 |  | ||||||
|     REV_INST: |     REV_INST: | ||||||
|     REV16_INST: |     REV16_INST: | ||||||
|     REVSH_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.  */ | // Compute whether an addition of A and B, giving RESULT, overflowed.
 | ||||||
| 
 | bool AddOverflow(ARMword a, ARMword b, ARMword result) | ||||||
| int |  | ||||||
| AddOverflow (ARMword a, ARMword b, ARMword result) |  | ||||||
| { | { | ||||||
|     return ((NEG (a) && NEG (b) && POS (result)) |     return ((NEG(a) && NEG(b) && POS(result)) || | ||||||
|             || (POS (a) && POS (b) && NEG (result))); |             (POS(a) && POS(b) && NEG(result))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Compute whether a subtraction of A and B, giving RESULT, overflowed.  */ | // Compute whether a subtraction of A and B, giving RESULT, overflowed.
 | ||||||
| 
 | bool SubOverflow(ARMword a, ARMword b, ARMword result) | ||||||
| int |  | ||||||
| SubOverflow (ARMword a, ARMword b, ARMword result) |  | ||||||
| { | { | ||||||
|     return ((NEG (a) && POS (b) && POS (result)) |     return ((NEG(a) && POS(b) && POS(result)) || | ||||||
|             || (POS (a) && NEG (b) && NEG (result))); |             (POS(a) && NEG(b) && NEG(result))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Assigns the C flag after an addition of a and b to give result.  */ | /* Assigns the C flag after an addition of a and b to give result.  */ | ||||||
|  |  | ||||||
|  | @ -70,6 +70,9 @@ | ||||||
| #define DATACACHE  1 | #define DATACACHE  1 | ||||||
| #define INSTCACHE  2 | #define INSTCACHE  2 | ||||||
| 
 | 
 | ||||||
|  | #define POS(i) ( (~(i)) >> 31 ) | ||||||
|  | #define NEG(i) ( (i) >> 31 ) | ||||||
|  | 
 | ||||||
| #ifndef __STDC__ | #ifndef __STDC__ | ||||||
| typedef char *VoidStar; | typedef char *VoidStar; | ||||||
| #endif | #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
 | //#define PXA250      0x69052903
 | ||||||
| // 0x69052903;  //PXA250 B1 from intel 278522-001.pdf
 | // 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_UndefInstr(ARMul_State*, ARMword); | ||||||
| extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword); | extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword); | ||||||
|  |  | ||||||
|  | @ -42,9 +42,6 @@ | ||||||
| #define R15FBIT (1L << 26) | #define R15FBIT (1L << 26) | ||||||
| #define R15IFBITS (3L << 26) | #define R15IFBITS (3L << 26) | ||||||
| 
 | 
 | ||||||
| #define POS(i) ( (~(i)) >> 31 ) |  | ||||||
| #define NEG(i) ( (i) >> 31 ) |  | ||||||
| 
 |  | ||||||
| #ifdef MODET			/* Thumb support.  */ | #ifdef MODET			/* Thumb support.  */ | ||||||
| /* ??? This bit is actually in the low order bit of the PC in the hardware.
 | /* ??? 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.  */ |    It isn't clear if the simulator needs to model that or not.  */ | ||||||
|  | @ -561,8 +558,7 @@ tdstate; | ||||||
| 
 | 
 | ||||||
| /* Prototypes for exported functions.  */ | /* Prototypes for exported functions.  */ | ||||||
| extern unsigned ARMul_NthReg (ARMword, unsigned); | extern unsigned ARMul_NthReg (ARMword, unsigned); | ||||||
| extern int AddOverflow (ARMword, ARMword, ARMword); | 
 | ||||||
| extern int SubOverflow (ARMword, ARMword, ARMword); |  | ||||||
| /* Prototypes for exported functions.  */ | /* Prototypes for exported functions.  */ | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|  extern "C" { |  extern "C" { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lioncash
						Lioncash