i386: BTR and page fault fixes from Carl, and basic implementation of FIST and FBLD FPU instructions.

This commit is contained in:
mahlemiut 2012-01-18 22:54:36 +00:00
parent a5c3667e46
commit d458480a07
5 changed files with 94 additions and 36 deletions

View File

@ -2002,7 +2002,7 @@ static void decode_opcode(char *s, const I386_OPCODE *op, UINT8 op1)
int i;
UINT8 op2;
if (op->flags & SPECIAL64)
if ((op->flags & SPECIAL64) && (address_size == 2))
op = &x64_opcode_alt[op->flags >> 24];
switch( op->flags & FLAGS_MASK )

View File

@ -337,8 +337,10 @@ static void I386OP(bt_rm16_r16)(i386_state *cpustate) // Opcode 0x0f a3
CYCLES(cpustate,CYCLES_BT_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(cpustate,ea);
UINT16 bit = LOAD_REG16(modrm);
ea += 2*(bit/16);
bit %= 16;
UINT16 dst = READ16(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;
@ -366,8 +368,10 @@ static void I386OP(btc_rm16_r16)(i386_state *cpustate) // Opcode 0x0f bb
CYCLES(cpustate,CYCLES_BTC_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(cpustate,ea);
UINT16 bit = LOAD_REG16(modrm);
ea += 2*(bit/16);
bit %= 16;
UINT16 dst = READ16(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;
@ -397,8 +401,10 @@ static void I386OP(btr_rm16_r16)(i386_state *cpustate) // Opcode 0x0f b3
CYCLES(cpustate,CYCLES_BTR_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(cpustate,ea);
UINT16 bit = LOAD_REG16(modrm);
ea += 2*(bit/16);
bit %= 16;
UINT16 dst = READ16(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;
@ -428,8 +434,10 @@ static void I386OP(bts_rm16_r16)(i386_state *cpustate) // Opcode 0x0f ab
CYCLES(cpustate,CYCLES_BTS_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT16 dst = READ16(cpustate,ea);
UINT16 bit = LOAD_REG16(modrm);
ea += 2*(bit/16);
bit %= 16;
UINT16 dst = READ16(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;

View File

@ -338,8 +338,10 @@ static void I386OP(bt_rm32_r32)(i386_state *cpustate) // Opcode 0x0f a3
CYCLES(cpustate,CYCLES_BT_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(cpustate,ea);
UINT32 bit = LOAD_REG32(modrm);
ea += 4*(bit/32);
bit %= 32;
UINT32 dst = READ32(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;
@ -367,8 +369,10 @@ static void I386OP(btc_rm32_r32)(i386_state *cpustate) // Opcode 0x0f bb
CYCLES(cpustate,CYCLES_BTC_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(cpustate,ea);
UINT32 bit = LOAD_REG32(modrm);
ea += 4*(bit/32);
bit %= 32;
UINT32 dst = READ32(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;
@ -398,8 +402,10 @@ static void I386OP(btr_rm32_r32)(i386_state *cpustate) // Opcode 0x0f b3
CYCLES(cpustate,CYCLES_BTR_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(cpustate,ea);
UINT32 bit = LOAD_REG32(modrm);
ea += 4*(bit/32);
bit %= 32;
UINT32 dst = READ32(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;
@ -429,8 +435,10 @@ static void I386OP(bts_rm32_r32)(i386_state *cpustate) // Opcode 0x0f ab
CYCLES(cpustate,CYCLES_BTS_REG_REG);
} else {
UINT32 ea = GetEA(cpustate,modrm);
UINT32 dst = READ32(cpustate,ea);
UINT32 bit = LOAD_REG32(modrm);
ea += 4*(bit/32);
bit %= 32;
UINT32 dst = READ32(cpustate,ea);
if( dst & (1 << bit) )
cpustate->CF = 1;
@ -468,7 +476,6 @@ static void I386OP(call_abs32)(i386_state *cpustate) // Opcode 0x9a
static void I386OP(call_rel32)(i386_state *cpustate) // Opcode 0xe8
{
INT32 disp = FETCH32(cpustate);
PUSH32(cpustate, cpustate->eip );
cpustate->eip += disp;
CHANGE_PC(cpustate,cpustate->eip);

View File

@ -867,28 +867,32 @@ INLINE UINT32 DEC32(i386_state *cpustate,UINT32 dst)
INLINE void PUSH16(i386_state *cpustate,UINT16 value)
{
UINT32 ea;
UINT32 ea, new_esp;
if( STACK_32BIT ) {
REG32(ESP) -= 2;
ea = i386_translate(cpustate, SS, REG32(ESP) );
new_esp = REG32(ESP) - 2;
ea = i386_translate(cpustate, SS, new_esp);
WRITE16(cpustate, ea, value );
REG32(ESP) = new_esp;
} else {
REG16(SP) -= 2;
ea = i386_translate(cpustate, SS, REG16(SP) );
new_esp = (REG16(SP) - 2) & 0xffff;
ea = i386_translate(cpustate, SS, new_esp);
WRITE16(cpustate, ea, value );
REG16(SP) = new_esp;
}
}
INLINE void PUSH32(i386_state *cpustate,UINT32 value)
{
UINT32 ea;
UINT32 ea, new_esp;
if( STACK_32BIT ) {
REG32(ESP) -= 4;
ea = i386_translate(cpustate, SS, REG32(ESP) );
new_esp = REG32(ESP) - 4;
ea = i386_translate(cpustate, SS, new_esp);
WRITE32(cpustate, ea, value );
REG32(ESP) = new_esp;
} else {
REG16(SP) -= 4;
ea = i386_translate(cpustate, SS, REG16(SP) );
new_esp = (REG16(SP) - 4) & 0xffff;
ea = i386_translate(cpustate, SS, new_esp);
WRITE32(cpustate, ea, value );
REG16(SP) = new_esp;
}
}
INLINE void PUSH8(i386_state *cpustate,UINT8 value)
@ -903,45 +907,51 @@ INLINE void PUSH8(i386_state *cpustate,UINT8 value)
INLINE UINT8 POP8(i386_state *cpustate)
{
UINT8 value;
UINT32 ea;
UINT32 ea, new_esp;
if( STACK_32BIT ) {
REG32(ESP) += 1;
ea = i386_translate(cpustate, SS, REG32(ESP) - 1);
new_esp = REG32(ESP) + 1;
ea = i386_translate(cpustate, SS, new_esp - 1);
value = READ8(cpustate, ea );
REG32(ESP) = new_esp;
} else {
REG16(SP) += 1;
ea = i386_translate(cpustate, SS, (REG16(SP) - 1) & 0xffff);
new_esp = REG16(SP) + 1;
ea = i386_translate(cpustate, SS, (new_esp - 1) & 0xffff);
value = READ8(cpustate, ea );
REG16(SP) = new_esp;
}
return value;
}
INLINE UINT16 POP16(i386_state *cpustate)
{
UINT16 value;
UINT32 ea;
UINT32 ea, new_esp;
if( STACK_32BIT ) {
REG32(ESP) += 2;
ea = i386_translate(cpustate, SS, REG32(ESP) - 2);
new_esp = REG32(ESP) + 2;
ea = i386_translate(cpustate, SS, new_esp - 2);
value = READ16(cpustate, ea );
REG32(ESP) = new_esp;
} else {
REG16(SP) += 2;
ea = i386_translate(cpustate, SS, (REG16(SP) - 2) & 0xffff);
new_esp = REG16(SP) + 2;
ea = i386_translate(cpustate, SS, (new_esp - 2) & 0xffff);
value = READ16(cpustate, ea );
REG16(SP) = new_esp;
}
return value;
}
INLINE UINT32 POP32(i386_state *cpustate)
{
UINT32 value;
UINT32 ea;
UINT32 ea, new_esp;
if( STACK_32BIT ) {
REG32(ESP) += 4;
ea = i386_translate(cpustate, SS, REG32(ESP) - 4);
new_esp = REG32(ESP) + 4;
ea = i386_translate(cpustate, SS, new_esp - 4);
value = READ32(cpustate, ea );
REG32(ESP) = new_esp;
} else {
REG16(SP) += 4;
ea = i386_translate(cpustate, SS, (REG16(SP) - 4) & 0xffff);
new_esp = REG16(SP) + 4;
ea = i386_translate(cpustate, SS, (new_esp - 4) & 0xffff);
value = READ32(cpustate, ea );
REG16(SP) = new_esp;
}
return value;
}

View File

@ -1529,6 +1529,16 @@ static void I386OP(fpu_group_df)(i386_state *cpustate) // Opcode 0xdf
break;
}
case 2: // FIST
{
X87_REG t;
t = X87_FROUND(cpustate,ST(0));
WRITE16(cpustate,ea,(INT16)t.i);
CYCLES(cpustate,1); // TODO
break;
}
case 3: // FISTP short
{
X87_REG t;
@ -1539,7 +1549,30 @@ static void I386OP(fpu_group_df)(i386_state *cpustate) // Opcode 0xdf
CYCLES(cpustate,29);
break;
}
case 4: // FBLD
{
int i;
double bcd_data = 0.0;
UINT8 byte;
X87_REG t;
for(i=0;i<9;i++)
{
byte = READ8(cpustate,ea+i);
bcd_data += floor(fmod((byte & 0x0f),10.0));
bcd_data *= 10.0;
byte >>= 4;
bcd_data += floor(fmod((byte & 0x0f),10.0));
bcd_data *= 10.0;
}
byte = READ8(cpustate,ea+9);
if(byte & 0x80)
bcd_data -= bcd_data;
t.f = bcd_data;
FPU_PUSH(cpustate,t);
CYCLES(cpustate,1); // TODO
}
case 5: // FILD long
{
X87_REG t;
@ -1563,7 +1596,7 @@ static void I386OP(fpu_group_df)(i386_state *cpustate) // Opcode 0xdf
res = (UINT8)floor(fmod(bcd_data,10.0));
bcd_data -= floor(fmod(bcd_data,10.0));
bcd_data /= 10.0;
res = (UINT8)floor(fmod(bcd_data,10.0))<<4;
res |= (UINT8)floor(fmod(bcd_data,10.0))<<4;
bcd_data -= floor(fmod(bcd_data,10.0));
bcd_data /= 10.0;
WRITE8(cpustate,ea+i,res);