blob: 3c36e6bae46c6c5609150ed6c43949fef1b4bd64 [file] [log] [blame]
// -*- mode: c++ -*-
// Copyright (c) 2012-2013 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.
//
// 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.
//
// Authors: Mbou Eyole
// Giacomo Gabrielli
let {{
simd64EnabledCheckCode = vfp64EnabledCheckCode
}};
def template NeonX2RegOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
protected:
typedef _Element Element;
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _op2)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template NeonX2RegImmOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
protected:
typedef _Element Element;
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
uint64_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _op2, _imm)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template NeonX1RegOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
protected:
typedef _Element Element;
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _op1)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template NeonX1RegImmOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
protected:
typedef _Element Element;
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _op1, uint64_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _imm)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template NeonX1Reg2ImmOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
protected:
typedef _Element Element;
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _op1, uint64_t _imm1,
uint64_t _imm2)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _imm1, _imm2)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template NeonX1RegImmOnlyOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
protected:
typedef _Element Element;
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, uint64_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _imm)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template NeonXExecDeclare {{
template
Fault %(class_name)s<%(targs)s>::execute(
ExecContext *, Trace::InstRecord *) const;
}};
def template NeonXEqualRegOpExecute {{
template <class Element>
Fault %(class_name)s<Element>::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
const unsigned rCount = %(r_count)d;
const unsigned eCount = rCount * sizeof(uint32_t) / sizeof(Element);
const unsigned eCountFull = 4 * sizeof(uint32_t) / sizeof(Element);
union RegVect {
uint32_t regs[rCount];
Element elements[eCount];
};
union FullRegVect {
uint32_t regs[4];
Element elements[eCountFull];
};
%(code)s;
if (fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
def template NeonXUnequalRegOpExecute {{
template <class Element>
Fault %(class_name)s<Element>::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
typedef typename bigger_type_t<Element>::type BigElement;
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
const unsigned rCount = %(r_count)d;
const unsigned eCount = rCount * sizeof(uint32_t) / sizeof(Element);
const unsigned eCountFull = 4 * sizeof(uint32_t) / sizeof(Element);
union RegVect {
uint32_t regs[rCount];
Element elements[eCount];
BigElement bigElements[eCount / 2];
};
union BigRegVect {
uint32_t regs[2 * rCount];
BigElement elements[eCount];
};
union FullRegVect {
uint32_t regs[4];
Element elements[eCountFull];
};
%(code)s;
if (fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
def template MicroNeonMemDeclare64 {{
class %(class_name)s : public %(base_class)s
{
protected:
// True if the base register is SP (used for SP alignment checking)
bool baseIsSP;
// Access size in bytes
uint8_t accSize;
// Vector element size (0 -> 8-bit, 1 -> 16-bit, 2 -> 32-bit,
// 3 -> 64-bit)
uint8_t eSize;
public:
%(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _ura,
uint32_t _imm, unsigned extraMemFlags, bool _baseIsSP,
uint8_t _accSize, uint8_t _eSize)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest,
_ura, _imm),
baseIsSP(_baseIsSP), accSize(_accSize), eSize(_eSize)
{
memAccessFlags |= extraMemFlags;
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
Fault completeAcc(PacketPtr, ExecContext *,
Trace::InstRecord *) const override;
};
}};
def template NeonLoadExecute64 {{
Fault %(class_name)s::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 (fault == NoFault) {
fault = xc->readMem(EA, dataPtr, accSize, memAccessFlags);
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template NeonLoadInitiateAcc64 {{
Fault %(class_name)s::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 (fault == NoFault) {
fault = xc->initiateMemRead(EA, accSize, memAccessFlags);
}
return fault;
}
}};
def template NeonLoadCompleteAcc64 {{
Fault %(class_name)s::completeAcc(
PacketPtr pkt, ExecContext *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(mem_decl)s;
%(op_decl)s;
%(op_rd)s;
MemUnion memUnion { { } };
memcpy(&memUnion, pkt->getPtr<uint8_t>(), pkt->getSize());
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template NeonStoreExecute64 {{
Fault %(class_name)s::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 (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = xc->writeMem(dataPtr, accSize, EA, memAccessFlags,
NULL);
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template NeonStoreInitiateAcc64 {{
Fault %(class_name)s::initiateAcc(
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;
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = xc->writeMem(memUnion.bytes, accSize, EA, memAccessFlags,
NULL);
}
return fault;
}
}};
def template NeonStoreCompleteAcc64 {{
Fault %(class_name)s::completeAcc(
PacketPtr pkt, ExecContext *xc, Trace::InstRecord *traceData) const
{
return NoFault;
}
}};
def template VMemMultDeclare64 {{
class %(class_name)s : public %(base_class)s
{
public:
// Constructor
%(class_name)s(ExtMachInst machInst, RegIndex rn, RegIndex vd,
RegIndex rm, uint8_t eSize, uint8_t dataSize,
uint8_t numStructElems, uint8_t numRegs, bool wb);
};
}};
def template VMemSingleDeclare64 {{
class %(class_name)s : public %(base_class)s
{
public:
// Constructor
%(class_name)s(ExtMachInst machInst, RegIndex rn, RegIndex vd,
RegIndex rm, uint8_t eSize, uint8_t dataSize,
uint8_t numStructElems, uint8_t index, bool wb,
bool replicate = false);
};
}};
def template VMemMultConstructor64 {{
%(class_name)s::%(class_name)s(
ExtMachInst machInst, RegIndex rn, RegIndex vd, RegIndex rm,
uint8_t _eSize, uint8_t _dataSize, uint8_t _numStructElems,
uint8_t _numRegs, bool _wb) :
%(base_class)s(
"%(mnemonic)s", machInst, %(op_class)s, rn, vd, rm,
_eSize, _dataSize, _numStructElems, _numRegs, _wb)
{
%(constructor)s;
}
}};
def template VMemSingleConstructor64 {{
%(class_name)s::%(class_name)s(
ExtMachInst machInst, RegIndex rn, RegIndex vd, RegIndex rm,
uint8_t _eSize, uint8_t _dataSize, uint8_t _numStructElems,
uint8_t _index, bool _wb, bool _replicate) :
%(base_class)s(
"%(mnemonic)s", machInst, %(op_class)s, rn, vd, rm,
_eSize, _dataSize, _numStructElems, _index, _wb,
_replicate)
{
%(constructor)s;
}
}};
def template MicroNeonMixDeclare64 {{
class %(class_name)s : public %(base_class)s
{
public:
%(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1,
uint8_t _eSize, uint8_t _dataSize,
uint8_t _numStructElems, uint8_t _numRegs,
uint8_t _step) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _eSize, _dataSize, _numStructElems,
_numRegs, _step)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template MicroNeonMixLaneDeclare64 {{
class %(class_name)s : public %(base_class)s
{
public:
%(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1,
uint8_t _eSize, uint8_t _dataSize,
uint8_t _numStructElems, uint8_t _lane, uint8_t _step,
bool _replicate = false) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _eSize, _dataSize, _numStructElems,
_lane, _step, _replicate)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template MicroNeonMixExecute64 {{
Fault %(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
uint64_t resTemp = 0;
resTemp = resTemp;
%(op_decl)s;
%(op_rd)s;
%(code)s;
if (fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};