blob: 43969b62f1c11b8d63047fa051c9c4ba0dd6be01 [file] [log] [blame]
// -*- mode:c++ -*-
// Copyright (c) 2010, 2012, 2014, 2016 ARM Limited
// 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.
//
// Copyright (c) 2007-2008 The Florida State University
// All rights reserved.
//
// 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.
def template PanicExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
trace::InstRecord *traceData) const
{
panic("Execute function executed when it shouldn't be!\n");
return NoFault;
}
}};
def template PanicInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
trace::InstRecord *traceData) const
{
panic("InitiateAcc function executed when it shouldn't be!\n");
return NoFault;
}
}};
def template PanicCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
trace::InstRecord *traceData) const
{
panic("CompleteAcc function executed when it shouldn't be!\n");
return NoFault;
}
}};
def template SwapExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
uint64_t memData = 0;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
%(preacc_code)s;
if (fault == NoFault) {
fault = writeMemAtomicLE(xc, traceData, Mem, EA,
memAccessFlags, &memData);
}
if (fault == NoFault) {
%(postacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template SwapInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
uint64_t memData = 0;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
%(preacc_code)s;
if (fault == NoFault) {
fault = writeMemTimingLE(xc, traceData, Mem, EA,
memAccessFlags, &memData);
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template SwapCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
if (%(predicate_test)s) {
// ARM instructions will not have a pkt if the predicate is false
getMemLE(pkt, Mem, traceData);
uint64_t memData = Mem;
%(postacc_code)s;
if (fault == NoFault) {
%(op_wb)s;
}
}
return fault;
}
}};
def template LoadExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
fault = readMemAtomicLE(
xc, traceData, EA, Mem, memAccessFlags);
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template NeonLoadExecute {{
template <class Element>
Fault
%(class_name)s<Element>::execute(
ExecContext *xc, trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(mem_decl)s;
%(op_rd)s;
%(ea_code)s;
MemUnion memUnion;
uint8_t *dataPtr = memUnion.bytes;
if (%(predicate_test)s) {
if (fault == NoFault) {
const auto size = %(size)d;
fault = readMemAtomic(xc, EA, dataPtr,
size, memAccessFlags,
std::vector<bool>(size, true));
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template StoreExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = writeMemAtomicLE(xc, traceData, Mem, EA,
memAccessFlags, NULL);
}
if (fault == NoFault) {
%(op_wb)s;
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template NeonStoreExecute {{
template <class Element>
Fault
%(class_name)s<Element>::execute(
ExecContext *xc, trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(mem_decl)s;
%(op_rd)s;
%(ea_code)s;
MemUnion memUnion;
uint8_t *dataPtr = memUnion.bytes;
if (%(predicate_test)s) {
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
const auto size = %(size)d;
fault = writeMemAtomic(xc, dataPtr, EA, size,
memAccessFlags, NULL,
std::vector<bool>(size, true));
}
if (fault == NoFault) {
%(op_wb)s;
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template StoreExExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
%(memacc_code)s;
}
uint64_t writeResult;
if (fault == NoFault) {
fault = writeMemAtomicLE(xc, traceData, Mem, EA,
memAccessFlags, &writeResult);
}
if (fault == NoFault) {
%(postacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template StoreExInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = writeMemTimingLE(xc, traceData, Mem, EA,
memAccessFlags, NULL);
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template StoreInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = writeMemTimingLE(xc, traceData, Mem, EA,
memAccessFlags, NULL);
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template NeonStoreInitiateAcc {{
template <class Element>
Fault
%(class_name)s<Element>::initiateAcc(
ExecContext *xc, trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(mem_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
MemUnion memUnion;
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
const auto size = %(size)d;
fault = writeMemTiming(xc, memUnion.bytes, EA,
size, memAccessFlags, nullptr,
std::vector<bool>(size, true));
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template LoadInitiateAcc {{
Fault
%(class_name)s::initiateAcc(ExecContext *xc,
trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_src_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
fault = initiateMemRead(xc, traceData, EA, Mem,
memAccessFlags);
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template NeonLoadInitiateAcc {{
template <class Element>
Fault
%(class_name)s<Element>::initiateAcc(
ExecContext *xc, trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
%(op_decl)s;
%(mem_decl)s;
%(op_rd)s;
%(ea_code)s;
if (%(predicate_test)s) {
if (fault == NoFault) {
const auto size = %(size)d;
fault = initiateMemRead(xc, EA, size, memAccessFlags,
std::vector<bool>(size, true));
}
} else {
xc->setPredicate(false);
}
return fault;
}
}};
def template LoadCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
if (%(predicate_test)s) {
// ARM instructions will not have a pkt if the predicate is false
getMemLE(pkt, Mem, traceData);
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
}
return fault;
}
}};
def template NeonLoadCompleteAcc {{
template <class Element>
Fault
%(class_name)s<Element>::completeAcc(
PacketPtr pkt, ExecContext *xc, trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(mem_decl)s;
%(op_decl)s;
%(op_rd)s;
if (%(predicate_test)s) {
// ARM instructions will not have a pkt if the predicate is false
MemUnion &memUnion = *(MemUnion *)pkt->getPtr<uint8_t>();
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
}
return fault;
}
}};
def template StoreCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
trace::InstRecord *traceData) const
{
return NoFault;
}
}};
def template NeonStoreCompleteAcc {{
template <class Element>
Fault
%(class_name)s<Element>::completeAcc(
PacketPtr pkt, ExecContext *xc, trace::InstRecord *traceData) const
{
return NoFault;
}
}};
def template StoreExCompleteAcc {{
Fault
%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
if (%(predicate_test)s) {
uint64_t writeResult = pkt->req->getExtraData();
%(postacc_code)s;
if (fault == NoFault) {
%(op_wb)s;
}
}
return fault;
}
}};
def template RfeDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _base, int _mode, bool _wb);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template SrsDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _regMode, int _mode, bool _wb);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template SwapDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _op1, uint32_t _base);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template LoadStoreDImmDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2,
uint32_t _base, bool _add, int32_t _imm);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template StoreExDImmDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _result, uint32_t _dest, uint32_t _dest2,
uint32_t _base, bool _add, int32_t _imm);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template LoadStoreImmDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
void
annotateFault(ArmISA::ArmFault *fault) override
{
%(fa_code)s
}
};
}};
def template StoreExImmDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _result, uint32_t _dest, uint32_t _base,
bool _add, int32_t _imm);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template StoreDRegDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2,
uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType,
uint32_t _index);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template StoreRegDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType,
uint32_t _index);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
void
annotateFault(ArmISA::ArmFault *fault) override
{
%(fa_code)s
}
};
}};
def template LoadDRegDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2,
uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType,
uint32_t _index);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
};
}};
def template LoadRegDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType,
uint32_t _index);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
void
annotateFault(ArmISA::ArmFault *fault) override
{
%(fa_code)s
}
};
}};
def template LoadImmDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
Fault execute(ExecContext *, trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
trace::InstRecord *) const override;
void
annotateFault(ArmISA::ArmFault *fault) override
{
%(fa_code)s
}
};
}};
def template RfeConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _base, int _mode, bool _wb) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_base, (AddrMode)_mode, _wb)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d];
int uopIdx = 0;
uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb);
uops[uopIdx]->setDelayedCommit();
#if %(use_wb)d
uops[++uopIdx] = new %(wb_decl)s;
uops[uopIdx]->setDelayedCommit();
#endif
#if %(use_pc)d
uops[++uopIdx] = new %(pc_decl)s;
#endif
uops[0]->setFirstMicroop();
uops[uopIdx]->setLastMicroop();
#endif
}
}};
def template SrsConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _regMode, int _mode, bool _wb) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(OperatingMode)_regMode, (AddrMode)_mode, _wb)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _regMode, _mode, _wb);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
}
}};
def template SwapConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _op1, uint32_t _base) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_op1, (RegIndex)_base)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
}
}};
def template LoadStoreDImmConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2,
uint32_t _base, bool _add, int32_t _imm) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_dest2,
(RegIndex)_base, _add, _imm)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add, _imm);
uops[0]->setFirstMicroop();
uops[0]->setDelayedCommit();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
}
}};
def template StoreExDImmConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _result, uint32_t _dest, uint32_t _dest2,
uint32_t _base, bool _add, int32_t _imm) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_result, (RegIndex)_dest, (RegIndex)_dest2,
(RegIndex)_base, _add, _imm)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _result, _dest, _dest2,
_base, _add, _imm);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
}
}};
def template LoadStoreImmConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add, int32_t _imm) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_base, _add, _imm)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
}
}};
def template StoreExImmConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _result, uint32_t _dest, uint32_t _base,
bool _add, int32_t _imm) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_result, (RegIndex)_dest,
(RegIndex)_base, _add, _imm)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _result, _dest,
_base, _add, _imm);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
}
}};
def template StoreDRegConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_dest2,
(RegIndex)_base, _add,
_shiftAmt, (ArmShiftType)_shiftType,
(RegIndex)_index)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
_shiftAmt, _shiftType, _index);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
}
}};
def template StoreRegConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_base, _add,
_shiftAmt, (ArmShiftType)_shiftType,
(RegIndex)_index)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
_shiftAmt, _shiftType, _index);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
}
}};
def template LoadDRegConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_dest2,
(RegIndex)_base, _add,
_shiftAmt, (ArmShiftType)_shiftType,
(RegIndex)_index)
{
%(set_reg_idx_arr)s;
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
if ((_dest == _index) || (_dest2 == _index)) {
RegIndex wbIndexReg = int_reg::Ureg0;
uops[0] = new MicroUopRegMov(machInst, int_reg::Ureg0, _index);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
_shiftAmt, _shiftType, _index);
uops[1]->setDelayedCommit();
uops[2] = new %(wb_decl)s;
uops[2]->setLastMicroop();
} else {
RegIndex wbIndexReg = index;
uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
_shiftAmt, _shiftType, _index);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
}
#endif
}
}};
def template LoadRegConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_base, _add,
_shiftAmt, (ArmShiftType)_shiftType,
(RegIndex)_index)
{
%(set_reg_idx_arr)s;
%(constructor)s;
[[maybe_unused]] bool conditional = false;
if (!(condCode == COND_AL || condCode == COND_UC)) {
conditional = true;
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
if (_dest == int_reg::Pc && !isFloating() && !isVector()) {
RegIndex wbIndexReg = index;
uops[0] = new %(acc_name)s(machInst, int_reg::Ureg0, _base, _add,
_shiftAmt, _shiftType, _index);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setDelayedCommit();
uops[2] = new MicroUopRegMov(machInst, int_reg::Pc,
int_reg::Ureg0);
uops[2]->setFlag(StaticInst::IsControl);
uops[2]->setFlag(StaticInst::IsIndirectControl);
if (conditional)
uops[2]->setFlag(StaticInst::IsCondControl);
else
uops[2]->setFlag(StaticInst::IsUncondControl);
uops[2]->setLastMicroop();
} else if(_dest == _index) {
RegIndex wbIndexReg = int_reg::Ureg0;
uops[0] = new MicroUopRegMov(machInst, int_reg::Ureg0, _index);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(acc_name)s(machInst, _dest, _base, _add,
_shiftAmt, _shiftType, _index);
uops[1]->setDelayedCommit();
uops[2] = new %(wb_decl)s;
uops[2]->setLastMicroop();
} else {
RegIndex wbIndexReg = index;
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
_shiftAmt, _shiftType, _index);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
}
#else
if (_dest == int_reg::Pc && !isFloating() && !isVector()) {
flags[IsControl] = true;
flags[IsIndirectControl] = true;
if (conditional)
flags[IsCondControl] = true;
else
flags[IsUncondControl] = true;
}
#endif
}
}};
def template LoadImmConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add, int32_t _imm) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(RegIndex)_dest, (RegIndex)_base, _add, _imm)
{
%(set_reg_idx_arr)s;
%(constructor)s;
[[maybe_unused]] bool conditional = false;
if (!(condCode == COND_AL || condCode == COND_UC)) {
conditional = true;
for (int x = 0; x < _numDestRegs; x++) {
setSrcRegIdx(_numSrcRegs++, destRegIdx(x));
}
}
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
if (_dest == int_reg::Pc && !isFloating() && !isVector()) {
uops[0] = new %(acc_name)s(machInst, int_reg::Ureg0, _base, _add,
_imm);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setDelayedCommit();
uops[2] = new MicroUopRegMov(
machInst, int_reg::Pc, int_reg::Ureg0);
uops[2]->setFlag(StaticInst::IsControl);
uops[2]->setFlag(StaticInst::IsIndirectControl);
/* Also set flags on the macroop so that pre-microop decomposition
branch prediction can work */
setFlag(StaticInst::IsControl);
setFlag(StaticInst::IsIndirectControl);
if (conditional) {
uops[2]->setFlag(StaticInst::IsCondControl);
setFlag(StaticInst::IsCondControl);
} else {
uops[2]->setFlag(StaticInst::IsUncondControl);
setFlag(StaticInst::IsUncondControl);
}
if (_base == int_reg::Sp && _add && _imm == 4 && %(is_ras_pop)s) {
uops[2]->setFlag(StaticInst::IsReturn);
setFlag(StaticInst::IsReturn);
}
uops[2]->setLastMicroop();
} else {
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
uops[0]->setDelayedCommit();
uops[0]->setFirstMicroop();
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
}
#else
if (_dest == int_reg::Pc && !isFloating() && !isVector()) {
flags[IsControl] = true;
flags[IsIndirectControl] = true;
if (conditional)
flags[IsCondControl] = true;
else
flags[IsUncondControl] = true;
}
#endif
}
}};