// -*- 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 %(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 %(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 %(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 %(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 %(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 %(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 Fault %(class_name)s::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 Fault %(class_name)s::execute(ExecContext *xc, Trace::InstRecord *traceData) const { typedef typename bigger_type_t::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(), 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; } }};