1
1
/////////////////////////////////////////////////////////////////////////
2
// $Id: xsave.cc,v 1.10 2008/05/10 13:34:47 sshwarts Exp $
2
// $Id: xsave.cc,v 1.16 2009/01/16 18:18:59 sshwarts Exp $
3
3
/////////////////////////////////////////////////////////////////////////
5
5
// Copyright (c) 2008 Stanislav Shwartsman
18
18
// You should have received a copy of the GNU Lesser General Public
19
19
// License along with this library; if not, write to the Free Software
20
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
22
22
/////////////////////////////////////////////////////////////////////////
42
42
BX_CPU_THIS_PTR prepareXSAVE();
44
BX_DEBUG(("XSAVE: save processor state XCR0=0x%08x", BX_CPU_THIS_PTR xcr0.getRegister()));
46
BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
48
bx_address laddr = get_laddr(i->seg(), RMAddr(i));
44
BX_DEBUG(("XSAVE: save processor state XCR0=0x%08x", BX_CPU_THIS_PTR xcr0.get32()));
46
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
48
bx_address laddr = get_laddr(i->seg(), eaddr);
50
50
if (laddr & 0x3f) {
51
51
BX_ERROR(("XSAVE: access not aligned to 64-byte"));
87
xmm.xmm32u(2) = (Bit32u)(BX_CPU_THIS_PTR the_i387.fip) & 0xffffffff;
87
xmm.xmm32u(2) = (Bit32u)(BX_CPU_THIS_PTR the_i387.fip);
88
88
xmm.xmm32u(3) = (BX_CPU_THIS_PTR the_i387.fcs);
91
write_virtual_dqword(i->seg(), RMAddr(i), (Bit8u *) &xmm);
91
write_virtual_dqword(i->seg(), eaddr, (Bit8u *) &xmm);
94
94
* x87 FPU Instruction Operand (Data) Pointer Offset (32/64 bits)
103
103
#if BX_SUPPORT_X86_64
104
104
if (i->os64L()) {
105
write_virtual_qword(i->seg(), RMAddr(i) + 16, BX_CPU_THIS_PTR the_i387.fdp);
105
write_virtual_qword(i->seg(), eaddr + 16, BX_CPU_THIS_PTR the_i387.fdp);
110
write_virtual_dword(i->seg(), RMAddr(i) + 16,
111
(Bit32u)(BX_CPU_THIS_PTR the_i387.fdp & 0xffffffff));
112
write_virtual_dword(i->seg(), RMAddr(i) + 20,
113
(Bit32u)(BX_CPU_THIS_PTR the_i387.fds));
110
write_virtual_dword(i->seg(), eaddr + 16, (Bit32u) BX_CPU_THIS_PTR the_i387.fdp);
111
write_virtual_dword(i->seg(), eaddr + 20, (Bit32u) BX_CPU_THIS_PTR the_i387.fds);
115
113
/* do not touch MXCSR state */
123
121
xmm.xmm64u(1) = 0;
124
122
xmm.xmm16u(4) = fp.exp;
126
write_virtual_dqword(i->seg(), RMAddr(i)+index*16+32, (Bit8u *) &xmm);
124
write_virtual_dqword(i->seg(), eaddr+index*16+32, (Bit8u *) &xmm);
130
128
/////////////////////////////////////////////////////////////////////////////
131
129
if (BX_CPU_THIS_PTR xcr0.get_SSE() && (EAX & BX_XCR0_SSE_MASK) != 0)
133
write_virtual_dword(i->seg(), RMAddr(i) + 24, BX_MXCSR_REGISTER);
134
write_virtual_dword(i->seg(), RMAddr(i) + 28, MXCSR_MASK);
131
write_virtual_dword(i->seg(), eaddr + 24, BX_MXCSR_REGISTER);
132
write_virtual_dword(i->seg(), eaddr + 28, MXCSR_MASK);
136
134
/* store XMM register file */
137
135
for(index=0; index < BX_XMM_REGISTERS; index++)
139
137
// save XMM8-XMM15 only in 64-bit mode
140
138
if (index < 8 || Is64BitMode()) {
141
139
write_virtual_dqword(i->seg(),
142
RMAddr(i)+index*16+160, (Bit8u *) &(BX_CPU_THIS_PTR xmm[index]));
140
eaddr+index*16+160, (Bit8u *) &(BX_CPU_THIS_PTR xmm[index]));
147
145
// skip header update for now, required to know if a CPU feature is in its initial state
149
147
BX_INFO(("XSAVE: required XSAVE support, use --enable-xsave option"));
148
exception(BX_UD_EXCEPTION, 0, 0);
161
159
BX_CPU_THIS_PTR prepareXSAVE();
163
BX_DEBUG(("XRSTOR: restore processor state XCR0=0x%08x", BX_CPU_THIS_PTR xcr0.getRegister()));
165
BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
167
bx_address laddr = get_laddr(i->seg(), RMAddr(i));
161
BX_DEBUG(("XRSTOR: restore processor state XCR0=0x%08x", BX_CPU_THIS_PTR xcr0.get32()));
163
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
164
bx_address laddr = get_laddr(i->seg(), eaddr);
169
166
if (laddr & 0x3f) {
170
167
BX_ERROR(("XRSTOR: access not aligned to 64-byte"));
171
168
exception(BX_GP_EXCEPTION, 0, 0);
174
Bit64u header1 = read_virtual_qword(i->seg(), RMAddr(i) + 512);
175
Bit64u header2 = read_virtual_qword(i->seg(), RMAddr(i) + 520);
176
Bit64u header3 = read_virtual_qword(i->seg(), RMAddr(i) + 528);
171
Bit64u header1 = read_virtual_qword(i->seg(), eaddr + 512);
172
Bit64u header2 = read_virtual_qword(i->seg(), eaddr + 520);
173
Bit64u header3 = read_virtual_qword(i->seg(), eaddr + 528);
178
if ((~BX_CPU_THIS_PTR xcr0.getRegister() & header1) != 0) {
175
if ((~BX_CPU_THIS_PTR xcr0.get32() & header1) != 0) {
179
176
BX_ERROR(("XRSTOR: Broken header state"));
180
177
exception(BX_GP_EXCEPTION, 0, 0);
195
192
if (header1 & BX_XCR0_FPU_MASK) {
196
193
// load FPU state from XSAVE area
197
read_virtual_dqword(i->seg(), RMAddr(i), (Bit8u *) &xmm);
194
read_virtual_dqword(i->seg(), eaddr, (Bit8u *) &xmm);
199
196
BX_CPU_THIS_PTR the_i387.cwd = xmm.xmm16u(0);
200
197
BX_CPU_THIS_PTR the_i387.swd = xmm.xmm16u(1);
216
213
BX_CPU_THIS_PTR the_i387.fip = xmm.xmm32u(2);
217
BX_CPU_THIS_PTR the_i387.fcs = xmm.xmm16u(5);
214
BX_CPU_THIS_PTR the_i387.fcs = xmm.xmm16u(6);
220
217
Bit32u tag_byte = xmm.xmmubyte(4);
222
219
/* Restore x87 FPU DP */
223
read_virtual_dqword(i->seg(), RMAddr(i) + 16, (Bit8u *) &xmm);
220
read_virtual_dqword(i->seg(), eaddr + 16, (Bit8u *) &xmm);
225
222
#if BX_SUPPORT_X86_64
226
223
if (i->os64L()) {
237
234
/* load i387 register file */
238
235
for(index=0; index < 8; index++)
240
read_virtual_tword(i->seg(), RMAddr(i)+index*16+32, &(BX_FPU_REG(index)));
238
reg.fraction = read_virtual_qword(i->seg(), eaddr+index*16+32);
239
reg.exp = read_virtual_word (i->seg(), eaddr+index*16+40);
240
BX_FPU_REG(index) = reg;
243
243
/* Restore floating point tag word - see desription for FXRSTOR instruction */
244
244
BX_CPU_THIS_PTR the_i387.twd = unpack_FPU_TW(tag_byte);
247
// initialize FPU with reset values
248
BX_CPU_THIS_PTR the_i387.init();
247
// initialize FPU with reset values
248
BX_CPU_THIS_PTR the_i387.init();
250
for (index=0;index<8;index++) {
251
BX_CPU_THIS_PTR the_i387.st_space[index].exp = 0;
252
BX_CPU_THIS_PTR the_i387.st_space[index].fraction = 0;
250
for (index=0;index<8;index++) {
251
floatx80 reg = { 0, 0 };
252
BX_FPU_REG(index) = reg;
257
257
/////////////////////////////////////////////////////////////////////////////
258
258
if (BX_CPU_THIS_PTR xcr0.get_SSE() && (EAX & BX_XCR0_SSE_MASK) != 0)
260
Bit32u new_mxcsr = read_virtual_dword(i->seg(), RMAddr(i) + 24);
260
Bit32u new_mxcsr = read_virtual_dword(i->seg(), eaddr + 24);
261
261
if(new_mxcsr & ~MXCSR_MASK)
262
262
exception(BX_GP_EXCEPTION, 0, 0);
268
268
// restore XMM8-XMM15 only in 64-bit mode
269
269
if (index < 8 || Is64BitMode()) {
270
270
read_virtual_dqword(i->seg(),
271
RMAddr(i)+index*16+160, (Bit8u *) &(BX_CPU_THIS_PTR xmm[index]));
271
eaddr+index*16+160, (Bit8u *) &(BX_CPU_THIS_PTR xmm[index]));
309
RAX = BX_CPU_THIS_PTR xcr0.getRegister();
309
RAX = BX_CPU_THIS_PTR xcr0.get32();
311
311
BX_INFO(("XGETBV: required XSAVE support, use --enable-xsave option"));
312
exception(BX_UD_EXCEPTION, 0, 0);
344
344
exception(BX_GP_EXCEPTION, 0, 0);
347
BX_CPU_THIS_PTR xcr0.setRegister(EAX);
347
BX_CPU_THIS_PTR xcr0.set32(EAX);
349
349
BX_INFO(("XSETBV: required XSAVE support, use --enable-xsave option"));
350
exception(BX_UD_EXCEPTION, 0, 0);