summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-04-06 15:19:23 +0000
committerGabe Black <gblack@eecs.umich.edu>2007-04-06 15:19:23 +0000
commit75e8838ba4020a03f53b66488ecfc756112b2861 (patch)
treea333e1daf3eee99b99c739facc33f402265a9846
parente633e23a3ab32dda963746bea43147d54599c01c (diff)
downloadgem5-75e8838ba4020a03f53b66488ecfc756112b2861.tar.xz
Clean up the code a little, fix (I think) a perceived problem with immediate sizes, and sign extend the 32-bit-acting-like-64-bit-immediates.
--HG-- extra : convert_revision : e59b747198cc79d50045bd2dc45b2e2b97bbffcc
-rw-r--r--src/arch/x86/predecoder.cc64
-rw-r--r--src/arch/x86/predecoder.hh2
-rw-r--r--src/arch/x86/predecoder_tables.cc18
-rw-r--r--src/arch/x86/types.hh46
-rw-r--r--src/arch/x86/utility.hh3
5 files changed, 85 insertions, 48 deletions
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
index 80971e7cf..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,16 +194,36 @@ 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]) {
@@ -351,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;
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 1df17d6d2..6562ab9f5 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -73,7 +73,7 @@ namespace X86ISA
static const uint8_t Prefixes[256];
static const uint8_t UsesModRM[2][256];
static const uint8_t ImmediateType[2][256];
- static const uint8_t ImmediateTypeToSize[3][10];
+ static const uint8_t SizeTypeToSize[3][10];
protected:
ThreadContext * tc;
diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc
index f233ad234..38b9c57a3 100644
--- a/src/arch/x86/predecoder_tables.cc
+++ b/src/arch/x86/predecoder_tables.cc
@@ -141,7 +141,7 @@ namespace X86ISA
}
};
- enum ImmediateTypes {
+ enum SizeType {
NoImm,
NI = NoImm,
ByteImm,
@@ -158,19 +158,19 @@ namespace X86ISA
VW = VWordImm,
ZWordImm,
ZW = ZWordImm,
- Pointer,
- PO = Pointer,
//The enter instruction takes -2- immediates for a total of 3 bytes
Enter,
- EN = Enter
+ EN = Enter,
+ Pointer,
+ PO = Pointer
};
- const uint8_t Predecoder::ImmediateTypeToSize[3][10] =
+ const uint8_t Predecoder::SizeTypeToSize[3][10] =
{
-// noimm byte word dword qword oword vword zword enter
- {0, 1, 2, 4, 8, 16, 2, 2, 3, 4}, //16 bit
- {0, 1, 2, 4, 8, 16, 4, 4, 3, 6}, //32 bit
- {0, 1, 2, 4, 8, 16, 4, 8, 3, 0} //64 bit
+// noimm byte word dword qword oword vword zword enter pointer
+ {0, 1, 2, 4, 8, 16, 2, 2, 3, 4 }, //16 bit
+ {0, 1, 2, 4, 8, 16, 4, 4, 3, 6 }, //32 bit
+ {0, 1, 2, 4, 8, 16, 4, 8, 3, 0 } //64 bit
};
//This table determines the immediate type. The first index is the
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index cdac3c00e..022f20ee5 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -70,25 +70,31 @@ namespace X86ISA
typedef uint64_t MachInst;
enum Prefixes {
- NoOverride = 0,
- CSOverride = 1,
- DSOverride = 2,
- ESOverride = 3,
- FSOverride = 4,
- GSOverride = 5,
- SSOverride = 6,
- //The Rex prefix obviously doesn't fit in with the above, but putting
- //it here lets us save double the space the enums take up.
- RexPrefix = 7,
+ NoOverride,
+ CSOverride,
+ DSOverride,
+ ESOverride,
+ FSOverride,
+ GSOverride,
+ SSOverride,
+ RexPrefix,
+ OperandSizeOverride,
+ AddressSizeOverride,
+ Lock,
+ Rep,
+ Repne
+ };
+
+ BitUnion8(LegacyPrefixVector)
+ Bitfield<7> repne;
+ Bitfield<6> rep;
+ Bitfield<5> lock;
+ Bitfield<4> addr;
+ Bitfield<3> op;
//There can be only one segment override, so they share the
//first 3 bits in the legacyPrefixes bitfield.
- SegmentOverride = 0x7,
- OperandSizeOverride = 8,
- AddressSizeOverride = 16,
- Lock = 32,
- Rep = 64,
- Repne = 128
- };
+ Bitfield<2,0> seg;
+ EndBitUnion(LegacyPrefixVector)
BitUnion8(ModRM)
Bitfield<7,6> mod;
@@ -118,7 +124,7 @@ namespace X86ISA
struct ExtMachInst
{
//Prefixes
- uint8_t legacy;
+ LegacyPrefixVector legacy;
Rex rex;
//This holds all of the bytes of the opcode
struct
@@ -140,6 +146,10 @@ namespace X86ISA
//Immediate fields
uint64_t immediate;
uint64_t displacement;
+
+ //The effective operand size.
+ uint8_t opSize;
+ //The
};
inline static std::ostream &
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index e0bd09515..1c98e7fbc 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -78,7 +78,8 @@ namespace __hash_namespace {
((uint64_t)emi.opcode.prefixA << 16) |
((uint64_t)emi.opcode.prefixB << 8) |
((uint64_t)emi.opcode.op)) ^
- emi.immediate ^ emi.displacement;
+ emi.immediate ^ emi.displacement ^
+ emi.opSize;
};
};
}