summaryrefslogtreecommitdiff
path: root/src/arch/x86/predecoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/predecoder.cc')
-rw-r--r--src/arch/x86/predecoder.cc81
1 files changed, 56 insertions, 25 deletions
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
index fbed4fe41..573012ee6 100644
--- a/src/arch/x86/predecoder.cc
+++ b/src/arch/x86/predecoder.cc
@@ -117,37 +117,33 @@ namespace X86ISA
//Operand size override prefixes
case OperandSizeOverride:
DPRINTF(Predecoder, "Found operand size override prefix.\n");
+ emi.legacy.op = true;
break;
case AddressSizeOverride:
DPRINTF(Predecoder, "Found address size override prefix.\n");
+ emi.legacy.addr = true;
break;
//Segment override prefixes
case CSOverride:
- DPRINTF(Predecoder, "Found cs segment override.\n");
- break;
case DSOverride:
- DPRINTF(Predecoder, "Found ds segment override.\n");
- break;
case ESOverride:
- DPRINTF(Predecoder, "Found es segment override.\n");
- break;
case FSOverride:
- DPRINTF(Predecoder, "Found fs segment override.\n");
- break;
case GSOverride:
- DPRINTF(Predecoder, "Found gs segment override.\n");
- break;
case SSOverride:
- DPRINTF(Predecoder, "Found ss segment override.\n");
+ DPRINTF(Predecoder, "Found segment override.\n");
+ emi.legacy.seg = prefix;
break;
case Lock:
DPRINTF(Predecoder, "Found lock prefix.\n");
+ emi.legacy.lock = true;
break;
case Rep:
DPRINTF(Predecoder, "Found rep prefix.\n");
+ emi.legacy.rep = true;
break;
case Repne:
DPRINTF(Predecoder, "Found repne prefix.\n");
+ emi.legacy.repne = true;
break;
case RexPrefix:
DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
@@ -198,25 +194,50 @@ namespace X86ISA
displacementCollected = 0;
emi.displacement = 0;
+ //Figure out the effective operand size. This can be overriden to
+ //a fixed value at the decoder level.
+ if(/*FIXME long mode*/1)
+ {
+ if(emi.rex && emi.rex.w)
+ emi.opSize = 3; // 64 bit operand size
+ else if(emi.legacy.op)
+ emi.opSize = 1; // 16 bit operand size
+ else
+ emi.opSize = 2; // 32 bit operand size
+ }
+ else if(/*FIXME default 32*/1)
+ {
+ if(emi.legacy.op)
+ emi.opSize = 1; // 16 bit operand size
+ else
+ emi.opSize = 2; // 32 bit operand size
+ }
+ else // 16 bit default operand size
+ {
+ if(emi.legacy.op)
+ emi.opSize = 2; // 32 bit operand size
+ else
+ emi.opSize = 1; // 16 bit operand size
+ }
+
//Figure out how big of an immediate we'll retreive based
//on the opcode.
- int immType = ImmediateType[
- emi.opcode.num - 1][nextByte];
- if(0) //16 bit mode
- immediateSize = ImmediateTypeToSize[0][immType];
- else if(!(emi.rex & 0x4)) //32 bit mode
- immediateSize = ImmediateTypeToSize[1][immType];
- else //64 bit mode
- immediateSize = ImmediateTypeToSize[2][immType];
+ int immType = ImmediateType[emi.opcode.num - 1][nextByte];
+ immediateSize = SizeTypeToSize[emi.opSize - 1][immType];
//Determine what to expect next
if (UsesModRM[emi.opcode.num - 1][nextByte]) {
nextState = ModRMState;
- } else if(immediateSize) {
- nextState = ImmediateState;
} else {
- emiIsReady = true;
- nextState = PrefixState;
+ //If there's no modRM byte, set it to 0 so we can detect
+ //that later.
+ emi.modRM = 0;
+ if(immediateSize) {
+ nextState = ImmediateState;
+ } else {
+ emiIsReady = true;
+ nextState = PrefixState;
+ }
}
}
return nextState;
@@ -241,11 +262,11 @@ namespace X86ISA
displacementSize = 0;
} else {
//figure out 32/64 bit displacement size
- if(nextByte & 0xC7 == 0x05 ||
+ if(nextByte & 0xC6 == 0x04 ||
nextByte & 0xC0 == 0x80)
displacementSize = 4;
else if(nextByte & 0xC0 == 0x40)
- displacementSize = 2;
+ displacementSize = 1;
else
displacementSize = 0;
}
@@ -346,6 +367,16 @@ namespace X86ISA
if(immediateSize == immediateCollected)
{
+ //XXX Warning! The following is an observed pattern and might
+ //not always be true!
+
+ //Instructions which use 64 bit operands but 32 bit immediates
+ //need to have the immediate sign extended to 64 bits.
+ //Instructions which use true 64 bit immediates won't be
+ //affected, and instructions that use true 32 bit immediates
+ //won't notice.
+ if(immediateSize == 4)
+ emi.immediate = sext<32>(emi.immediate);
DPRINTF(Predecoder, "Collected immediate %#x.\n",
emi.immediate);
emiIsReady = true;