Merge pull request #166 from bunnei/skyeye-vfp-fixes
SkyEye ARM/VFP fixes
This commit is contained in:
commit
7f9bcacdf7
|
@ -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…
Reference in New Issue