arch-arm: Implement AT as standalone instructions (#1697)
Moving the address translation logic outside of the ISA::setMiscReg will allow it to return and potentially invoke a fault upon execution of the AT instruction. This change affects AArch64 mode only
This commit is contained in:
@@ -1430,6 +1430,9 @@ DataAbort::annotate(AnnotationIDs id, uint64_t val)
|
|||||||
case OFA:
|
case OFA:
|
||||||
faultAddr = val;
|
faultAddr = val;
|
||||||
break;
|
break;
|
||||||
|
case WnR:
|
||||||
|
write = val;
|
||||||
|
break;
|
||||||
// Just ignore unknown ID's
|
// Just ignore unknown ID's
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ class ArmFault : public FaultBase
|
|||||||
// the abort is triggered by a CMO. The faulting address is
|
// the abort is triggered by a CMO. The faulting address is
|
||||||
// then the address specified in the register argument of the
|
// then the address specified in the register argument of the
|
||||||
// instruction and not the cacheline address (See FAR doc)
|
// instruction and not the cacheline address (See FAR doc)
|
||||||
|
WnR, // Write or Read. it should be forced to 1 when
|
||||||
|
// Cache maintainance and address translation instruction.
|
||||||
|
|
||||||
// AArch64 only
|
// AArch64 only
|
||||||
SF, // DataAbort: width of the accessed register is SixtyFour
|
SF, // DataAbort: width of the accessed register is SixtyFour
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "arch/arm/isa.hh"
|
#include "arch/arm/isa.hh"
|
||||||
|
|
||||||
#include "arch/arm/tlbi_op.hh"
|
#include "arch/arm/tlbi_op.hh"
|
||||||
|
#include "debug/MiscRegs.hh"
|
||||||
|
|
||||||
namespace gem5
|
namespace gem5
|
||||||
{
|
{
|
||||||
@@ -2533,4 +2534,113 @@ TlbiOp64::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<Fault, uint64_t>
|
||||||
|
AtOp64::performAt(ExecContext *xc, MiscRegIndex dest_idx, RegVal val) const
|
||||||
|
{
|
||||||
|
ThreadContext* tc = xc->tcBase();
|
||||||
|
|
||||||
|
switch (dest_idx) {
|
||||||
|
case MISCREG_AT_S1E1R_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E1Tran, BaseMMU::Read, 0, val);
|
||||||
|
case MISCREG_AT_S1E1W_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E1Tran, BaseMMU::Write, 0, val);
|
||||||
|
case MISCREG_AT_S1E0R_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E0Tran, BaseMMU::Read,
|
||||||
|
MMU::UserMode, val);
|
||||||
|
case MISCREG_AT_S1E0W_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E0Tran, BaseMMU::Write,
|
||||||
|
MMU::UserMode, val);
|
||||||
|
case MISCREG_AT_S1E2R_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E2Tran, BaseMMU::Read, 0, val);
|
||||||
|
case MISCREG_AT_S1E2W_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E2Tran, BaseMMU::Write, 0, val);
|
||||||
|
case MISCREG_AT_S12E1R_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S12E1Tran, BaseMMU::Read, 0, val);
|
||||||
|
case MISCREG_AT_S12E1W_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S12E1Tran, BaseMMU::Write,
|
||||||
|
0, val);
|
||||||
|
case MISCREG_AT_S12E0R_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S12E0Tran, BaseMMU::Read,
|
||||||
|
MMU::UserMode, val);
|
||||||
|
case MISCREG_AT_S12E0W_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S12E0Tran, BaseMMU::Write,
|
||||||
|
MMU::UserMode, val);
|
||||||
|
case MISCREG_AT_S1E3R_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E3Tran, BaseMMU::Read, 0, val);
|
||||||
|
case MISCREG_AT_S1E3W_Xt:
|
||||||
|
return addressTranslation64(tc, MMU::S1E3Tran, BaseMMU::Write, 0, val);
|
||||||
|
default:
|
||||||
|
return std::make_pair(NoFault, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(NoFault, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Fault, uint64_t>
|
||||||
|
AtOp64::addressTranslation64(ThreadContext* tc,
|
||||||
|
ArmISA::MMU::ArmTranslationType tran_type,
|
||||||
|
BaseMMU::Mode mode, Request::Flags flags, RegVal val) const
|
||||||
|
{
|
||||||
|
// If we're in timing mode then doing the translation in
|
||||||
|
// functional mode then we're slightly distorting performance
|
||||||
|
// results obtained from simulations. The translation should be
|
||||||
|
// done in the same mode the core is running in. NOTE: This
|
||||||
|
// can't be an atomic translation because that causes problems
|
||||||
|
// with unexpected atomic snoop requests.
|
||||||
|
warn_once("Doing AT (address translation) in functional mode! Fix Me!\n");
|
||||||
|
|
||||||
|
auto req = std::make_shared<Request>(
|
||||||
|
val, 0, flags, Request::funcRequestorId,
|
||||||
|
tc->pcState().instAddr(), tc->contextId());
|
||||||
|
|
||||||
|
Fault fault = getMMUPtr(tc)->translateAtomic(
|
||||||
|
req, tc, mode, tran_type);
|
||||||
|
|
||||||
|
PAR par = 0;
|
||||||
|
bool raise_fault = false;
|
||||||
|
if (fault == NoFault) {
|
||||||
|
Addr paddr = req->getPaddr();
|
||||||
|
uint64_t attr = getMMUPtr(tc)->getAttr();
|
||||||
|
// clear LAPE bit from attribute.
|
||||||
|
attr &= ~ uint64_t(0x800);
|
||||||
|
uint64_t attr1 = attr >> 56;
|
||||||
|
if (!(attr1 >> 4) || attr1 == 0x44) {
|
||||||
|
attr |= 0x100;
|
||||||
|
attr &= ~ uint64_t(0x80);
|
||||||
|
}
|
||||||
|
par = (paddr & mask(47, 12)) | attr;
|
||||||
|
DPRINTF(MiscRegs, "AT: Translated addr %#x: PAR_EL1: %#x\n",
|
||||||
|
val, par);
|
||||||
|
} else {
|
||||||
|
ArmFault *arm_fault = static_cast<ArmFault *>(fault.get());
|
||||||
|
arm_fault->update(tc);
|
||||||
|
// Set fault bit and FSR
|
||||||
|
FSR fsr = arm_fault->getFsr(tc);
|
||||||
|
|
||||||
|
arm_fault->annotate(ArmFault::CM, 1); // CM
|
||||||
|
arm_fault->annotate(ArmFault::WnR, 1); // Force WnR as 1
|
||||||
|
|
||||||
|
par.f = 1; // F bit
|
||||||
|
par.fst = fsr.status; // FST
|
||||||
|
par.ptw = (arm_fault->iss() >> 7) & 0x1; // S1PTW
|
||||||
|
par.s = arm_fault->isStage2() ? 1 : 0; // S
|
||||||
|
// set RES1 bit [11].
|
||||||
|
par |= 0x800;
|
||||||
|
|
||||||
|
// Only raise fault for external abort and stage 2 fault,
|
||||||
|
// see R~NHWXL~ in Arm-ARM.
|
||||||
|
raise_fault = arm_fault->isExternalAbort() || par.ptw;
|
||||||
|
|
||||||
|
DPRINTF(MiscRegs, "AT: Translated addr %#x fault fsr %#x: PAR: %#x\n",
|
||||||
|
val, fsr, par);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fault filter.
|
||||||
|
if (fault != NoFault && !raise_fault) {
|
||||||
|
fault = NoFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(fault, par);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace gem5
|
} // namespace gem5
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#define __ARCH_ARM_INSTS_MISC64_HH__
|
#define __ARCH_ARM_INSTS_MISC64_HH__
|
||||||
|
|
||||||
#include "arch/arm/insts/static_inst.hh"
|
#include "arch/arm/insts/static_inst.hh"
|
||||||
|
#include "arch/arm/mmu.hh"
|
||||||
#include "arch/arm/tlbi_op.hh"
|
#include "arch/arm/tlbi_op.hh"
|
||||||
#include "arch/arm/types.hh"
|
#include "arch/arm/types.hh"
|
||||||
|
|
||||||
@@ -339,6 +340,23 @@ class TlbiOp64 : public MiscRegRegImmOp64
|
|||||||
ArmISA::MiscRegIndex idx, RegVal value) const;
|
ArmISA::MiscRegIndex idx, RegVal value) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AtOp64 : public MiscRegRegImmOp64
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
AtOp64(const char *mnem, ArmISA::ExtMachInst _machInst,
|
||||||
|
OpClass __opClass, ArmISA::MiscRegIndex _dest,
|
||||||
|
RegIndex _op1) :
|
||||||
|
MiscRegRegImmOp64(mnem, _machInst, __opClass, _dest, _op1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::pair<Fault, uint64_t> performAt(ExecContext *xc,
|
||||||
|
ArmISA::MiscRegIndex idx, RegVal val) const;
|
||||||
|
|
||||||
|
std::pair<Fault, uint64_t> addressTranslation64(ThreadContext* tc,
|
||||||
|
ArmISA::MMU::ArmTranslationType tran_type,
|
||||||
|
BaseMMU::Mode mode, Request::Flags flags, RegVal val) const;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace gem5
|
} // namespace gem5
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1293,46 +1293,6 @@ ISA::setMiscReg(RegIndex idx, RegVal val)
|
|||||||
idx = MISCREG_CPSR;
|
idx = MISCREG_CPSR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E1R_Xt:
|
|
||||||
addressTranslation64(MMU::S1E1Tran, BaseMMU::Read, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S1E1W_Xt:
|
|
||||||
addressTranslation64(MMU::S1E1Tran, BaseMMU::Write, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S1E0R_Xt:
|
|
||||||
addressTranslation64(MMU::S1E0Tran, BaseMMU::Read,
|
|
||||||
MMU::UserMode, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S1E0W_Xt:
|
|
||||||
addressTranslation64(MMU::S1E0Tran, BaseMMU::Write,
|
|
||||||
MMU::UserMode, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S1E2R_Xt:
|
|
||||||
addressTranslation64(MMU::S1E2Tran, BaseMMU::Read, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S1E2W_Xt:
|
|
||||||
addressTranslation64(MMU::S1E2Tran, BaseMMU::Write, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S12E1R_Xt:
|
|
||||||
addressTranslation64(MMU::S12E1Tran, BaseMMU::Read, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S12E1W_Xt:
|
|
||||||
addressTranslation64(MMU::S12E1Tran, BaseMMU::Write, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S12E0R_Xt:
|
|
||||||
addressTranslation64(MMU::S12E0Tran, BaseMMU::Read,
|
|
||||||
MMU::UserMode, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S12E0W_Xt:
|
|
||||||
addressTranslation64(MMU::S12E0Tran, BaseMMU::Write,
|
|
||||||
MMU::UserMode, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S1E3R_Xt:
|
|
||||||
addressTranslation64(MMU::S1E3Tran, BaseMMU::Read, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_AT_S1E3W_Xt:
|
|
||||||
addressTranslation64(MMU::S1E3Tran, BaseMMU::Write, 0, val);
|
|
||||||
return;
|
|
||||||
case MISCREG_L2CTLR:
|
case MISCREG_L2CTLR:
|
||||||
warn("miscreg L2CTLR (%s) written with %#x. ignored...\n",
|
warn("miscreg L2CTLR (%s) written with %#x. ignored...\n",
|
||||||
miscRegName[idx], uint32_t(val));
|
miscRegName[idx], uint32_t(val));
|
||||||
@@ -1596,57 +1556,6 @@ ISA::unserialize(CheckpointIn &cp)
|
|||||||
updateRegMap(tmp_cpsr);
|
updateRegMap(tmp_cpsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ISA::addressTranslation64(MMU::ArmTranslationType tran_type,
|
|
||||||
BaseMMU::Mode mode, Request::Flags flags, RegVal val)
|
|
||||||
{
|
|
||||||
// If we're in timing mode then doing the translation in
|
|
||||||
// functional mode then we're slightly distorting performance
|
|
||||||
// results obtained from simulations. The translation should be
|
|
||||||
// done in the same mode the core is running in. NOTE: This
|
|
||||||
// can't be an atomic translation because that causes problems
|
|
||||||
// with unexpected atomic snoop requests.
|
|
||||||
warn_once("Doing AT (address translation) in functional mode! Fix Me!\n");
|
|
||||||
|
|
||||||
auto req = std::make_shared<Request>(
|
|
||||||
val, 0, flags, Request::funcRequestorId,
|
|
||||||
tc->pcState().instAddr(), tc->contextId());
|
|
||||||
|
|
||||||
Fault fault = getMMUPtr(tc)->translateFunctional(
|
|
||||||
req, tc, mode, tran_type);
|
|
||||||
|
|
||||||
PAR par = 0;
|
|
||||||
if (fault == NoFault) {
|
|
||||||
Addr paddr = req->getPaddr();
|
|
||||||
uint64_t attr = getMMUPtr(tc)->getAttr();
|
|
||||||
uint64_t attr1 = attr >> 56;
|
|
||||||
if (!attr1 || attr1 ==0x44) {
|
|
||||||
attr |= 0x100;
|
|
||||||
attr &= ~ uint64_t(0x80);
|
|
||||||
}
|
|
||||||
par = (paddr & mask(47, 12)) | attr;
|
|
||||||
DPRINTF(MiscRegs,
|
|
||||||
"MISCREG: Translated addr %#x: PAR_EL1: %#xx\n",
|
|
||||||
val, par);
|
|
||||||
} else {
|
|
||||||
ArmFault *arm_fault = static_cast<ArmFault *>(fault.get());
|
|
||||||
arm_fault->update(tc);
|
|
||||||
// Set fault bit and FSR
|
|
||||||
FSR fsr = arm_fault->getFsr(tc);
|
|
||||||
|
|
||||||
par.f = 1; // F bit
|
|
||||||
par.fst = fsr.status; // FST
|
|
||||||
par.ptw = (arm_fault->iss() >> 7) & 0x1; // S1PTW
|
|
||||||
par.s = arm_fault->isStage2() ? 1 : 0; // S
|
|
||||||
|
|
||||||
DPRINTF(MiscRegs,
|
|
||||||
"MISCREG: Translated addr %#x fault fsr %#x: PAR: %#x\n",
|
|
||||||
val, fsr, par);
|
|
||||||
}
|
|
||||||
setMiscRegNoEffect(MISCREG_PAR_EL1, par);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ISA::addressTranslation(MMU::ArmTranslationType tran_type,
|
ISA::addressTranslation(MMU::ArmTranslationType tran_type,
|
||||||
BaseMMU::Mode mode, Request::Flags flags, RegVal val)
|
BaseMMU::Mode mode, Request::Flags flags, RegVal val)
|
||||||
|
|||||||
@@ -173,8 +173,6 @@ namespace ArmISA
|
|||||||
protected:
|
protected:
|
||||||
void addressTranslation(MMU::ArmTranslationType tran_type,
|
void addressTranslation(MMU::ArmTranslationType tran_type,
|
||||||
BaseMMU::Mode mode, Request::Flags flags, RegVal val);
|
BaseMMU::Mode mode, Request::Flags flags, RegVal val);
|
||||||
void addressTranslation64(MMU::ArmTranslationType tran_type,
|
|
||||||
BaseMMU::Mode mode, Request::Flags flags, RegVal val);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelfDebug*
|
SelfDebug*
|
||||||
|
|||||||
@@ -624,6 +624,21 @@ namespace Aarch64
|
|||||||
TLBI_CASE_VARIANTS(MISCREG_TLBI_RVALE3OS)
|
TLBI_CASE_VARIANTS(MISCREG_TLBI_RVALE3OS)
|
||||||
return new Tlbi64ShareableHub(
|
return new Tlbi64ShareableHub(
|
||||||
machInst, miscReg, rt, dec.dvmEnabled);
|
machInst, miscReg, rt, dec.dvmEnabled);
|
||||||
|
// AT instructions
|
||||||
|
case MISCREG_AT_S1E1R_Xt:
|
||||||
|
case MISCREG_AT_S1E1W_Xt:
|
||||||
|
case MISCREG_AT_S1E0R_Xt:
|
||||||
|
case MISCREG_AT_S1E0W_Xt:
|
||||||
|
case MISCREG_AT_S1E2R_Xt:
|
||||||
|
case MISCREG_AT_S1E2W_Xt:
|
||||||
|
case MISCREG_AT_S12E1R_Xt:
|
||||||
|
case MISCREG_AT_S12E1W_Xt:
|
||||||
|
case MISCREG_AT_S12E0R_Xt:
|
||||||
|
case MISCREG_AT_S12E0W_Xt:
|
||||||
|
case MISCREG_AT_S1E3R_Xt:
|
||||||
|
case MISCREG_AT_S1E3W_Xt:
|
||||||
|
return new At64Hub(machInst, miscReg,
|
||||||
|
MiscRegIndex::MISCREG_PAR_EL1, rt);
|
||||||
default:
|
default:
|
||||||
return new Msr64(machInst, miscReg, rt);
|
return new Msr64(machInst, miscReg, rt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -401,6 +401,20 @@ let {{
|
|||||||
exec_output += DvmInitiateAcc.subst(msrTlbiSIop)
|
exec_output += DvmInitiateAcc.subst(msrTlbiSIop)
|
||||||
exec_output += DvmCompleteAcc.subst(msrTlbiSIop)
|
exec_output += DvmCompleteAcc.subst(msrTlbiSIop)
|
||||||
|
|
||||||
|
atCode = msr_check_code + '''
|
||||||
|
uint64_t par_result;
|
||||||
|
std::tie(fault, par_result) = performAt(xc, flat_idx, XOp1);
|
||||||
|
MiscDest_ud = XOp1;
|
||||||
|
MiscDest2_ud = par_result;
|
||||||
|
'''
|
||||||
|
msrAtIop = ArmInstObjParams("msr", "At64Hub", "AtOp64",
|
||||||
|
{
|
||||||
|
"code" : atCode
|
||||||
|
})
|
||||||
|
header_output += AtDeclare.subst(msrAtIop)
|
||||||
|
decoder_output += AtConstructor.subst(msrAtIop)
|
||||||
|
exec_output += BasicExecute.subst(msrAtIop)
|
||||||
|
|
||||||
msrNZCVCode = '''
|
msrNZCVCode = '''
|
||||||
CPSR cpsr = XOp1;
|
CPSR cpsr = XOp1;
|
||||||
CondCodesNZ = cpsr.nz;
|
CondCodesNZ = cpsr.nz;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// -*- mode:c++ -*-
|
// -*- mode:c++ -*-
|
||||||
// Copyright (c) 2010-2014, 2016-2018, 2021-2022 Arm Limited
|
// Copyright (c) 2010-2014, 2016-2018, 2021-2022, 2024 Arm Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// The license below extends only to copyright in the software and shall
|
// The license below extends only to copyright in the software and shall
|
||||||
@@ -470,6 +470,7 @@ def operands {{
|
|||||||
|
|
||||||
#Abstracted control reg operands
|
#Abstracted control reg operands
|
||||||
'MiscDest': CntrlReg('dest'),
|
'MiscDest': CntrlReg('dest'),
|
||||||
|
'MiscDest2': CntrlReg('dest2'),
|
||||||
'MiscOp1': CntrlReg('op1'),
|
'MiscOp1': CntrlReg('op1'),
|
||||||
'MiscNsBankedDest': CntrlNsBankedReg('dest'),
|
'MiscNsBankedDest': CntrlNsBankedReg('dest'),
|
||||||
'MiscNsBankedOp1': CntrlNsBankedReg('op1'),
|
'MiscNsBankedOp1': CntrlNsBankedReg('op1'),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// -*- mode:c++ -*-
|
// -*- mode:c++ -*-
|
||||||
|
|
||||||
// Copyright (c) 2011,2017-2022 Arm Limited
|
// Copyright (c) 2011,2017-2022,2024 Arm Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// The license below extends only to copyright in the software and shall
|
// The license below extends only to copyright in the software and shall
|
||||||
@@ -303,6 +303,22 @@ class %(class_name)s : public %(base_class)s
|
|||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
def template AtDeclare {{
|
||||||
|
class %(class_name)s : public %(base_class)s
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ArmISA::MiscRegIndex dest2;
|
||||||
|
%(reg_idx_arr_decl)s;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
%(class_name)s(ExtMachInst machInst, MiscRegIndex _dest,
|
||||||
|
MiscRegIndex _dest2, RegIndex _op1);
|
||||||
|
|
||||||
|
Fault execute(ExecContext *, trace::InstRecord *) const override;
|
||||||
|
};
|
||||||
|
}};
|
||||||
|
|
||||||
def template DvmDeclare {{
|
def template DvmDeclare {{
|
||||||
/**
|
/**
|
||||||
* Static instruction class for "%(mnemonic)s".
|
* Static instruction class for "%(mnemonic)s".
|
||||||
@@ -339,6 +355,18 @@ def template DvmTlbiConstructor {{
|
|||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
def template AtConstructor {{
|
||||||
|
%(class_name)s::%(class_name)s(ExtMachInst machInst, MiscRegIndex _dest,
|
||||||
|
MiscRegIndex _dest2, RegIndex _op1) :
|
||||||
|
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
|
||||||
|
_dest, _op1),
|
||||||
|
dest2(_dest2)
|
||||||
|
{
|
||||||
|
%(set_reg_idx_arr)s;
|
||||||
|
%(constructor)s;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
def template DvmConstructor {{
|
def template DvmConstructor {{
|
||||||
%(class_name)s::%(class_name)s(ExtMachInst machInst, bool dvm_enabled) :
|
%(class_name)s::%(class_name)s(ExtMachInst machInst, bool dvm_enabled) :
|
||||||
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
|
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
|
||||||
|
|||||||
Reference in New Issue
Block a user