arch-x86: Use the new op bases for memory microops.

Change-Id: I73538b547093e6f872e085686ea164ef89527321
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/42346
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-03-04 02:34:52 -08:00
parent 9271dd659c
commit 6142401b55
7 changed files with 327 additions and 298 deletions

View File

@@ -51,7 +51,6 @@ Source('faults.cc')
Source('fs_workload.cc')
Source('insts/badmicroop.cc')
Source('insts/microfpop.cc')
Source('insts/microldstop.cc')
Source('insts/micromediaop.cc')
Source('insts/microop.cc')
Source('insts/microregop.cc')

View File

@@ -1,78 +0,0 @@
/*
* Copyright (c) 2007 The Hewlett-Packard Development Company
* Copyright (c) 2015 Advanced Micro Devices, Inc.
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 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 holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* 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.
*/
#include "arch/x86/insts/microldstop.hh"
#include <string>
namespace X86ISA
{
std::string
LdStOp::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
if (flags[IsLoad])
printDestReg(response, 0, dataSize);
else
printSrcReg(response, 2, dataSize);
response << ", ";
printMem(response, segment, scale, index, base, disp, addressSize, false);
return response.str();
}
std::string
LdStSplitOp::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
int baseRegIdx = flags[IsLoad] ? 0 : 2;
response << "[";
printDestReg(response, baseRegIdx, dataSize);
response << ", ";
printDestReg(response, baseRegIdx+1, dataSize);
response << "], ";
printMem(response, segment, scale, index, base, disp, addressSize, false);
return response.str();
}
}

View File

