rewritten xsave/xrestor for more modular functionality. todo: replace walk through state using simple for loop
This commit is contained in:
parent
93d9590f3b
commit
648221d419
@ -4905,6 +4905,33 @@ public: // for now...
|
||||
BX_SMF void print_state_AVX(void);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_AVX
|
||||
BX_SMF void xsave_ymm_state(bxInstruction_c *i, bx_address offset);
|
||||
#if BX_SUPPORT_EVEX
|
||||
BX_SMF void xsave_opmask_state(bxInstruction_c *i, bx_address offset);
|
||||
BX_SMF void xsave_zmm_hi256_state(bxInstruction_c *i, bx_address offset);
|
||||
BX_SMF void xsave_hi_zmm_state(bxInstruction_c *i, bx_address offset);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_AVX
|
||||
BX_SMF void xrstor_ymm_state(bxInstruction_c *i, bx_address offset);
|
||||
#if BX_SUPPORT_EVEX
|
||||
BX_SMF void xrstor_opmask_state(bxInstruction_c *i, bx_address offset);
|
||||
BX_SMF void xrstor_zmm_hi256_state(bxInstruction_c *i, bx_address offset);
|
||||
BX_SMF void xrstor_hi_zmm_state(bxInstruction_c *i, bx_address offset);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_AVX
|
||||
BX_SMF void xrstor_init_ymm_state(void);
|
||||
#if BX_SUPPORT_EVEX
|
||||
BX_SMF void xrstor_init_opmask_state(void);
|
||||
BX_SMF void xrstor_init_zmm_hi256_state(void);
|
||||
BX_SMF void xrstor_init_hi_zmm_state(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
BX_SMF bx_bool is_monitor(bx_phy_address addr, unsigned len);
|
||||
BX_SMF void check_monitor(bx_phy_address addr, unsigned len);
|
||||
|
@ -151,56 +151,29 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XSAVE(bxInstruction_c *i)
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_AVX
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_save_enable_mask & BX_XCR0_YMM_MASK) != 0)
|
||||
{
|
||||
/* store AVX state */
|
||||
for(index=0; index < 16; index++)
|
||||
{
|
||||
// save YMM8-YMM15 only in 64-bit mode
|
||||
if (index < 8 || long64_mode()) {
|
||||
write_virtual_xmmword(i->seg(),
|
||||
(eaddr+index*16+XSAVE_YMM_STATE_OFFSET) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG_LANE(index, 1)));
|
||||
}
|
||||
}
|
||||
|
||||
xsave_ymm_state(i, eaddr+XSAVE_YMM_STATE_OFFSET);
|
||||
header1 |= BX_XCR0_YMM_MASK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_save_enable_mask & BX_XCR0_OPMASK_MASK) != 0)
|
||||
{
|
||||
// save OPMASK state to XSAVE area
|
||||
for(index=0; index < 8; index++) {
|
||||
write_virtual_qword(i->seg(), (eaddr+index*8+XSAVE_OPMASK_STATE_OFFSET) & asize_mask, BX_READ_OPMASK(index));
|
||||
}
|
||||
|
||||
xsave_opmask_state(i, eaddr+XSAVE_OPMASK_STATE_OFFSET);
|
||||
header1 |= BX_XCR0_OPMASK_MASK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_save_enable_mask & BX_XCR0_ZMM_HI256_MASK) != 0)
|
||||
{
|
||||
// save upper part of ZMM registrs to XSAVE area
|
||||
for(index=0; index < 16; index++) {
|
||||
write_virtual_ymmword(i->seg(), (eaddr+index*32+XSAVE_ZMM_HI256_STATE_OFFSET) & asize_mask,
|
||||
(Bit8u *)(&BX_READ_ZMM_REG_HI(index)));
|
||||
}
|
||||
|
||||
xsave_zmm_hi256_state(i, eaddr+XSAVE_ZMM_HI256_STATE_OFFSET);
|
||||
header1 |= BX_XCR0_ZMM_HI256_MASK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_save_enable_mask & BX_XCR0_HI_ZMM_MASK) != 0)
|
||||
{
|
||||
// load ZMM state from XSAVE area
|
||||
for(index=0; index < 16; index++) {
|
||||
write_virtual_zmmword(i->seg(), (eaddr+index*64+XSAVE_HI_ZMM_STATE_OFFSET) & asize_mask,
|
||||
(Bit8u *)(&BX_READ_AVX_REG(index+16)));
|
||||
}
|
||||
|
||||
xsave_hi_zmm_state(i, eaddr+XSAVE_HI_ZMM_STATE_OFFSET);
|
||||
header1 |= BX_XCR0_HI_ZMM_MASK;
|
||||
}
|
||||
#endif
|
||||
@ -375,24 +348,10 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XRSTOR(bxInstruction_c *i)
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_load_enable_mask & BX_XCR0_YMM_MASK) != 0)
|
||||
{
|
||||
if (header1 & BX_XCR0_YMM_MASK) {
|
||||
// load AVX state from XSAVE area
|
||||
for(index=0; index < 16; index++)
|
||||
{
|
||||
// restore YMM8-YMM15 only in 64-bit mode
|
||||
if (index < 8 || long64_mode()) {
|
||||
read_virtual_xmmword(i->seg(),
|
||||
(eaddr+index*16+XSAVE_YMM_STATE_OFFSET) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG_LANE(index, 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// initialize upper part of AVX registers with reset values
|
||||
for(index=0; index < 16; index++) {
|
||||
// set YMM8-YMM15 only in 64-bit mode
|
||||
if (index < 8 || long64_mode()) BX_CLEAR_AVX_HIGH128(index);
|
||||
}
|
||||
}
|
||||
if (header1 & BX_XCR0_YMM_MASK)
|
||||
xrstor_ymm_state(i, eaddr+XSAVE_YMM_STATE_OFFSET);
|
||||
else
|
||||
xrstor_init_ymm_state();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -400,55 +359,28 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XRSTOR(bxInstruction_c *i)
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_load_enable_mask & BX_XCR0_OPMASK_MASK) != 0)
|
||||
{
|
||||
if (header1 & BX_XCR0_OPMASK_MASK) {
|
||||
// load opmask registers from XSAVE area
|
||||
for(index=0; index < 8; index++) {
|
||||
Bit64u opmask = read_virtual_qword(i->seg(), (eaddr+index*8+XSAVE_OPMASK_STATE_OFFSET) & asize_mask);
|
||||
BX_WRITE_OPMASK(index, opmask);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// initialize opmask registers with reset values
|
||||
for(index=0; index < 8; index++) {
|
||||
BX_WRITE_OPMASK(index, 0);
|
||||
}
|
||||
}
|
||||
if (header1 & BX_XCR0_OPMASK_MASK)
|
||||
xrstor_opmask_state(i, eaddr+XSAVE_OPMASK_STATE_OFFSET);
|
||||
else
|
||||
xrstor_init_opmask_state();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_load_enable_mask & BX_XCR0_ZMM_HI256_MASK) != 0)
|
||||
{
|
||||
if (header1 & BX_XCR0_ZMM_HI256_MASK) {
|
||||
// load upper part of ZMM registers from XSAVE area
|
||||
for(index=0; index < 16; index++) {
|
||||
read_virtual_ymmword(i->seg(), (eaddr+index*32+XSAVE_ZMM_HI256_STATE_OFFSET) & asize_mask,
|
||||
(Bit8u *)(&BX_READ_ZMM_REG_HI(index)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// initialize upper part of ZMM registers with reset values
|
||||
for(index=0; index < 16; index++) {
|
||||
BX_CLEAR_AVX_HIGH256(index);
|
||||
}
|
||||
}
|
||||
if (header1 & BX_XCR0_ZMM_HI256_MASK)
|
||||
xrstor_zmm_hi256_state(i, eaddr+XSAVE_ZMM_HI256_STATE_OFFSET);
|
||||
else
|
||||
xrstor_init_zmm_hi256_state();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
if ((features_load_enable_mask & BX_XCR0_HI_ZMM_MASK) != 0)
|
||||
{
|
||||
if (header1 & BX_XCR0_HI_ZMM_MASK) {
|
||||
// load ZMM state from XSAVE area
|
||||
for(index=0; index < 16; index++) {
|
||||
read_virtual_zmmword(i->seg(), (eaddr+index*64+XSAVE_HI_ZMM_STATE_OFFSET) & asize_mask,
|
||||
(Bit8u *)(&BX_READ_AVX_REG(index+16)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// initialize upper part of ZMM registers with reset values
|
||||
for(index=0; index < 16; index++) {
|
||||
BX_CLEAR_AVX_REG(index+16);
|
||||
}
|
||||
}
|
||||
if (header1 & BX_XCR0_HI_ZMM_MASK)
|
||||
xrstor_hi_zmm_state(i, eaddr+XSAVE_HI_ZMM_STATE_OFFSET);
|
||||
else
|
||||
xrstor_init_hi_zmm_state();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -457,6 +389,141 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XRSTOR(bxInstruction_c *i)
|
||||
BX_NEXT_INSTR(i);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_AVX
|
||||
|
||||
// YMM state management //
|
||||
|
||||
void BX_CPU_C::xsave_ymm_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
/* store AVX state */
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
// save YMM8-YMM15 only in 64-bit mode
|
||||
if (index < 8 || long64_mode()) {
|
||||
write_virtual_xmmword(i->seg(), (offset + index*16) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG_LANE(index, 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_ymm_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
// load AVX state from XSAVE area
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
// restore YMM8-YMM15 only in 64-bit mode
|
||||
if (index < 8 || long64_mode()) {
|
||||
read_virtual_xmmword(i->seg(), (offset + index*16) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG_LANE(index, 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_init_ymm_state(void)
|
||||
{
|
||||
// initialize upper part of AVX registers with reset values
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
// set YMM8-YMM15 only in 64-bit mode
|
||||
if (index < 8 || long64_mode()) BX_CLEAR_AVX_HIGH128(index);
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
|
||||
// Opmask state management //
|
||||
|
||||
void BX_CPU_C::xsave_opmask_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
// save OPMASK state to XSAVE area
|
||||
for(unsigned index=0; index < 8; index++) {
|
||||
write_virtual_qword(i->seg(), (offset+index*8) & asize_mask, BX_READ_OPMASK(index));
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_opmask_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
// load opmask registers from XSAVE area
|
||||
for(unsigned index=0; index < 8; index++) {
|
||||
Bit64u opmask = read_virtual_qword(i->seg(), (offset+index*8) & asize_mask);
|
||||
BX_WRITE_OPMASK(index, opmask);
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_init_opmask_state(void)
|
||||
{
|
||||
// initialize opmask registers with reset values
|
||||
for(unsigned index=0; index < 8; index++) {
|
||||
BX_WRITE_OPMASK(index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// ZMM_HI256 (upper part of zmm0..zmm15 registers) state management //
|
||||
|
||||
void BX_CPU_C::xsave_zmm_hi256_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
// save upper part of ZMM registers to XSAVE area
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
write_virtual_ymmword(i->seg(), (offset+index*32) & asize_mask, (Bit8u *)(&BX_READ_ZMM_REG_HI(index)));
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_zmm_hi256_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
// load upper part of ZMM registers from XSAVE area
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
read_virtual_ymmword(i->seg(), (offset+index*32) & asize_mask, (Bit8u *)(&BX_READ_ZMM_REG_HI(index)));
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_init_zmm_hi256_state(void)
|
||||
{
|
||||
// initialize upper part of ZMM registers with reset values
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
BX_CLEAR_AVX_HIGH256(index);
|
||||
}
|
||||
}
|
||||
|
||||
// HI_ZMM (zmm15..zmm31) state management //
|
||||
|
||||
void BX_CPU_C::xsave_hi_zmm_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
// save high ZMM state to XSAVE area
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
write_virtual_zmmword(i->seg(), (offset+index*64) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG(index+16)));
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_hi_zmm_state(bxInstruction_c *i, bx_address offset)
|
||||
{
|
||||
bx_address asize_mask = i->asize_mask();
|
||||
|
||||
// load high ZMM state from XSAVE area
|
||||
for(unsigned index=0; index < 16; index++) {
|
||||
read_virtual_zmmword(i->seg(), (offset+index*64) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG(index+16)));
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPU_C::xrstor_init_hi_zmm_state(void)
|
||||
{
|
||||
// initialize high ZMM registers with reset values
|
||||
for(unsigned index=16; index < 32; index++) {
|
||||
BX_CLEAR_AVX_REG(index);
|
||||
}
|
||||
}
|
||||
#endif // BX_SUPPORT_EVEX
|
||||
|
||||
#endif
|
||||
|
||||
/* 0F 01 D0 */
|
||||
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XGETBV(bxInstruction_c *i)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user