mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #166 from bunnei/skyeye-vfp-fixes
SkyEye ARM/VFP fixes
This commit is contained in:
		
						commit
						7f9bcacdf7
					
				
					 5 changed files with 2395 additions and 1911 deletions
				
			
		|  | @ -63,13 +63,6 @@ static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int); | ||||||
| static void Handle_Load_Double (ARMul_State *, ARMword); | static void Handle_Load_Double (ARMul_State *, ARMword); | ||||||
| static void Handle_Store_Double (ARMul_State *, ARMword); | static void Handle_Store_Double (ARMul_State *, ARMword); | ||||||
| 
 | 
 | ||||||
| void |  | ||||||
| XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far); |  | ||||||
| int              |  | ||||||
| XScale_debug_moe (ARMul_State * state, int moe); |  | ||||||
| unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, |  | ||||||
|                                         unsigned cpnum); |  | ||||||
| 
 |  | ||||||
| static int | static int | ||||||
| handle_v6_insn (ARMul_State * state, ARMword instr); | handle_v6_insn (ARMul_State * state, ARMword instr); | ||||||
| 
 | 
 | ||||||
|  | @ -376,7 +369,7 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
| #endif | #endif | ||||||
| { | { | ||||||
|     /* The PC pipeline value depends on whether ARM
 |     /* The PC pipeline value depends on whether ARM
 | ||||||
|     or Thumb instructions are being  |     or Thumb instructions are being | ||||||
|     d.  */ |     d.  */ | ||||||
|     ARMword isize; |     ARMword isize; | ||||||
|     ARMword instr;		/* The current instruction.  */ |     ARMword instr;		/* The current instruction.  */ | ||||||
|  | @ -538,6 +531,7 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
|             state->AbortAddr = 1; |             state->AbortAddr = 1; | ||||||
| 
 | 
 | ||||||
|             instr = ARMul_LoadInstrN (state, pc, isize); |             instr = ARMul_LoadInstrN (state, pc, isize); | ||||||
|  | 
 | ||||||
|             //chy 2006-04-12, for ICE debug
 |             //chy 2006-04-12, for ICE debug
 | ||||||
|             have_bp=ARMul_ICE_debug(state,instr,pc); |             have_bp=ARMul_ICE_debug(state,instr,pc); | ||||||
| #if 0 | #if 0 | ||||||
|  | @ -562,6 +556,7 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
|         } |         } | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|         instr = ARMul_LoadInstrN (state, pc, isize); |         instr = ARMul_LoadInstrN (state, pc, isize); | ||||||
|         state->last_instr = state->CurrInstr; |         state->last_instr = state->CurrInstr; | ||||||
|         state->CurrInstr = instr; |         state->CurrInstr = instr; | ||||||
|  | @ -952,9 +947,8 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
|             case t_decoded: |             case t_decoded: | ||||||
|                 /* ARM instruction available.  */ |                 /* ARM instruction available.  */ | ||||||
|                 //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp);
 |                 //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp);
 | ||||||
|                  | 
 | ||||||
