Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86 --HG-- extra : convert_revision : 8e624bb95cb9f478ca7ac1dbbd64e20674e3e224
This commit is contained in:
commit
a3ed19f82a
11 changed files with 167 additions and 148 deletions
|
@ -79,6 +79,13 @@ output header {{
|
||||||
void printReg(std::ostream &os, int reg) const;
|
void printReg(std::ostream &os, int reg) const;
|
||||||
void printSrcReg(std::ostream &os, int reg) const;
|
void printSrcReg(std::ostream &os, int reg) const;
|
||||||
void printDestReg(std::ostream &os, int reg) const;
|
void printDestReg(std::ostream &os, int reg) const;
|
||||||
|
|
||||||
|
inline uint64_t merge(uint64_t into, uint64_t val, int size) const
|
||||||
|
{
|
||||||
|
//FIXME This needs to be significantly more sophisticated
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
|
@ -95,9 +95,6 @@
|
||||||
//malfunction of the decode mechanism.
|
//malfunction of the decode mechanism.
|
||||||
##include "error.isa"
|
##include "error.isa"
|
||||||
|
|
||||||
//Include code to build up macro op instructions
|
|
||||||
##include "macroop.isa"
|
|
||||||
|
|
||||||
//Include a format which implements a batch of instructions which do the same
|
//Include a format which implements a batch of instructions which do the same
|
||||||
//thing on a variety of inputs
|
//thing on a variety of inputs
|
||||||
##include "multi.isa"
|
##include "multi.isa"
|
||||||
|
|
|
@ -55,16 +55,20 @@
|
||||||
//
|
//
|
||||||
// Authors: Gabe Black
|
// Authors: Gabe Black
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
// Execute method for macroops.
|
||||||
//
|
def template MacroExecPanic {{
|
||||||
// Instructions that do the same thing to multiple sets of arguments.
|
Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
|
||||||
//
|
{
|
||||||
|
panic("Tried to execute macroop directly!");
|
||||||
|
M5_DUMMY_RETURN
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
output header {{
|
output header {{
|
||||||
|
|
||||||
// Base class for most macroops, except ones that need to commit as
|
// Base class for most macroops, except ones that need to commit as
|
||||||
// they go.
|
// they go.
|
||||||
class X86MacroInst : public X86StaticInst
|
class X86MacroInst : public StaticInst
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
const uint32_t numMicroOps;
|
const uint32_t numMicroOps;
|
||||||
|
@ -72,7 +76,7 @@ output header {{
|
||||||
//Constructor.
|
//Constructor.
|
||||||
X86MacroInst(const char *mnem, ExtMachInst _machInst,
|
X86MacroInst(const char *mnem, ExtMachInst _machInst,
|
||||||
uint32_t _numMicroOps)
|
uint32_t _numMicroOps)
|
||||||
: X86StaticInst(mnem, _machInst, No_OpClass),
|
: StaticInst(mnem, _machInst, No_OpClass),
|
||||||
numMicroOps(_numMicroOps)
|
numMicroOps(_numMicroOps)
|
||||||
{
|
{
|
||||||
assert(numMicroOps);
|
assert(numMicroOps);
|
||||||
|
@ -85,9 +89,6 @@ output header {{
|
||||||
delete [] microOps;
|
delete [] microOps;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string generateDisassembly(Addr pc,
|
|
||||||
const SymbolTable *symtab) const;
|
|
||||||
|
|
||||||
StaticInstPtr * microOps;
|
StaticInstPtr * microOps;
|
||||||
|
|
||||||
StaticInstPtr fetchMicroOp(MicroPC microPC)
|
StaticInstPtr fetchMicroOp(MicroPC microPC)
|
||||||
|
@ -96,21 +97,7 @@ output header {{
|
||||||
return microOps[microPC];
|
return microOps[microPC];
|
||||||
}
|
}
|
||||||
|
|
||||||
%(BasicExecPanic)s
|
%(MacroExecPanic)s
|
||||||
};
|
|
||||||
|
|
||||||
// Base class for macroops which commit as they go. This is for
|
|
||||||
// instructions which can be partially completed like those with the
|
|
||||||
// rep prefix. This prevents those instructions from overflowing
|
|
||||||
// buffers with uncommitted microops.
|
|
||||||
class X86RollingMacroInst : public X86MacroInst
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
//Constructor.
|
|
||||||
X86RollingMacroInst(const char *mnem, ExtMachInst _machInst,
|
|
||||||
uint32_t _numMicroOps)
|
|
||||||
: X86MacroInst(mnem, _machInst, numMicroOps)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
@ -121,34 +108,24 @@ def template MacroConstructor {{
|
||||||
{
|
{
|
||||||
%(constructor)s;
|
%(constructor)s;
|
||||||
//alloc_micro_ops is the code that sets up the microOps
|
//alloc_micro_ops is the code that sets up the microOps
|
||||||
//array in the parent class. This hook will hopefully
|
//array in the parent class.
|
||||||
//allow all that to be automated.
|
|
||||||
%(alloc_micro_ops)s;
|
%(alloc_micro_ops)s;
|
||||||
setMicroFlags();
|
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
def genMacroOp(name, Name, ops, rolling = False):
|
def genMacroOp(name, Name, opSeq):
|
||||||
baseClass = 'X86MacroInst'
|
baseClass = 'X86MacroInst'
|
||||||
if rolling:
|
numMicroOps = len(opSeq.ops)
|
||||||
baseClass = 'X86RollingMacroInst'
|
|
||||||
numMicroOps = len(ops)
|
|
||||||
allocMicroOps = ''
|
allocMicroOps = ''
|
||||||
micropc = 0
|
micropc = 0
|
||||||
allocMicroOps += \
|
for op in opSeq.ops:
|
||||||
"microOps[0] = %s;\n" % \
|
allocMicroOps += \
|
||||||
op.getAllocator(True, not rolling, True, False)
|
"microOps[%d] = %s;\n" % \
|
||||||
micropc += 1
|
(micropc, op.getAllocator(True, op.delayed,
|
||||||
if numMicroOps > 2:
|
micropc == 0,
|
||||||
for op in ops[1:-1]:
|
micropc == numMicroOps - 1))
|
||||||
allocMicroOps += \
|
micropc += 1
|
||||||
"microOps[%d] = %s;\n" % \
|
|
||||||
(micropc, op.getAllocator(True, not rolling, False, False))
|
|
||||||
micropc += 1
|
|
||||||
allocMicroOps += \
|
|
||||||
"microOps[%d] = %s;\n" % \
|
|
||||||
op.getAllocator(True, not rolling, False, True)
|
|
||||||
iop = InstObjParams(name, Name, baseClass,
|
iop = InstObjParams(name, Name, baseClass,
|
||||||
{'code' : '', 'num_micro_ops' : numMicroOps,
|
{'code' : '', 'num_micro_ops' : numMicroOps,
|
||||||
'alloc_micro_ops' : allocMicroOps})
|
'alloc_micro_ops' : allocMicroOps})
|
|
@ -72,26 +72,34 @@
|
||||||
|
|
||||||
namespace X86ISA;
|
namespace X86ISA;
|
||||||
|
|
||||||
//Include the simple microcode assembler
|
//Include the simple microcode assembler. This will hopefully stay
|
||||||
|
//unspecialized for x86 and can later be made available to other ISAs.
|
||||||
##include "microasm.isa"
|
##include "microasm.isa"
|
||||||
|
|
||||||
//Include the bitfield definitions
|
//Include code to build macroops.
|
||||||
##include "bitfields.isa"
|
##include "macroop.isa"
|
||||||
|
|
||||||
//Include the operand_types and operand definitions
|
|
||||||
##include "operands.isa"
|
|
||||||
|
|
||||||
//Include the base class for x86 instructions, and some support code
|
//Include the base class for x86 instructions, and some support code
|
||||||
|
//Code in this file should be general and useful everywhere
|
||||||
##include "base.isa"
|
##include "base.isa"
|
||||||
|
|
||||||
//Include the instruction definitions
|
|
||||||
##include "insts/insts.isa"
|
|
||||||
|
|
||||||
//Include the definitions for the instruction formats
|
//Include the definitions for the instruction formats
|
||||||
##include "formats/formats.isa"
|
##include "formats/formats.isa"
|
||||||
|
|
||||||
//Include the definitions of the micro ops
|
//Include the operand_types and operand definitions. These are needed by
|
||||||
|
//the microop definitions.
|
||||||
|
##include "operands.isa"
|
||||||
|
|
||||||
|
//Include the definitions of the micro ops.
|
||||||
|
//These are StaticInst classes which stand on their own and make up an
|
||||||
|
//internal instruction set.
|
||||||
##include "microops/microops.isa"
|
##include "microops/microops.isa"
|
||||||
|
|
||||||
|
//Include the instruction definitions which are microop assembler programs.
|
||||||
|
##include "insts/insts.isa"
|
||||||
|
|
||||||
|
//Include the bitfield definitions
|
||||||
|
##include "bitfields.isa"
|
||||||
|
|
||||||
//Include the decoder definition
|
//Include the decoder definition
|
||||||
##include "decoder/decoder.isa"
|
##include "decoder/decoder.isa"
|
||||||
|
|
|
@ -61,23 +61,6 @@
|
||||||
// variety of operands
|
// variety of operands
|
||||||
//
|
//
|
||||||
|
|
||||||
let {{
|
|
||||||
# This builds either a regular or macro op to implement the sequence of
|
|
||||||
# ops we give it.
|
|
||||||
def genInst(name, Name, ops):
|
|
||||||
# If we can implement this instruction with exactly one microop, just
|
|
||||||
# use that directly.
|
|
||||||
newStmnt = ''
|
|
||||||
if len(ops) == 1:
|
|
||||||
decode_block = "return (X86StaticInst *)(%s);" % \
|
|
||||||
ops[0].getAllocator()
|
|
||||||
return ('', '', decode_block, '')
|
|
||||||
else:
|
|
||||||
# Build a macroop to contain the sequence of microops we've
|
|
||||||
# been given.
|
|
||||||
return genMacroOp(name, Name, ops)
|
|
||||||
}};
|
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
# This code builds up a decode block which decodes based on switchval.
|
# This code builds up a decode block which decodes based on switchval.
|
||||||
# vals is a dict which matches case values with what should be decoded to.
|
# vals is a dict which matches case values with what should be decoded to.
|
||||||
|
@ -187,14 +170,8 @@ let {{
|
||||||
|
|
||||||
# At this point, we've built up "code" to have all the necessary extra
|
# At this point, we've built up "code" to have all the necessary extra
|
||||||
# instructions needed to implement whatever types of operands were
|
# instructions needed to implement whatever types of operands were
|
||||||
# specified. Now we'll assemble it it into a microOp sequence.
|
# specified. Now we'll assemble it it into a StaticInst.
|
||||||
ops = assembleMicro(code)
|
return assembleMicro(name, Name, code)
|
||||||
|
|
||||||
# Build a macroop to contain the sequence of microops we've
|
|
||||||
# constructed. The decode block will be used to fill in our
|
|
||||||
# inner decode structure, and the rest will be concatenated and
|
|
||||||
# passed back.
|
|
||||||
return genInst(name, Name, ops)
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -202,6 +179,13 @@ let {{
|
||||||
// The microcode assembler
|
// The microcode assembler
|
||||||
//
|
//
|
||||||
|
|
||||||
|
let {{
|
||||||
|
# These are used when setting up microops so that they can specialize their
|
||||||
|
# base class template properly.
|
||||||
|
RegOpType = "RegisterOperand"
|
||||||
|
ImmOpType = "ImmediateOperand"
|
||||||
|
}};
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
class MicroOpStatement(object):
|
class MicroOpStatement(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -242,19 +226,9 @@ let {{
|
||||||
return 'new %s%s(machInst%s%s)' % (self.className, signature, self.microFlagsText(microFlags), args)
|
return 'new %s%s(machInst%s%s)' % (self.className, signature, self.microFlagsText(microFlags), args)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
let {{
|
|
||||||
def buildLabelDict(ops):
|
|
||||||
labels = {}
|
|
||||||
micropc = 0
|
|
||||||
for op in ops:
|
|
||||||
if op.label:
|
|
||||||
labels[op.label] = count
|
|
||||||
micropc += 1
|
|
||||||
return labels
|
|
||||||
}};
|
|
||||||
|
|
||||||
let{{
|
let{{
|
||||||
def assembleMicro(code):
|
def assembleMicro(name, Name, code):
|
||||||
|
|
||||||
# This function takes in a block of microcode assembly and returns
|
# This function takes in a block of microcode assembly and returns
|
||||||
# a python list of objects which describe it.
|
# a python list of objects which describe it.
|
||||||
|
|
||||||
|
@ -341,7 +315,13 @@ let{{
|
||||||
lineMatch = lineRe.search(code)
|
lineMatch = lineRe.search(code)
|
||||||
|
|
||||||
# Decode the labels into displacements
|
# Decode the labels into displacements
|
||||||
labels = buildLabelDict(statements)
|
|
||||||
|
labels = {}
|
||||||
|
micropc = 0
|
||||||
|
for statement in statements:
|
||||||
|
if statement.label:
|
||||||
|
labels[statement.label] = count
|
||||||
|
micropc += 1
|
||||||
micropc = 0
|
micropc = 0
|
||||||
for statement in statements:
|
for statement in statements:
|
||||||
for arg in statement.args:
|
for arg in statement.args:
|
||||||
|
@ -353,5 +333,15 @@ let{{
|
||||||
# micropc + 1 + displacement.
|
# micropc + 1 + displacement.
|
||||||
arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
|
arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
|
||||||
micropc += 1
|
micropc += 1
|
||||||
return statements
|
|
||||||
|
# If we can implement this instruction with exactly one microop, just
|
||||||
|
# use that directly.
|
||||||
|
if len(statements) == 1:
|
||||||
|
decode_block = "return %s;" % \
|
||||||
|
statements[0].getAllocator()
|
||||||
|
return ('', '', decode_block, '')
|
||||||
|
else:
|
||||||
|
# Build a macroop to contain the sequence of microops we've
|
||||||
|
# been given.
|
||||||
|
return genMacroOp(name, Name, statements)
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -63,12 +63,15 @@ output header {{
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//A class which is the base of all x86 micro ops it provides a function to
|
//A class which is the base of all x86 micro ops. It provides a function to
|
||||||
//set necessary flags appropriately.
|
//set necessary flags appropriately.
|
||||||
output header {{
|
output header {{
|
||||||
class X86MicroOpBase : public X86StaticInst
|
class X86MicroOpBase : public X86StaticInst
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
uint8_t opSize;
|
||||||
|
uint8_t addrSize;
|
||||||
|
|
||||||
X86MicroOpBase(bool isMicro, bool isDelayed,
|
X86MicroOpBase(bool isMicro, bool isDelayed,
|
||||||
bool isFirst, bool isLast,
|
bool isFirst, bool isLast,
|
||||||
const char *mnem, ExtMachInst _machInst,
|
const char *mnem, ExtMachInst _machInst,
|
||||||
|
@ -94,6 +97,7 @@ def template BaseMicroOpTemplateDeclare {{
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
def buildBaseMicroOpTemplate(Name, numParams):
|
def buildBaseMicroOpTemplate(Name, numParams):
|
||||||
|
assert(numParams > 0)
|
||||||
signature = "<"
|
signature = "<"
|
||||||
signature += "int SignatureOperandTypeSpecifier0"
|
signature += "int SignatureOperandTypeSpecifier0"
|
||||||
for count in xrange(1,numParams):
|
for count in xrange(1,numParams):
|
||||||
|
@ -102,10 +106,9 @@ let {{
|
||||||
signature += ">"
|
signature += ">"
|
||||||
subs = {"signature" : signature, "class_name" : Name}
|
subs = {"signature" : signature, "class_name" : Name}
|
||||||
return BaseMicroOpTemplateDeclare.subst(subs)
|
return BaseMicroOpTemplateDeclare.subst(subs)
|
||||||
|
}};
|
||||||
|
|
||||||
RegOpType = "RegisterOperand"
|
let {{
|
||||||
ImmOpType = "ImmediateOperand"
|
|
||||||
|
|
||||||
def buildMicroOpTemplateDict(*params):
|
def buildMicroOpTemplateDict(*params):
|
||||||
signature = "<"
|
signature = "<"
|
||||||
if len(params):
|
if len(params):
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 &
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue