diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2012-06-04 10:43:09 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2012-06-04 10:43:09 -0700 |
commit | 35fa5074aa256880f70591eb656dceeb1a7feae0 (patch) | |
tree | 79704dcdb74aa43ee14c3cdb0d9aff19a41a570a /src/arch/x86/isa/decoder/two_byte_opcodes.isa | |
parent | 7b73c36f5d52073025223dcdaca749758d274d52 (diff) | |
download | gem5-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.
Diffstat (limited to 'src/arch/x86/isa/decoder/two_byte_opcodes.isa')
-rw-r--r-- | src/arch/x86/isa/decoder/two_byte_opcodes.isa | 17 |
1 files changed, 12 insertions, 5 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); |