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:
@@ -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')
|
||||
|
||||
116
src/arch/arm/insts/sve_mem.cc
Normal file
116
src/arch/arm/insts/sve_mem.cc
Normal 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
|
||||
153
src/arch/arm/insts/sve_mem.hh
Normal file
153
src/arch/arm/insts/sve_mem.hh
Normal 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__
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -99,6 +99,7 @@ split decoder;
|
||||
|
||||
//SVE
|
||||
##include "sve.isa"
|
||||
##include "sve_mem.isa"
|
||||
|
||||
//m5 Pseudo-ops
|
||||
##include "m5ops.isa"
|
||||
|
||||
453
src/arch/arm/isa/insts/sve_mem.isa
Normal file
453
src/arch/arm/isa/insts/sve_mem.isa
Normal 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)
|
||||
|
||||
}};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
386
src/arch/arm/isa/templates/sve_mem.isa
Normal file
386
src/arch/arm/isa/templates/sve_mem.isa
Normal 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;
|
||||
}
|
||||
}};
|
||||
|
||||
@@ -83,3 +83,4 @@
|
||||
|
||||
//Templates for SVE instructions
|
||||
##include "sve.isa"
|
||||
##include "sve_mem.isa"
|
||||
|
||||
Reference in New Issue
Block a user