diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2010-08-25 19:10:42 -0500 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2010-08-25 19:10:42 -0500 |
commit | 6368edb281f162e4fbb0a91744992a25134135f4 (patch) | |
tree | e84dfa7d10903e6c7a56e01cc6ca23f4b0d41908 /src/arch/arm/isa/templates | |
parent | f4f6b31df1a8787a12d71108eac24543bdf541e3 (diff) | |
download | gem5-6368edb281f162e4fbb0a91744992a25134135f4.tar.xz |
ARM: Implement all ARM SIMD instructions.
Diffstat (limited to 'src/arch/arm/isa/templates')
-rw-r--r-- | src/arch/arm/isa/templates/macromem.isa | 192 | ||||
-rw-r--r-- | src/arch/arm/isa/templates/mem.isa | 200 | ||||
-rw-r--r-- | src/arch/arm/isa/templates/neon.isa | 227 | ||||
-rw-r--r-- | src/arch/arm/isa/templates/templates.isa | 3 |
4 files changed, 620 insertions, 2 deletions
diff --git a/src/arch/arm/isa/templates/macromem.isa b/src/arch/arm/isa/templates/macromem.isa index 400342a29..5397a2637 100644 --- a/src/arch/arm/isa/templates/macromem.isa +++ b/src/arch/arm/isa/templates/macromem.isa @@ -74,7 +74,32 @@ def template MicroMemConstructor {{ //////////////////////////////////////////////////////////////////// // -// Integer = Integer op Immediate microops +// Neon load/store microops +// + +def template MicroNeonMemDeclare {{ + template <class Element> + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, RegIndex _dest, + RegIndex _ura, uint32_t _imm, unsigned extraMemFlags) + : %(base_class)s("%(mnemonic)s", machInst, + %(op_class)s, _dest, _ura, _imm) + { + memAccessFlags |= extraMemFlags; + %(constructor)s; + } + + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; +}}; + +//////////////////////////////////////////////////////////////////// +// +// Integer = Integer op Integer microops // def template MicroIntDeclare {{ @@ -82,13 +107,130 @@ def template MicroIntDeclare {{ { public: %(class_name)s(ExtMachInst machInst, + RegIndex _ura, RegIndex _urb, RegIndex _urc); + %(BasicExecDeclare)s + }; +}}; + +def template MicroIntConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst, + RegIndex _ura, + RegIndex _urb, + RegIndex _urc) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _ura, _urb, _urc) + { + %(constructor)s; + } +}}; + +def template MicroNeonMemExecDeclare {{ + template + Fault %(class_name)s<%(targs)s>::execute( + %(CPU_exec_context)s *, Trace::InstRecord *) const; + template + Fault %(class_name)s<%(targs)s>::initiateAcc( + %(CPU_exec_context)s *, Trace::InstRecord *) const; + template + Fault %(class_name)s<%(targs)s>::completeAcc(PacketPtr, + %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +def template MicroNeonExecDeclare {{ + template + Fault %(class_name)s<%(targs)s>::execute( + %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +//////////////////////////////////////////////////////////////////// +// +// Neon (de)interlacing microops +// + +def template MicroNeonMixDeclare {{ + template <class Element> + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1, + uint8_t _step) : + %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _step) + { + %(constructor)s; + } + + %(BasicExecDeclare)s + }; +}}; + +def template MicroNeonMixExecute {{ + template <class Element> + Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t resTemp = 0; + resTemp = resTemp; + %(op_decl)s; + %(op_rd)s; + + if (%(predicate_test)s) + { + %(code)s; + if (fault == NoFault) + { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +//////////////////////////////////////////////////////////////////// +// +// Neon (un)packing microops using a particular lane +// + +def template MicroNeonMixLaneDeclare {{ + template <class Element> + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1, + uint8_t _step, unsigned _lane) : + %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _dest, _op1, _step, _lane) + { + %(constructor)s; + } + + %(BasicExecDeclare)s + }; +}}; + +//////////////////////////////////////////////////////////////////// +// +// Integer = Integer op Immediate microops +// + +def template MicroIntImmDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, RegIndex _ura, RegIndex _urb, uint8_t _imm); %(BasicExecDeclare)s }; }}; -def template MicroIntConstructor {{ +def template MicroIntImmConstructor {{ %(class_name)s::%(class_name)s(ExtMachInst machInst, RegIndex _ura, RegIndex _urb, @@ -132,6 +274,52 @@ def template MacroMemConstructor {{ }}; +def template VMemMultDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, unsigned width, + RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, + uint32_t size, uint32_t align, RegIndex rm); + %(BasicExecPanic)s +}; +}}; + +def template VMemMultConstructor {{ +%(class_name)s::%(class_name)s(ExtMachInst machInst, unsigned width, + RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, + uint32_t size, uint32_t align, RegIndex rm) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, width, + rn, vd, regs, inc, size, align, rm) +{ + %(constructor)s; +} +}}; + +def template VMemSingleDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + // Constructor + %(class_name)s(ExtMachInst machInst, bool all, unsigned width, + RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, + uint32_t size, uint32_t align, RegIndex rm, unsigned lane = 0); + %(BasicExecPanic)s +}; +}}; + +def template VMemSingleConstructor {{ +%(class_name)s::%(class_name)s(ExtMachInst machInst, bool all, unsigned width, + RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, + uint32_t size, uint32_t align, RegIndex rm, unsigned lane) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, all, width, + rn, vd, regs, inc, size, align, rm, lane) +{ + %(constructor)s; +} +}}; + def template MacroVFPMemDeclare {{ /** * Static instructions class for a store multiple instruction diff --git a/src/arch/arm/isa/templates/mem.isa b/src/arch/arm/isa/templates/mem.isa index 84cd1dd8f..686a8b0aa 100644 --- a/src/arch/arm/isa/templates/mem.isa +++ b/src/arch/arm/isa/templates/mem.isa @@ -180,6 +180,42 @@ def template LoadExecute {{ } }}; +def template NeonLoadExecute {{ + template <class Element> + Fault %(class_name)s<Element>::execute( + %(CPU_exec_context)s *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) { + fault = xc->readBytes(EA, dataPtr, %(size)d, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + def template StoreExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const @@ -217,6 +253,46 @@ def template StoreExecute {{ } }}; +def template NeonStoreExecute {{ + template <class Element> + Fault %(class_name)s<Element>::execute( + %(CPU_exec_context)s *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) { + fault = xc->writeBytes(dataPtr, %(size)d, EA, + memAccessFlags, NULL); + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + def template StoreExExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const @@ -336,6 +412,45 @@ def template StoreInitiateAcc {{ } }}; +def template NeonStoreInitiateAcc {{ + template <class Element> + Fault %(class_name)s<Element>::initiateAcc( + %(CPU_exec_context)s *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) { + fault = xc->writeBytes(memUnion.bytes, %(size)d, EA, + memAccessFlags, NULL); + } + + // Need to write back any potential address register update + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + def template LoadInitiateAcc {{ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const @@ -363,6 +478,31 @@ def template LoadInitiateAcc {{ } }}; +def template NeonLoadInitiateAcc {{ + template <class Element> + Fault %(class_name)s<Element>::initiateAcc( + %(CPU_exec_context)s *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 = xc->readBytes(EA, NULL, %(size)d, memAccessFlags); + } + } else if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + def template LoadCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, @@ -395,6 +535,40 @@ def template LoadCompleteAcc {{ } }}; +def template NeonLoadCompleteAcc {{ + template <class Element> + Fault %(class_name)s<Element>::completeAcc( + PacketPtr pkt, %(CPU_exec_context)s *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; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + def template StoreCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, @@ -420,6 +594,32 @@ def template StoreCompleteAcc {{ } }}; +def template NeonStoreCompleteAcc {{ + template <class Element> + Fault %(class_name)s<Element>::completeAcc( + PacketPtr pkt, %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + + if (%(predicate_test)s) + { + if (fault == NoFault) { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + def template StoreExCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s *xc, diff --git a/src/arch/arm/isa/templates/neon.isa b/src/arch/arm/isa/templates/neon.isa new file mode 100644 index 000000000..e402979dc --- /dev/null +++ b/src/arch/arm/isa/templates/neon.isa @@ -0,0 +1,227 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2010 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: Gabe Black + +def template NeonRegRegRegOpDeclare {{ +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; + } + + %(BasicExecDeclare)s +}; +}}; + +def template NeonRegRegRegImmOpDeclare {{ +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; + } + + %(BasicExecDeclare)s +}; +}}; + +def template NeonRegRegImmOpDeclare {{ +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; + } + + %(BasicExecDeclare)s +}; +}}; + +def template NeonRegImmOpDeclare {{ +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; + } + + %(BasicExecDeclare)s +}; +}}; + +def template NeonRegRegOpDeclare {{ +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; + } + + %(BasicExecDeclare)s +}; +}}; + +def template NeonExecDeclare {{ + template + Fault %(class_name)s<%(targs)s>::execute( + %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +def template NeonEqualRegExecute {{ + template <class Element> + Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *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(FloatRegBits) / sizeof(Element); + + union RegVect { + FloatRegBits regs[rCount]; + Element elements[eCount]; + }; + + if (%(predicate_test)s) + { + %(code)s; + if (fault == NoFault) + { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; + +output header {{ + uint16_t nextBiggerType(uint8_t); + uint32_t nextBiggerType(uint16_t); + uint64_t nextBiggerType(uint32_t); + int16_t nextBiggerType(int8_t); + int32_t nextBiggerType(int16_t); + int64_t nextBiggerType(int32_t); +}}; + +def template NeonUnequalRegExecute {{ + template <class Element> + Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + typedef typeof(nextBiggerType((Element)0)) BigElement; + Fault fault = NoFault; + %(op_decl)s; + %(op_rd)s; + + const unsigned rCount = %(r_count)d; + const unsigned eCount = rCount * sizeof(FloatRegBits) / sizeof(Element); + + union RegVect { + FloatRegBits regs[rCount]; + Element elements[eCount]; + BigElement bigElements[eCount / 2]; + }; + + union BigRegVect { + FloatRegBits regs[2 * rCount]; + BigElement elements[eCount]; + }; + + if (%(predicate_test)s) + { + %(code)s; + if (fault == NoFault) + { + %(op_wb)s; + } + } + + if (fault == NoFault && machInst.itstateMask != 0) { + xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); + } + + return fault; + } +}}; diff --git a/src/arch/arm/isa/templates/templates.isa b/src/arch/arm/isa/templates/templates.isa index 2584ec1f2..148139225 100644 --- a/src/arch/arm/isa/templates/templates.isa +++ b/src/arch/arm/isa/templates/templates.isa @@ -60,3 +60,6 @@ //Templates for VFP instructions ##include "vfp.isa" + +//Templates for Neon instructions +##include "neon.isa" |