|                 if (armOp == 0xDEADC0DE) |                 if (armOp == 0xDEADC0DE) { | ||||||
|                 { |  | ||||||
|                     DEBUG("Failed to decode thumb opcode %04X at %08X\n", instr, pc); |                     DEBUG("Failed to decode thumb opcode %04X at %08X\n", instr, pc); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -967,7 +961,6 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
| 
 |  | ||||||
|         /* Check the condition codes.  */ |         /* Check the condition codes.  */ | ||||||
|         if ((temp = TOPBITS (28)) == AL) { |         if ((temp = TOPBITS (28)) == AL) { | ||||||
|             /* Vile deed in the need for speed. */ |             /* Vile deed in the need for speed. */ | ||||||
|  | @ -1124,6 +1117,7 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
| 
 | 
 | ||||||
| //chy 2003-08-24 now #if 0 .... #endif  process cp14, cp15.reg14, I disable it...
 | //chy 2003-08-24 now #if 0 .... #endif  process cp14, cp15.reg14, I disable it...
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|         /* Actual execution of instructions begins here.  */ |         /* Actual execution of instructions begins here.  */ | ||||||
|         /* If the condition codes don't match, stop here.  */ |         /* If the condition codes don't match, stop here.  */ | ||||||
|         if (temp) { |         if (temp) { | ||||||
|  | @ -2308,12 +2302,9 @@ mainswitch: | ||||||
|                         if (state->Aborted) { |                         if (state->Aborted) { | ||||||
|                             TAKEABORT; |                             TAKEABORT; | ||||||
|                         } |                         } | ||||||
|                         if (enter) |                         if (enter) { | ||||||
|                         { |  | ||||||
|                             state->Reg[DESTReg] = 0; |                             state->Reg[DESTReg] = 0; | ||||||
|                         } |                         } else { | ||||||
|                         else |  | ||||||
|                         { |  | ||||||
|                             state->Reg[DESTReg] = 1; |                             state->Reg[DESTReg] = 1; | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|  | @ -3063,7 +3054,27 @@ mainswitch: | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case 0x68:	/* Store Word, No WriteBack, Post Inc, Reg.  */ |                 case 0x68:	/* Store Word, No WriteBack, Post Inc, Reg.  */ | ||||||
|                     if (BIT (4)) { |                     //ichfly PKHBT PKHTB todo check this
 | ||||||
|  |                     if ((instr & 0x70) == 0x10) //pkhbt
 | ||||||
|  |                     { | ||||||
|  |                         u8 idest = BITS(12, 15); | ||||||
|  |                         u8 rfis = BITS(16, 19); | ||||||
|  |                         u8 rlast = BITS(0, 3); | ||||||
|  |                         u8 ishi = BITS(7,11); | ||||||
|  |                         state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000); | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     else if ((instr & 0x70) == 0x50)//pkhtb
 | ||||||
|  |                     { | ||||||
|  |                         u8 idest = BITS(12, 15); | ||||||
|  |                         u8 rfis = BITS(16, 19); | ||||||
|  |                         u8 rlast = BITS(0, 3); | ||||||
|  |                         u8 ishi = BITS(7, 11); | ||||||
|  |                         if (ishi == 0)ishi = 0x20; | ||||||
|  |                         state->Reg[idest] = (((int)(state->Reg[rlast]) >> (int)(ishi))& 0xFFFF) | ((state->Reg[rfis]) & 0xFFFF0000); | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     else if (BIT (4)) { | ||||||
| #ifdef MODE32 | #ifdef MODE32 | ||||||
|                         if (state->is_v6 |                         if (state->is_v6 | ||||||
|                                 && handle_v6_insn (state, instr)) |                                 && handle_v6_insn (state, instr)) | ||||||
|  | @ -3675,7 +3686,13 @@ mainswitch: | ||||||
| 
 | 
 | ||||||
|                 /* Co-Processor Data Transfers.  */ |                 /* Co-Processor Data Transfers.  */ | ||||||
|                 case 0xc4: |                 case 0xc4: | ||||||
|                     if (state->is_v5) { |                     if ((instr & 0x0FF00FF0) == 0xC400B10) //vmov BIT(0-3), BIT(12-15), BIT(16-20),  vmov d0, r0, r0
 | ||||||
|  |                     { | ||||||
|  |                         state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)]; | ||||||
|  |                         state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)]; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     else if (state->is_v5) { | ||||||
|                         /* Reading from R15 is UNPREDICTABLE.  */ |                         /* Reading from R15 is UNPREDICTABLE.  */ | ||||||
|                         if (BITS (12, 15) == 15 || BITS (16, 19) == 15) |                         if (BITS (12, 15) == 15 || BITS (16, 19) == 15) | ||||||
|                             ARMul_UndefInstr (state, instr); |                             ARMul_UndefInstr (state, instr); | ||||||
|  | @ -3695,13 +3712,21 @@ mainswitch: | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case 0xc5: |                 case 0xc5: | ||||||
|                     if (state->is_v5) { |                     if ((instr & 0x00000FF0) == 0xB10) //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0
 | ||||||
|  |                     { | ||||||
|  |                         state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1]; | ||||||
|  |                         state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1]; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     else if (state->is_v5) { | ||||||
|                         /* Writes to R15 are UNPREDICATABLE.  */ |                         /* Writes to R15 are UNPREDICATABLE.  */ | ||||||
|                         if (DESTReg == 15 || LHSReg == 15) |                         if (DESTReg == 15 || LHSReg == 15) | ||||||
|                             ARMul_UndefInstr (state, instr); |                             ARMul_UndefInstr (state, instr); | ||||||
|                         /* Is access to the coprocessor allowed ?  */ |                         /* Is access to the coprocessor allowed ?  */ | ||||||
|                         else if (!CP_ACCESS_ALLOWED(state, CPNum)) |                         else if (!CP_ACCESS_ALLOWED(state, CPNum)) | ||||||
|                             ARMul_UndefInstr (state, instr); |                         { | ||||||
|  |                             ARMul_UndefInstr(state, instr); | ||||||
|  |                         } | ||||||
|                         else { |                         else { | ||||||
|                             /* MRRC, ARMv5TE and up */ |                             /* MRRC, ARMv5TE and up */ | ||||||
|                             ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); |                             ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); | ||||||
|  | @ -4059,9 +4084,11 @@ TEST_EMULATE: | ||||||
|             //        continue;
 |             //        continue;
 | ||||||
|             else if (state->Emulate != RUN) |             else if (state->Emulate != RUN) | ||||||
|                 break; |                 break; | ||||||
|         } |        | ||||||
|         while (state->NumInstrsToExecute--); |     } | ||||||
| 
 | 
 | ||||||
|  |         while (state->NumInstrsToExecute); | ||||||
|  | exit: | ||||||
|         state->decoded = decoded; |         state->decoded = decoded; | ||||||
|         state->loaded = loaded; |         state->loaded = loaded; | ||||||
|         state->pc = pc; |         state->pc = pc; | ||||||
|  | @ -5686,12 +5713,98 @@ L_stm_s_takeabort: | ||||||
|         case 0x3f: |         case 0x3f: | ||||||
|             printf ("Unhandled v6 insn: rbit\n"); |             printf ("Unhandled v6 insn: rbit\n"); | ||||||
|             break; |             break; | ||||||
|  | #endif | ||||||
|         case 0x61: |         case 0x61: | ||||||
|             printf ("Unhandled v6 insn: sadd/ssub\n"); |             if ((instr & 0xFF0) == 0xf70)//ssub16
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(12, 15); | ||||||
|  |                 u8 src1 = BITS(16, 19); | ||||||
|  |                 u8 src2 = BITS(0, 3); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 state->Reg[tar] = (a1 - a2)&0xFFFF | (((b1 - b2)&0xFFFF)<< 0x10); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else if ((instr & 0xFF0) == 0xf10)//sadd16
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(12, 15); | ||||||
|  |                 u8 src1 = BITS(16, 19); | ||||||
|  |                 u8 src2 = BITS(0, 3); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 state->Reg[tar] = (a1 + a2)&0xFFFF | (((b1 + b2)&0xFFFF)<< 0x10); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else if ((instr & 0xFF0) == 0xf50)//ssax
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(12, 15); | ||||||
|  |                 u8 src1 = BITS(16, 19); | ||||||
|  |                 u8 src2 = BITS(0, 3); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 state->Reg[tar] = (a1 - b2) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else if ((instr & 0xFF0) == 0xf30)//sasx
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(12, 15); | ||||||
|  |                 u8 src1 = BITS(16, 19); | ||||||
|  |                 u8 src2 = BITS(0, 3); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 state->Reg[tar] = (a2 - b1) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else printf ("Unhandled v6 insn: sadd/ssub\n"); | ||||||
|             break; |             break; | ||||||
|         case 0x62: |         case 0x62: | ||||||
|             printf ("Unhandled v6 insn: qadd/qsub\n"); |             if ((instr & 0xFF0) == 0xf70)//QSUB16
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(12, 15); | ||||||
|  |                 u8 src1 = BITS(16, 19); | ||||||
|  |                 u8 src2 = BITS(0, 3); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 s32 res1 = (a1 - b1); | ||||||
|  |                 s32 res2 = (a2 - b2); | ||||||
|  |                 if (res1 > 0x7FFF) res1 = 0x7FFF; | ||||||
|  |                 if (res2 > 0x7FFF) res2 = 0x7FFF; | ||||||
|  |                 if (res1 < 0x7FFF) res1 = -0x8000; | ||||||
|  |                 if (res2 < 0x7FFF) res2 = -0x8000; | ||||||
|  |                 state->Reg[tar] = (res1 & 0xFFFF) | ((res2 & 0xFFFF) << 0x10); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else if ((instr & 0xFF0) == 0xf10)//QADD16
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(12, 15); | ||||||
|  |                 u8 src1 = BITS(16, 19); | ||||||
|  |                 u8 src2 = BITS(0, 3); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 s32 res1 = (a1 + b1); | ||||||
|  |                 s32 res2 = (a2 + b2); | ||||||
|  |                 if (res1 > 0x7FFF) res1 = 0x7FFF; | ||||||
|  |                 if (res2 > 0x7FFF) res2 = 0x7FFF; | ||||||
|  |                 if (res1 < 0x7FFF) res1 = -0x8000; | ||||||
|  |                 if (res2 < 0x7FFF) res2 = -0x8000; | ||||||
|  |                 state->Reg[tar] = ((res1) & 0xFFFF) | (((res2) & 0xFFFF) << 0x10); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else printf ("Unhandled v6 insn: qadd/qsub\n"); | ||||||
|             break; |             break; | ||||||
|  | #if 0 | ||||||
|         case 0x63: |         case 0x63: | ||||||
|             printf ("Unhandled v6 insn: shadd/shsub\n"); |             printf ("Unhandled v6 insn: shadd/shsub\n"); | ||||||
|             break; |             break; | ||||||
|  | @ -5709,10 +5822,65 @@ L_stm_s_takeabort: | ||||||
|             break; |             break; | ||||||
| #endif | #endif | ||||||
|         case 0x6c: |         case 0x6c: | ||||||
|             printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); |             if ((instr & 0xf03f0) == 0xf0070) //uxtb16
 | ||||||
|  |             { | ||||||
|  |                 u8 src1 = BITS(0, 3); | ||||||
|  |                 u8 tar = BITS(12, 15); | ||||||
|  |                 u32 base = state->Reg[src1]; | ||||||
|  |                 u32 shamt = BITS(9,10)* 8; | ||||||
|  |                 u32 in = ((base << (32 - shamt)) | (base >> shamt)); | ||||||
|  |                 state->Reg[tar] = in & 0x00FF00FF; | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); | ||||||
|             break; |             break; | ||||||
|         case 0x70: |         case 0x70: | ||||||
|             printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); |             if ((instr & 0xf0d0) == 0xf010)//smuad //ichfly
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(16, 19); | ||||||
|  |                 u8 src1 = BITS(0, 3); | ||||||
|  |                 u8 src2 = BITS(8, 11); | ||||||
|  |                 u8 swap = BIT(5); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 state->Reg[tar] = a1*a2 + b1*b2; | ||||||
|  |                 return 1; | ||||||
|  | 
 | ||||||
|  |             } | ||||||
|  |             else if ((instr & 0xf0d0) == 0xf050)//smusd
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(16, 19); | ||||||
|  |                 u8 src1 = BITS(0, 3); | ||||||
|  |                 u8 src2 = BITS(8, 11); | ||||||
|  |                 u8 swap = BIT(5); | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 state->Reg[tar] = a1*a2 - b1*b2; | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else if ((instr & 0xd0) == 0x10)//smlad
 | ||||||
|  |             { | ||||||
|  |                 u8 tar = BITS(16, 19); | ||||||
|  |                 u8 src1 = BITS(0, 3); | ||||||
|  |                 u8 src2 = BITS(8, 11); | ||||||
|  |                 u8 src3 = BITS(12, 15); | ||||||
|  |                 u8 swap = BIT(5); | ||||||
|  | 
 | ||||||
|  |                 u32 a3 = state->Reg[src3]; | ||||||
|  | 
 | ||||||
|  |                 s16 a1 = (state->Reg[src1] & 0xFFFF); | ||||||
|  |                 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); | ||||||
|  |                 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); | ||||||
|  |                 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); | ||||||
|  |                 state->Reg[tar] = a1*a2 + b1*b2 + a3; | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             else printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); | ||||||
|             break; |             break; | ||||||
|         case 0x74: |         case 0x74: | ||||||
|             printf ("Unhandled v6 insn: smlald/smlsld\n"); |             printf ("Unhandled v6 insn: smlald/smlsld\n"); | ||||||
|  | @ -5750,13 +5918,10 @@ L_stm_s_takeabort: | ||||||
|                 if (state->Aborted) { |                 if (state->Aborted) { | ||||||
|                     TAKEABORT; |                     TAKEABORT; | ||||||
|                 } |                 } | ||||||
|                  | 
 | ||||||
|                 if (enter) |                 if (enter) { | ||||||
|                 { |  | ||||||
|                     state->Reg[DESTReg] = 0; |                     state->Reg[DESTReg] = 0; | ||||||
|                 } |                 } else { | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     state->Reg[DESTReg] = 1; |                     state->Reg[DESTReg] = 1; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -5795,12 +5960,9 @@ L_stm_s_takeabort: | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|                 if (enter) |                 if (enter) { | ||||||
|                 { |  | ||||||
|                     state->Reg[DESTReg] = 0; |                     state->Reg[DESTReg] = 0; | ||||||
|                 } |                 } else { | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     state->Reg[DESTReg] = 1; |                     state->Reg[DESTReg] = 1; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -5853,8 +6015,25 @@ L_stm_s_takeabort: | ||||||
| 
 | 
 | ||||||
|             case 0x01: |             case 0x01: | ||||||
|             case 0xf3: |             case 0xf3: | ||||||
|                 printf ("Unhandled v6 insn: ssat\n"); |                 //ichfly
 | ||||||
|                 return 0; |                 //SSAT16
 | ||||||
|  |             { | ||||||
|  |                          u8 tar = BITS(12,15); | ||||||
|  |                          u8 src = BITS(0, 3); | ||||||
|  |                          u8 val = BITS(16, 19) + 1; | ||||||
|  |                          s16 a1 = (state->Reg[src]); | ||||||
|  |                          s16 a2 = (state->Reg[src] >> 0x10); | ||||||
|  |                          s16 min = (s16)(0x8000) >> (16 - val); | ||||||
|  |                          s16 max = 0x7FFF >> (16 - val); | ||||||
|  |                          if (min > a1) a1 = min; | ||||||
|  |                          if (max < a1) a1 = max; | ||||||
|  |                          if (min > a2) a2 = min; | ||||||
|  |                          if (max < a2) a2 = max; | ||||||
|  |                          u32 temp2 = ((u32)(a2)) << 0x10; | ||||||
|  |                          state->Reg[tar] = (a1&0xFFFF) | (temp2); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |                 return 1; | ||||||
|             default: |             default: | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|  | @ -5944,8 +6123,21 @@ L_stm_s_takeabort: | ||||||
| 
 | 
 | ||||||
|             case 0x01: |             case 0x01: | ||||||
|             case 0xf3: |             case 0xf3: | ||||||
|                 printf ("Unhandled v6 insn: usat\n"); |                 //ichfly
 | ||||||
|                 return 0; |                 //USAT16
 | ||||||
|  |                 { | ||||||
|  |                     u8 tar = BITS(12, 15); | ||||||
|  |                     u8 src = BITS(0, 3); | ||||||
|  |                     u8 val = BITS(16, 19); | ||||||
|  |                     s16 a1 = (state->Reg[src]); | ||||||
|  |                     s16 a2 = (state->Reg[src] >> 0x10); | ||||||
|  |                     s16 max = 0xFFFF >> (16 - val); | ||||||
|  |                     if (max < a1) a1 = max; | ||||||
|  |                     if (max < a2) a2 = max; | ||||||
|  |                     u32 temp2 = ((u32)(a2)) << 0x10; | ||||||
|  |                     state->Reg[tar] = (a1 & 0xFFFF) | (temp2); | ||||||
|  |                 } | ||||||
|  |                 return 1; | ||||||
|             default: |             default: | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -28,230 +28,270 @@ | ||||||
| #include "core/arm/skyeye_common/armdefs.h" | #include "core/arm/skyeye_common/armdefs.h" | ||||||
| #include "core/arm/skyeye_common/vfp/vfp.h" | #include "core/arm/skyeye_common/vfp/vfp.h" | ||||||
| 
 | 
 | ||||||
|  | #define DEBUG DBG | ||||||
|  | 
 | ||||||
| //ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
 | //ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
 | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPInit (ARMul_State *state) | VFPInit (ARMul_State *state) | ||||||
| { | { | ||||||
| 	state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |  |     state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | | ||||||
| 		VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; |                                         VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; | ||||||
| 	state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0; |     state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0; | ||||||
| 	state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0; |     state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0; | ||||||
| 	 |  | ||||||
| 	//persistent_state = state;
 |  | ||||||
| 	/* Reset only specify VFP_FPEXC_EN = '0' */ |  | ||||||
| 
 | 
 | ||||||
| 	return No_exp; |     //persistent_state = state;
 | ||||||
|  |     /* Reset only specify VFP_FPEXC_EN = '0' */ | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value) | VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value) | ||||||
| { | { | ||||||
| 	/* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ |     /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ | ||||||
| 	int CoProc = BITS (8, 11); /* 10 or 11 */ |     int CoProc = BITS (8, 11); /* 10 or 11 */ | ||||||
| 	int OPC_1 = BITS (21, 23); |     int OPC_1 = BITS (21, 23); | ||||||
| 	int Rt = BITS (12, 15); |     int Rt = BITS (12, 15); | ||||||
| 	int CRn = BITS (16, 19); |     int CRn = BITS (16, 19); | ||||||
| 	int CRm = BITS (0, 3); |     int CRm = BITS (0, 3); | ||||||
| 	int OPC_2 = BITS (5, 7); |     int OPC_2 = BITS (5, 7); | ||||||
| 	 |  | ||||||
| 	/* TODO check access permission */ |  | ||||||
| 	 |  | ||||||
| 	/* CRn/opc1 CRm/opc2 */ |  | ||||||
| 	 |  | ||||||
| 	if (CoProc == 10 || CoProc == 11) |  | ||||||
| 	{ |  | ||||||
| 		#define VFP_MRC_TRANS |  | ||||||
| 		#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |  | ||||||
| 		#undef VFP_MRC_TRANS |  | ||||||
| 	} |  | ||||||
| 	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",  |  | ||||||
| 	       instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); |  | ||||||
| 
 | 
 | ||||||
| 	return ARMul_CANT; |     /* TODO check access permission */ | ||||||
|  | 
 | ||||||
|  |     /* CRn/opc1 CRm/opc2 */ | ||||||
|  | 
 | ||||||
|  |     if (CoProc == 10 || CoProc == 11) { | ||||||
|  | #define VFP_MRC_TRANS | ||||||
|  | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | ||||||
|  | #undef VFP_MRC_TRANS | ||||||
|  |     } | ||||||
|  |     DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", | ||||||
|  |           instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); | ||||||
|  | 
 | ||||||
|  |     return ARMul_CANT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value) | VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value) | ||||||
| { | { | ||||||
| 	/* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ |     /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ | ||||||
| 	int CoProc = BITS (8, 11); /* 10 or 11 */ |     int CoProc = BITS (8, 11); /* 10 or 11 */ | ||||||
| 	int OPC_1 = BITS (21, 23); |     int OPC_1 = BITS (21, 23); | ||||||
| 	int Rt = BITS (12, 15); |     int Rt = BITS (12, 15); | ||||||
| 	int CRn = BITS (16, 19); |     int CRn = BITS (16, 19); | ||||||
| 	int CRm = BITS (0, 3); |     int CRm = BITS (0, 3); | ||||||
| 	int OPC_2 = BITS (5, 7); |     int OPC_2 = BITS (5, 7); | ||||||
| 	 |  | ||||||
| 	/* TODO check access permission */ |  | ||||||
| 	 |  | ||||||
| 	/* CRn/opc1 CRm/opc2 */ |  | ||||||
| 	if (CoProc == 10 || CoProc == 11) |  | ||||||
| 	{ |  | ||||||
| 		#define VFP_MCR_TRANS |  | ||||||
| 		#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |  | ||||||
| 		#undef VFP_MCR_TRANS |  | ||||||
| 	} |  | ||||||
| 	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",  |  | ||||||
| 	       instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); |  | ||||||
| 
 | 
 | ||||||
| 	return ARMul_CANT; |     /* TODO check access permission */ | ||||||
|  | 
 | ||||||
|  |     /* CRn/opc1 CRm/opc2 */ | ||||||
|  |     if (CoProc == 10 || CoProc == 11) { | ||||||
|  | #define VFP_MCR_TRANS | ||||||
|  | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | ||||||
|  | #undef VFP_MCR_TRANS | ||||||
|  |     } | ||||||
|  |     DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", | ||||||
|  |           instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); | ||||||
|  | 
 | ||||||
|  |     return ARMul_CANT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2) | VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * value2) | ||||||
| { | { | ||||||
| 	/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ |     /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ | ||||||
| 	int CoProc = BITS (8, 11); /* 10 or 11 */ |     int CoProc = BITS (8, 11); /* 10 or 11 */ | ||||||
| 	int OPC_1 = BITS (4, 7); |     int OPC_1 = BITS (4, 7); | ||||||
| 	int Rt = BITS (12, 15); |     int Rt = BITS (12, 15); | ||||||
| 	int Rt2 = BITS (16, 19); |     int Rt2 = BITS (16, 19); | ||||||
| 	int CRm = BITS (0, 3); |     int CRm = BITS (0, 3); | ||||||
| 	 |  | ||||||
| 	if (CoProc == 10 || CoProc == 11) |  | ||||||
| 	{ |  | ||||||
| 		#define VFP_MRRC_TRANS |  | ||||||
| 		#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |  | ||||||
| 		#undef VFP_MRRC_TRANS |  | ||||||
| 	} |  | ||||||
| 	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",  |  | ||||||
| 	       instr, CoProc, OPC_1, Rt, Rt2, CRm); |  | ||||||
| 
 | 
 | ||||||
| 	return ARMul_CANT; |     if (CoProc == 10 || CoProc == 11) { | ||||||
|  | #define VFP_MRRC_TRANS | ||||||
|  | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | ||||||
|  | #undef VFP_MRRC_TRANS | ||||||
|  |     } | ||||||
|  |     DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", | ||||||
|  |           instr, CoProc, OPC_1, Rt, Rt2, CRm); | ||||||
|  | 
 | ||||||
|  |     return ARMul_CANT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2) | VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2) | ||||||
| { | { | ||||||
| 	/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ |     /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ | ||||||
| 	int CoProc = BITS (8, 11); /* 10 or 11 */ |     int CoProc = BITS (8, 11); /* 10 or 11 */ | ||||||
| 	int OPC_1 = BITS (4, 7); |     int OPC_1 = BITS (4, 7); | ||||||
| 	int Rt = BITS (12, 15); |     int Rt = BITS (12, 15); | ||||||
| 	int Rt2 = BITS (16, 19); |     int Rt2 = BITS (16, 19); | ||||||
| 	int CRm = BITS (0, 3); |     int CRm = BITS (0, 3); | ||||||
| 	 |  | ||||||
| 	/* TODO check access permission */ |  | ||||||
| 	 |  | ||||||
| 	/* CRn/opc1 CRm/opc2 */ |  | ||||||
| 	 |  | ||||||
| 	if (CoProc == 11 || CoProc == 10) |  | ||||||
| 	{ |  | ||||||
| 		#define VFP_MCRR_TRANS |  | ||||||
| 		#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |  | ||||||
| 		#undef VFP_MCRR_TRANS |  | ||||||
| 	} |  | ||||||
| 	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",  |  | ||||||
| 	       instr, CoProc, OPC_1, Rt, Rt2, CRm); |  | ||||||
| 
 | 
 | ||||||
| 	return ARMul_CANT; |     /* TODO check access permission */ | ||||||
|  | 
 | ||||||
|  |     /* CRn/opc1 CRm/opc2 */ | ||||||
|  | 
 | ||||||
|  |     if (CoProc == 11 || CoProc == 10) { | ||||||
|  | #define VFP_MCRR_TRANS | ||||||
|  | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | ||||||
|  | #undef VFP_MCRR_TRANS | ||||||
|  |     } | ||||||
|  |     DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", | ||||||
|  |           instr, CoProc, OPC_1, Rt, Rt2, CRm); | ||||||
|  | 
 | ||||||
