summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa/templates
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-08-25 19:10:42 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-08-25 19:10:42 -0500
commit6368edb281f162e4fbb0a91744992a25134135f4 (patch)
treee84dfa7d10903e6c7a56e01cc6ca23f4b0d41908 /src/arch/arm/isa/templates
parentf4f6b31df1a8787a12d71108eac24543bdf541e3 (diff)
downloadgem5-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.isa192
-rw-r--r--src/arch/arm/isa/templates/mem.isa200
-rw-r--r--src/arch/arm/isa/templates/neon.isa227
-rw-r--r--src/arch/arm/isa/templates/templates.isa3
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"