Fixed a problem in LDMXCSR instruction

Beta version of FXSAVE/FXRSTOR instructions implementation
(still imcomplete, doesn't fully restore FPU state)
This commit is contained in:
Stanislav Shwartsman 2002-11-22 21:21:31 +00:00
parent 6f798350f1
commit 2b2e773dde

View File

@ -48,9 +48,13 @@ void BX_CPU_C::LDMXCSR(bxInstruction_c *i)
#if BX_SUPPORT_SSE >= 1
BX_CPU_THIS_PTR prepareSSE();
read_virtual_dword(i->seg(), RMAddr(i), &BX_MXCSR_REGISTER);
if(BX_MXCSR_REGISTER & ~MXCSR_MASK)
Bit32u new_mxcsr;
read_virtual_dword(i->seg(), RMAddr(i), &new_mxcsr);
if(new_mxcsr & ~MXCSR_MASK)
exception(BX_GP_EXCEPTION, 0, 0);
BX_MXCSR_REGISTER = new_mxcsr;
#else
BX_INFO(("LDMXCSR: SSE not supported in current configuration"));
UndefinedOpcode(i);
@ -71,20 +75,176 @@ void BX_CPU_C::STMXCSR(bxInstruction_c *i)
#endif
}
/* 0F AE Grp15 000 */
void BX_CPU_C::FXSAVE(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
BX_INFO(("FXSAVE: SSE instruction still not implemented"));
BxPackedXmmRegister xmm;
Bit16u twd = BX_CPU_THIS_PTR the_i387.soft.twd, tbd = 0;
unsigned index;
xmm.xmm16u(0) = BX_CPU_THIS_PTR the_i387.soft.cwd;
xmm.xmm16u(1) = BX_CPU_THIS_PTR the_i387.soft.swd;
if(twd & 0x0003 == 0x0003) tbd |= 0x010000;
if(twd & 0x000c == 0x000c) tbd |= 0x020000;
if(twd & 0x0030 == 0x0030) tbd |= 0x040000;
if(twd & 0x00c0 == 0x00c0) tbd |= 0x080000;
if(twd & 0x0300 == 0x0300) tbd |= 0x100000;
if(twd & 0x0c00 == 0x0c00) tbd |= 0x200000;
if(twd & 0x3000 == 0x3000) tbd |= 0x400000;
if(twd & 0xc000 == 0xc000) tbd |= 0x800000;
xmm.xmm16u(2) = tbd;
/* x87 FPU Opcode (16 bits) */
/* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */
xmm.xmm16u(3) = 0; /* still not implemented */
/*
* x87 FPU IP Offset (32 bits)
* The contents of this field differ depending on the current
* addressing mode (16/32 bit) when the FXSAVE instruction was executed:
* + 32-bit mode-32-bit IP offset
* + 16-bit mode-low 16 bits are IP offset; high 16 bits are reserved.
*
* x87 CS FPU IP Selector (16 bits)
*/
xmm.xmm64u(1) = 0; /* still not implemented */
writeVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &xmm);
/*
* x87 FPU Instruction Operand (Data) Pointer Offset (32 bits)
* The contents of this field differ depending on the current
* addressing mode (16/32 bit) when the FXSAVE instruction was executed:
* + 32-bit mode-32-bit offset
* + 16-bit mode-low 16 bits are offset; high 16 bits are reserved.
*
* x87 DS FPU Instruction Operand (Data) Pointer Selector (16 bits)
*/
xmm.xmm64u(0) = 0; /* still not implemented */
xmm.xmm32u(2) = BX_MXCSR_REGISTER;
xmm.xmm32u(3) = MXCSR_MASK;
writeVirtualDQwordAligned(i->seg(), RMAddr(i) + 16, (Bit8u *) &xmm);
/* store i387 register file */
for(index=0; index < 8; index++)
{
Bit8u *r387 = (Bit8u *) &(BX_CPU_THIS_PTR the_i387.soft.st_space[index]);
writeVirtualDQwordAligned(i->seg(), RMAddr(i)+index*16+32, r387);
}
/* store XMM register file */
for(index=0; index < BX_XMM_REGISTERS; index++)
{
Bit8u *r128 = (Bit8u *) &(BX_CPU_THIS_PTR xmm[index]);
writeVirtualDQwordAligned(i->seg(), RMAddr(i)+index*16+160, r128);
}
/* do not touch reserved fields */
#else
BX_INFO(("FXSAVE: SSE not supported in current configuration"));
UndefinedOpcode(i);
#endif
}
/* 0F AE Grp15 001 */
void BX_CPU_C::FXRSTOR(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 1
BX_INFO(("FXRSTOR : SSE instruction still not implemented"));
BxPackedXmmRegister xmm;
Bit32u tbd, twd = 0;
unsigned index;
readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &xmm);
BX_CPU_THIS_PTR the_i387.soft.cwd = xmm.xmm16u(0);
BX_CPU_THIS_PTR the_i387.soft.swd = xmm.xmm16u(1);
/* TOS restore still not implemented */
/* FOO/FPU IP restore still not implemented */
/*
* Note that the original format for FTW can be recreated from the stored
* FTW valid bits and the stored 80-bit FP data (assuming the stored data
* was not the contents of MMX registers) using the following table:
| Exponent | Exponent | Fraction | J,M bits | FTW valid | x87 FTW |
| all 1s | all 0s | all 0s | | | |
-------------------------------------------------------------------
| 0 | 0 | 0 | 0x | 1 | S 10 |
| 0 | 0 | 0 | 1x | 1 | V 00 |
-------------------------------------------------------------------
| 0 | 0 | 1 | 00 | 1 | S 10 |
| 0 | 0 | 1 | 10 | 1 | V 00 |
-------------------------------------------------------------------
| 0 | 1 | 0 | 0x | 1 | S 10 |
| 0 | 1 | 0 | 1x | 1 | V 10 |
-------------------------------------------------------------------
| 0 | 1 | 1 | 00 | 1 | S 01 |
| 0 | 1 | 1 | 10 | 1 | V 10 |
-------------------------------------------------------------------
| 1 | 0 | 0 | 1x | 1 | S 10 |
| 1 | 0 | 0 | 1x | 1 | V 10 |
-------------------------------------------------------------------
| 1 | 0 | 1 | 00 | 1 | S 10 |
| 1 | 0 | 1 | 10 | 1 | V 10 |
-------------------------------------------------------------------
| all combinations above | 1 | E 11 |
*
* The J-bit is defined to be the 1-bit binary integer to the left
* of the decimal place in the significand.
*
* The M-bit is defined to be the most significant bit of the fractional
* portion of the significand (i.e., the bit immediately to the right of
* the decimal place). When the M-bit is the most significant bit of the
* fractional portion of the significand, it must be 0 if the fraction
* is all 0's.
*/ /* still not implemented */
tbd = xmm.xmm16u(2);
if(tbd & 0x010000) twd |= 0x0003;
if(tbd & 0x020000) twd |= 0x000c;
if(tbd & 0x040000) twd |= 0x0030;
if(tbd & 0x080000) twd |= 0x00c0;
if(tbd & 0x100000) twd |= 0x0300;
if(tbd & 0x200000) twd |= 0x0c00;
if(tbd & 0x400000) twd |= 0x3000;
if(tbd & 0x800000) twd |= 0xc000;
BX_CPU_THIS_PTR the_i387.soft.twd = twd;
readVirtualDQwordAligned(i->seg(), RMAddr(i) + 16, (Bit8u *) &xmm);
/* FPU DP restore still not implemented */
Bit32u new_mxcsr = xmm.xmm32u(2);
Bit32u mxcsr_msk = xmm.xmm32u(3);
if(! mxcsr_msk) mxcsr_msk = MXCSR_MASK;
if(new_mxcsr & ~mxcsr_msk)
exception(BX_GP_EXCEPTION, 0, 0);
BX_MXCSR_REGISTER = new_mxcsr;
/* load i387 register file */
for(index=0; index < 8; index++)
{
Bit8u *r387 = (Bit8u *) &(BX_CPU_THIS_PTR the_i387.soft.st_space[index]);
readVirtualDQwordAligned(i->seg(), RMAddr(i)+index*16+32, r387);
}
/* load XMM register file */
for(index=0; index < BX_XMM_REGISTERS; index++)
{
Bit8u *r128 = (Bit8u *) &(BX_CPU_THIS_PTR xmm[index]);
readVirtualDQwordAligned(i->seg(), RMAddr(i)+index*16+160, r128);
}
#else
BX_INFO(("FXRSTOR: SSE not supported in current configuration"));
UndefinedOpcode(i);