|  |     return ARMul_CANT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value) | VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value) | ||||||
| { | { | ||||||
| 	/* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ |     /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ | ||||||
| 	int CoProc = BITS (8, 11); /* 10 or 11 */ |     int CoProc = BITS (8, 11); /* 10 or 11 */ | ||||||
| 	int CRd = BITS (12, 15); |     int CRd = BITS (12, 15); | ||||||
| 	int Rn = BITS (16, 19); |     int Rn = BITS (16, 19); | ||||||
| 	int imm8 = BITS (0, 7); |     int imm8 = BITS (0, 7); | ||||||
| 	int P = BIT(24); |     int P = BIT(24); | ||||||
| 	int U = BIT(23); |     int U = BIT(23); | ||||||
| 	int D = BIT(22); |     int D = BIT(22); | ||||||
| 	int W = BIT(21); |     int W = BIT(21); | ||||||
| 	 |  | ||||||
| 	/* TODO check access permission */ |  | ||||||
| 	 |  | ||||||
| 	/* VSTM */ |  | ||||||
| 	if ( (P|U|D|W) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1); |  | ||||||
| 	} |  | ||||||
| 	if (CoProc == 10 || CoProc == 11) |  | ||||||
| 	{ |  | ||||||
| 		#if 1 |  | ||||||
| 		if (P == 0 && U == 0 && W == 0) |  | ||||||
| 		{ |  | ||||||
| 			DEBUG_LOG(ARM11, "VSTM Related encodings\n"); exit(-1); |  | ||||||
| 		} |  | ||||||
| 		if (P == U && W == 1) |  | ||||||
| 		{ |  | ||||||
| 			DEBUG_LOG(ARM11, "UNDEFINED\n"); exit(-1); |  | ||||||
| 		} |  | ||||||
| 		#endif |  | ||||||
| 
 | 
 | ||||||
| 		#define VFP_STC_TRANS |     /* TODO check access permission */ | ||||||
| 		#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |  | ||||||
| 		#undef VFP_STC_TRANS |  | ||||||
| 	} |  | ||||||
| 	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",  |  | ||||||
| 	       instr, CoProc, CRd, Rn, imm8, P, U, D, W); |  | ||||||
| 
 | 
 | ||||||
