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:
parent
e633e23a3a
commit
75e8838ba4
5 changed files with 85 additions and 48 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 &
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue