X86: Ensure that the CPUID instruction always writes its outputs.
The CPUID instruction was implemented so that it would only write its results if the instruction was successful. This works fine on the simple CPU where unwritten registers retain their old values, but on a CPU like O3 with renaming this is broken. The instruction needs to write the old values back into the registers explicitly if they aren't being changed.
This commit is contained in:
parent
7b73c36f5d
commit
35fa5074aa
2 changed files with 13 additions and 9 deletions
|
@ -721,12 +721,19 @@
|
|||
0x1: pop_fs();
|
||||
0x2: CPUIDInst::CPUID({{
|
||||
CpuidResult result;
|
||||
success = doCpuid(xc->tcBase(), bits(Rax, 31, 0),
|
||||
bool success = doCpuid(xc->tcBase(), bits(Rax, 31, 0),
|
||||
bits(Rcx, 31, 0), result);
|
||||
Rax = result.rax;
|
||||
Rbx = result.rbx;
|
||||
Rcx = result.rcx;
|
||||
Rdx = result.rdx;
|
||||
if (success) {
|
||||
Rax = result.rax;
|
||||
Rbx = result.rbx;
|
||||
Rcx = result.rcx;
|
||||
Rdx = result.rdx;
|
||||
} else {
|
||||
Rax = Rax;
|
||||
Rbx = Rbx;
|
||||
Rcx = Rcx;
|
||||
Rdx = Rdx;
|
||||
}
|
||||
}});
|
||||
0x3: Inst::BT(Ev,Gv);
|
||||
0x4: Inst::SHLD(Ev,Gv,Ib);
|
||||
|
|
|
@ -73,13 +73,10 @@ def template CPUIDExecute {{
|
|||
{
|
||||
// If the CPUID instruction used a valid function number, this will
|
||||
// be set to true. Otherwise, the instruction does nothing.
|
||||
bool success;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(code)s;
|
||||
if (success) {
|
||||
%(op_wb)s;
|
||||
}
|
||||
%(op_wb)s;
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
|
Loading…
Reference in a new issue