| 	return ARMul_CANT; |     /* VSTM */ | ||||||
|  |     if ( (P|U|D|W) == 0 ) { | ||||||
|  |         DEBUG("In %s, UNDEFINED\n", __FUNCTION__); | ||||||
|  |         exit(-1); | ||||||
|  |     } | ||||||
|  |     if (CoProc == 10 || CoProc == 11) { | ||||||
|  | #if 1 | ||||||
|  |         if (P == 0 && U == 0 && W == 0) { | ||||||
|  |             DEBUG("VSTM Related encodings\n"); | ||||||
|  |             exit(-1); | ||||||
|  |         } | ||||||
|  |         if (P == U && W == 1) { | ||||||
|  |             DEBUG("UNDEFINED\n"); | ||||||
|  |             exit(-1); | ||||||
|  |         } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define VFP_STC_TRANS | ||||||
|  | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | ||||||
|  | #undef VFP_STC_TRANS | ||||||
|  |     } | ||||||
|  |     DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", | ||||||
|  |           instr, CoProc, CRd, Rn, imm8, P, U, D, W); | ||||||
|  | 
 | ||||||
|  |     return ARMul_CANT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value) | VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value) | ||||||
| { | { | ||||||
| 	/* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ |     /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ | ||||||
| 	int CoProc = BITS (8, 11); /* 10 or 11 */ |     int CoProc = BITS (8, 11); /* 10 or 11 */ | ||||||
| 	int CRd = BITS (12, 15); |     int CRd = BITS (12, 15); | ||||||
| 	int Rn = BITS (16, 19); |     int Rn = BITS (16, 19); | ||||||
| 	int imm8 = BITS (0, 7); |     int imm8 = BITS (0, 7); | ||||||
| 	int P = BIT(24); |     int P = BIT(24); | ||||||
| 	int U = BIT(23); |     int U = BIT(23); | ||||||
| 	int D = BIT(22); |     int D = BIT(22); | ||||||
| 	int W = BIT(21); |     int W = BIT(21); | ||||||
| 	 |  | ||||||
| 	/* TODO check access permission */ |  | ||||||
| 	 |  | ||||||
| 	if ( (P|U|D|W) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1); |  | ||||||
| 	} |  | ||||||
| 	if (CoProc == 10 || CoProc == 11) |  | ||||||
| 	{ |  | ||||||
| 		#define VFP_LDC_TRANS |  | ||||||
| 		#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |  | ||||||
| 		#undef VFP_LDC_TRANS |  | ||||||
| 	} |  | ||||||
| 	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",  |  | ||||||
| 	       instr, CoProc, CRd, Rn, imm8, P, U, D, W); |  | ||||||
| 
 | 
 | ||||||