@@ -40,6 +40,7 @@
#define __ARCH_X86_INSTS_MICROLDSTOP_HH__
#include "arch/x86/insts/microop.hh"
#include "arch/x86/insts/microop_args.hh"
#include "arch/x86/ldstflags.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
@@ -54,65 +55,80 @@ namespace X86ISA
class MemOp : public X86MicroopBase
{
protected:
const uint8_t scale;
const RegIndex index;
const RegIndex base;
const uint64_t disp;
const uint8_t segment;
const uint8_t dataSize;
const uint8_t addressSize;
const Request::FlagsType memFlags;
RegIndex foldOBit, foldABit;
//Constructor
MemOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass),
scale(_scale), index(_index.index()), base(_base.index()),
disp(_disp), segment(_segment.index()),
dataSize(_dataSize), addressSize(_addressSize),
memFlags(_memFlags | _segment.index())
{
assert(_segment.index() < NUM_SEGMENTREGS);
foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
foldABit = (addressSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
}
MemOp(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem,
uint64_t set_flags, OpClass op_class,
uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags) :
X86MicroopBase(mach_inst, mnem, inst_mnem, set_flags, op_class),
memFlags(mem_flags),
dataSize(data_size), addressSize(address_size),
foldOBit((dataSize == 1 && !mach_inst.rex.present) ? 1 << 6 : 0),
foldABit((addressSize == 1 && !mach_inst.rex.present) ? 1 << 6 : 0)
{}
public:
const uint8_t dataSize;
const uint8_t addressSize;
const RegIndex foldOBit, foldABit;
};
/**
* Base class for load and store ops using one register
* Base class for load ops using one integer register.
*/
class LdStOp : public MemOp
class LdStOp : public InstOperands<MemOp, FoldedDataOp, AddrOp>
{
protected:
const RegIndex data;
//Constructor
LdStOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
LdStOp(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem,
uint64_t set_flags, InstRegIndex _data,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
MemOp(_machInst, mnem, _instMnem, setFlags,
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
data(_data.index())
{
}
uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags, OpClass op_class) :
InstOperands<MemOp, FoldedDataOp, AddrOp>(
mach_inst, mnem, inst_mnem, set_flags, op_class,
_data, { _scale, _index, _base, _disp, _segment },
data_size, address_size, mem_flags | _segment.index())
{}
};
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
/**
* Base class for load ops using one FP register.
*/
class LdStFpOp : public InstOperands<MemOp, FloatDataOp, AddrOp>
{
protected:
LdStFpOp(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem,
uint64_t set_flags, InstRegIndex _data,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags, OpClass op_class) :
InstOperands<MemOp, FloatDataOp, AddrOp>(
mach_inst, mnem, inst_mnem, set_flags, op_class,
_data, { _scale, _index, _base, _disp, _segment },
data_size, address_size, mem_flags | _segment.index())
{}
};
/**
* Base class for the tia microop which has no destination register.
*/
class MemNoDataOp : public InstOperands<MemOp, AddrOp>
{
protected:
MemNoDataOp(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem,
uint64_t set_flags, uint8_t _scale, InstRegIndex _index,
InstRegIndex _base, uint64_t _disp, InstRegIndex _segment,
uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags, OpClass op_class) :
InstOperands<MemOp, AddrOp>(
mach_inst, mnem, inst_mnem, set_flags, op_class,
{ _scale, _index, _base, _disp, _segment },
data_size, address_size, mem_flags | _segment.index())
{}
};
/**
@@ -120,33 +136,21 @@ class LdStOp : public MemOp
* call them split ops for this reason. These are mainly used to
* implement cmpxchg8b and cmpxchg16b.
*/
class LdStSplitOp : public MemOp
class LdStSplitOp :
public InstOperands<MemOp, FoldedDataLowOp, FoldedDataHiOp, AddrOp>
{
protected:
const RegIndex dataLow;
const RegIndex dataHi;
//Constructor
LdStSplitOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
LdStSplitOp(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem,
uint64_t set_flags, InstRegIndex data_low, InstRegIndex data_hi,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _dataLow, InstRegIndex _dataHi,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
MemOp(_machInst, mnem, _instMnem, setFlags,
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
dataLow(_dataLow.index()),
dataHi(_dataHi.index())
{
}
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags, OpClass op_class) :
InstOperands<MemOp, FoldedDataLowOp, FoldedDataHiOp, AddrOp>(
mach_inst, mnem, inst_mnem, set_flags, op_class,
data_low, data_hi, { _scale, _index, _base, _disp, _segment },
data_size, address_size, mem_flags | _segment.index())
{}
};
}

View File

@@ -46,7 +46,7 @@ struct DestOp
using ArgType = InstRegIndex;
const RegIndex dest;
const size_t size;
RegIndex index() const { return dest; }
RegIndex opIndex() const { return dest; }
DestOp(RegIndex _dest, size_t _size) : dest(_dest), size(_size) {}
};
@@ -56,7 +56,7 @@ struct Src1Op
using ArgType = InstRegIndex;
const RegIndex src1;
const size_t size;
RegIndex index() const { return src1; }
RegIndex opIndex() const { return src1; }
Src1Op(RegIndex _src1, size_t _size) : src1(_src1), size(_size) {}
};
@@ -66,11 +66,42 @@ struct Src2Op
using ArgType = InstRegIndex;
const RegIndex src2;
const size_t size;
RegIndex index() const { return src2; }
RegIndex opIndex() const { return src2; }
Src2Op(RegIndex _src2, size_t _size) : src2(_src2), size(_size) {}
};
struct DataOp
{
using ArgType = InstRegIndex;
const RegIndex data;
const size_t size;
RegIndex opIndex() const { return data; }
DataOp(RegIndex _data, size_t _size) : data(_data), size(_size) {}
};
struct DataHiOp
{
using ArgType = InstRegIndex;
const RegIndex dataHi;
const size_t size;
RegIndex opIndex() const { return dataHi; }
DataHiOp(RegIndex data_hi, size_t _size) : dataHi(data_hi), size(_size) {}
};
struct DataLowOp
{
using ArgType = InstRegIndex;
const RegIndex dataLow;
const size_t size;
RegIndex opIndex() const { return dataLow; }
DataLowOp(RegIndex data_low, size_t _size) : dataLow(data_low), size(_size)
{}
};
template <class Base>
struct FoldedOp : public Base
{
@@ -82,7 +113,7 @@ struct FoldedOp : public Base
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(IntRegClass, this->index()),
X86StaticInst::printReg(os, RegId(IntRegClass, this->opIndex()),
this->size);
}
};
@@ -96,7 +127,7 @@ struct CrOp : public Base
void
print(std::ostream &os) const
{
ccprintf(os, "cr%d", this->index());
ccprintf(os, "cr%d", this->opIndex());
}
};
@@ -109,7 +140,7 @@ struct DbgOp : public Base
void
print(std::ostream &os) const
{
ccprintf(os, "dr%d", this->index());
ccprintf(os, "dr%d", this->opIndex());
}
};
@@ -123,7 +154,7 @@ struct SegOp : public Base
void
print(std::ostream &os) const
{
X86StaticInst::printSegment(os, this->index());
X86StaticInst::printSegment(os, this->opIndex());
}
};
@@ -138,7 +169,23 @@ struct MiscOp : public Base
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(MiscRegClass, this->index()),
X86StaticInst::printReg(os, RegId(MiscRegClass, this->opIndex()),
this->size);
}
};
template <class Base>
struct FloatOp : public Base
{
template <class InstType>
FloatOp(InstType *inst, typename Base::ArgType idx) :
Base(idx.index(), inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(FloatRegClass, this->opIndex()),
this->size);
}
};
@@ -157,6 +204,11 @@ using MiscSrc1Op = MiscOp<Src1Op>;
using FoldedSrc2Op = FoldedOp<Src2Op>;
using FoldedDataOp = FoldedOp<DataOp>;
using FloatDataOp = FloatOp<DataOp>;
using FoldedDataHiOp = FoldedOp<DataHiOp>;
using FoldedDataLowOp = FoldedOp<DataLowOp>;
struct Imm8Op
{
using ArgType = uint8_t;
@@ -173,6 +225,42 @@ struct Imm8Op
}
};
struct AddrOp
{
struct ArgType
{
uint8_t scale;
InstRegIndex index;
InstRegIndex base;
uint64_t disp;
InstRegIndex segment;
};
const uint8_t scale;
const RegIndex index;
const RegIndex base;
const uint64_t disp;
const uint8_t segment;
const size_t size;
template <class InstType>
AddrOp(InstType *inst, const ArgType &args) : scale(args.scale),
index(INTREG_FOLDED(args.index.index(), inst->foldABit)),
base(INTREG_FOLDED(args.base.index(), inst->foldABit)),
disp(args.disp), segment(args.segment.index()),
size(inst->addressSize)
{
assert(segment < NUM_SEGMENTREGS);
}
void
print(std::ostream &os) const
{
X86StaticInst::printMem(
os, segment, scale, index, base, disp, size, false);
}
};
template <typename Base, typename ...Operands>
class InstOperands : public Base, public Operands...
{

View File

@@ -58,37 +58,37 @@ def macroop PREFETCH_T0_P
def macroop CLFLUSH_M
{
clflushopt t0, seg, sib, disp, dataSize=1
clflushopt seg, sib, disp, dataSize=1
mfence
};
def macroop CLFLUSH_P
{
rdip t7
clflushopt t0, seg, riprel, disp, dataSize=1
clflushopt seg, riprel, disp, dataSize=1
mfence
};
def macroop CLFLUSHOPT_M
{
clflushopt t0, seg, sib, disp, dataSize=1
clflushopt seg, sib, disp, dataSize=1
};
def macroop CLFLUSHOPT_P
{
rdip t7
clflushopt t0, seg, riprel, disp, dataSize=1
clflushopt seg, riprel, disp, dataSize=1
};
def macroop CLWB_M
{
clwb t1, seg, sib, disp, dataSize=1
clwb seg, sib, disp, dataSize=1
};
def macroop CLWB_P
{
rdip t7
clwb t1, seg, riprel, disp, dataSize=1
clwb seg, riprel, disp, dataSize=1
};
'''

View File

@@ -58,8 +58,7 @@ def template MicroLeaExecute {{
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
%(code)s;
if(fault == NoFault)
{
if (fault == NoFault) {
%(op_wb)s;
}
@@ -74,13 +73,16 @@ def template MicroLeaDeclare {{
%(reg_idx_arr_decl)s;
public:
%(class_name)s(ExtMachInst _machInst,
const char * instMnem, uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags);
template <typename ...Args>
%(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
uint64_t set_flags, uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags, Args ...args) :
%(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
args..., data_size, address_size, mem_flags, %(op_class)s)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
@@ -89,8 +91,9 @@ def template MicroLeaDeclare {{
// Load templates
def template MicroLoadExecute {{
Fault %(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
Fault
%(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Addr EA;
@@ -108,8 +111,7 @@ def template MicroLoadExecute {{
// For prefetches, ignore any faults/exceptions.
return NoFault;
}
if(fault == NoFault)
{
if (fault == NoFault) {
%(op_wb)s;
}
@@ -118,8 +120,9 @@ def template MicroLoadExecute {{
}};
def template MicroLoadInitiateAcc {{
Fault %(class_name)s::initiateAcc(ExecContext * xc,
Trace::InstRecord * traceData) const
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Addr EA;
@@ -129,16 +132,16 @@ def template MicroLoadInitiateAcc {{
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
fault = initiateMemRead(xc, traceData, EA,
%(memDataSize)s, memFlags);
fault = initiateMemRead(xc, traceData, EA, %(memDataSize)s, memFlags);
return fault;
}
}};
def template MicroLoadCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext * xc,
Trace::InstRecord * traceData) const
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
@@ -149,8 +152,7 @@ def template MicroLoadCompleteAcc {{
%(code)s;
if(fault == NoFault)
{
if (fault == NoFault) {
%(op_wb)s;
}
@@ -161,7 +163,8 @@ def template MicroLoadCompleteAcc {{
// Store templates
def template MicroStoreExecute {{
Fault %(class_name)s::execute(ExecContext * xc,
Fault
%(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
@@ -176,7 +179,7 @@ def template MicroStoreExecute {{
if (fault == NoFault) {
fault = writeMemAtomic(xc, traceData, Mem, dataSize, EA,
memFlags, NULL);
memFlags, NULL);
if (fault == NoFault) {
%(op_wb)s;
}
@@ -187,8 +190,9 @@ def template MicroStoreExecute {{
}};
def template MicroStoreInitiateAcc {{
Fault %(class_name)s::initiateAcc(ExecContext * xc,
Trace::InstRecord * traceData) const
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
@@ -202,15 +206,16 @@ def template MicroStoreInitiateAcc {{
if (fault == NoFault) {
fault = writeMemTiming(xc, traceData, Mem, dataSize, EA,
memFlags, NULL);
memFlags, NULL);
}
return fault;
}
}};
def template MicroStoreCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
ExecContext * xc, Trace::InstRecord * traceData) const
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
Trace::InstRecord *traceData) const
{
%(op_decl)s;
%(op_rd)s;
@@ -227,13 +232,17 @@ def template MicroLdStOpDeclare {{
%(reg_idx_arr_decl)s;
public:
%(class_name)s(ExtMachInst _machInst,
const char * instMnem, uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags);
template <typename ...Args>
%(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
uint64_t set_flags, uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags, Args ...args) :
%(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
args..., data_size, address_size, mem_flags, %(op_class)s)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
@@ -251,13 +260,13 @@ def template MicroLdStSplitOpDeclare {{
%(reg_idx_arr_decl)s;
public:
%(class_name)s(ExtMachInst _machInst,
const char * instMnem, uint64_t setFlags,
%(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
uint64_t set_flags,
InstRegIndex data_low, InstRegIndex data_hi,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _dataLow, InstRegIndex _dataHi,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags);
uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags);
Fault execute(ExecContext *, Trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
@@ -266,36 +275,17 @@ def template MicroLdStSplitOpDeclare {{
};
}};
def template MicroLdStOpConstructor {{
%(class_name)s::%(class_name)s(
ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
_scale, _index, _base,
_disp, _segment, _data,
_dataSize, _addressSize, _memFlags, %(op_class)s)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
}};
def template MicroLdStSplitOpConstructor {{
%(class_name)s::%(class_name)s(
ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
%(class_name)s::%(class_name)s(ExtMachInst mach_inst,
const char *inst_mnem, uint64_t set_flags,
InstRegIndex data_low, InstRegIndex data_hi,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _dataLow, InstRegIndex _dataHi,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
_scale, _index, _base,
_disp, _segment, _dataLow, _dataHi,
_dataSize, _addressSize, _memFlags, %(op_class)s)
uint8_t data_size, uint8_t address_size,
Request::FlagsType mem_flags) :
%(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
data_low, data_hi, _scale, _index, _base, _disp, _segment,
data_size, address_size, mem_flags, %(op_class)s)
{
%(set_reg_idx_arr)s;
%(constructor)s;
@@ -332,9 +322,9 @@ let {{
def getAllocator(self, microFlags):
allocator = '''new %(class_name)s(machInst, macrocodeBlock,
%(flags)s, %(scale)s, %(index)s, %(base)s,
%(disp)s, %(segment)s, %(data)s,
%(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
%(flags)s, %(dataSize)s, %(addressSize)s, %(memFlags)s,
%(data)s, %(scale)s, %(index)s, %(base)s,
%(disp)s, %(segment)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags) + self.instFlags,
"scale" : self.scale, "index" : self.index,
@@ -376,13 +366,13 @@ let {{
allocString = '''
(%(dataSize)s >= 4) ?
(StaticInstPtr)(new %(class_name)sBig(machInst,
macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
%(base)s, %(disp)s, %(segment)s, %(data)s,
%(dataSize)s, %(addressSize)s, %(memFlags)s)) :
macrocodeBlock, %(flags)s, %(dataSize)s,
%(addressSize)s, %(memFlags)s, %(data)s, %(scale)s,
%(index)s, %(base)s, %(disp)s, %(segment)s)) :
(StaticInstPtr)(new %(class_name)s(machInst,
macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
%(base)s, %(disp)s, %(segment)s, %(data)s,
%(dataSize)s, %(addressSize)s, %(memFlags)s))
macrocodeBlock, %(flags)s, %(dataSize)s,
%(addressSize)s, %(memFlags)s, %(data)s, %(scale)s,
%(index)s, %(base)s, %(disp)s, %(segment)s))
'''
allocator = allocString % {
"class_name" : self.className,
@@ -406,9 +396,8 @@ let {{
def getAllocator(self, microFlags):
allocString = '''(StaticInstPtr)(new %(class_name)s(machInst,
macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
%(base)s, %(disp)s, %(segment)s,
%(dataLow)s, %(dataHi)s,
macrocodeBlock, %(flags)s, %(dataLow)s, %(dataHi)s,
%(scale)s, %(index)s, %(base)s, %(disp)s, %(segment)s,
%(dataSize)s, %(addressSize)s, %(memFlags)s))
'''
allocator = allocString % {
@@ -423,6 +412,34 @@ let {{
"memFlags" : self.memFlags}
return allocator
class MemNoDataOp(X86Microop):
def __init__(self, segment, addr, disp=0,
dataSize="env.dataSize", addressSize="env.addressSize",
baseFlags="0"):
[self.scale, self.index, self.base] = addr
self.disp = disp
self.segment = segment
self.dataSize = dataSize
self.addressSize = addressSize
self.instFlags = ""
self.memFlags = baseFlags + "| " \
"(machInst.legacy.addr ? (AddrSizeFlagBit << FlagShift) : 0)"
def getAllocator(self, microFlags):
allocator = '''new %(class_name)s(machInst, macrocodeBlock,
%(flags)s, %(dataSize)s, %(addressSize)s, %(memFlags)s,
%(scale)s, %(index)s, %(base)s, %(disp)s,
%(segment)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags) + self.instFlags,
"scale" : self.scale, "index" : self.index,
"base" : self.base,
"disp" : self.disp,
"segment" : self.segment,
"dataSize" : self.dataSize, "addressSize" : self.addressSize,
"memFlags" : self.memFlags}
return allocator
}};
let {{
@@ -440,7 +457,7 @@ let {{
def defineMicroLoadOp(mnemonic, code, bigCode='',
mem_flags="0", big=True, nonSpec=False,
implicitStack=False):
implicitStack=False, is_float=False):
global header_output
global decoder_output
global exec_output
@@ -448,19 +465,23 @@ let {{
Name = mnemonic
name = mnemonic.lower()
if is_float:
base = 'X86ISA::LdStFpOp'
else:
base = 'X86ISA::LdStOp'
# Build up the all register version of this micro op
iops = [InstObjParams(name, Name, 'X86ISA::LdStOp',
iops = [InstObjParams(name, Name, base,
{ "code": code,
"ea_code": calculateEA,
"memDataSize": "dataSize" })]
if big:
iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp',
iops += [InstObjParams(name, Name + "Big", base,
{ "code": bigCode,
"ea_code": calculateEA,
"memDataSize": "dataSize" })]
for iop in iops:
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)
@@ -503,7 +524,8 @@ let {{
'(StoreCheck << FlagShift) | Request::LOCKED_RMW',
nonSpec=True)
defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False)
defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big=False,
is_float=True)
defineMicroLoadOp('Ldfp87', code='''
switch (dataSize)
@@ -517,7 +539,7 @@ let {{
default:
panic("Unhandled data size in LdFp87.\\n");
}
''', big = False)
''', big=False, is_float=True)
# Load integer from memory into x87 top-of-stack register.
# Used to implement fild instruction.
@@ -536,7 +558,7 @@ let {{
default:
panic("Unhandled data size in LdIFp87.\\n");
}
''', big = False)
''', big=False, is_float=True)
def defineMicroLoadSplitOp(mnemonic, code, mem_flags="0", nonSpec=False):
global header_output
@@ -584,7 +606,7 @@ let {{
nonSpec=True)
def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0",
implicitStack=False):
implicitStack=False, is_float=False, has_data=True):
global header_output
global decoder_output
global exec_output
@@ -592,14 +614,20 @@ let {{
Name = mnemonic
name = mnemonic.lower()
if not has_data:
base = 'X86ISA::MemNoDataOp'
elif is_float:
base = 'X86ISA::LdStFpOp'
else:
base = 'X86ISA::LdStOp'
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
iop = InstObjParams(name, Name, base,
{ "code": code,
"complete_code": completeCode,
"ea_code": calculateEA,
"memDataSize": "dataSize" })
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)
@@ -612,17 +640,25 @@ let {{
else:
addressSize = "env.addressSize"
class StoreOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize=addressSize,
atCPL0=False, nonSpec=False, implicitStack=implicitStack,
uncacheable=False):
super(StoreOp, self).__init__(data, segment, addr, disp,
dataSize, addressSize, mem_flags, atCPL0, False,
nonSpec, implicitStack, uncacheable)
self.className = Name
self.mnemonic = name
if has_data:
class StoreOp(LdStOp):
def __init__(self, data, segment, addr, disp=0,
dataSize="env.dataSize", addressSize=addressSize,
atCPL0=False, nonSpec=False,
implicitStack=implicitStack, uncacheable=False):
super(StoreOp, self).__init__(data, segment, addr, disp,
dataSize, addressSize, mem_flags, atCPL0, False,
nonSpec, implicitStack, uncacheable)
self.className = Name
self.mnemonic = name
else:
class StoreOp(MemNoDataOp):
def __init__(self, segment, addr, disp=0,
dataSize="env.dataSize", addressSize=addressSize):
super(StoreOp, self).__init__(segment, addr, disp,
dataSize, addressSize, mem_flags)
self.className = Name
self.mnemonic = name
microopClasses[name] = StoreOp
@@ -632,7 +668,7 @@ let {{
defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
mem_flags="Request::LOCKED_RMW")
defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;')
defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;', is_float=True)
defineMicroStoreOp('Stfp87', code='''
switch (dataSize)
@@ -647,13 +683,14 @@ let {{
default:
panic("Unhandled data size in StFp87.\\n");
}
''')
''', is_float=True)
defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS",
has_data=False)
defineMicroStoreOp('Clflushopt', 'Mem = 0;',
mem_flags="Request::CLEAN | Request::INVALIDATE" +
" | Request::DST_POC")
defineMicroStoreOp('Clwb', 'Mem = 0;',
" | Request::DST_POC", has_data=False)
defineMicroStoreOp('Clwb', 'Mem = 0;', has_data=False,
mem_flags="Request::CLEAN | Request::DST_POC")
def defineMicroStoreSplitOp(mnemonic, code,
@@ -706,7 +743,6 @@ let {{
"ea_code": "EA = " + segmentEAExpr,
"memDataSize": "dataSize" })
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
class LeaOp(LdStOp):
@@ -721,35 +757,15 @@ let {{
microopClasses["lea"] = LeaOp
iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
iop = InstObjParams("tia", "Tia", 'X86ISA::MemNoDataOp',
{ "code": "xc->demapPage(EA, 0);",
"ea_code": calculateEA,
"memDataSize": "dataSize" })
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
class TiaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize"):
super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
addr, disp, dataSize, addressSize, "0", False, False,
False, False, False)
self.className = "Tia"
self.mnemonic = "tia"
class TiaOp(MemNoDataOp):
className = "Tia"
mnemonic = "tia"
microopClasses["tia"] = TiaOp
class CdaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize", atCPL0=False):
super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
addr, disp, dataSize, addressSize, "Request::NO_ACCESS",
atCPL0, False, False, False, False)
self.className = "Cda"
self.mnemonic = "cda"
microopClasses["cda"] = CdaOp
}};

View File

@@ -93,13 +93,13 @@ def operands {{
'SSrcReg1': intReg('src1', 1),
'SrcReg2': foldInt('src2', 'foldOBit', 2),
'SSrcReg2': intReg('src2', 2),
'Index': foldInt('index', 'foldABit', 3),
'Base': foldInt('base', 'foldABit', 4),
'Index': intReg('index', 3),
'Base': intReg('base', 4),
'DestReg': foldInt('dest', 'foldOBit', 5),
'SDestReg': intReg('dest', 5),
'Data': foldInt('data', 'foldOBit', 6),
'DataLow': foldInt('dataLow', 'foldOBit', 6),
'DataHi': foldInt('dataHi', 'foldOBit', 6),
'Data': intReg('data', 6),
'DataLow': intReg('dataLow', 6),
'DataHi': intReg('dataHi', 6),
'ProdLow': impIntReg(0, 7),
'ProdHi': impIntReg(1, 8),
'Quotient': impIntReg(2, 9),