arch-arm: Add initial support for SVE contiguous loads/stores

Thanks to Pau Cabre and Adria Armejach Sanosa for their contribution
of bugfixes.

Change-Id: If8983cf85d95cddb187c90967a94ddfe2414bc46
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/13519
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
Giacomo Gabrielli
2017-11-08 16:06:12 +00:00
parent c58cb8c9db
commit 8ddec45de4
10 changed files with 1429 additions and 1 deletions

View File

@@ -61,6 +61,7 @@ if env['TARGET_ISA'] == 'arm':
Source('insts/pseudo.cc')
Source('insts/static_inst.cc')
Source('insts/sve.cc')
Source('insts/sve_mem.cc')
Source('insts/vfp.cc')
Source('insts/fplib.cc')
Source('insts/crypto.cc')

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2017 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: Giacomo Gabrielli
*/
#include "arch/arm/insts/sve_mem.hh"
namespace ArmISA
{
std::string
SveMemVecFillSpill::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, "", false);
printVecReg(ss, dest, true);
ccprintf(ss, ", [");
printIntReg(ss, base);
if (imm != 0) {
ccprintf(ss, ", #%d, mul vl", imm);
}
ccprintf(ss, "]");
return ss.str();
}
std::string
SveMemPredFillSpill::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, "", false);
printVecPredReg(ss, dest);
ccprintf(ss, ", [");
printIntReg(ss, base);
if (imm != 0) {
ccprintf(ss, ", #%d, mul vl", imm);
}
ccprintf(ss, "]");
return ss.str();
}
std::string
SveContigMemSS::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
// TODO: add suffix to transfer register and scaling factor (LSL #<x>)
std::stringstream ss;
printMnemonic(ss, "", false);
ccprintf(ss, "{");
printVecReg(ss, dest, true);
ccprintf(ss, "}, ");
printVecPredReg(ss, gp);
ccprintf(ss, "/z, ");
ccprintf(ss, ", [");
printIntReg(ss, base);
ccprintf(ss, ", ");
printIntReg(ss, offset);
ccprintf(ss, "]");
return ss.str();
}
std::string
SveContigMemSI::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
// TODO: add suffix to transfer register
std::stringstream ss;
printMnemonic(ss, "", false);
ccprintf(ss, "{");
printVecReg(ss, dest, true);
ccprintf(ss, "}, ");
printVecPredReg(ss, gp);
ccprintf(ss, "/z, ");
ccprintf(ss, ", [");
printIntReg(ss, base);
if (imm != 0) {
ccprintf(ss, ", #%d, mul vl", imm);
}
ccprintf(ss, "]");
return ss.str();
}
} // namespace ArmISA

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 2017 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: Giacomo Gabrielli
*/
#ifndef __ARCH_ARM_SVE_MEM_HH__
#define __ARCH_ARM_SVE_MEM_HH__
#include "arch/arm/insts/static_inst.hh"
#include "arch/arm/tlb.hh"
namespace ArmISA
{
class SveMemVecFillSpill : public ArmStaticInst
{
protected:
IntRegIndex dest;
IntRegIndex base;
uint64_t imm;
/// True if the base register is SP (used for SP alignment checking).
bool baseIsSP;
unsigned memAccessFlags;
SveMemVecFillSpill(const char *mnem, ExtMachInst _machInst,
OpClass __opClass, IntRegIndex _dest,
IntRegIndex _base, uint64_t _imm)
: ArmStaticInst(mnem, _machInst, __opClass),
dest(_dest), base(_base), imm(_imm),
memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
{
baseIsSP = isSP(_base);
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class SveMemPredFillSpill : public ArmStaticInst
{
protected:
IntRegIndex dest;
IntRegIndex base;
uint64_t imm;
/// True if the base register is SP (used for SP alignment checking).
bool baseIsSP;
unsigned memAccessFlags;
SveMemPredFillSpill(const char *mnem, ExtMachInst _machInst,
OpClass __opClass, IntRegIndex _dest,
IntRegIndex _base, uint64_t _imm)
: ArmStaticInst(mnem, _machInst, __opClass),
dest(_dest), base(_base), imm(_imm),
memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
{
baseIsSP = isSP(_base);
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class SveContigMemSS : public ArmStaticInst
{
protected:
IntRegIndex dest;
IntRegIndex gp;
IntRegIndex base;
IntRegIndex offset;
/// True if the base register is SP (used for SP alignment checking).
bool baseIsSP;
unsigned memAccessFlags;
SveContigMemSS(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
IntRegIndex _offset)
: ArmStaticInst(mnem, _machInst, __opClass),
dest(_dest), gp(_gp), base(_base), offset(_offset),
memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
{
baseIsSP = isSP(_base);
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class SveContigMemSI : public ArmStaticInst
{
protected:
IntRegIndex dest;
IntRegIndex gp;
IntRegIndex base;
uint64_t imm;
/// True if the base register is SP (used for SP alignment checking).
bool baseIsSP;
unsigned memAccessFlags;
SveContigMemSI(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
uint64_t _imm)
: ArmStaticInst(mnem, _machInst, __opClass),
dest(_dest), gp(_gp), base(_base), imm(_imm),
memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
{
baseIsSP = isSP(_base);
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
} // namespace ArmISA
#endif // __ARCH_ARM_SVE_MEM_HH__

View File

@@ -2896,12 +2896,152 @@ namespace Aarch64
StaticInstPtr
decodeSveMemGather32(ExtMachInst machInst)
{
// TODO: for now only LDR and LD1R are implemented
if (bits(machInst, 22) && bits(machInst, 15)) {
IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
IntRegIndex rn = makeSP(
(IntRegIndex) (uint8_t) bits(machInst, 9, 5));
uint64_t imm = bits(machInst, 21, 16);
IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
uint8_t dtype = (bits(machInst, 24, 23) << 2) |
bits(machInst, 14, 13);
return decodeSveContigLoadSIInsts<SveLoadAndRepl>(
dtype, machInst, zt, pg, rn, imm, false, true);
} else if (bits(machInst, 24, 22) == 0x6 &&
bits(machInst, 15, 13) == 0x0 &&
bits(machInst, 4) == 0x0) {
IntRegIndex pt = (IntRegIndex) (uint8_t) bits(machInst, 3, 0);
IntRegIndex rn = makeSP(
(IntRegIndex) (uint8_t) bits(machInst, 9, 5));
uint64_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
bits(machInst, 12, 10));
return new SveLdrPred(machInst, pt, rn, imm);
} else if (bits(machInst, 24, 22) == 0x6 &&
bits(machInst, 15, 13) == 0x2) {
IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
IntRegIndex rn = makeSP(
(IntRegIndex) (uint8_t) bits(machInst, 9, 5));
uint64_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
bits(machInst, 12, 10));
return new SveLdrVec(machInst, zt, rn, imm);
}
return new Unknown64(machInst);
} // decodeSveMemGather32
StaticInstPtr
decodeSveLoadBcastQuadSS(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveLoadBcastQuadSS
StaticInstPtr
decodeSveLoadBcastQuadSI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveLoadBcastQuadSI
StaticInstPtr
decodeSveContigLoadSS(ExtMachInst machInst)
{
IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
IntRegIndex rm = makeSP(
(IntRegIndex) (uint8_t) bits(machInst, 20, 16));
IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
if (rm == 0x1f) {
return new Unknown64(machInst);
}
return decodeSveContigLoadSSInsts<SveContigLoadSS>(
bits(machInst, 24, 21), machInst, zt, pg, rn, rm, false);
} // decodeSveContigLoadSS
StaticInstPtr
decodeSveContigFFLoadSS(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveContigFFLoadSS
StaticInstPtr
decodeSveContigLoadSI(ExtMachInst machInst)
{
IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
uint64_t imm = sext<4>(bits(machInst, 19, 16));
IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
return decodeSveContigLoadSIInsts<SveContigLoadSI>(
bits(machInst, 24, 21), machInst, zt, pg, rn, imm, false);
} // decodeSveContigLoadSI
StaticInstPtr
decodeSveContigNFLoadSI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveContigNFLoadSI
StaticInstPtr
decodeSveContigNTLoadSS(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveContigNTLoadSS
StaticInstPtr
decodeSveLoadStructsSS(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveLoadStructsSS
StaticInstPtr
decodeSveContigNTLoadSI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveContigNTLoadSI
StaticInstPtr
decodeSveLoadStructsSI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveLoadStructsSI
StaticInstPtr
decodeSveMemContigLoad(ExtMachInst machInst)
{
switch (bits(machInst, 15, 13)) {
case 0x0:
return decodeSveLoadBcastQuadSS(machInst);
case 0x1:
if (bits(machInst, 20) == 0x0) {
return decodeSveLoadBcastQuadSI(machInst);
}
break;
case 0x2:
return decodeSveContigLoadSS(machInst);
case 0x3:
return decodeSveContigFFLoadSS(machInst);
case 0x5:
if (bits(machInst, 20) == 0x0) {
return decodeSveContigLoadSI(machInst);
} else {
return decodeSveContigNFLoadSI(machInst);
}
case 0x6:
if (bits(machInst, 22, 21) == 0x0) {
return decodeSveContigNTLoadSS(machInst);
} else {
return decodeSveLoadStructsSS(machInst);
}
case 0x7:
if (bits(machInst, 20) == 0) {
if (bits(machInst, 22, 21) == 0x0) {
return decodeSveContigNTLoadSI(machInst);
} else {
return decodeSveLoadStructsSI(machInst);
}
}
break;
}
return new Unknown64(machInst);
} // decodeSveMemContigLoad
@@ -2911,9 +3051,185 @@ namespace Aarch64
return new Unknown64(machInst);
} // decodeSveMemGather64
StaticInstPtr
decodeSveContigStoreSS(ExtMachInst machInst)
{
IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
IntRegIndex rm = makeSP(
(IntRegIndex) (uint8_t) bits(machInst, 20, 16));
IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
if (rm == 0x1f) {
return new Unknown64(machInst);
}
return decodeSveContigStoreSSInsts<SveContigStoreSS>(
bits(machInst, 24, 21), machInst, zt, pg, rn, rm);
} // decodeSveContigStoreSS
StaticInstPtr
decodeSveContigStoreSI(ExtMachInst machInst)
{
IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
int8_t imm = sext<4>(bits(machInst, 19, 16));
IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
return decodeSveContigStoreSIInsts<SveContigStoreSI>(
bits(machInst, 24, 21), machInst, zt, pg, rn, imm);
} // decodeSveContigStoreSI
StaticInstPtr
decodeSveContigNTStoreSS(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveContigNTStoreSS
StaticInstPtr
decodeSveScatterStore64SV32U(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore64SV32U
StaticInstPtr
decodeSveScatterStore64SV64U(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore64SV64U
StaticInstPtr
decodeSveContigNTStoreSI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveContigNTStoreSI
StaticInstPtr
decodeSveScatterStore64VI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore64VI
StaticInstPtr
decodeSveScatterStore32SV32S(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore32SV32S
StaticInstPtr
decodeSveStoreStructsSS(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveStoreStructsSS
StaticInstPtr
decodeSveStoreStructsSI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveStoreStructsSI
StaticInstPtr
decodeSveScatterStore32SV32U(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore32SV32U
StaticInstPtr
decodeSveScatterStore32VI(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore32VI
StaticInstPtr
decodeSveScatterStore64SV32S(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore64SV32S
StaticInstPtr
decodeSveScatterStore64SV64S(ExtMachInst machInst)
{
return new Unknown64(machInst);
} // decodeSveScatterStore64SV64S
StaticInstPtr
decodeSveMemStore(ExtMachInst machInst)
{
switch (bits(machInst, 15, 13)) {
case 0x0:
if (bits(machInst, 24, 22) == 0x6 && bits(machInst, 4) == 0x0) {
IntRegIndex pt = (IntRegIndex) (uint8_t) bits(machInst, 3, 0);
IntRegIndex rn = makeSP(
(IntRegIndex) (uint8_t) bits(machInst, 9, 5));
int16_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
bits(machInst, 12, 10));
return new SveStrPred(machInst, pt, rn, imm);
}
break;
case 0x2:
if (bits(machInst, 24, 22) == 0x6) {
IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
IntRegIndex rn = makeSP(
(IntRegIndex) (uint8_t) bits(machInst, 9, 5));
int16_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
bits(machInst, 12, 10));
return new SveStrVec(machInst, zt, rn, imm);
} else {
return decodeSveContigStoreSS(machInst);
}
break;
case 0x3:
if (bits(machInst, 22, 21) == 0x0) {
return decodeSveContigNTStoreSS(machInst);
} else {
return decodeSveStoreStructsSS(machInst);
}
case 0x4:
case 0x6:
switch (bits(machInst, 22, 21)) {
case 0x0:
return decodeSveScatterStore64SV32U(machInst);
case 0x1:
if (bits(machInst, 24, 23) != 0x0) {
return decodeSveScatterStore64SV32S(machInst);
}
break;
case 0x2:
if (bits(machInst, 24, 23) != 0x3) {
return decodeSveScatterStore32SV32U(machInst);
}
break;
case 0x3:
return decodeSveScatterStore32SV32S(machInst);
}
break;
case 0x5:
switch (bits(machInst, 22, 21)) {
case 0x0:
return decodeSveScatterStore64SV64U(machInst);
case 0x1:
if (bits(machInst, 24, 23) != 0x0) {
return decodeSveScatterStore64SV64S(machInst);
}
break;
case 0x2:
return decodeSveScatterStore64VI(machInst);
case 0x3:
if (bits(machInst, 24, 23) != 0x3) {
return decodeSveScatterStore64VI(machInst);
}
break;
}
break;
case 0x7:
if (bits(machInst, 20) == 0x0) {
return decodeSveContigStoreSI(machInst);
} else if (bits(machInst, 22, 21) == 0x0) {
return decodeSveContigNTStoreSI(machInst);
} else {
return decodeSveStoreStructsSI(machInst);
}
}
return new Unknown64(machInst);
} // decodeSveMemStore

View File

@@ -65,6 +65,7 @@ output header {{
#include "arch/arm/insts/pseudo.hh"
#include "arch/arm/insts/static_inst.hh"
#include "arch/arm/insts/sve.hh"
#include "arch/arm/insts/sve_mem.hh"
#include "arch/arm/insts/vfp.hh"
#include "arch/arm/isa_traits.hh"
#include "mem/packet.hh"

View File

@@ -99,6 +99,7 @@ split decoder;
//SVE
##include "sve.isa"
##include "sve_mem.isa"
//m5 Pseudo-ops
##include "m5ops.isa"

View File

@@ -0,0 +1,453 @@
// Copyright (c) 2017 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: Giacomo Gabrielli
// @file Definition of SVE memory access instructions.
output header {{
// Decodes SVE contiguous load instructions, scalar plus scalar form.
template <template <typename T1, typename T2> class Base>
StaticInstPtr
decodeSveContigLoadSSInsts(uint8_t dtype, ExtMachInst machInst,
IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
IntRegIndex rm, bool firstFaulting)
{
const char* mn = firstFaulting ? "ldff1" : "ld1";
switch (dtype) {
case 0x0:
return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x1:
return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x2:
return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x3:
return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x4:
return new Base<int64_t, int32_t>(mn, machInst, zt, pg, rn, rm);
case 0x5:
return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
case 0x6:
return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
case 0x7:
return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
case 0x8:
return new Base<int64_t, int16_t>(mn, machInst, zt, pg, rn, rm);
case 0x9:
return new Base<int32_t, int16_t>(mn, machInst, zt, pg, rn, rm);
case 0xa:
return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
case 0xb:
return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
case 0xc:
return new Base<int64_t, int8_t>(mn, machInst, zt, pg, rn, rm);
case 0xd:
return new Base<int32_t, int8_t>(mn, machInst, zt, pg, rn, rm);
case 0xe:
return new Base<int16_t, int8_t>(mn, machInst, zt, pg, rn, rm);
case 0xf:
return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, rm);
}
return new Unknown64(machInst);
}
// Decodes SVE contiguous load instructions, scalar plus immediate form.
template <template <typename T1, typename T2> class Base>
StaticInstPtr
decodeSveContigLoadSIInsts(uint8_t dtype, ExtMachInst machInst,
IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
uint64_t imm, bool firstFaulting,
bool replicate = false)
{
assert(!(replicate && firstFaulting));
const char* mn = replicate ? "ld1r" :
(firstFaulting ? "ldff1" : "ld1");
switch (dtype) {
case 0x0:
return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x1:
return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x2:
return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x3:
return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x4:
return new Base<int64_t, int32_t>(mn, machInst, zt, pg, rn, imm);
case 0x5:
return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
case 0x6:
return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
case 0x7:
return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
case 0x8:
return new Base<int64_t, int16_t>(mn, machInst, zt, pg, rn, imm);
case 0x9:
return new Base<int32_t, int16_t>(mn, machInst, zt, pg, rn, imm);
case 0xa:
return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
case 0xb:
return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
case 0xc:
return new Base<int64_t, int8_t>(mn, machInst, zt, pg, rn, imm);
case 0xd:
return new Base<int32_t, int8_t>(mn, machInst, zt, pg, rn, imm);
case 0xe:
return new Base<int16_t, int8_t>(mn, machInst, zt, pg, rn, imm);
case 0xf:
return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, imm);
}
return new Unknown64(machInst);
}
// Decodes SVE contiguous store instructions, scalar plus scalar form.
template <template <typename T1, typename T2> class Base>
StaticInstPtr
decodeSveContigStoreSSInsts(uint8_t dtype, ExtMachInst machInst,
IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
IntRegIndex rm)
{
const char* mn = "st1";
switch (dtype) {
case 0x0:
return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x1:
return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x2:
return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x3:
return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
case 0x5:
return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
case 0x6:
return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
case 0x7:
return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
case 0xa:
return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
case 0xb:
return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
case 0xf:
return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, rm);
}
return new Unknown64(machInst);
}
// Decodes SVE contiguous store instructions, scalar plus immediate form.
template <template <typename T1, typename T2> class Base>
StaticInstPtr
decodeSveContigStoreSIInsts(uint8_t dtype, ExtMachInst machInst,
IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
int8_t imm)
{
const char* mn = "st1";
switch (dtype) {
case 0x0:
return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x1:
return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x2:
return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x3:
return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
case 0x5:
return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
case 0x6:
return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
case 0x7:
return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
case 0xa:
return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
case 0xb:
return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
case 0xf:
return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, imm);
}
return new Unknown64(machInst);
}
// NOTE: SVE load-and-replicate instructions are decoded with
// decodeSveContigLoadSIInsts(...).
}};
let {{
header_output = ''
exec_output = ''
decoders = { 'Generic': {} }
SPAlignmentCheckCode = '''
if (this->baseIsSP && bits(XBase, 3, 0) &&
SPAlignmentCheckEnabled(xc->tcBase())) {
return std::make_shared<SPAlignmentFault>();
}
'''
def emitSveMemFillSpill(isPred):
global header_output, exec_output, decoders
eaCode = SPAlignmentCheckCode + '''
int memAccessSize = %(memacc_size)s;
EA = XBase + ((int64_t) imm * %(memacc_size)s)''' % {
'memacc_size': 'eCount / 8' if isPred else 'eCount'}
if isPred:
loadMemAccCode = '''
int index = 0;
uint8_t byte;
for (int i = 0; i < eCount / 8; i++) {
byte = memDataView[i];
for (int j = 0; j < 8; j++, index++) {
PDest_x[index] = (byte >> j) & 1;
}
}
'''
storeMemAccCode = '''
int index = 0;
uint8_t byte;
for (int i = 0; i < eCount / 8; i++) {
byte = 0;
for (int j = 0; j < 8; j++, index++) {
byte |= PDest_x[index] << j;
}
memDataView[i] = byte;
}
'''
storeWrEnableCode = '''
auto wrEn = std::vector<bool>(eCount / 8, true);
'''
else:
loadMemAccCode = '''
for (int i = 0; i < eCount; i++) {
AA64FpDest_x[i] = memDataView[i];
}
'''
storeMemAccCode = '''
for (int i = 0; i < eCount; i++) {
memDataView[i] = AA64FpDest_x[i];
}
'''
storeWrEnableCode = '''
auto wrEn = std::vector<bool>(sizeof(MemElemType) * eCount, true);
'''
loadIop = InstObjParams('ldr',
'SveLdrPred' if isPred else 'SveLdrVec',
'SveMemPredFillSpill' if isPred else 'SveMemVecFillSpill',
{'tpl_header': '',
'tpl_args': '',
'memacc_code': loadMemAccCode,
'ea_code' : sveEnabledCheckCode + eaCode,
'fa_code' : ''},
['IsMemRef', 'IsLoad'])
storeIop = InstObjParams('str',
'SveStrPred' if isPred else 'SveStrVec',
'SveMemPredFillSpill' if isPred else 'SveMemVecFillSpill',
{'tpl_header': '',
'tpl_args': '',
'wren_code': storeWrEnableCode,
'memacc_code': storeMemAccCode,
'ea_code' : sveEnabledCheckCode + eaCode,
'fa_code' : ''},
['IsMemRef', 'IsStore'])
header_output += SveMemFillSpillOpDeclare.subst(loadIop)
header_output += SveMemFillSpillOpDeclare.subst(storeIop)
exec_output += (
SveContigLoadExecute.subst(loadIop) +
SveContigLoadInitiateAcc.subst(loadIop) +
SveContigLoadCompleteAcc.subst(loadIop) +
SveContigStoreExecute.subst(storeIop) +
SveContigStoreInitiateAcc.subst(storeIop) +
SveContigStoreCompleteAcc.subst(storeIop))
loadTplArgs = (
('uint8_t', 'uint8_t'),
('uint16_t', 'uint8_t'),
('uint32_t', 'uint8_t'),
('uint64_t', 'uint8_t'),
('int64_t', 'int32_t'),
('uint16_t', 'uint16_t'),
('uint32_t', 'uint16_t'),
('uint64_t', 'uint16_t'),
('int64_t', 'int16_t'),
('int32_t', 'int16_t'),
('uint32_t', 'uint32_t'),
('uint64_t', 'uint32_t'),
('int64_t', 'int8_t'),
('int32_t', 'int8_t'),
('int16_t', 'int8_t'),
('uint64_t', 'uint64_t'),
)
storeTplArgs = (
('uint8_t', 'uint8_t'),
('uint16_t', 'uint8_t'),
('uint32_t', 'uint8_t'),
('uint64_t', 'uint8_t'),
('uint16_t', 'uint16_t'),
('uint32_t', 'uint16_t'),
('uint64_t', 'uint16_t'),
('uint32_t', 'uint32_t'),
('uint64_t', 'uint32_t'),
('uint64_t', 'uint64_t'),
)
# Generates definitions for SVE contiguous loads
def emitSveContigMemInsts(offsetIsImm):
global header_output, exec_output, decoders
tplHeader = 'template <class RegElemType, class MemElemType>'
tplArgs = '<RegElemType, MemElemType>'
eaCode = SPAlignmentCheckCode + '''
int memAccessSize = eCount * sizeof(MemElemType);
EA = XBase + '''
if offsetIsImm:
eaCode += '((int64_t) this->imm * eCount * sizeof(MemElemType))'
else:
eaCode += '(XOffset * sizeof(MemElemType));'
loadMemAccCode = '''
for (int i = 0; i < eCount; i++) {
if (GpOp_x[i]) {
AA64FpDest_x[i] = memDataView[i];
} else {
AA64FpDest_x[i] = 0;
}
}
'''
storeMemAccCode = '''
for (int i = 0; i < eCount; i++) {
if (GpOp_x[i]) {
memDataView[i] = AA64FpDest_x[i];
} else {
memDataView[i] = 0;
for (int j = 0; j < sizeof(MemElemType); j++) {
wrEn[sizeof(MemElemType) * i + j] = false;
}
}
}
'''
storeWrEnableCode = '''
auto wrEn = std::vector<bool>(sizeof(MemElemType) * eCount, true);
'''
loadIop = InstObjParams('ld1',
'SveContigLoadSI' if offsetIsImm else 'SveContigLoadSS',
'SveContigMemSI' if offsetIsImm else 'SveContigMemSS',
{'tpl_header': tplHeader,
'tpl_args': tplArgs,
'memacc_code': loadMemAccCode,
'ea_code' : sveEnabledCheckCode + eaCode,
'fa_code' : ''},
['IsMemRef', 'IsLoad'])
storeIop = InstObjParams('st1',
'SveContigStoreSI' if offsetIsImm else 'SveContigStoreSS',
'SveContigMemSI' if offsetIsImm else 'SveContigMemSS',
{'tpl_header': tplHeader,
'tpl_args': tplArgs,
'wren_code': storeWrEnableCode,
'memacc_code': storeMemAccCode,
'ea_code' : sveEnabledCheckCode + eaCode,
'fa_code' : ''},
['IsMemRef', 'IsStore'])
if offsetIsImm:
header_output += SveContigMemSIOpDeclare.subst(loadIop)
header_output += SveContigMemSIOpDeclare.subst(storeIop)
else:
header_output += SveContigMemSSOpDeclare.subst(loadIop)
header_output += SveContigMemSSOpDeclare.subst(storeIop)
exec_output += (
SveContigLoadExecute.subst(loadIop) +
SveContigLoadInitiateAcc.subst(loadIop) +
SveContigLoadCompleteAcc.subst(loadIop) +
SveContigStoreExecute.subst(storeIop) +
SveContigStoreInitiateAcc.subst(storeIop) +
SveContigStoreCompleteAcc.subst(storeIop))
for args in loadTplArgs:
substDict = {'tpl_args': '<%s>' % ', '.join(args),
'class_name': 'SveContigLoadSI' if offsetIsImm
else 'SveContigLoadSS'}
exec_output += SveContigMemExecDeclare.subst(substDict)
for args in storeTplArgs:
substDict = {'tpl_args': '<%s>' % ', '.join(args),
'class_name': 'SveContigStoreSI' if offsetIsImm
else 'SveContigStoreSS'}
exec_output += SveContigMemExecDeclare.subst(substDict)
# Generates definitions for SVE load-and-replicate instructions
def emitSveLoadAndRepl():
global header_output, exec_output, decoders
tplHeader = 'template <class RegElemType, class MemElemType>'
tplArgs = '<RegElemType, MemElemType>'
eaCode = SPAlignmentCheckCode + '''
EA = XBase + imm * sizeof(MemElemType);'''
memAccCode = '''
for (int i = 0; i < eCount; i++) {
if (GpOp_x[i]) {
AA64FpDest_x[i] = memData;
} else {
AA64FpDest_x[i] = 0;
}
}
'''
iop = InstObjParams('ld1r',
'SveLoadAndRepl',
'SveContigMemSI',
{'tpl_header': tplHeader,
'tpl_args': tplArgs,
'memacc_code': memAccCode,
'ea_code' : sveEnabledCheckCode + eaCode,
'fa_code' : ''},
['IsMemRef', 'IsLoad'])
header_output += SveContigMemSIOpDeclare.subst(iop)
exec_output += (
SveLoadAndReplExecute.subst(iop) +
SveLoadAndReplInitiateAcc.subst(iop) +
SveLoadAndReplCompleteAcc.subst(iop))
for args in loadTplArgs:
substDict = {'tpl_args': '<%s>' % ', '.join(args),
'class_name': 'SveLoadAndRepl'}
exec_output += SveContigMemExecDeclare.subst(substDict)
# LD1[S]{B,H,W,D} (scalar plus immediate)
emitSveContigMemInsts(True)
# LD1[S]{B,H,W,D} (scalar plus scalar)
emitSveContigMemInsts(False)
# LD1R[S]{B,H,W,D}
emitSveLoadAndRepl()
# LDR (predicate), STR (predicate)
emitSveMemFillSpill(True)
# LDR (vector), STR (vector)
emitSveMemFillSpill(False)
}};

View File

@@ -38,7 +38,7 @@
let {{
sveEnabledCheckCode = '''
if (FullSystem) {
fault = checkSveEnabled(xc->tcBase(), Cpsr, Cpacr64);
fault = this->checkSveEnabled(xc->tcBase(), Cpsr, Cpacr64);
if (fault != NoFault) {
return fault;
}

View File

@@ -0,0 +1,386 @@
// Copyright (c) 2017 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: Giacomo Gabrielli
def template SveMemFillSpillOpDeclare {{
class %(class_name)s : public %(base_class)s
{
protected:
typedef uint8_t TPElem;
typedef uint8_t RegElemType;
typedef uint8_t MemElemType;
public:
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _base, uint64_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _base, _imm)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
virtual void
annotateFault(ArmFault *fault) {
%(fa_code)s
}
};
}};
def template SveContigMemSSOpDeclare {{
%(tpl_header)s
class %(class_name)s : public %(base_class)s
{
protected:
typedef RegElemType TPElem;
public:
%(class_name)s(const char* mnem, ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
IntRegIndex _offset)
: %(base_class)s(mnem, machInst, %(op_class)s,
_dest, _gp, _base, _offset)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
virtual void
annotateFault(ArmFault *fault) {
%(fa_code)s
}
};
}};
def template SveContigMemSIOpDeclare {{
%(tpl_header)s
class %(class_name)s : public %(base_class)s
{
protected:
typedef RegElemType TPElem;
public:
%(class_name)s(const char* mnem, ExtMachInst machInst,
IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
uint64_t _imm)
: %(base_class)s(mnem, machInst, %(op_class)s,
_dest, _gp, _base, _imm)
{
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const;
Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
virtual void
annotateFault(ArmFault *fault) {
%(fa_code)s
}
};
}};
def template SveContigMemExecDeclare {{
template
Fault %(class_name)s%(tpl_args)s::execute(ExecContext *,
Trace::InstRecord *) const;
template
Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *,
Trace::InstRecord *) const;
template
Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr,
ExecContext *, Trace::InstRecord *) const;
}};
def template SveContigLoadExecute {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
xc->tcBase());
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
TheISA::VecRegContainer memData;
auto memDataView = memData.as<MemElemType>();
if (fault == NoFault) {
fault = xc->readMem(EA, memData.raw_ptr<uint8_t>(), memAccessSize,
this->memAccessFlags);
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template SveContigLoadInitiateAcc {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
xc->tcBase());
%(op_src_decl)s;
%(op_rd)s;
%(ea_code)s;
if (fault == NoFault) {
fault = xc->initiateMemRead(EA, memAccessSize,
this->memAccessFlags);
}
return fault;
}
}};
def template SveContigLoadCompleteAcc {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
ExecContext *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
xc->tcBase());
%(op_decl)s;
%(op_rd)s;
TheISA::VecRegContainer memData;
auto memDataView = memData.as<MemElemType>();
memcpy(memData.raw_ptr<uint8_t>(), pkt->getPtr<uint8_t>(),
pkt->getSize());
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template SveContigStoreExecute {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
xc->tcBase());
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
TheISA::VecRegContainer memData;
auto memDataView = memData.as<MemElemType>();
%(wren_code)s;
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
this->memAccessFlags, NULL, wrEn);
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template SveContigStoreInitiateAcc {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
xc->tcBase());
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
TheISA::VecRegContainer memData;
auto memDataView = memData.as<MemElemType>();
%(wren_code)s;
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
this->memAccessFlags, NULL, wrEn);
}
return fault;
}
}};
def template SveContigStoreCompleteAcc {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
ExecContext *xc, Trace::InstRecord *traceData) const
{
return NoFault;
}
}};
def template SveLoadAndReplExecute {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
xc->tcBase());
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
MemElemType memData;
if (fault == NoFault) {
fault = readMemAtomic(xc, traceData, EA, memData,
this->memAccessFlags);
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};
def template SveLoadAndReplInitiateAcc {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
%(op_src_decl)s;
%(op_rd)s;
%(ea_code)s;
MemElemType memData;
if (fault == NoFault) {
fault = initiateMemRead(xc, traceData, EA, memData,
this->memAccessFlags);
}
return fault;
}
}};
def template SveLoadAndReplCompleteAcc {{
%(tpl_header)s
Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
ExecContext *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
bool aarch64 M5_VAR_USED = true;
unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
xc->tcBase());
%(op_decl)s;
%(op_rd)s;
MemElemType memData;
getMem(pkt, memData, traceData);
if (fault == NoFault) {
%(memacc_code)s;
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};

View File

@@ -83,3 +83,4 @@
//Templates for SVE instructions
##include "sve.isa"
##include "sve_mem.isa"