| 	return ARMul_CANT; |     /* TODO check access permission */ | ||||||
|  | 
 | ||||||
|  |     if ( (P|U|D|W) == 0 ) { | ||||||
|  |         DEBUG("In %s, UNDEFINED\n", __FUNCTION__); | ||||||
|  |         exit(-1); | ||||||
|  |     } | ||||||
|  |     if (CoProc == 10 || CoProc == 11) { | ||||||
|  | #define VFP_LDC_TRANS | ||||||
|  | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | ||||||
|  | #undef VFP_LDC_TRANS | ||||||
|  |     } | ||||||
|  |     DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", | ||||||
|  |           instr, CoProc, CRd, Rn, imm8, P, U, D, W); | ||||||
|  | 
 | ||||||
|  |     return ARMul_CANT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
| VFPCDP (ARMul_State * state, unsigned type, ARMword instr) | VFPCDP (ARMul_State * state, unsigned type, u32 instr) | ||||||
| { | { | ||||||
| 	/* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ |     /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ | ||||||
| 	int CoProc = BITS (8, 11); /* 10 or 11 */ |     int CoProc = BITS (8, 11); /* 10 or 11 */ | ||||||
| 	int OPC_1 = BITS (20, 23); |     int OPC_1 = BITS (20, 23); | ||||||
| 	int CRd = BITS (12, 15); |     int CRd = BITS (12, 15); | ||||||
| 	int CRn = BITS (16, 19); |     int CRn = BITS (16, 19); | ||||||
| 	int CRm = BITS (0, 3); |     int CRm = BITS (0, 3); | ||||||
| 	int OPC_2 = BITS (5, 7); |     int OPC_2 = BITS (5, 7); | ||||||
| 	 |  | ||||||
| 	/* TODO check access permission */ |  | ||||||
| 	 |  | ||||||
| 	/* CRn/opc1 CRm/opc2 */ |  | ||||||
| 
 | 
 | ||||||
| 	if (CoProc == 10 || CoProc == 11) |     //ichfly
 | ||||||
| 	{ |     /*if ((instr & 0x0FBF0FD0) == 0x0EB70AC0) //vcvt.f64.f32	d8, s16 (s is bit 0-3 and LSB bit 22) (d is bit 12 - 15 MSB is Bit 6)
 | ||||||
| 		#define VFP_CDP_TRANS |     { | ||||||
| 		#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |         struct vfp_double vdd; | ||||||
| 		#undef VFP_CDP_TRANS |         struct vfp_single vsd; | ||||||
| 		 |         int dn = BITS(12, 15) + (BIT(22) << 4); | ||||||
| 		int exceptions = 0; |         int sd = (BITS(0, 3) << 1) + BIT(5); | ||||||
| 		if (CoProc == 10) |         s32 n = vfp_get_float(state, sd); | ||||||
| 			exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); |         vfp_single_unpack(&vsd, n); | ||||||
| 		else  |         if (vsd.exponent & 0x80) | ||||||
| 			exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); |         { | ||||||
|  |             vdd.exponent = (vsd.exponent&~0x80) | 0x400; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             vdd.exponent = vsd.exponent | 0x380; | ||||||
|  |         } | ||||||
|  |         vdd.sign = vsd.sign; | ||||||
|  |         vdd.significand = (u64)(vsd.significand & ~0xC0000000) << 32; // I have no idea why but the 2 uppern bits are not from the significand
 | ||||||
|  |         vfp_put_double(state, vfp_double_pack(&vdd), dn); | ||||||
|  |         return ARMul_DONE; | ||||||
|  |     } | ||||||
|  |     if ((instr & 0x0FBF0FD0) == 0x0EB70BC0) //vcvt.f32.f64	s15, d6
 | ||||||
|  |     { | ||||||
|  |         struct vfp_double vdd; | ||||||
|  |         struct vfp_single vsd; | ||||||
|  |         int sd = BITS(0, 3) + (BIT(5) << 4); | ||||||
|  |         int dn = (BITS(12, 15) << 1) + BIT(22); | ||||||
|  |         vfp_double_unpack(&vdd, vfp_get_double(state, sd)); | ||||||
|  |         if (vdd.exponent & 0x400) //todo if the exponent is to low or to high for this convert
 | ||||||
|  |         { | ||||||
|  |             vsd.exponent = (vdd.exponent) | 0x80; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             vsd.exponent = vdd.exponent & ~0x80; | ||||||
|  |         } | ||||||
|  |         vsd.exponent &= 0xFF; | ||||||
|  |        // vsd.exponent = vdd.exponent >> 3;
 | ||||||
|  |         vsd.sign = vdd.sign; | ||||||
|  |         vsd.significand = ((u64)(vdd.significand ) >> 32)& ~0xC0000000; | ||||||
|  |         vfp_put_float(state, vfp_single_pack(&vsd), dn); | ||||||
|  |         return ARMul_DONE; | ||||||
|  |     }*/ | ||||||
| 
 | 
 | ||||||
| 		vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); |     /* TODO check access permission */ | ||||||
| 
 | 
 | ||||||
| 		return ARMul_DONE; |     /* CRn/opc1 CRm/opc2 */ | ||||||
| 	} | 
 | ||||||
| 	DEBUG_LOG(ARM11, "Can't identify %x\n", instr); |     if (CoProc == 10 || CoProc == 11) { | ||||||
| 	return ARMul_CANT; | #define VFP_CDP_TRANS | ||||||
|  | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | ||||||
|  | #undef VFP_CDP_TRANS | ||||||
|  | 
 | ||||||
|  |         int exceptions = 0; | ||||||
|  |         if (CoProc == 10) | ||||||
|  |             exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); | ||||||
|  |         else | ||||||
|  |             exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); | ||||||
|  | 
 | ||||||
|  |         vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]); | ||||||
|  | 
 | ||||||
|  |         return ARMul_DONE; | ||||||
|  |     } | ||||||
|  |     DEBUG("Can't identify %x\n", instr); | ||||||
|  |     return ARMul_CANT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -301,29 +341,29 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr) | ||||||
| /* Miscellaneous functions */ | /* Miscellaneous functions */ | ||||||
| int32_t vfp_get_float(arm_core_t* state, unsigned int reg) | int32_t vfp_get_float(arm_core_t* state, unsigned int reg) | ||||||
| { | { | ||||||
| 	DBG("VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]); |     DEBUG("VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]); | ||||||
| 	return state->ExtReg[reg]; |     return state->ExtReg[reg]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg) | void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg) | ||||||
| { | { | ||||||
| 	DBG("VFP put float: s%d <= [%08x]\n", reg, val); |     DEBUG("VFP put float: s%d <= [%08x]\n", reg, val); | ||||||
| 	state->ExtReg[reg] = val; |     state->ExtReg[reg] = val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint64_t vfp_get_double(arm_core_t* state, unsigned int reg) | uint64_t vfp_get_double(arm_core_t* state, unsigned int reg) | ||||||
| { | { | ||||||
| 	uint64_t result; |     uint64_t result; | ||||||
| 	result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; |     result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; | ||||||
| 	DBG("VFP get double: s[%d-%d]=[%016llx]\n", reg*2+1, reg*2, result); |     DEBUG("VFP get double: s[%d-%d]=[%016llx]\n", reg*2+1, reg*2, result); | ||||||
| 	return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg) | void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg) | ||||||
| { | { | ||||||
| 	DBG("VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg*2+1, reg*2, (uint32_t) (val>>32), (uint32_t) (val & 0xffffffff)); |     DEBUG("VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg*2+1, reg*2, (uint32_t) (val>>32), (uint32_t) (val & 0xffffffff)); | ||||||
| 	state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff); |     state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff); | ||||||
| 	state->ExtReg[reg*2+1] = (uint32_t) (val>>32); |     state->ExtReg[reg*2+1] = (uint32_t) (val>>32); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -333,25 +373,25 @@ void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg) | ||||||
|  */ |  */ | ||||||
| void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) | void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) | ||||||
| { | { | ||||||
| 	int si_code = 0; |     int si_code = 0; | ||||||
| 
 | 
 | ||||||
| 	vfpdebug("VFP: raising exceptions %08x\n", exceptions); |     vfpdebug("VFP: raising exceptions %08x\n", exceptions); | ||||||
| 
 | 
 | ||||||
| 	if (exceptions == VFP_EXCEPTION_ERROR) { |     if (exceptions == VFP_EXCEPTION_ERROR) { | ||||||
| 		DEBUG_LOG(ARM11, "unhandled bounce %x\n", inst); |         DEBUG("unhandled bounce %x\n", inst); | ||||||
| 		exit(-1); |         exit(-1); | ||||||
| 		return; |         return; | ||||||
| 	} |     } | ||||||
| 
 | 
 | ||||||
| 	/*
 |     /*
 | ||||||
| 	 * If any of the status flags are set, update the FPSCR. |      * If any of the status flags are set, update the FPSCR. | ||||||
| 	 * Comparison instructions always return at least one of |      * Comparison instructions always return at least one of | ||||||
| 	 * these flags set. |      * these flags set. | ||||||
| 	 */ |      */ | ||||||
| 	if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) |     if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) | ||||||
| 		fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); |         fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); | ||||||
| 
 | 
 | ||||||
