| // -*- 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 |
| } |
| }}; |