Merge vm1.(none):/home/stever/bk/newmem-head
into vm1.(none):/home/stever/bk/newmem-cache2 --HG-- extra : convert_revision : 9002940097a166c8442ae1adf41b974227968920
This commit is contained in:
@@ -277,9 +277,10 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
|
||||
if strip:
|
||||
stripped_bin = bin + '.stripped'
|
||||
if sys.platform == 'sunos5':
|
||||
newEnv.Command(stripped_bin, bin, 'cp $SOURCE $TARGET; strip $TARGET')
|
||||
cmd = 'cp $SOURCE $TARGET; strip $TARGET'
|
||||
else:
|
||||
newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET')
|
||||
cmd = 'strip $SOURCE -o $TARGET'
|
||||
newEnv.Command(stripped_bin, bin, cmd)
|
||||
bin = stripped_bin
|
||||
targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
|
||||
newEnv.M5Binary = targets[0]
|
||||
|
||||
@@ -44,8 +44,6 @@ namespace AlphaISA
|
||||
{
|
||||
protected:
|
||||
ThreadContext * tc;
|
||||
//The pc of the current instruction
|
||||
Addr fetchPC;
|
||||
//The extended machine instruction being generated
|
||||
ExtMachInst ext_inst;
|
||||
|
||||
@@ -69,10 +67,8 @@ namespace AlphaISA
|
||||
|
||||
//Use this to give data to the predecoder. This should be used
|
||||
//when there is control flow.
|
||||
void moreBytes(Addr pc, Addr _fetchPC, Addr off, MachInst inst)
|
||||
void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
|
||||
{
|
||||
fetchPC = _fetchPC;
|
||||
assert(off == 0);
|
||||
ext_inst = inst;
|
||||
#if FULL_SYSTEM
|
||||
if (pc && 0x1)
|
||||
|
||||
@@ -131,7 +131,8 @@ def handle_statement(parser, container, statement):
|
||||
microop = eval('parser.microops[statement.mnemonic](%s)' %
|
||||
statement.params)
|
||||
except:
|
||||
print_error("Error creating microop object.")
|
||||
print_error("Error creating microop object with mnemonic %s." % \
|
||||
statement.mnemonic)
|
||||
raise
|
||||
try:
|
||||
for label in statement.labels:
|
||||
@@ -237,9 +238,7 @@ def t_params_PARAMS(t):
|
||||
unescapeParamsRE = re.compile(r'(\\[\n;\\])')
|
||||
def unescapeParams(mo):
|
||||
val = mo.group(0)
|
||||
print "About to sub %s for %s" % (val[1], val)
|
||||
return val[1]
|
||||
print "Looking for matches in %s" % t.value
|
||||
t.value = unescapeParamsRE.sub(unescapeParams, t.value)
|
||||
t.lexer.begin('asm')
|
||||
return t
|
||||
@@ -482,9 +481,9 @@ class MicroAssembler(object):
|
||||
def assemble(self, asm):
|
||||
self.parser.parse(asm, lexer=self.lexer)
|
||||
# Begin debug printing
|
||||
for macroop in self.parser.macroops.values():
|
||||
print macroop
|
||||
print self.parser.rom
|
||||
#for macroop in self.parser.macroops.values():
|
||||
# print macroop
|
||||
#print self.parser.rom
|
||||
# End debug printing
|
||||
macroops = self.parser.macroops
|
||||
self.parser.macroops = {}
|
||||
|
||||
@@ -66,9 +66,8 @@ namespace MipsISA
|
||||
|
||||
//Use this to give data to the predecoder. This should be used
|
||||
//when there is control flow.
|
||||
void moreBytes(Addr pc, Addr fetchPC, Addr off, MachInst inst)
|
||||
void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
|
||||
{
|
||||
assert(off == 0);
|
||||
emi = inst;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,10 +67,8 @@ namespace SparcISA
|
||||
|
||||
//Use this to give data to the predecoder. This should be used
|
||||
//when there is control flow.
|
||||
void moreBytes(Addr pc, Addr fetchPC, Addr off, MachInst inst)
|
||||
void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
|
||||
{
|
||||
assert(off == 0);
|
||||
|
||||
emi = inst;
|
||||
//The I bit, bit 13, is used to figure out where the ASI
|
||||
//should come from. Use that in the ExtMachInst. This is
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
|
||||
Import('*')
|
||||
if env['TARGET_ISA'] == 'x86':
|
||||
Source('emulenv.cc')
|
||||
Source('floatregfile.cc')
|
||||
Source('intregfile.cc')
|
||||
Source('miscregfile.cc')
|
||||
|
||||
92
src/arch/x86/emulenv.cc
Normal file
92
src/arch/x86/emulenv.cc
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2007 The Hewlett-Packard Development Company
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use of this software in source and binary forms,
|
||||
* with or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* The software must be used only for Non-Commercial Use which means any
|
||||
* use which is NOT directed to receiving any direct monetary
|
||||
* compensation for, or commercial advantage from such use. Illustrative
|
||||
* examples of non-commercial use are academic research, personal study,
|
||||
* teaching, education and corporate research & development.
|
||||
* Illustrative examples of commercial use are distributing products for
|
||||
* commercial advantage and providing services using the software for
|
||||
* commercial advantage.
|
||||
*
|
||||
* If you wish to use this software or functionality therein that may be
|
||||
* covered by patents for commercial use, please contact:
|
||||
* Director of Intellectual Property Licensing
|
||||
* Office of Strategy and Technology
|
||||
* Hewlett-Packard Company
|
||||
* 1501 Page Mill Road
|
||||
* Palo Alto, California 94304
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. Redistributions
|
||||
* in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution. Neither the name of
|
||||
* the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission. No right of
|
||||
* sublicense is granted herewith. Derivatives of the software and
|
||||
* output created using the software may be prepared, but only for
|
||||
* Non-Commercial Uses. Derivatives of the software may be shared with
|
||||
* others provided: (i) the others agree to abide by the list of
|
||||
* conditions herein which includes the Non-Commercial Use restrictions;
|
||||
* and (ii) such Derivatives of the software include the above copyright
|
||||
* notice to acknowledge the contribution from this software where
|
||||
* applicable, this list of conditions and the disclaimer below.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include "arch/x86/emulenv.hh"
|
||||
#include "base/misc.hh"
|
||||
|
||||
using namespace X86ISA;
|
||||
|
||||
void EmulEnv::doModRM(const ExtMachInst & machInst)
|
||||
{
|
||||
assert(machInst.modRM.mod != 3);
|
||||
//Use the SIB byte for addressing if the modrm byte calls for it.
|
||||
if (machInst.modRM.rm == 4 && machInst.addrSize != 2) {
|
||||
scale = 1 << machInst.sib.scale;
|
||||
index = machInst.sib.index;
|
||||
base = machInst.sib.base;
|
||||
//In this special case, we don't use a base. The displacement also
|
||||
//changes, but that's managed by the predecoder.
|
||||
if (machInst.sib.base == INTREG_RBP && machInst.modRM.mod == 0)
|
||||
base = NUM_INTREGS;
|
||||
//In -this- special case, we don't use an index.
|
||||
if (machInst.sib.index == INTREG_RSP)
|
||||
index = NUM_INTREGS;
|
||||
} else {
|
||||
if (machInst.addrSize == 2) {
|
||||
warn("I'm not really using 16 bit MODRM like I'm supposed to!\n");
|
||||
} else {
|
||||
scale = 0;
|
||||
base = machInst.modRM.rm;
|
||||
if (machInst.modRM.mod == 0 && machInst.modRM.rm == 5) {
|
||||
base = NUM_INTREGS;
|
||||
if (machInst.mode.submode == SixtyFourBitMode)
|
||||
base = NUM_INTREGS+7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
90
src/arch/x86/emulenv.hh
Normal file
90
src/arch/x86/emulenv.hh
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2007 The Hewlett-Packard Development Company
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use of this software in source and binary forms,
|
||||
* with or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* The software must be used only for Non-Commercial Use which means any
|
||||
* use which is NOT directed to receiving any direct monetary
|
||||
* compensation for, or commercial advantage from such use. Illustrative
|
||||
* examples of non-commercial use are academic research, personal study,
|
||||
* teaching, education and corporate research & development.
|
||||
* Illustrative examples of commercial use are distributing products for
|
||||
* commercial advantage and providing services using the software for
|
||||
* commercial advantage.
|
||||
*
|
||||
* If you wish to use this software or functionality therein that may be
|
||||
* covered by patents for commercial use, please contact:
|
||||
* Director of Intellectual Property Licensing
|
||||
* Office of Strategy and Technology
|
||||
* Hewlett-Packard Company
|
||||
* 1501 Page Mill Road
|
||||
* Palo Alto, California 94304
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. Redistributions
|
||||
* in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution. Neither the name of
|
||||
* the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission. No right of
|
||||
* sublicense is granted herewith. Derivatives of the software and
|
||||
* output created using the software may be prepared, but only for
|
||||
* Non-Commercial Uses. Derivatives of the software may be shared with
|
||||
* others provided: (i) the others agree to abide by the list of
|
||||
* conditions herein which includes the Non-Commercial Use restrictions;
|
||||
* and (ii) such Derivatives of the software include the above copyright
|
||||
* notice to acknowledge the contribution from this software where
|
||||
* applicable, this list of conditions and the disclaimer below.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_X86_EMULENV_HH__
|
||||
#define __ARCH_X86_EMULENV_HH__
|
||||
|
||||
#include "arch/x86/types.hh"
|
||||
#include "arch/x86/intregs.hh"
|
||||
|
||||
namespace X86ISA
|
||||
{
|
||||
struct EmulEnv
|
||||
{
|
||||
RegIndex reg;
|
||||
RegIndex regm;
|
||||
uint8_t scale;
|
||||
RegIndex index;
|
||||
RegIndex base;
|
||||
int dataSize;
|
||||
int addressSize;
|
||||
int stackSize;
|
||||
|
||||
EmulEnv(RegIndex _reg, RegIndex _regm,
|
||||
int _dataSize, int _addressSize, int _stackSize) :
|
||||
reg(_reg), regm(_regm),
|
||||
scale(0), index(NUM_INTREGS),
|
||||
base(NUM_INTREGS),
|
||||
dataSize(_dataSize), addressSize(_addressSize),
|
||||
stackSize(_stackSize)
|
||||
{;}
|
||||
|
||||
void doModRM(const ExtMachInst & machInst);
|
||||
};
|
||||
};
|
||||
|
||||
#endif // __ARCH_X86_TYPES_HH__
|
||||
@@ -95,6 +95,14 @@ output header {{
|
||||
/**
|
||||
* Base class for all X86 static instructions.
|
||||
*/
|
||||
BitUnion64(X86IntReg)
|
||||
Bitfield<63,0> R;
|
||||
Bitfield<31,0> E;
|
||||
Bitfield<15,0> X;
|
||||
Bitfield<15,8> H;
|
||||
Bitfield<7, 0> L;
|
||||
EndBitUnion(X86IntReg)
|
||||
|
||||
class X86StaticInst : public StaticInst
|
||||
{
|
||||
protected:
|
||||
@@ -114,10 +122,50 @@ output header {{
|
||||
|
||||
inline uint64_t merge(uint64_t into, uint64_t val, int size) const
|
||||
{
|
||||
//FIXME This needs to be significantly more sophisticated
|
||||
X86IntReg reg;
|
||||
reg = into;
|
||||
//FIXME This needs to be handle high bytes as well
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
reg.L = val;
|
||||
break;
|
||||
case 2:
|
||||
reg.X = val;
|
||||
break;
|
||||
case 4:
|
||||
//XXX Check if this should be zeroed or sign extended
|
||||
reg = 0;
|
||||
reg.E = val;
|
||||
break;
|
||||
case 8:
|
||||
reg.R = val;
|
||||
break;
|
||||
default:
|
||||
panic("Tried to merge with unrecognized size %d.\n", size);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
inline uint64_t pick(uint64_t from, int size)
|
||||
{
|
||||
X86IntReg reg;
|
||||
reg = from;
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
return reg.L;
|
||||
case 2:
|
||||
return reg.E;
|
||||
case 4:
|
||||
return reg.X;
|
||||
case 8:
|
||||
return reg.R;
|
||||
default:
|
||||
panic("Tried to pick with unrecognized size %d.\n", size);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}};
|
||||
|
||||
@@ -128,6 +176,39 @@ output decoder {{
|
||||
ccprintf(os, "\t%s ", mnemonic);
|
||||
}
|
||||
|
||||
inline void printMnemonic(std::ostream &os,
|
||||
const char * instMnemonic, const char * mnemonic)
|
||||
{
|
||||
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
|
||||
{
|
||||
@@ -197,6 +278,8 @@ output decoder {{
|
||||
case INTREG_R15W:
|
||||
ccprintf(os, "r15");
|
||||
break;
|
||||
default:
|
||||
ccprintf(os, "t%d", reg - NUM_INTREGS);
|
||||
}
|
||||
} else if (reg < Ctrl_Base_DepTag) {
|
||||
ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -63,8 +63,14 @@
|
||||
0x00: decode OPCODE_OP_BOTTOM3 {
|
||||
0x4: ADD();
|
||||
0x5: ADD();
|
||||
0x6: push_ES();
|
||||
0x7: pop_ES();
|
||||
0x6: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: push_ES();
|
||||
}
|
||||
0x7: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: pop_ES();
|
||||
}
|
||||
default: ADD();
|
||||
}
|
||||
0x01: decode OPCODE_OP_BOTTOM3 {
|
||||
@@ -74,7 +80,10 @@
|
||||
0x3: or_Gv_Ev();
|
||||
0x4: or_Al_Ib();
|
||||
0x5: or_rAX_Iz();
|
||||
0x6: push_CS();
|
||||
0x6: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: push_CS();
|
||||
}
|
||||
//Any time this is seen, it should generate a two byte opcode
|
||||
0x7: M5InternalError::error(
|
||||
{{"Saw a one byte opcode whose value was 0x0F!"}});
|
||||
@@ -86,8 +95,14 @@
|
||||
0x3: adc_Gv_Ev();
|
||||
0x4: adc_Al_Ib();
|
||||
0x5: adc_rAX_Iz();
|
||||
0x6: push_SS();
|
||||
0x7: pop_SS();
|
||||
0x6: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: push_SS();
|
||||
}
|
||||
0x7: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: pop_SS();
|
||||
}
|
||||
}
|
||||
0x03: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: sbb_Eb_Gb();
|
||||
@@ -96,8 +111,14 @@
|
||||
0x3: sbb_Gv_Ev();
|
||||
0x4: sbb_Al_Ib();
|
||||
0x5: sbb_rAX_Iz();
|
||||
0x6: push_DS();
|
||||
0x7: pop_DS();
|
||||
0x6: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: push_DS();
|
||||
}
|
||||
0x7: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: pop_DS();
|
||||
}
|
||||
}
|
||||
0x04: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: and_Eb_Gb();
|
||||
@@ -108,7 +129,10 @@
|
||||
0x5: and_rAX_Iz();
|
||||
0x6: M5InternalError::error(
|
||||
{{"Tried to execute the ES segment override prefix!"}});
|
||||
0x7: daa();
|
||||
0x7: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: daa();
|
||||
}
|
||||
}
|
||||
0x05: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: sub_Eb_Gb();
|
||||
@@ -126,7 +150,10 @@
|
||||
0x5: Inst::XOR(rAx,Iz);
|
||||
0x6: M5InternalError::error(
|
||||
{{"Tried to execute the SS segment override prefix!"}});
|
||||
0x7: aaa();
|
||||
0x7: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: aaa();
|
||||
}
|
||||
default: MultiInst::XOR(OPCODE_OP_BOTTOM3,
|
||||
[Eb,Gb], [Ev,Gv],
|
||||
[Gb,Eb], [Gv,Ev]);
|
||||
@@ -140,53 +167,78 @@
|
||||
0x5: cmp_rAX_Iz();
|
||||
0x6: M5InternalError::error(
|
||||
{{"Tried to execute the DS segment override prefix!"}});
|
||||
0x7: aas();
|
||||
0x7: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: aas();
|
||||
}
|
||||
}
|
||||
0x08: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: inc_eAX();
|
||||
0x1: inc_eCX();
|
||||
0x2: inc_eDX();
|
||||
0x3: inc_eBX();
|
||||
0x4: inc_eSP();
|
||||
0x5: inc_eBP();
|
||||
0x6: inc_eSI();
|
||||
0x7: inc_eDI();
|
||||
0x08: decode MODE_SUBMODE {
|
||||
0x0: M5InternalError::error (
|
||||
{{"Tried to execute an REX prefix!"}});
|
||||
default: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: inc_eAX();
|
||||
0x1: inc_eCX();
|
||||
0x2: inc_eDX();
|
||||
0x3: inc_eBX();
|
||||
0x4: inc_eSP();
|
||||
0x5: inc_eBP();
|
||||
0x6: inc_eSI();
|
||||
0x7: inc_eDI();
|
||||
}
|
||||
}
|
||||
0x09: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: dec_eAX();
|
||||
0x1: dec_eCX();
|
||||
0x2: dec_eDX();
|
||||
0x3: dec_eBX();
|
||||
0x4: dec_eSP();
|
||||
0x5: dec_eBP();
|
||||
0x6: dec_eSI();
|
||||
0x7: dec_eDI();
|
||||
0x09: decode MODE_SUBMODE {
|
||||
0x0: M5InternalError::error (
|
||||
{{"Tried to execute an REX prefix!"}});
|
||||
default: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: dec_eAX();
|
||||
0x1: dec_eCX();
|
||||
0x2: dec_eDX();
|
||||
0x3: dec_eBX();
|
||||
0x4: dec_eSP();
|
||||
0x5: dec_eBP();
|
||||
0x6: dec_eSI();
|
||||
0x7: dec_eDI();
|
||||
}
|
||||
}
|
||||
0x0A: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: Inst::PUSH(rAx);
|
||||
0x1: push_rCX();
|
||||
0x2: push_rDX();
|
||||
0x3: push_rBX();
|
||||
0x4: Inst::PUSH(rSP);
|
||||
0x5: push_rBP();
|
||||
0x6: push_rSI();
|
||||
0x7: push_rDI();
|
||||
}
|
||||
0x0B: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: pop_rAX();
|
||||
0x1: pop_rCX();
|
||||
0x2: pop_rDX();
|
||||
0x3: pop_rBX();
|
||||
0x4: pop_rSP();
|
||||
0x5: pop_rBP();
|
||||
0x6: Inst::POP(rSI);
|
||||
0x7: pop_rDI();
|
||||
format Inst {
|
||||
0x0A: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: PUSH(rAx);
|
||||
0x1: PUSH(rCx);
|
||||
0x2: PUSH(rDx);
|
||||
0x3: PUSH(rBx);
|
||||
0x4: PUSH(rSP);
|
||||
0x5: PUSH(rBP);
|
||||
0x6: PUSH(rSI);
|
||||
0x7: PUSH(rDI);
|
||||
}
|
||||
0x0B: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: POP(rAx);
|
||||
0x1: POP(rCx);
|
||||
0x2: POP(rDx);
|
||||
0x3: POP(rBx);
|
||||
0x4: POP(rSP);
|
||||
0x5: POP(rBP);
|
||||
0x6: POP(rSI);
|
||||
0x7: POP(rDI);
|
||||
}
|
||||
}
|
||||
0x0C: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: pusha();
|
||||
0x1: popa();
|
||||
0x2: bound_Gv_Ma();
|
||||
0x3: arpl_Ew_Gw();
|
||||
0x0: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: pusha();
|
||||
}
|
||||
0x1: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: popa();
|
||||
}
|
||||
0x2: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: bound_Gv_Ma();
|
||||
}
|
||||
0x3: decode MODE_SUBMODE {
|
||||
0x0: Inst::MOVSXD(Gv,Ed);
|
||||
default: arpl_Ew_Gw();
|
||||
}
|
||||
0x4: M5InternalError::error(
|
||||
{{"Tried to execute the FS segment override prefix!"}});
|
||||
0x5: M5InternalError::error(
|
||||
@@ -228,8 +280,21 @@
|
||||
}
|
||||
0x10: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: group1_Eb_Ib();
|
||||
0x1: group1_Ev_Iz();
|
||||
0x2: group1_Eb_Ib();
|
||||
//0x1: group1_Ev_Iz();
|
||||
0x1: decode MODRM_REG {
|
||||
0x0: add_Ev_Iz();
|
||||
0x1: or_Ev_Ibz();
|
||||
0x2: adc_Ev_Iz();
|
||||
0x3: sbb_Ev_Iz();
|
||||
0x4: Inst::AND(Ev,Iz);
|
||||
0x5: Inst::SUB(Ev,Iz);
|
||||
0x6: xor_Ev_Iz();
|
||||
0x7: cmp_Ev_Iz();
|
||||
}
|
||||
0x2: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: group1_Eb_Ib();
|
||||
}
|
||||
//0x3: group1_Ev_Ib();
|
||||
0x3: decode MODRM_REG {
|
||||
0x0: add_Eb_Ib();
|
||||
@@ -241,8 +306,8 @@
|
||||
0x6: xor_Eb_Ib();
|
||||
0x7: cmp_Eb_Ib();
|
||||
}
|
||||
0x4: test_Eb_Gb();
|
||||
0x5: test_Ev_Gv();
|
||||
0x4: Inst::TEST(Eb,Gb);
|
||||
0x5: Inst::TEST(Ev,Gv);
|
||||
0x6: xchg_Eb_Gb();
|
||||
0x7: xchg_Ev_Gv();
|
||||
}
|
||||
@@ -250,14 +315,14 @@
|
||||
0x0: Inst::MOV(Eb,Gb);
|
||||
0x1: Inst::MOV(Ev,Gv);
|
||||
0x2: Inst::MOV(Gb,Eb);
|
||||
0x3: Inst::MOV(Gv,Eb);
|
||||
0x3: Inst::MOV(Gv,Ev);
|
||||
0x4: mov_MwRv_Sw(); //What to do with this one?
|
||||
0x5: lea_Gv_M();
|
||||
0x5: Inst::LEA(Gv,M);
|
||||
0x6: mov_Sw_MwRv();
|
||||
0x7: group10_Ev(); //Make sure this is Ev
|
||||
}
|
||||
0x12: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: nop_or_pause(); //Check for repe prefix
|
||||
default: nop_or_pause(); //Check for repe prefix
|
||||
0x1: xchg_rCX_rAX();
|
||||
0x2: xchg_rDX_rAX();
|
||||
0x3: xchg_rVX_rAX();
|
||||
@@ -269,12 +334,23 @@
|
||||
0x13: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: cbw_or_cwde_or_cdqe_rAX();
|
||||
0x1: cwd_or_cdq_or_cqo_rAX_rDX();
|
||||
0x2: call_Ap();
|
||||
0x2: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: call_Ap();
|
||||
}
|
||||
0x3: fwait(); //aka wait
|
||||
0x4: pushf_Fv();
|
||||
0x5: popf_Fv();
|
||||
0x6: sahf();
|
||||
0x7: lahf();
|
||||
//Both of these should be illegal only if CPUID.AHF64=0,
|
||||
//according to sandpile.org
|
||||
0x6: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: sahf();
|
||||
}
|
||||
0x7: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: lahf();
|
||||
}
|
||||
}
|
||||
0x14: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: mov_Al_Ob();
|
||||
@@ -287,8 +363,8 @@
|
||||
0x7: cmps_Yv_Xv();
|
||||
}
|
||||
0x15: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: test_Al_Ib();
|
||||
0x1: test_rAX_Iz();
|
||||
0x0: Inst::TEST(rAl,Ib);
|
||||
0x1: Inst::TEST(rAX,Iz);
|
||||
0x2: stos_Yb_Al();
|
||||
0x3: stos_Yv_rAX();
|
||||
0x4: lods_Al_Xb();
|
||||
@@ -306,23 +382,31 @@
|
||||
0x6: mov_Dh_Ib();
|
||||
0x7: mov_Bh_Ib();
|
||||
}
|
||||
0x17: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: mov_rAX_Iv();
|
||||
0x1: mov_rCX_Iv();
|
||||
0x2: mov_rDX_Iv();
|
||||
0x3: mov_rBX_Iv();
|
||||
0x4: mov_rSP_Iv();
|
||||
0x5: mov_rBP_Iv();
|
||||
0x6: mov_rSI_Iv();
|
||||
0x7: mov_rDI_Iv();
|
||||
format Inst {
|
||||
0x17: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: MOV(rAX,Iv);
|
||||
0x1: MOV(rCX,Iv);
|
||||
0x2: MOV(rDX,Iv);
|
||||
0x3: MOV(rBX,Iv);
|
||||
0x4: MOV(rSP,Iv);
|
||||
0x5: MOV(rBP,Iv);
|
||||
0x6: MOV(rSI,Iv);
|
||||
0x7: MOV(rDI,Iv);
|
||||
}
|
||||
}
|
||||
0x18: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: group2_Eb_Ib();
|
||||
0x1: group2_Ev_Ib();
|
||||
0x2: ret_near_Iw();
|
||||
0x3: ret_near();
|
||||
0x4: les_Gz_Mp();
|
||||
0x5: lds_Gz_Mp();
|
||||
0x4: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: les_Gz_Mp();
|
||||
}
|
||||
0x5: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: lds_Gz_Mp();
|
||||
}
|
||||
//0x6: group12_Eb_Ib();
|
||||
0x6: decode MODRM_REG {
|
||||
0x0: Inst::MOV(Eb,Ib);
|
||||
@@ -339,7 +423,10 @@
|
||||
0x3: ret_far();
|
||||
0x4: int3();
|
||||
0x5: int_Ib();
|
||||
0x6: into();
|
||||
0x6: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: into();
|
||||
}
|
||||
0x7: iret();
|
||||
}
|
||||
0x1A: decode OPCODE_OP_BOTTOM3 {
|
||||
@@ -347,9 +434,18 @@
|
||||
0x1: group2_Ev_1();
|
||||
0x2: group2_Eb_Cl();
|
||||
0x3: group2_Ev_Cl();
|
||||
0x4: aam_Ib();
|
||||
0x5: aad_Ib();
|
||||
0x6: salc();
|
||||
0x4: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: aam_Ib();
|
||||
}
|
||||
0x5: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: aad_Ib();
|
||||
}
|
||||
0x6: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: salc();
|
||||
}
|
||||
0x7: xlat();
|
||||
}
|
||||
0x1B: decode OPCODE_OP_BOTTOM3 {
|
||||
@@ -373,9 +469,12 @@
|
||||
0x7: out_Ib_eAX();
|
||||
}
|
||||
0x1D: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: call_Jz();
|
||||
0x0: Inst::CALL(Jz);
|
||||
0x1: jmp_Jz();
|
||||
0x2: jmp_Ap();
|
||||
0x2: decode MODE_SUBMODE {
|
||||
0x0: This_should_be_an_illegal_instruction();
|
||||
default: jmp_Ap();
|
||||
}
|
||||
0x3: jmp_Jb();
|
||||
0x4: in_Al_Dx();
|
||||
0x5: in_eAX_Dx();
|
||||
|
||||
@@ -70,8 +70,8 @@ def format Inst(*opTypeSet) {{
|
||||
def format MultiInst(switchVal, *opTypeSets) {{
|
||||
switcher = {}
|
||||
for (count, opTypeSet) in zip(xrange(len(opTypeSets)), opTypeSets):
|
||||
switcher[count] = (Name, opTypeSet, EmulEnv())
|
||||
blocks = doSplitDecode(specializeInst, switchVal, switcher)
|
||||
switcher[count] = (specializeInst, Name, opTypeSet, EmulEnv())
|
||||
blocks = doSplitDecode(switchVal, switcher)
|
||||
(header_output, decoder_output,
|
||||
decode_block, exec_output) = blocks.makeList()
|
||||
}};
|
||||
|
||||
@@ -96,6 +96,7 @@ output header {{
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "arch/x86/emulenv.hh"
|
||||
#include "arch/x86/faults.hh"
|
||||
#include "arch/x86/isa_traits.hh"
|
||||
#include "arch/x86/regfile.hh"
|
||||
|
||||
@@ -53,7 +53,31 @@
|
||||
#
|
||||
# Authors: Gabe Black
|
||||
|
||||
microcode = ""
|
||||
microcode = '''
|
||||
def macroop SUB_R_I
|
||||
{
|
||||
subi "env.reg", "env.reg", "IMMEDIATE"
|
||||
};
|
||||
|
||||
def macroop SUB_M_I
|
||||
{
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
subi "NUM_INTREGS+1", "NUM_INTREGS+1", "IMMEDIATE"
|
||||
st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop SUB_P_I
|
||||
{
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
subi "NUM_INTREGS+1", "NUM_INTREGS+1", "IMMEDIATE"
|
||||
st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
'''
|
||||
#let {{
|
||||
# class ADC(Inst):
|
||||
# "Adc ^0 ^0 ^1"
|
||||
|
||||
@@ -53,8 +53,47 @@
|
||||
#
|
||||
# Authors: Gabe Black
|
||||
|
||||
microcode = ""
|
||||
#let {{
|
||||
# class TEST(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
#}};
|
||||
microcode = '''
|
||||
def macroop TEST_M_R
|
||||
{
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
and "NUM_INTREGS", "NUM_INTREGS+1", "env.reg"
|
||||
};
|
||||
|
||||
def macroop TEST_P_R
|
||||
{
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
and "NUM_INTREGS", "NUM_INTREGS+1", "env.reg"
|
||||
};
|
||||
|
||||
def macroop TEST_R_R
|
||||
{
|
||||
and "NUM_INTREGS", "env.reg", "env.regm"
|
||||
};
|
||||
|
||||
def macroop TEST_M_I
|
||||
{
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
limm "NUM_INTREGS+2", "IMMEDIATE"
|
||||
and "NUM_INTREGS", "NUM_INTREGS+1", "NUM_INTREGS+2"
|
||||
};
|
||||
|
||||
def macroop TEST_P_I
|
||||
{
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
limm "NUM_INTREGS+2", "IMMEDIATE"
|
||||
and "NUM_INTREGS", "NUM_INTREGS+1", "NUM_INTREGS+2"
|
||||
};
|
||||
|
||||
def macroop TEST_R_I
|
||||
{
|
||||
limm "NUM_INTREGS+1", "IMMEDIATE"
|
||||
and "NUM_INTREGS", "env.reg", "NUM_INTREGS+1"
|
||||
};
|
||||
'''
|
||||
|
||||
@@ -53,7 +53,18 @@
|
||||
#
|
||||
# Authors: Gabe Black
|
||||
|
||||
microcode = ""
|
||||
microcode = '''
|
||||
def macroop CALL_I
|
||||
{
|
||||
.adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;"
|
||||
|
||||
limm "NUM_INTREGS+2", "IMMEDIATE"
|
||||
rdip "NUM_INTREGS+1"
|
||||
subi "INTREG_RSP", "INTREG_RSP", "env.dataSize"
|
||||
st "NUM_INTREGS+1", 2, [0, "NUM_INTREGS", "INTREG_RSP"]
|
||||
wrip "NUM_INTREGS+1", "NUM_INTREGS+2"
|
||||
};
|
||||
'''
|
||||
#let {{
|
||||
# class CALL(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
|
||||
@@ -59,20 +59,55 @@ def macroop MOV_R_R {
|
||||
};
|
||||
|
||||
def macroop MOV_M_R {
|
||||
#Do a store to put the register operand into memory
|
||||
st "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop MOV_P_R {
|
||||
rdip "NUM_INTREGS+7"
|
||||
st "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop MOV_R_M {
|
||||
#Do a load to fill the register operand from memory
|
||||
ld "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop MOV_R_P {
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop MOV_R_I {
|
||||
limm "env.reg", "env.immediate"
|
||||
limm "env.reg", "IMMEDIATE"
|
||||
};
|
||||
|
||||
def macroop MOV_M_I {
|
||||
limm "env.reg", "env.immediate"
|
||||
#Do a store to put the register operand into memory
|
||||
limm "NUM_INTREGS+1", "IMMEDIATE"
|
||||
st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop MOV_P_I {
|
||||
rdip "NUM_INTREGS+7"
|
||||
limm "NUM_INTREGS+1", "IMMEDIATE"
|
||||
st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop MOVSXD_R_R {
|
||||
sext "env.reg", "env.regm", "env.dataSize"
|
||||
};
|
||||
|
||||
def macroop MOVSXD_R_M {
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
sext "env.reg", "NUM_INTREGS+1", "env.dataSize"
|
||||
};
|
||||
|
||||
def macroop MOVSXD_R_P {
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
sext "env.reg", "NUM_INTREGS+1", "env.dataSize"
|
||||
};
|
||||
'''
|
||||
#let {{
|
||||
|
||||
@@ -55,28 +55,28 @@
|
||||
|
||||
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 {{
|
||||
# class POP(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
# class POPA(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
# class POPA(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
# class POPAD(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
# class PUSH(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
# class PUSHA(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
# class PUSHAD(Inst):
|
||||
|
||||
@@ -53,8 +53,13 @@
|
||||
#
|
||||
# Authors: Gabe Black
|
||||
|
||||
microcode = ""
|
||||
#let {{
|
||||
# class LEA(Inst):
|
||||
# "GenFault ${new UnimpInstFault}"
|
||||
#}};
|
||||
microcode = '''
|
||||
def macroop LEA_R_M {
|
||||
lea "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop LEA_R_P {
|
||||
rdip "NUM_INTREGS+7"
|
||||
lea "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
|
||||
};
|
||||
'''
|
||||
|
||||
@@ -61,51 +61,77 @@ 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"
|
||||
#Do a store to write the destination
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
xor "NUM_INTREGS+1", "NUM_INTREGS+1", "env.reg"
|
||||
st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop XOR_P_R
|
||||
{
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
xor "NUM_INTREGS+1", "NUM_INTREGS+1", "env.reg"
|
||||
st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop XOR_R_M
|
||||
{
|
||||
#Do a load to get one of the sources
|
||||
xor "env.reg", "env.reg", "NUM_INTREGS"
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
xor "env.reg", "env.reg", "NUM_INTREGS+1"
|
||||
};
|
||||
|
||||
def macroop XOR_R_P
|
||||
{
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
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"
|
||||
#Do a store to write the destination
|
||||
ld "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
limm "NUM_INTREGS+1", "IMMEDIATE"
|
||||
and "NUM_INTREGS+2", "NUM_INTREGS+2", "NUM_INTREGS+1"
|
||||
st "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
|
||||
def macroop AND_P_I
|
||||
{
|
||||
rdip "NUM_INTREGS+7"
|
||||
ld "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
limm "NUM_INTREGS+1", "IMMEDIATE"
|
||||
and "NUM_INTREGS+2", "NUM_INTREGS+2", "NUM_INTREGS+1"
|
||||
st "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \
|
||||
"DISPLACEMENT"
|
||||
};
|
||||
'''
|
||||
#let {{
|
||||
#microcodeString = '''
|
||||
# def macroop AND
|
||||
# {
|
||||
# And reg reg regm
|
||||
# };
|
||||
# def macroop OR
|
||||
# {
|
||||
# Or reg reg regm
|
||||
# };
|
||||
# def macroop XOR
|
||||
# {
|
||||
# Xor reg reg regm
|
||||
# };
|
||||
# def macroop NOT
|
||||
# {
|
||||
# Xor reg reg "0xFFFFFFFFFFFFFFFFULL"
|
||||
|
||||
@@ -111,6 +111,12 @@ output header {{
|
||||
};
|
||||
}};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// X86 specific
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Basic instruction class declaration template.
|
||||
def template MacroDeclare {{
|
||||
namespace X86Macroop
|
||||
@@ -122,17 +128,19 @@ def template MacroDeclare {{
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
%(class_name)s(ExtMachInst machInst, EmulEnv env);
|
||||
%(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env);
|
||||
};
|
||||
};
|
||||
}};
|
||||
|
||||
// Basic instruction class constructor template.
|
||||
def template MacroConstructor {{
|
||||
inline X86Macroop::%(class_name)s::%(class_name)s(ExtMachInst machInst, EmulEnv env)
|
||||
inline X86Macroop::%(class_name)s::%(class_name)s(
|
||||
ExtMachInst machInst, EmulEnv env)
|
||||
: %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s)
|
||||
{
|
||||
%(adjust_env)s;
|
||||
%(do_modrm)s;
|
||||
%(constructor)s;
|
||||
//alloc_microops is the code that sets up the microops
|
||||
//array in the parent class.
|
||||
@@ -140,11 +148,6 @@ def template MacroConstructor {{
|
||||
}
|
||||
}};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// X86 specific
|
||||
//
|
||||
|
||||
let {{
|
||||
from micro_asm import Combinational_Macroop, Rom_Macroop
|
||||
class X86Macroop(Combinational_Macroop):
|
||||
@@ -157,6 +160,7 @@ let {{
|
||||
}
|
||||
self.declared = False
|
||||
self.adjust_env = ""
|
||||
self.doModRM = ""
|
||||
def getAllocator(self, env):
|
||||
return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator())
|
||||
def getDeclaration(self):
|
||||
@@ -180,30 +184,11 @@ let {{
|
||||
iop = InstObjParams(self.name, self.name, "Macroop",
|
||||
{"code" : "", "num_microops" : numMicroops,
|
||||
"alloc_microops" : allocMicroops,
|
||||
"adjust_env" : self.adjust_env})
|
||||
"adjust_env" : self.adjust_env,
|
||||
"do_modrm" : self.doModRM})
|
||||
return MacroConstructor.subst(iop);
|
||||
}};
|
||||
|
||||
output header {{
|
||||
struct EmulEnv
|
||||
{
|
||||
X86ISA::RegIndex reg;
|
||||
X86ISA::RegIndex regm;
|
||||
uint64_t immediate;
|
||||
uint64_t displacement;
|
||||
int addressSize;
|
||||
int dataSize;
|
||||
|
||||
EmulEnv(X86ISA::RegIndex _reg, X86ISA::RegIndex _regm,
|
||||
uint64_t _immediate, uint64_t _displacement,
|
||||
int _addressSize, int _dataSize) :
|
||||
reg(_reg), regm(_regm),
|
||||
immediate(_immediate), displacement(_displacement),
|
||||
addressSize(_addressSize), dataSize(_dataSize)
|
||||
{;}
|
||||
};
|
||||
}};
|
||||
|
||||
let {{
|
||||
class EmulEnv(object):
|
||||
def __init__(self):
|
||||
@@ -211,17 +196,17 @@ 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"
|
||||
self.doModRM = False
|
||||
|
||||
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:
|
||||
@@ -235,12 +220,15 @@ let {{
|
||||
}};
|
||||
|
||||
let {{
|
||||
doModRMString = "env.doModRM(machInst);\n"
|
||||
def genMacroop(Name, env):
|
||||
blocks = OutputBlocks()
|
||||
if not macroopDict.has_key(Name):
|
||||
raise Exception, "Unrecognized instruction: %s" % Name
|
||||
macroop = macroopDict[Name]
|
||||
if not macroop.declared:
|
||||
if env.doModRM:
|
||||
macroop.doModRM = doModRMString
|
||||
blocks.header_output = macroop.getDeclaration()
|
||||
blocks.decoder_output = macroop.getDefinition()
|
||||
macroop.declared = True
|
||||
|
||||
@@ -68,7 +68,7 @@ let {{
|
||||
import sys
|
||||
sys.path[0:0] = ["src/arch/x86/isa/"]
|
||||
from insts import microcode
|
||||
print microcode
|
||||
# print microcode
|
||||
from micro_asm import MicroAssembler, Rom_Macroop, Rom
|
||||
mainRom = Rom('main ROM')
|
||||
assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop)
|
||||
|
||||
@@ -59,8 +59,11 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
def template MicroLdStOpDeclare {{
|
||||
class %(class_name)s : public X86MicroopBase
|
||||
output header {{
|
||||
/**
|
||||
* Base class for load and store ops
|
||||
*/
|
||||
class LdStOp : public X86MicroopBase
|
||||
{
|
||||
protected:
|
||||
const uint8_t scale;
|
||||
@@ -71,6 +74,76 @@ 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();
|
||||
}
|
||||
}};
|
||||
|
||||
// LEA template
|
||||
|
||||
def template MicroLeaExecute {{
|
||||
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)
|
||||
{
|
||||
%(op_wb)s;
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template MicroLeaDeclare {{
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
protected:
|
||||
void buildMe();
|
||||
|
||||
public:
|
||||
@@ -93,6 +166,181 @@ def template MicroLdStOpDeclare {{
|
||||
};
|
||||
}};
|
||||
|
||||
// Load templates
|
||||
|
||||
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:
|
||||
%(class_name)s(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);
|
||||
|
||||
%(class_name)s(ExtMachInst _machInst,
|
||||
const char * instMnem,
|
||||
uint8_t _scale, RegIndex _index, RegIndex _base,
|
||||
uint64_t _disp, uint8_t _segment,
|
||||
RegIndex _data,
|
||||
uint8_t _dataSize, uint8_t _addressSize);
|
||||
|
||||
%(BasicExecDeclare)s
|
||||
|
||||
%(InitiateAccDeclare)s
|
||||
|
||||
%(CompleteAccDeclare)s
|
||||
};
|
||||
}};
|
||||
|
||||
def template MicroLdStOpConstructor {{
|
||||
|
||||
inline void %(class_name)s::buildMe()
|
||||
@@ -107,11 +355,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 +367,120 @@ 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, segment, addr, disp = 0):
|
||||
super(LoadOp, self).__init__(data, segment, addr, disp)
|
||||
self.className = Name
|
||||
self.mnemonic = name
|
||||
|
||||
microopClasses[name] = StoreOp
|
||||
|
||||
defineMicroLoadOp('St', 'Mem = Data;')
|
||||
|
||||
iop = InstObjParams("lea", "Lea", 'LdStOp',
|
||||
{"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA})
|
||||
header_output += MicroLeaDeclare.subst(iop)
|
||||
decoder_output += MicroLdStOpConstructor.subst(iop)
|
||||
exec_output += MicroLeaExecute.subst(iop)
|
||||
|
||||
class LeaOp(LdStOp):
|
||||
def __init__(self, data, segment, addr, disp = 0):
|
||||
super(LeaOp, self).__init__(data, segment, addr, disp)
|
||||
self.className = "Lea"
|
||||
self.mnemonic = "lea"
|
||||
|
||||
microopClasses["lea"] = LeaOp
|
||||
}};
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ def template MicroLimmOpDeclare {{
|
||||
const uint64_t imm;
|
||||
void buildMe();
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
|
||||
public:
|
||||
%(class_name)s(ExtMachInst _machInst,
|
||||
const char * instMnem,
|
||||
@@ -93,6 +96,20 @@ def template MicroLimmOpDeclare {{
|
||||
};
|
||||
}};
|
||||
|
||||
def template MicroLimmOpDisassembly {{
|
||||
std::string %(class_name)s::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
|
||||
printMnemonic(response, instMnem, mnemonic);
|
||||
printReg(response, dest);
|
||||
response << ", ";
|
||||
ccprintf(response, "%#x", imm);
|
||||
return response.str();
|
||||
}
|
||||
}};
|
||||
|
||||
def template MicroLimmOpConstructor {{
|
||||
|
||||
inline void %(class_name)s::buildMe()
|
||||
@@ -148,5 +165,6 @@ let {{
|
||||
{"code" : "DestReg = imm;"})
|
||||
header_output += MicroLimmOpDeclare.subst(iop)
|
||||
decoder_output += MicroLimmOpConstructor.subst(iop)
|
||||
decoder_output += MicroLimmOpDisassembly.subst(iop)
|
||||
exec_output += MicroLimmOpExecute.subst(iop)
|
||||
}};
|
||||
|
||||
@@ -59,6 +59,100 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
output header {{
|
||||
/**
|
||||
* Base classes for RegOps which provides a generateDisassembly method.
|
||||
*/
|
||||
class RegOp : public X86MicroopBase
|
||||
{
|
||||
protected:
|
||||
const RegIndex src1;
|
||||
const RegIndex src2;
|
||||
const RegIndex dest;
|
||||
const bool setStatus;
|
||||
const uint8_t dataSize;
|
||||
const uint8_t ext;
|
||||
|
||||
// Constructor
|
||||
RegOp(ExtMachInst _machInst,
|
||||
const char *mnem, const char *_instMnem,
|
||||
bool isMicro, bool isDelayed,
|
||||
bool isFirst, bool isLast,
|
||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext,
|
||||
OpClass __opClass) :
|
||||
X86MicroopBase(_machInst, mnem, _instMnem,
|
||||
isMicro, isDelayed, isFirst, isLast,
|
||||
__opClass),
|
||||
src1(_src1), src2(_src2), dest(_dest),
|
||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class RegOpImm : public X86MicroopBase
|
||||
{
|
||||
protected:
|
||||
const RegIndex src1;
|
||||
const uint8_t imm8;
|
||||
const RegIndex dest;
|
||||
const bool setStatus;
|
||||
const uint8_t dataSize;
|
||||
const uint8_t ext;
|
||||
|
||||
// Constructor
|
||||
RegOpImm(ExtMachInst _machInst,
|
||||
const char * mnem, const char *_instMnem,
|
||||
bool isMicro, bool isDelayed,
|
||||
bool isFirst, bool isLast,
|
||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext,
|
||||
OpClass __opClass) :
|
||||
X86MicroopBase(_machInst, mnem, _instMnem,
|
||||
isMicro, isDelayed, isFirst, isLast,
|
||||
__opClass),
|
||||
src1(_src1), imm8(_imm8), dest(_dest),
|
||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
std::string RegOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
|
||||
printMnemonic(response, instMnem, mnemonic);
|
||||
printReg(response, dest);
|
||||
response << ", ";
|
||||
printReg(response, src1);
|
||||
response << ", ";
|
||||
printReg(response, src2);
|
||||
return response.str();
|
||||
}
|
||||
|
||||
std::string RegOpImm::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
|
||||
printMnemonic(response, instMnem, mnemonic);
|
||||
printReg(response, dest);
|
||||
response << ", ";
|
||||
printReg(response, src1);
|
||||
ccprintf(response, ", %#x", imm8);
|
||||
return response.str();
|
||||
}
|
||||
}};
|
||||
|
||||
def template MicroRegOpExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
@@ -101,12 +195,6 @@ def template MicroRegOpDeclare {{
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
protected:
|
||||
const RegIndex src1;
|
||||
const RegIndex src2;
|
||||
const RegIndex dest;
|
||||
const bool setStatus;
|
||||
const uint8_t dataSize;
|
||||
const uint8_t ext;
|
||||
void buildMe();
|
||||
|
||||
public:
|
||||
@@ -130,12 +218,6 @@ def template MicroRegOpImmDeclare {{
|
||||
class %(class_name)sImm : public %(base_class)s
|
||||
{
|
||||
protected:
|
||||
const RegIndex src1;
|
||||
const uint8_t imm8;
|
||||
const RegIndex dest;
|
||||
const bool setStatus;
|
||||
const uint8_t dataSize;
|
||||
const uint8_t ext;
|
||||
void buildMe();
|
||||
|
||||
public:
|
||||
@@ -166,9 +248,9 @@ def template MicroRegOpConstructor {{
|
||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
false, false, false, false, %(op_class)s),
|
||||
src1(_src1), src2(_src2), dest(_dest),
|
||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
||||
false, false, false, false,
|
||||
_src1, _src2, _dest, _setStatus, _dataSize, _ext,
|
||||
%(op_class)s)
|
||||
{
|
||||
buildMe();
|
||||
}
|
||||
@@ -179,9 +261,9 @@ def template MicroRegOpConstructor {{
|
||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
isMicro, isDelayed, isFirst, isLast, %(op_class)s),
|
||||
src1(_src1), src2(_src2), dest(_dest),
|
||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
||||
isMicro, isDelayed, isFirst, isLast,
|
||||
_src1, _src2, _dest, _setStatus, _dataSize, _ext,
|
||||
%(op_class)s)
|
||||
{
|
||||
buildMe();
|
||||
}
|
||||
@@ -199,9 +281,9 @@ def template MicroRegOpImmConstructor {{
|
||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
false, false, false, false, %(op_class)s),
|
||||
src1(_src1), imm8(_imm8), dest(_dest),
|
||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
||||
false, false, false, false,
|
||||
_src1, _imm8, _dest, _setStatus, _dataSize, _ext,
|
||||
%(op_class)s)
|
||||
{
|
||||
buildMe();
|
||||
}
|
||||
@@ -212,9 +294,9 @@ def template MicroRegOpImmConstructor {{
|
||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
isMicro, isDelayed, isFirst, isLast, %(op_class)s),
|
||||
src1(_src1), imm8(_imm8), dest(_dest),
|
||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
||||
isMicro, isDelayed, isFirst, isLast,
|
||||
_src1, _imm8, _dest, _setStatus, _dataSize, _ext,
|
||||
%(op_class)s)
|
||||
{
|
||||
buildMe();
|
||||
}
|
||||
@@ -227,7 +309,7 @@ let {{
|
||||
self.src1 = src1
|
||||
self.src2 = src2
|
||||
self.setStatus = False
|
||||
self.dataSize = 1
|
||||
self.dataSize = "env.dataSize"
|
||||
self.ext = 0
|
||||
|
||||
def getAllocator(self, *microFlags):
|
||||
@@ -249,7 +331,7 @@ let {{
|
||||
self.src1 = src1
|
||||
self.imm8 = imm8
|
||||
self.setStatus = False
|
||||
self.dataSize = 1
|
||||
self.dataSize = "env.dataSize"
|
||||
self.ext = 0
|
||||
|
||||
def getAllocator(self, *microFlags):
|
||||
@@ -274,11 +356,20 @@ let {{
|
||||
decoder_output = ""
|
||||
exec_output = ""
|
||||
|
||||
def defineMicroRegOp(mnemonic, code):
|
||||
def setUpMicroRegOp(name, Name, base, code, child):
|
||||
global header_output
|
||||
global decoder_output
|
||||
global exec_output
|
||||
global microopClasses
|
||||
|
||||
iop = InstObjParams(name, Name, base, {"code" : code})
|
||||
header_output += MicroRegOpDeclare.subst(iop)
|
||||
decoder_output += MicroRegOpConstructor.subst(iop)
|
||||
exec_output += MicroRegOpExecute.subst(iop)
|
||||
|
||||
microopClasses[name] = child
|
||||
|
||||
def defineMicroRegOp(mnemonic, code):
|
||||
Name = mnemonic
|
||||
name = mnemonic.lower()
|
||||
|
||||
@@ -289,34 +380,23 @@ let {{
|
||||
regCode = matcher.sub("SrcReg2", code)
|
||||
immCode = matcher.sub("imm8", code)
|
||||
|
||||
# Build up the all register version of this micro op
|
||||
iop = InstObjParams(name, Name, 'X86MicroopBase', {"code" : regCode})
|
||||
header_output += MicroRegOpDeclare.subst(iop)
|
||||
decoder_output += MicroRegOpConstructor.subst(iop)
|
||||
exec_output += MicroRegOpExecute.subst(iop)
|
||||
|
||||
# Build the all register version of this micro op
|
||||
class RegOpChild(RegOp):
|
||||
def __init__(self, dest, src1, src2):
|
||||
super(RegOpChild, self).__init__(dest, src1, src2)
|
||||
self.className = Name
|
||||
self.mnemonic = name
|
||||
|
||||
microopClasses[name] = RegOpChild
|
||||
setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild);
|
||||
|
||||
# Build up the immediate version of this micro op
|
||||
iop = InstObjParams(name + "i", Name,
|
||||
'X86MicroopBase', {"code" : immCode})
|
||||
header_output += MicroRegOpImmDeclare.subst(iop)
|
||||
decoder_output += MicroRegOpImmConstructor.subst(iop)
|
||||
exec_output += MicroRegOpImmExecute.subst(iop)
|
||||
|
||||
class RegOpImmChild(RegOpImm):
|
||||
def __init__(self, dest, src1, imm):
|
||||
super(RegOpImmChild, self).__init__(dest, src1, imm)
|
||||
# Build the immediate version of this micro op
|
||||
class RegOpChildImm(RegOpImm):
|
||||
def __init__(self, dest, src1, src2):
|
||||
super(RegOpChildImm, self).__init__(dest, src1, src2)
|
||||
self.className = Name + "Imm"
|
||||
self.mnemonic = name + "i"
|
||||
|
||||
microopClasses[name + "i"] = RegOpImmChild
|
||||
setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm);
|
||||
|
||||
defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to set OF,CF,SF
|
||||
defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)')
|
||||
@@ -328,4 +408,68 @@ let {{
|
||||
defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)') #Needs to set OF,CF,SF and not DestReg
|
||||
defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)')
|
||||
|
||||
# This has it's own function because Wr ops have implicit destinations
|
||||
def defineMicroRegOpWr(mnemonic, code):
|
||||
Name = mnemonic
|
||||
name = mnemonic.lower()
|
||||
|
||||
# Find op2 in each of the instruction definitions. Create two versions
|
||||
# of the code, one with an integer operand, and one with an immediate
|
||||
# operand.
|
||||
matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
|
||||
regCode = matcher.sub("SrcReg2", code)
|
||||
immCode = matcher.sub("imm8", code)
|
||||
|
||||
# Build the all register version of this micro op
|
||||
class RegOpChild(RegOp):
|
||||
def __init__(self, src1, src2):
|
||||
super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2)
|
||||
self.className = Name
|
||||
self.mnemonic = name
|
||||
|
||||
setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild);
|
||||
|
||||
# Build the immediate version of this micro op
|
||||
class RegOpChildImm(RegOpImm):
|
||||
def __init__(self, src1, src2):
|
||||
super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2)
|
||||
self.className = Name + "Imm"
|
||||
self.mnemonic = name + "i"
|
||||
|
||||
setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm);
|
||||
|
||||
defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2')
|
||||
|
||||
# This has it's own function because Rd ops don't always have two parameters
|
||||
def defineMicroRegOpRd(mnemonic, code):
|
||||
Name = mnemonic
|
||||
name = mnemonic.lower()
|
||||
|
||||
class RegOpChild(RegOp):
|
||||
def __init__(self, dest, src1 = "NUM_INTREGS"):
|
||||
super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS")
|
||||
self.className = Name
|
||||
self.mnemonic = name
|
||||
|
||||
setUpMicroRegOp(name, Name, "RegOp", code, RegOpChild);
|
||||
|
||||
defineMicroRegOpRd('Rdip', 'DestReg = RIP')
|
||||
|
||||
def defineMicroRegOpImm(mnemonic, code):
|
||||
Name = mnemonic
|
||||
name = mnemonic.lower()
|
||||
|
||||
class RegOpChild(RegOpImm):
|
||||
def __init__(self, dest, src1, src2):
|
||||
super(RegOpChild, self).__init__(dest, src1, src2)
|
||||
self.className = Name
|
||||
self.mnemonic = name
|
||||
|
||||
setUpMicroRegOp(name, Name, "RegOpImm", code, RegOpChild);
|
||||
|
||||
defineMicroRegOpImm('Sext', '''
|
||||
IntReg val = SrcReg1;
|
||||
int sign_bit = bits(val, imm8-1, imm8-1);
|
||||
val = sign_bit ? (val | ~mask(imm8)) : val;
|
||||
DestReg = merge(DestReg, val, dataSize);''')
|
||||
}};
|
||||
|
||||
@@ -59,8 +59,27 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
def template MicroFaultExecute {{
|
||||
Fault %(class_name)s ::execute(%(CPU_exec_context)s *xc,
|
||||
output header {{
|
||||
class MicroFault : public X86MicroopBase
|
||||
{
|
||||
protected:
|
||||
Fault fault;
|
||||
void buildMe();
|
||||
|
||||
public:
|
||||
MicroFault(ExtMachInst _machInst, const char * instMnem,
|
||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||
Fault _fault);
|
||||
|
||||
MicroFault(ExtMachInst _machInst, const char * instMnem,
|
||||
Fault _fault);
|
||||
|
||||
%(BasicExecDeclare)s
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
Fault MicroFault::execute(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
//Return the fault we were constructed with
|
||||
@@ -68,58 +87,35 @@ def template MicroFaultExecute {{
|
||||
}
|
||||
}};
|
||||
|
||||
def template MicroFaultDeclare {{
|
||||
class %(class_name)s : public X86MicroopBase
|
||||
{
|
||||
protected:
|
||||
Fault fault;
|
||||
void buildMe();
|
||||
|
||||
public:
|
||||
%(class_name)s(ExtMachInst _machInst,
|
||||
const char * instMnem,
|
||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||
Fault _fault);
|
||||
|
||||
%(class_name)s(ExtMachInst _machInst,
|
||||
const char * instMnem,
|
||||
Fault _fault);
|
||||
|
||||
%(BasicExecDeclare)s
|
||||
};
|
||||
}};
|
||||
|
||||
def template MicroFaultConstructor {{
|
||||
|
||||
inline void %(class_name)s::buildMe()
|
||||
{
|
||||
%(constructor)s;
|
||||
}
|
||||
|
||||
inline %(class_name)s::%(class_name)s(
|
||||
output decoder {{
|
||||
inline MicroFault::MicroFault(
|
||||
ExtMachInst machInst, const char * instMnem, Fault _fault) :
|
||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
false, false, false, false, %(op_class)s), fault(_fault)
|
||||
X86MicroopBase(machInst, "fault", instMnem,
|
||||
false, false, false, false, No_OpClass), fault(_fault)
|
||||
{
|
||||
buildMe();
|
||||
}
|
||||
|
||||
inline %(class_name)s::%(class_name)s(
|
||||
inline MicroFault::MicroFault(
|
||||
ExtMachInst machInst, const char * instMnem,
|
||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||
Fault _fault) :
|
||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
isMicro, isDelayed, isFirst, isLast, %(op_class)s),
|
||||
X86MicroopBase(machInst, "fault", instMnem,
|
||||
isMicro, isDelayed, isFirst, isLast, No_OpClass),
|
||||
fault(_fault)
|
||||
{
|
||||
buildMe();
|
||||
}
|
||||
}};
|
||||
|
||||
let {{
|
||||
# This microop takes in a single parameter, a fault to return.
|
||||
iop = InstObjParams("fault", "GenFault", 'X86MicroopBase', {"code" : ""})
|
||||
header_output += MicroFaultDeclare.subst(iop)
|
||||
decoder_output += MicroFaultConstructor.subst(iop)
|
||||
exec_output += MicroFaultExecute.subst(iop)
|
||||
class Fault(X86Microop):
|
||||
def __init__(self, fault):
|
||||
self.fault = fault
|
||||
|
||||
def getAllocator(self, *microFlags):
|
||||
allocator = '''new MicroFault(machInst, mnemonic
|
||||
%(flags)s, %(fault)s)''' % {
|
||||
"flags" : self.microFlagsText(microFlags),
|
||||
"fault" : self.fault}
|
||||
return allocator
|
||||
microopClasses["fault"] = Fault
|
||||
}};
|
||||
|
||||
@@ -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)
|
||||
}};
|
||||
|
||||
@@ -64,18 +64,18 @@
|
||||
let {{
|
||||
# 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.
|
||||
# builder is called on the exploded contents of "vals" values to generate
|
||||
# whatever code should be used.
|
||||
def doSplitDecode(builder, switchVal, vals, default = None):
|
||||
# Each element of the dict is a list containing a function and then the
|
||||
# arguments to pass to it.
|
||||
def doSplitDecode(switchVal, vals, default = None):
|
||||
blocks = OutputBlocks()
|
||||
blocks.decode_block = 'switch(%s) {\n' % switchVal
|
||||
for (val, todo) in vals.items():
|
||||
new_blocks = builder(*todo)
|
||||
new_blocks = todo[0](*todo[1:])
|
||||
new_blocks.decode_block = \
|
||||
'\tcase %s: %s\n' % (val, new_blocks.decode_block)
|
||||
blocks.append(new_blocks)
|
||||
if default:
|
||||
new_blocks = builder(*default)
|
||||
new_blocks = default[0](*default[1:])
|
||||
new_blocks.decode_block = \
|
||||
'\tdefault: %s\n' % new_blocks.decode_block
|
||||
blocks.append(new_blocks)
|
||||
@@ -83,9 +83,30 @@ let {{
|
||||
return blocks
|
||||
}};
|
||||
|
||||
let {{
|
||||
def doRipRelativeDecode(Name, opTypes, env):
|
||||
# print "RIPing %s with opTypes %s" % (Name, opTypes)
|
||||
normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), copy.copy(env))
|
||||
ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), copy.copy(env))
|
||||
|
||||
blocks = OutputBlocks()
|
||||
blocks.append(normBlocks)
|
||||
blocks.append(ripBlocks)
|
||||
|
||||
blocks.decode_block = '''
|
||||
if(machInst.modRM.mod == 0 &&
|
||||
machInst.modRM.rm == 5 &&
|
||||
machInst.mode.submode == SixtyFourBitMode)
|
||||
{ %s }
|
||||
else
|
||||
{ %s }''' % \
|
||||
(ripBlocks.decode_block, normBlocks.decode_block)
|
||||
return blocks
|
||||
}};
|
||||
|
||||
let {{
|
||||
class OpType(object):
|
||||
parser = re.compile(r"(?P<tag>[A-Z][A-Z]*)(?P<size>[a-z][a-z]*)|(r(?P<reg>[A-Z0-9]*)(?P<rsize>[a-z]*))")
|
||||
parser = re.compile(r"(?P<tag>[A-Z]+)(?P<size>[a-z]*)|(r(?P<reg>[A-Z0-9]+)(?P<rsize>[a-z]*))")
|
||||
def __init__(self, opTypeString):
|
||||
match = OpType.parser.search(opTypeString)
|
||||
if match == None:
|
||||
@@ -105,14 +126,15 @@ let {{
|
||||
while len(opTypes):
|
||||
# Parse the operand type string we're working with
|
||||
opType = OpType(opTypes[0])
|
||||
opTypes.pop(0)
|
||||
|
||||
if opType.reg:
|
||||
#Figure out what to do with fixed register operands
|
||||
#This is the index to use, so we should stick it some place.
|
||||
if opType.reg in ("A", "B", "C", "D"):
|
||||
env.addReg("INTREG_R%sX" % opType.reg)
|
||||
env.addReg("INTREG_R%sX | (REX_B << 3)" % opType.reg)
|
||||
else:
|
||||
env.addReg("INTREG_R%s" % opType.reg)
|
||||
env.addReg("INTREG_R%s | (REX_B << 3)" % opType.reg)
|
||||
if opType.size:
|
||||
if opType.rsize in ("l", "h", "b"):
|
||||
print "byte"
|
||||
@@ -121,6 +143,11 @@ let {{
|
||||
else:
|
||||
print "Didn't recognize fixed register size %s!" % opType.rsize
|
||||
Name += "_R"
|
||||
elif opType.tag == "M":
|
||||
# This refers to memory. The macroop constructor sets up modrm
|
||||
# addressing. Non memory modrm settings should cause an error.
|
||||
Name += "_M"
|
||||
env.doModRM = True
|
||||
elif opType.tag == None or opType.size == None:
|
||||
raise Exception, "Problem parsing operand tag: %s" % opType.tag
|
||||
elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"):
|
||||
@@ -130,40 +157,24 @@ let {{
|
||||
elif opType.tag in ("E", "Q", "W"):
|
||||
# This might refer to memory or to a register. We need to
|
||||
# divide it up farther.
|
||||
regTypes = copy.copy(opTypes)
|
||||
regTypes.pop(0)
|
||||
regEnv = copy.copy(env)
|
||||
regEnv.addReg(ModRMRMIndex)
|
||||
regName = Name + "_R"
|
||||
# This needs to refer to memory, but we'll fill in the details
|
||||
# later. It needs to take into account unaligned memory
|
||||
# addresses.
|
||||
memTypes = copy.copy(opTypes)
|
||||
memTypes.pop(0)
|
||||
# This refers to memory. The macroop constructor should set up
|
||||
# modrm addressing.
|
||||
memEnv = copy.copy(env)
|
||||
memName = Name + "_M"
|
||||
print "%0"
|
||||
return doSplitDecode(specializeInst, "MODRM_MOD",
|
||||
{"3" : (regName, regTypes, regEnv)},
|
||||
(memName, memTypes, memEnv))
|
||||
memEnv.doModRM = True
|
||||
return doSplitDecode("MODRM_MOD",
|
||||
{"3" : (specializeInst, Name + "_R", copy.copy(opTypes), regEnv)},
|
||||
(doRipRelativeDecode, Name, copy.copy(opTypes), memEnv))
|
||||
elif opType.tag in ("I", "J"):
|
||||
# Immediates
|
||||
print "IMMEDIATE"
|
||||
Name += "_I"
|
||||
elif opType.tag == "M":
|
||||
# This needs to refer to memory, but we'll fill in the details
|
||||
# later. It needs to take into account unaligned memory
|
||||
# addresses.
|
||||
print "%0"
|
||||
Name += "_M"
|
||||
elif opType.tag in ("PR", "R", "VR"):
|
||||
# There should probably be a check here to verify that mod
|
||||
# is equal to 11b
|
||||
# Non register modrm settings should cause an error
|
||||
env.addReg(ModRMRMIndex)
|
||||
Name += "_R"
|
||||
else:
|
||||
raise Exception, "Unrecognized tag %s." % opType.tag
|
||||
opTypes.pop(0)
|
||||
|
||||
# Generate code to return a macroop of the given name which will
|
||||
# operate in the "emulation environment" env
|
||||
|
||||
@@ -81,8 +81,8 @@ namespace X86ISA
|
||||
|
||||
// These enumerate all the registers for dependence tracking.
|
||||
enum DependenceTags {
|
||||
//The number of microcode registers needs to be added to this
|
||||
FP_Base_DepTag = 16,
|
||||
//There are 16 microcode registers at the moment
|
||||
FP_Base_DepTag = 32,
|
||||
Ctrl_Base_DepTag =
|
||||
FP_Base_DepTag +
|
||||
//mmx/x87 registers
|
||||
@@ -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;
|
||||
|
||||
@@ -264,31 +264,30 @@ namespace X86ISA
|
||||
Predecoder::State Predecoder::doModRMState(uint8_t nextByte)
|
||||
{
|
||||
State nextState = ErrorState;
|
||||
emi.modRM = nextByte;
|
||||
ModRM modRM;
|
||||
modRM = nextByte;
|
||||
DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
|
||||
if (0) {//FIXME in 16 bit mode
|
||||
//figure out 16 bit displacement size
|
||||
if(nextByte & 0xC7 == 0x06 ||
|
||||
nextByte & 0xC0 == 0x80)
|
||||
if(modRM.mod == 0 && modRM.rm == 6 || modRM.mod == 2)
|
||||
displacementSize = 2;
|
||||
else if(nextByte & 0xC0 == 0x40)
|
||||
else if(modRM.mod == 1)
|
||||
displacementSize = 1;
|
||||
else
|
||||
displacementSize = 0;
|
||||
} else {
|
||||
//figure out 32/64 bit displacement size
|
||||
if(nextByte & 0xC6 == 0x04 ||
|
||||
nextByte & 0xC0 == 0x80)
|
||||
if(modRM.mod == 0 && (modRM.rm == 4 || modRM.rm == 5)
|
||||
|| modRM.mod == 2)
|
||||
displacementSize = 4;
|
||||
else if(nextByte & 0xC0 == 0x40)
|
||||
else if(modRM.mod == 1)
|
||||
displacementSize = 1;
|
||||
else
|
||||
displacementSize = 0;
|
||||
}
|
||||
//If there's an SIB, get that next.
|
||||
//There is no SIB in 16 bit mode.
|
||||
if(nextByte & 0x7 == 4 &&
|
||||
nextByte & 0xC0 != 0xC0) {
|
||||
if(modRM.rm == 4 && modRM.mod != 3) {
|
||||
// && in 32/64 bit mode)
|
||||
nextState = SIBState;
|
||||
} else if(displacementSize) {
|
||||
@@ -301,6 +300,7 @@ namespace X86ISA
|
||||
}
|
||||
//The ModRM byte is consumed no matter what
|
||||
consumeByte();
|
||||
emi.modRM = modRM;
|
||||
return nextState;
|
||||
}
|
||||
|
||||
|
||||
@@ -195,12 +195,12 @@ namespace X86ISA
|
||||
|
||||
//Use this to give data to the predecoder. This should be used
|
||||
//when there is control flow.
|
||||
void moreBytes(Addr pc, Addr fetchPC, Addr off, MachInst data)
|
||||
void moreBytes(Addr pc, Addr fetchPC, MachInst data)
|
||||
{
|
||||
DPRINTF(Predecoder, "Getting more bytes.\n");
|
||||
basePC = fetchPC;
|
||||
offset = off;
|
||||
offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
|
||||
fetchChunk = data;
|
||||
assert(off < sizeof(MachInst));
|
||||
outOfBytes = false;
|
||||
process();
|
||||
}
|
||||
|
||||
@@ -268,7 +268,6 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
|
||||
int argv_array_size = intSize * (argv.size() + 1);
|
||||
|
||||
int argc_size = intSize;
|
||||
int window_save_size = intSize * 16;
|
||||
|
||||
int space_needed =
|
||||
mysterious_size +
|
||||
@@ -276,8 +275,7 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
|
||||
aux_array_size +
|
||||
envp_array_size +
|
||||
argv_array_size +
|
||||
argc_size +
|
||||
window_save_size;
|
||||
argc_size;
|
||||
|
||||
stack_min = stack_base - space_needed;
|
||||
stack_min &= alignmentMask;
|
||||
@@ -296,10 +294,6 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
|
||||
Addr envp_array_base = auxv_array_base - envp_array_size;
|
||||
Addr argv_array_base = envp_array_base - argv_array_size;
|
||||
Addr argc_base = argv_array_base - argc_size;
|
||||
#ifndef NDEBUG
|
||||
// only used in DPRINTF
|
||||
Addr window_save_base = argc_base - window_save_size;
|
||||
#endif
|
||||
|
||||
DPRINTF(X86, "The addresses of items on the initial stack:\n");
|
||||
DPRINTF(X86, "0x%x - file name\n", file_name_base);
|
||||
@@ -309,7 +303,6 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
|
||||
DPRINTF(X86, "0x%x - envp array\n", envp_array_base);
|
||||
DPRINTF(X86, "0x%x - argv array\n", argv_array_base);
|
||||
DPRINTF(X86, "0x%x - argc \n", argc_base);
|
||||
DPRINTF(X86, "0x%x - window save\n", window_save_base);
|
||||
DPRINTF(X86, "0x%x - stack min\n", stack_min);
|
||||
|
||||
// write contents to stack
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace X86ISA
|
||||
} opcode;
|
||||
//Modifier bytes
|
||||
ModRM modRM;
|
||||
uint8_t sib;
|
||||
Sib sib;
|
||||
//Immediate fields
|
||||
uint64_t immediate;
|
||||
uint64_t displacement;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -269,12 +269,10 @@ Tick
|
||||
BaseCPU::nextCycle(Tick begin_tick)
|
||||
{
|
||||
Tick next_tick = begin_tick;
|
||||
next_tick -= (next_tick % clock);
|
||||
if (next_tick % clock != 0)
|
||||
next_tick = next_tick - (next_tick % clock) + clock;
|
||||
next_tick += phase;
|
||||
|
||||
while (next_tick < curTick)
|
||||
next_tick += clock;
|
||||
|
||||
assert(next_tick >= curTick);
|
||||
return next_tick;
|
||||
}
|
||||
|
||||
@@ -650,7 +650,7 @@ Trace::InstRecord::dump()
|
||||
<< endl;
|
||||
|
||||
predecoder.setTC(thread);
|
||||
predecoder.moreBytes(m5Pc, m5Pc, 0,
|
||||
predecoder.moreBytes(m5Pc, m5Pc,
|
||||
shared_data->instruction);
|
||||
|
||||
assert(predecoder.extMachInstReady());
|
||||
|
||||
@@ -55,7 +55,7 @@ class DerivO3CPU(BaseCPU):
|
||||
checker.itb = Parent.itb
|
||||
checker.dtb = Parent.dtb
|
||||
|
||||
cachePorts = Param.Unsigned("Cache Ports")
|
||||
cachePorts = Param.Unsigned(200, "Cache Ports")
|
||||
icache_port = Port("Instruction Port")
|
||||
dcache_port = Port("Data Port")
|
||||
_mem_ports = ['icache_port', 'dcache_port']
|
||||
@@ -137,15 +137,15 @@ class DerivO3CPU(BaseCPU):
|
||||
function_trace = Param.Bool(False, "Enable function trace")
|
||||
function_trace_start = Param.Tick(0, "Cycle to start function trace")
|
||||
|
||||
smtNumFetchingThreads = Param.Unsigned("SMT Number of Fetching Threads")
|
||||
smtFetchPolicy = Param.String("SMT Fetch policy")
|
||||
smtLSQPolicy = Param.String("SMT LSQ Sharing Policy")
|
||||
smtLSQThreshold = Param.String("SMT LSQ Threshold Sharing Parameter")
|
||||
smtIQPolicy = Param.String("SMT IQ Sharing Policy")
|
||||
smtIQThreshold = Param.String("SMT IQ Threshold Sharing Parameter")
|
||||
smtROBPolicy = Param.String("SMT ROB Sharing Policy")
|
||||
smtROBThreshold = Param.String("SMT ROB Threshold Sharing Parameter")
|
||||
smtCommitPolicy = Param.String("SMT Commit Policy")
|
||||
smtNumFetchingThreads = Param.Unsigned(1, "SMT Number of Fetching Threads")
|
||||
smtFetchPolicy = Param.String('SingleThread', "SMT Fetch policy")
|
||||
smtLSQPolicy = Param.String('Partitioned', "SMT LSQ Sharing Policy")
|
||||
smtLSQThreshold = Param.Int(100, "SMT LSQ Threshold Sharing Parameter")
|
||||
smtIQPolicy = Param.String('Partitioned', "SMT IQ Sharing Policy")
|
||||
smtIQThreshold = Param.Int(100, "SMT IQ Threshold Sharing Parameter")
|
||||
smtROBPolicy = Param.String('Partitioned', "SMT ROB Sharing Policy")
|
||||
smtROBThreshold = Param.Int(100, "SMT ROB Threshold Sharing Parameter")
|
||||
smtCommitPolicy = Param.String('RoundRobin', "SMT Commit Policy")
|
||||
|
||||
def addPrivateSplitL1Caches(self, ic, dc):
|
||||
BaseCPU.addPrivateSplitL1Caches(self, ic, dc)
|
||||
|
||||
@@ -204,19 +204,17 @@ FullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, Params *params)
|
||||
_status = Idle;
|
||||
}
|
||||
|
||||
checker = NULL;
|
||||
|
||||
if (params->checker) {
|
||||
#if USE_CHECKER
|
||||
if (params->checker) {
|
||||
BaseCPU *temp_checker = params->checker;
|
||||
checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
|
||||
#if FULL_SYSTEM
|
||||
checker->setSystem(params->system);
|
||||
#endif
|
||||
#else
|
||||
panic("Checker enabled but not compiled in!");
|
||||
#endif // USE_CHECKER
|
||||
} else {
|
||||
checker = NULL;
|
||||
}
|
||||
#endif // USE_CHECKER
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
thread.resize(number_of_threads);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "base/statistics.hh"
|
||||
#include "base/timebuf.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "config/use_checker.hh"
|
||||
#include "cpu/activity.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/simple_thread.hh"
|
||||
@@ -617,11 +618,13 @@ class FullO3CPU : public BaseO3CPU
|
||||
/** The global sequence number counter. */
|
||||
InstSeqNum globalSeqNum;//[Impl::MaxThreads];
|
||||
|
||||
#if USE_CHECKER
|
||||
/** Pointer to the checker, which can dynamically verify
|
||||
* instruction results at run time. This can be set to NULL if it
|
||||
* is not being used.
|
||||
*/
|
||||
Checker<DynInstPtr> *checker;
|
||||
#endif
|
||||
|
||||
#if FULL_SYSTEM
|
||||
/** Pointer to the system. */
|
||||
|
||||
@@ -1128,7 +1128,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||
(&cacheData[tid][offset]));
|
||||
|
||||
predecoder.setTC(cpu->thread[tid]->getTC());
|
||||
predecoder.moreBytes(fetch_PC, fetch_PC, 0, inst);
|
||||
predecoder.moreBytes(fetch_PC, fetch_PC, inst);
|
||||
|
||||
ext_inst = predecoder.getExtMachInst();
|
||||
|
||||
|
||||
@@ -521,15 +521,15 @@ AtomicSimpleCPU::tick()
|
||||
dcache_access = false; // assume no dcache access
|
||||
|
||||
//Fetch more instruction memory if necessary
|
||||
if(predecoder.needMoreBytes())
|
||||
{
|
||||
//if(predecoder.needMoreBytes())
|
||||
//{
|
||||
icache_access = true;
|
||||
ifetch_pkt->reinitFromRequest();
|
||||
|
||||
icache_latency = icachePort.sendAtomic(ifetch_pkt);
|
||||
// ifetch_req is initialized to read the instruction directly
|
||||
// into the CPU object's inst field.
|
||||
}
|
||||
//}
|
||||
|
||||
preExecute();
|
||||
|
||||
|
||||
@@ -379,11 +379,11 @@ BaseSimpleCPU::preExecute()
|
||||
//This should go away once the constructor can be set up properly
|
||||
predecoder.setTC(thread->getTC());
|
||||
//If more fetch data is needed, pass it in.
|
||||
if(predecoder.needMoreBytes())
|
||||
predecoder.moreBytes(thread->readPC(),
|
||||
(thread->readPC() & PCMask) + fetchOffset, 0, inst);
|
||||
else
|
||||
predecoder.process();
|
||||
Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset;
|
||||
//if(predecoder.needMoreBytes())
|
||||
predecoder.moreBytes(thread->readPC(), fetchPC, inst);
|
||||
//else
|
||||
// predecoder.process();
|
||||
|
||||
//If an instruction is ready, decode it. Otherwise, we'll have to
|
||||
//fetch beyond the MachInst at the current pc.
|
||||
|
||||
@@ -560,8 +560,7 @@ TimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt)
|
||||
{
|
||||
if (pkt->isResponse()) {
|
||||
// delay processing of returned data until next CPU clock edge
|
||||
Tick mem_time = pkt->req->getTime();
|
||||
Tick next_tick = cpu->nextCycle(mem_time);
|
||||
Tick next_tick = cpu->nextCycle(curTick);
|
||||
|
||||
if (next_tick == curTick)
|
||||
cpu->completeIfetch(pkt);
|
||||
@@ -655,8 +654,7 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt)
|
||||
{
|
||||
if (pkt->isResponse()) {
|
||||
// delay processing of returned data until next CPU clock edge
|
||||
Tick mem_time = pkt->req->getTime();
|
||||
Tick next_tick = cpu->nextCycle(mem_time);
|
||||
Tick next_tick = cpu->nextCycle(curTick);
|
||||
|
||||
if (next_tick == curTick)
|
||||
cpu->completeDataAccess(pkt);
|
||||
|
||||
@@ -64,7 +64,8 @@ class EtherDump(SimObject):
|
||||
|
||||
class IGbE(PciDevice):
|
||||
type = 'IGbE'
|
||||
hardware_address = Param.String("Ethernet Hardware Address")
|
||||
hardware_address = Param.EthernetAddr(NextEthernetAddr,
|
||||
"Ethernet Hardware Address")
|
||||
use_flow_control = Param.Bool(False,
|
||||
"Should we use xon/xoff flow contorl (UNIMPLEMENTD)")
|
||||
rx_fifo_size = Param.MemorySize('384kB', "Size of the rx FIFO")
|
||||
@@ -100,9 +101,9 @@ class IGbEInt(EtherInt):
|
||||
type = 'IGbEInt'
|
||||
device = Param.IGbE("Ethernet device of this interface")
|
||||
|
||||
|
||||
|
||||
class EtherDevBase(PciDevice):
|
||||
type = 'EtherDevBase'
|
||||
abstract = True
|
||||
hardware_address = Param.EthernetAddr(NextEthernetAddr,
|
||||
"Ethernet Hardware Address")
|
||||
|
||||
|
||||
@@ -115,11 +115,14 @@ void Bus::occupyBus(PacketPtr pkt)
|
||||
//Bring tickNextIdle up to the present tick
|
||||
//There is some potential ambiguity where a cycle starts, which might make
|
||||
//a difference when devices are acting right around a cycle boundary. Using
|
||||
//a < allows things which happen exactly on a cycle boundary to take up only
|
||||
//the following cycle. Anthing that happens later will have to "wait" for
|
||||
//the end of that cycle, and then start using the bus after that.
|
||||
while (tickNextIdle < curTick)
|
||||
tickNextIdle += clock;
|
||||
//a < allows things which happen exactly on a cycle boundary to take up
|
||||
//only the following cycle. Anything that happens later will have to "wait"
|
||||
//for the end of that cycle, and then start using the bus after that.
|
||||
if (tickNextIdle < curTick) {
|
||||
tickNextIdle = curTick;
|
||||
if (tickNextIdle % clock != 0)
|
||||
tickNextIdle = curTick - (curTick % clock) + clock;
|
||||
}
|
||||
|
||||
// The packet will be sent. Figure out how long it occupies the bus, and
|
||||
// how much of that time is for the first "word", aka bus width.
|
||||
@@ -132,10 +135,9 @@ void Bus::occupyBus(PacketPtr pkt)
|
||||
// We're using the "adding instead of dividing" trick again here
|
||||
if (pkt->hasData()) {
|
||||
int dataSize = pkt->getSize();
|
||||
for (int transmitted = 0; transmitted < dataSize;
|
||||
transmitted += width) {
|
||||
numCycles += dataSize/width;
|
||||
if (dataSize % width)
|
||||
numCycles++;
|
||||
}
|
||||
} else {
|
||||
// If the packet didn't have data, it must have been a response.
|
||||
// Those use the bus for one cycle to send their data.
|
||||
|
||||
1
src/mem/cache/BaseCache.py
vendored
1
src/mem/cache/BaseCache.py
vendored
@@ -90,3 +90,4 @@ class BaseCache(MemObject):
|
||||
"Only prefetch on data not on instruction accesses")
|
||||
cpu_side = Port("Port on side closer to CPU")
|
||||
mem_side = Port("Port on side closer to MEM")
|
||||
addr_range = VectorParam.AddrRange(AllMemory, "The address range in bytes")
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <bitset>
|
||||
|
||||
#include "base/compiler.hh"
|
||||
#include "base/fast_alloc.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "sim/host.hh"
|
||||
@@ -177,7 +178,7 @@ class MemCmd
|
||||
* ultimate destination and back, possibly being conveyed by several
|
||||
* different Packets along the way.)
|
||||
*/
|
||||
class Packet
|
||||
class Packet : public FastAlloc
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -257,7 +258,7 @@ class Packet
|
||||
/** A virtual base opaque structure used to hold coherence-related
|
||||
* state. A specific subclass would be derived from this to
|
||||
* carry state specific to a particular coherence protocol. */
|
||||
class CoherenceState {
|
||||
class CoherenceState : public FastAlloc {
|
||||
public:
|
||||
virtual ~CoherenceState() {}
|
||||
};
|
||||
@@ -274,7 +275,7 @@ class Packet
|
||||
* needed to process it. A specific subclass would be derived
|
||||
* from this to carry state specific to a particular sending
|
||||
* device. */
|
||||
class SenderState {
|
||||
class SenderState : public FastAlloc {
|
||||
public:
|
||||
virtual ~SenderState() {}
|
||||
};
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#ifndef __MEM_REQUEST_HH__
|
||||
#define __MEM_REQUEST_HH__
|
||||
|
||||
#include "base/fast_alloc.hh"
|
||||
#include "sim/host.hh"
|
||||
#include "sim/core.hh"
|
||||
|
||||
@@ -76,7 +77,7 @@ const uint32_t MEM_SWAP = 0x100000;
|
||||
const uint32_t MEM_SWAP_COND = 0x200000;
|
||||
|
||||
|
||||
class Request
|
||||
class Request : public FastAlloc
|
||||
{
|
||||
private:
|
||||
/**
|
||||
@@ -153,6 +154,8 @@ class Request
|
||||
setVirt(_asid, _vaddr, _size, _flags, _pc);
|
||||
}
|
||||
|
||||
~Request() {} // for FastAlloc
|
||||
|
||||
/**
|
||||
* Set up CPU and thread numbers. */
|
||||
void setThreadContext(int _cpuNum, int _threadNum)
|
||||
|
||||
@@ -40,7 +40,7 @@ class LiveProcess(Process):
|
||||
type = 'LiveProcess'
|
||||
executable = Param.String('', "executable (overrides cmd[0] if set)")
|
||||
cmd = VectorParam.String("command line (executable plus arguments)")
|
||||
env = VectorParam.String('', "environment settings")
|
||||
env = VectorParam.String([], "environment settings")
|
||||
cwd = Param.String('', "current working directory")
|
||||
input = Param.String('cin', "filename for stdin")
|
||||
uid = Param.Int(100, 'user id')
|
||||
|
||||
@@ -39,6 +39,7 @@ class System(SimObject):
|
||||
physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
|
||||
mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
|
||||
if build_env['FULL_SYSTEM']:
|
||||
abstract = True
|
||||
boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
|
||||
"boot processor frequency")
|
||||
init_param = Param.UInt64(0, "numerical value to pass into simulator")
|
||||
|
||||
Reference in New Issue
Block a user