Merge zizzer.eecs.umich.edu:/bk/newmem

into  ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86

--HG--
extra : convert_revision : 2dfc24b0720b3b378858a289e4bb6f4ee7132b3d
This commit is contained in:
Gabe Black 2007-06-19 14:18:46 +00:00
commit 053c715f21
11 changed files with 381 additions and 46 deletions

View file

@ -182,6 +182,33 @@ output decoder {{
ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic);
}
void printSegment(std::ostream &os, int segment)
{
switch (segment)
{
case 0:
ccprintf(os, "ES");
break;
case 1:
ccprintf(os, "CS");
break;
case 2:
ccprintf(os, "SS");
break;
case 3:
ccprintf(os, "DS");
break;
case 4:
ccprintf(os, "FS");
break;
case 5:
ccprintf(os, "GS");
break;
default:
panic("Unrecognized segment %d\n", segment);
}
}
void
X86StaticInst::printSrcReg(std::ostream &os, int reg) const
{

View file

@ -100,3 +100,8 @@ def bitfield SIB_BASE sib.base;
def bitfield OPSIZE opSize;
def bitfield ADDRSIZE addrSize;
def bitfield STACKSIZE stackSize;
def bitfield MODE mode;
def bitfield MODE_MODE mode.mode;
def bitfield MODE_SUBMODE mode.submode;

View file

@ -67,11 +67,11 @@ def macroop MOV_R_M {
};
def macroop MOV_R_I {
limm "env.reg", "env.immediate"
limm "env.reg", "IMMEDIATE"
};
def macroop MOV_M_I {
limm "env.reg", "env.immediate"
limm "env.reg", "IMMEDIATE"
#Do a store to put the register operand into memory
};
'''

View file

@ -55,15 +55,21 @@
microcode = '''
def macroop POP_R {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;"
# There needs to be a load here to actually "pop" the data
ld "env.reg", 2, [0, "NUM_INTREGS", "INTREG_RSP"]
addi "INTREG_RSP", "INTREG_RSP", "env.dataSize"
};
def macroop PUSH_R {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;"
subi "INTREG_RSP", "INTREG_RSP", "env.dataSize"
# There needs to be a store here to actually "push" the data
st "env.reg", 2, [0, "NUM_INTREGS", "INTREG_RSP"]
};
'''
#let {{

View file

@ -61,34 +61,34 @@ def macroop XOR_R_R
def macroop XOR_R_I
{
limm "NUM_INTREGS", "env.immediate"
xor "env.reg", "env.reg", "NUM_INTREGS"
limm "NUM_INTREGS+1", "IMMEDIATE"
xor "env.reg", "env.reg", "NUM_INTREGS+1"
};
def macroop XOR_M_R
{
#Do a load to get one of the sources
xor "NUM_INTREGS", "NUM_INTREGS", "env.reg"
xor "NUM_INTREGS+1", "NUM_INTREGS+1", "env.reg"
#Do a store to write the destination
};
def macroop XOR_R_M
{
#Do a load to get one of the sources
xor "env.reg", "env.reg", "NUM_INTREGS"
xor "env.reg", "env.reg", "NUM_INTREGS+1"
};
def macroop AND_R_I
{
limm "NUM_INTREGS", "env.immediate"
and "env.reg", "env.reg", "NUM_INTREGS"
limm "NUM_INTREGS+1", "IMMEDIATE"
and "env.reg", "env.reg", "NUM_INTREGS+1"
};
def macroop AND_M_I
{
#Do a load to get one of the sources
limm "NUM_INTREGS", "env.immediate"
and "NUM_INTREGS", "NUM_INTREGS", "NUM_INTREGS+1"
limm "NUM_INTREGS+1", "IMMEDIATE"
and "NUM_INTREGS+1", "NUM_INTREGS+1", "NUM_INTREGS+2"
#Do a store to write the destination
};
'''

View file

@ -189,17 +189,18 @@ output header {{
{
X86ISA::RegIndex reg;
X86ISA::RegIndex regm;
uint64_t immediate;
uint64_t displacement;
int addressSize;
uint8_t scale;
X86ISA::RegIndex index;
X86ISA::RegIndex base;
int dataSize;
int addressSize;
int stackSize;
EmulEnv(X86ISA::RegIndex _reg, X86ISA::RegIndex _regm,
uint64_t _immediate, uint64_t _displacement,
int _addressSize, int _dataSize) :
int _dataSize, int _addressSize, int _stackSize) :
reg(_reg), regm(_regm),
immediate(_immediate), displacement(_displacement),
addressSize(_addressSize), dataSize(_dataSize)
dataSize(_dataSize), addressSize(_addressSize),
stackSize(_stackSize)
{;}
};
}};
@ -211,17 +212,15 @@ let {{
self.regUsed = False
self.regm = "0"
self.regmUsed = False
self.immediate = "IMMEDIATE"
self.displacement = "DISPLACEMENT"
self.addressSize = "ADDRSIZE"
self.dataSize = "OPSIZE"
self.stackSize = "STACKSIZE"
def getAllocator(self):
return '''EmulEnv(%(reg)s,
%(regm)s,
%(immediate)s,
%(displacement)s,
%(dataSize)s,
%(addressSize)s,
%(dataSize)s)''' % \
%(stackSize)s)''' % \
self.__dict__
def addReg(self, reg):
if not self.regUsed:

View file

@ -59,8 +59,14 @@
//
//////////////////////////////////////////////////////////////////////////
def template MicroLdStOpDeclare {{
class %(class_name)s : public X86MicroopBase
// Load templates
output header {{
/**
* Base class for load and store ops
*/
class LdStOp : public X86MicroopBase
{
protected:
const uint8_t scale;
@ -71,6 +77,195 @@ def template MicroLdStOpDeclare {{
const RegIndex data;
const uint8_t dataSize;
const uint8_t addressSize;
//Constructor
LdStOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
OpClass __opClass) :
X86MicroopBase(machInst, mnem, _instMnem,
isMicro, isDelayed, isFirst, isLast, __opClass),
scale(_scale), index(_index), base(_base),
disp(_disp), segment(_segment),
data(_data),
dataSize(_dataSize), addressSize(_addressSize)
{}
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string LdStOp::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
printReg(response, data);
response << ", ";
printSegment(response, segment);
ccprintf(response, ":[%d*", scale);
printReg(response, index);
response << " + ";
printReg(response, base);
ccprintf(response, " + %#x]", disp);
return response.str();
}
}};
def template MicroLoadExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
if(fault == NoFault)
{
%(code)s;
}
if(fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
def template MicroLoadInitiateAcc {{
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
return fault;
}
}};
def template MicroLoadCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
%(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
Mem = pkt->get<typeof(Mem)>();
%(code)s;
if(fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
// Store templates
def template MicroStoreExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
%(code)s;
if(fault == NoFault)
{
fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
EA, 0, 0);
}
if(fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
def template MicroStoreInitiateAcc {{
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
%(code)s;
if(fault == NoFault)
{
fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
EA, 0, 0);
}
if(fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
def template MicroStoreCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
return NoFault;
}
}};
// Common templates
//This delcares the initiateAcc function in memory operations
def template InitiateAccDeclare {{
Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
//This declares the completeAcc function in memory operations
def template CompleteAccDeclare {{
Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
def template MicroLdStOpDeclare {{
class %(class_name)s : public %(base_class)s
{
protected:
void buildMe();
public:
@ -90,6 +285,10 @@ def template MicroLdStOpDeclare {{
uint8_t _dataSize, uint8_t _addressSize);
%(BasicExecDeclare)s
%(InitiateAccDeclare)s
%(CompleteAccDeclare)s
};
}};
@ -107,11 +306,10 @@ def template MicroLdStOpConstructor {{
RegIndex _data,
uint8_t _dataSize, uint8_t _addressSize) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
false, false, false, false, %(op_class)s),
scale(_scale), index(_index), base(_base),
disp(_disp), segment(_segment),
data(_data),
dataSize(_dataSize), addressSize(_addressSize)
false, false, false, false,
_scale, _index, _base,
_disp, _segment, _data,
_dataSize, _addressSize, %(op_class)s)
{
buildMe();
}
@ -120,17 +318,106 @@ def template MicroLdStOpConstructor {{
ExtMachInst machInst, const char * instMnem,
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t segment,
RegIndex data,
uint8_t dataSize, uint8_t addressSize) :
uint64_t _disp, uint8_t _segment,
RegIndex _data,
uint8_t _dataSize, uint8_t _addressSize) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
isMicro, isDelayed, isFirst, isLast, %(op_class)s),
scale(_scale), index(_index), base(_base),
disp(_disp), segment(_segment),
data(_data),
dataSize(_dataSize), addressSize(_addressSize)
isMicro, isDelayed, isFirst, isLast,
_scale, _index, _base,
_disp, _segment, _data,
_dataSize, _addressSize, %(op_class)s)
{
buildMe();
}
}};
let {{
class LdStOp(X86Microop):
def __init__(self, data, segment, addr, disp):
self.data = data
[self.scale, self.index, self.base] = addr
self.disp = disp
self.segment = segment
self.dataSize = "env.dataSize"
self.addressSize = "env.addressSize"
def getAllocator(self, *microFlags):
allocator = '''new %(class_name)s(machInst, mnemonic
%(flags)s, %(scale)s, %(index)s, %(base)s,
%(disp)s, %(segment)s, %(data)s,
%(dataSize)s, %(addressSize)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
"scale" : self.scale, "index" : self.index,
"base" : self.base,
"disp" : self.disp,
"segment" : self.segment, "data" : self.data,
"dataSize" : self.dataSize, "addressSize" : self.addressSize}
return allocator
}};
let {{
# Make these empty strings so that concatenating onto
# them will always work.
header_output = ""
decoder_output = ""
exec_output = ""
calculateEA = "EA = scale * Index + Base + disp;"
def defineMicroLoadOp(mnemonic, code):
global header_output
global decoder_output
global exec_output
global microopClasses
Name = mnemonic
name = mnemonic.lower()
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'LdStOp',
{"code": code, "ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLoadExecute.subst(iop)
exec_output += MicroLoadInitiateAcc.subst(iop)
exec_output += MicroLoadCompleteAcc.subst(iop)
class LoadOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0):
super(LoadOp, self).__init__(data, segment, addr, disp)
self.className = Name
self.mnemonic = name
microopClasses[name] = LoadOp
defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
def defineMicroStoreOp(mnemonic, code):
global header_output
global decoder_output
global exec_output
global microopClasses
Name = mnemonic
name = mnemonic.lower()
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'LdStOp',
{"code": code, "ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroStoreExecute.subst(iop)
exec_output += MicroStoreInitiateAcc.subst(iop)
exec_output += MicroStoreCompleteAcc.subst(iop)
class StoreOp(LdStOp):
def __init__(self, data, addr, segment):
super(LoadOp, self).__init__(data, addr, segment)
self.className = Name
self.mnemonic = name
microopClasses[name] = StoreOp
defineMicroLoadOp('St', 'Mem = Data;')
}};

View file

@ -99,7 +99,9 @@ def operands {{
'DestReg': ('IntReg', 'uqw', 'dest', 'IsInteger', 1),
'SrcReg1': ('IntReg', 'uqw', 'src1', 'IsInteger', 2),
'SrcReg2': ('IntReg', 'uqw', 'src2', 'IsInteger', 3),
'IntRegOp0': ('IntReg', 'udw', 'param0', 'IsInteger', 1),
'IntRegOp1': ('IntReg', 'udw', 'param1', 'IsInteger', 2),
'IntRegOp2': ('IntReg', 'udw', 'param2', 'IsInteger', 2),
'Base': ('IntReg', 'uqw', 'base', 'IsInteger', 4),
'Index': ('IntReg', 'uqw', 'index', 'IsInteger', 5),
'Data': ('IntReg', 'uqw', 'data', 'IsInteger', 6),
'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 10),
'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
}};

View file

@ -93,7 +93,7 @@ namespace X86ISA
// semantically meaningful register indices
//There is no such register in X86
const int ZeroReg = 0;
const int ZeroReg = NUM_INTREGS;
const int StackPointerReg = INTREG_RSP;
//X86 doesn't seem to have a link register
const int ReturnAddressReg = 0;

View file

@ -169,6 +169,8 @@ namespace X86ISA
uint8_t opSize;
//The effective address size.
uint8_t addrSize;
//The effective stack size.
uint8_t stackSize;
//Mode information
OperatingMode mode;
@ -193,8 +195,6 @@ namespace X86ISA
inline static bool
operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
{
if(emi1.mode != emi2.mode)
return false;
if(emi1.legacy != emi2.legacy)
return false;
if(emi1.rex != emi2.rex)
@ -215,6 +215,14 @@ namespace X86ISA
return false;
if(emi1.displacement != emi2.displacement)
return false;
if(emi1.mode != emi2.mode)
return false;
if(emi1.opSize != emi2.opSize)
return false;
if(emi1.addrSize != emi2.addrSize)
return false;
if(emi1.stackSize != emi2.stackSize)
return false;
return true;
}

View file

@ -79,7 +79,8 @@ namespace __hash_namespace {
((uint64_t)emi.opcode.prefixB << 8) |
((uint64_t)emi.opcode.op)) ^
emi.immediate ^ emi.displacement ^
emi.mode ^ emi.opSize;
emi.mode ^
emi.opSize ^ emi.addrSize ^ emi.stackSize;
};
};
}