summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2012-06-04 10:43:09 -0700
committerGabe Black <gblack@eecs.umich.edu>2012-06-04 10:43:09 -0700
commit35fa5074aa256880f70591eb656dceeb1a7feae0 (patch)
tree79704dcdb74aa43ee14c3cdb0d9aff19a41a570a
parent7b73c36f5d52073025223dcdaca749758d274d52 (diff)
downloadgem5-35fa5074aa256880f70591eb656dceeb1a7feae0.tar.xz
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.
-rw-r--r--src/arch/x86/isa/decoder/two_byte_opcodes.isa17
-rw-r--r--src/arch/x86/isa/formats/cpuid.isa5
2 files changed, 13 insertions, 9 deletions
diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
index 34b79a6a4..3b187d625 100644
--- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
@@ -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);
diff --git a/src/arch/x86/isa/formats/cpuid.isa b/src/arch/x86/isa/formats/cpuid.isa
index cc3070ded..535f1e925 100644
--- a/src/arch/x86/isa/formats/cpuid.isa
+++ b/src/arch/x86/isa/formats/cpuid.isa
@@ -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;
}
}};