| 	fpscr |= exceptions; |     fpscr |= exceptions; | ||||||
| 
 | 
 | ||||||
| 	state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr; |     state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ | ||||||
| #define pr_info //printf
 | #define pr_info //printf
 | ||||||
| #define pr_debug //printf
 | #define pr_debug //printf
 | ||||||
| 
 | 
 | ||||||
| static u32 vfp_fls(int x); | static u32 fls(int x); | ||||||
| #define do_div(n, base) {n/=base;} | #define do_div(n, base) {n/=base;} | ||||||
| 
 | 
 | ||||||
| /* From vfpinstr.h */ | /* From vfpinstr.h */ | ||||||
|  | @ -502,7 +502,7 @@ struct op { | ||||||
| 	u32 flags; | 	u32 flags; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static u32 vfp_fls(int x) | static u32 fls(int x) | ||||||
| { | { | ||||||
| 	int r = 32; | 	int r = 32; | ||||||
| 
 | 
 | ||||||
|  | @ -532,4 +532,9 @@ static u32 vfp_fls(int x) | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | u32 vfp_double_normaliseroundintern(ARMul_State* state, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func); | ||||||
|  | u32 vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, struct vfp_double *vdm, u32 fpscr); | ||||||
|  | u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn, struct vfp_double *vdm, u32 fpscr); | ||||||
|  | u32 vfp_double_fcvtsinterncutting(ARMul_State* state, int sd, struct vfp_double* dm, u32 fpscr); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue