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
This commit is contained in:
Gabe Black 2007-04-06 15:19:23 +00:00
parent e633e23a3a
commit 75e8838ba4
5 changed files with 85 additions and 48 deletions

View file

@ -117,37 +117,33 @@ namespace X86ISA
//Operand size override prefixes //Operand size override prefixes
case OperandSizeOverride: case OperandSizeOverride:
DPRINTF(Predecoder, "Found operand size override prefix.\n"); DPRINTF(Predecoder, "Found operand size override prefix.\n");
emi.legacy.op = true;
break; break;
case AddressSizeOverride: case AddressSizeOverride:
DPRINTF(Predecoder, "Found address size override prefix.\n"); DPRINTF(Predecoder, "Found address size override prefix.\n");
emi.legacy.addr = true;
break; break;
//Segment override prefixes //Segment override prefixes
case CSOverride: case CSOverride:
DPRINTF(Predecoder, "Found cs segment override.\n");
break;
case DSOverride: case DSOverride:
DPRINTF(Predecoder, "Found ds segment override.\n");
break;
case ESOverride: case ESOverride:
DPRINTF(Predecoder, "Found es segment override.\n");
break;
case FSOverride: case FSOverride:
DPRINTF(Predecoder, "Found fs segment override.\n");
break;
case GSOverride: case GSOverride:
DPRINTF(Predecoder, "Found gs segment override.\n");
break;
case SSOverride: case SSOverride:
DPRINTF(Predecoder, "Found ss segment override.\n"); DPRINTF(Predecoder, "Found segment override.\n");
emi.legacy.seg = prefix;
break; break;
case Lock: case Lock:
DPRINTF(Predecoder, "Found lock prefix.\n"); DPRINTF(Predecoder, "Found lock prefix.\n");
emi.legacy.lock = true;
break; break;
case Rep: case Rep:
DPRINTF(Predecoder, "Found rep prefix.\n"); DPRINTF(Predecoder, "Found rep prefix.\n");
emi.legacy.rep = true;
break; break;
case Repne: case Repne:
DPRINTF(Predecoder, "Found repne prefix.\n"); DPRINTF(Predecoder, "Found repne prefix.\n");
emi.legacy.repne = true;
break; break;
case RexPrefix: case RexPrefix:
DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte); DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
@ -198,16 +194,36 @@ namespace X86ISA
displacementCollected = 0; displacementCollected = 0;
emi.displacement = 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 //Figure out how big of an immediate we'll retreive based
//on the opcode. //on the opcode.
int immType = ImmediateType[ int immType = ImmediateType[emi.opcode.num - 1][nextByte];
emi.opcode.num - 1][nextByte]; immediateSize = SizeTypeToSize[emi.opSize - 1][immType];
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];
//Determine what to expect next //Determine what to expect next
if (UsesModRM[emi.opcode.num - 1][nextByte]) { if (UsesModRM[emi.opcode.num - 1][nextByte]) {
@ -351,6 +367,16 @@ namespace X86ISA
if(immediateSize == immediateCollected) 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", DPRINTF(Predecoder, "Collected immediate %#x.\n",
emi.immediate); emi.immediate);
emiIsReady = true; emiIsReady = true;

View file

@ -73,7 +73,7 @@ namespace X86ISA
static const uint8_t Prefixes[256]; static const uint8_t Prefixes[256];
static const uint8_t UsesModRM[2][256]; static const uint8_t UsesModRM[2][256];
static const uint8_t ImmediateType[2][256]; static const uint8_t ImmediateType[2][256];
static const uint8_t ImmediateTypeToSize[3][10]; static const uint8_t SizeTypeToSize[3][10];
protected: protected:
ThreadContext * tc; ThreadContext * tc;

View file

@ -141,7 +141,7 @@ namespace X86ISA
} }
}; };
enum ImmediateTypes { enum SizeType {
NoImm, NoImm,
NI = NoImm, NI = NoImm,
ByteImm, ByteImm,
@ -158,19 +158,19 @@ namespace X86ISA
VW = VWordImm, VW = VWordImm,
ZWordImm, ZWordImm,
ZW = ZWordImm, ZW = ZWordImm,
Pointer,
PO = Pointer,
//The enter instruction takes -2- immediates for a total of 3 bytes //The enter instruction takes -2- immediates for a total of 3 bytes
Enter, 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 // 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, 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, 4, 3, 6 }, //32 bit
{0, 1, 2, 4, 8, 16, 4, 8, 3, 0} //64 bit {0, 1, 2, 4, 8, 16, 4, 8, 3, 0 } //64 bit
}; };
//This table determines the immediate type. The first index is the //This table determines the immediate type. The first index is the

View file

@ -70,25 +70,31 @@ namespace X86ISA
typedef uint64_t MachInst; typedef uint64_t MachInst;
enum Prefixes { enum Prefixes {
NoOverride = 0, NoOverride,
CSOverride = 1, CSOverride,
DSOverride = 2, DSOverride,
ESOverride = 3, ESOverride,
FSOverride = 4, FSOverride,
GSOverride = 5, GSOverride,
SSOverride = 6, SSOverride,
//The Rex prefix obviously doesn't fit in with the above, but putting RexPrefix,
//it here lets us save double the space the enums take up. OperandSizeOverride,
RexPrefix = 7, 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 //There can be only one segment override, so they share the
//first 3 bits in the legacyPrefixes bitfield. //first 3 bits in the legacyPrefixes bitfield.
SegmentOverride = 0x7, Bitfield<2,0> seg;
OperandSizeOverride = 8, EndBitUnion(LegacyPrefixVector)
AddressSizeOverride = 16,
Lock = 32,
Rep = 64,
Repne = 128
};
BitUnion8(ModRM) BitUnion8(ModRM)
Bitfield<7,6> mod; Bitfield<7,6> mod;
@ -118,7 +124,7 @@ namespace X86ISA
struct ExtMachInst struct ExtMachInst
{ {
//Prefixes //Prefixes
uint8_t legacy; LegacyPrefixVector legacy;
Rex rex; Rex rex;
//This holds all of the bytes of the opcode //This holds all of the bytes of the opcode
struct struct
@ -140,6 +146,10 @@ namespace X86ISA
//Immediate fields //Immediate fields
uint64_t immediate; uint64_t immediate;
uint64_t displacement; uint64_t displacement;
//The effective operand size.
uint8_t opSize;
//The
}; };
inline static std::ostream & inline static std::ostream &

View file

@ -78,7 +78,8 @@ namespace __hash_namespace {
((uint64_t)emi.opcode.prefixA << 16) | ((uint64_t)emi.opcode.prefixA << 16) |
((uint64_t)emi.opcode.prefixB << 8) | ((uint64_t)emi.opcode.prefixB << 8) |
((uint64_t)emi.opcode.op)) ^ ((uint64_t)emi.opcode.op)) ^
emi.immediate ^ emi.displacement; emi.immediate ^ emi.displacement ^
emi.opSize;
}; };
}; };
} }