arch-arm,cpu: Add initial support for Arm SVE
This changeset adds initial support for the Arm Scalable Vector Extension (SVE) by implementing: - support for most data-processing instructions (no loads/stores yet); - basic system-level support. Additional authors: - Javier Setoain <javier.setoain@arm.com> - Gabor Dozsa <gabor.dozsa@arm.com> - Giacomo Travaglini <giacomo.travaglini@arm.com> Thanks to Pau Cabre for his contribution of bugfixes. Change-Id: I1808b5ff55b401777eeb9b99c9a1129e0d527709 Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/13515 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2012-2013, 2015-2016, 2018 ARM Limited
|
||||
# Copyright (c) 2012-2013, 2015-2018 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
@@ -41,6 +41,7 @@ from m5.proxy import *
|
||||
from m5.SimObject import SimObject
|
||||
|
||||
from m5.objects.ArmPMU import ArmPMU
|
||||
from m5.objects.ArmSystem import SveVectorLength
|
||||
from m5.objects.ISACommon import VecRegRenameMode
|
||||
|
||||
# Enum for DecoderFlavour
|
||||
@@ -115,3 +116,8 @@ class ArmISA(SimObject):
|
||||
# It is rather executed as a NOP.
|
||||
impdef_nop = Param.Bool(False,
|
||||
"Any access to a MISCREG_IMPDEF_UNIMPL register is executed as NOP")
|
||||
|
||||
# This is required because in SE mode a generic System SimObject is
|
||||
# allocated, instead of an ArmSystem
|
||||
sve_vl_se = Param.SveVectorLength(1,
|
||||
"SVE vector length in quadwords (128-bit), SE-mode only")
|
||||
|
||||
@@ -52,6 +52,8 @@ class ArmMachineType(Enum):
|
||||
'DTOnly' : -1,
|
||||
}
|
||||
|
||||
class SveVectorLength(UInt8): min = 1; max = 16
|
||||
|
||||
class ArmSystem(System):
|
||||
type = 'ArmSystem'
|
||||
cxx_header = "arch/arm/system.hh"
|
||||
@@ -80,6 +82,10 @@ class ArmSystem(System):
|
||||
"Supported physical address range in bits when using AArch64 (ARMv8)")
|
||||
have_large_asid_64 = Param.Bool(False,
|
||||
"True if ASID is 16 bits in AArch64 (ARMv8)")
|
||||
have_sve = Param.Bool(True,
|
||||
"True if SVE is implemented (ARMv8)")
|
||||
sve_vl = Param.SveVectorLength(1,
|
||||
"SVE vector length in quadwords (128-bit)")
|
||||
|
||||
semihosting = Param.ArmSemihosting(NULL,
|
||||
"Enable support for the Arm semihosting by settings this parameter")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# Copyright (c) 2009, 2012-2013, 2018 ARM Limited
|
||||
# Copyright (c) 2009, 2012-2013, 2017-2018 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
@@ -60,6 +60,7 @@ if env['TARGET_ISA'] == 'arm':
|
||||
Source('insts/pred_inst.cc')
|
||||
Source('insts/pseudo.cc')
|
||||
Source('insts/static_inst.cc')
|
||||
Source('insts/sve.cc')
|
||||
Source('insts/vfp.cc')
|
||||
Source('insts/fplib.cc')
|
||||
Source('insts/crypto.cc')
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Decoder.hh"
|
||||
#include "sim/full_system.hh"
|
||||
|
||||
namespace ArmISA
|
||||
{
|
||||
@@ -54,11 +55,13 @@ namespace ArmISA
|
||||
GenericISA::BasicDecodeCache Decoder::defaultCache;
|
||||
|
||||
Decoder::Decoder(ISA* isa)
|
||||
: data(0), fpscrLen(0), fpscrStride(0), decoderFlavour(isa
|
||||
? isa->decoderFlavour()
|
||||
: Enums::Generic)
|
||||
: data(0), fpscrLen(0), fpscrStride(0),
|
||||
decoderFlavour(isa->decoderFlavour())
|
||||
{
|
||||
reset();
|
||||
|
||||
// Initialize SVE vector length
|
||||
sveLen = (isa->getCurSveVecLenInBitsAtReset() >> 7) - 1;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -157,6 +160,7 @@ Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
|
||||
emi.aarch64 = pc.aarch64();
|
||||
emi.fpscrLen = fpscrLen;
|
||||
emi.fpscrStride = fpscrStride;
|
||||
emi.sveLen = sveLen;
|
||||
|
||||
const Addr alignment(pc.thumb() ? 0x1 : 0x3);
|
||||
emi.decoderFault = static_cast<uint8_t>(
|
||||
|
||||
@@ -72,6 +72,12 @@ class Decoder
|
||||
int fpscrLen;
|
||||
int fpscrStride;
|
||||
|
||||
/**
|
||||
* SVE vector length, encoded in the same format as the ZCR_EL<x>.LEN
|
||||
* bitfields.
|
||||
*/
|
||||
int sveLen;
|
||||
|
||||
Enums::DecoderFlavour decoderFlavour;
|
||||
|
||||
/// A cache of decoded instruction objects.
|
||||
@@ -197,6 +203,11 @@ class Decoder
|
||||
fpscrLen = fpscr.len;
|
||||
fpscrStride = fpscr.stride;
|
||||
}
|
||||
|
||||
void setSveLen(uint8_t len)
|
||||
{
|
||||
sveLen = len;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ArmISA
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "arch/arm/insts/static_inst.hh"
|
||||
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "arch/arm/isa.hh"
|
||||
#include "base/condcodes.hh"
|
||||
#include "base/cprintf.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
@@ -292,17 +293,20 @@ ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
|
||||
}
|
||||
|
||||
void
|
||||
ArmStaticInst::printIntReg(std::ostream &os, RegIndex reg_idx) const
|
||||
ArmStaticInst::printIntReg(std::ostream &os, RegIndex reg_idx,
|
||||
uint8_t opWidth) const
|
||||
{
|
||||
if (opWidth == 0)
|
||||
opWidth = intWidth;
|
||||
if (aarch64) {
|
||||
if (reg_idx == INTREG_UREG0)
|
||||
ccprintf(os, "ureg0");
|
||||
else if (reg_idx == INTREG_SPX)
|
||||
ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp");
|
||||
ccprintf(os, "%s%s", (opWidth == 32) ? "w" : "", "sp");
|
||||
else if (reg_idx == INTREG_X31)
|
||||
ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x");
|
||||
ccprintf(os, "%szr", (opWidth == 32) ? "w" : "x");
|
||||
else
|
||||
ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg_idx);
|
||||
ccprintf(os, "%s%d", (opWidth == 32) ? "w" : "x", reg_idx);
|
||||
} else {
|
||||
switch (reg_idx) {
|
||||
case PCReg:
|
||||
@@ -341,9 +345,16 @@ ArmStaticInst::printFloatReg(std::ostream &os, RegIndex reg_idx) const
|
||||
}
|
||||
|
||||
void
|
||||
ArmStaticInst::printVecReg(std::ostream &os, RegIndex reg_idx) const
|
||||
ArmStaticInst::printVecReg(std::ostream &os, RegIndex reg_idx,
|
||||
bool isSveVecReg) const
|
||||
{
|
||||
ccprintf(os, "v%d", reg_idx);
|
||||
ccprintf(os, "%s%d", isSveVecReg ? "z" : "v", reg_idx);
|
||||
}
|
||||
|
||||
void
|
||||
ArmStaticInst::printVecPredReg(std::ostream &os, RegIndex reg_idx) const
|
||||
{
|
||||
ccprintf(os, "p%d", reg_idx);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -955,6 +966,55 @@ ArmStaticInst::undefinedFault64(ThreadContext *tc,
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault
|
||||
ArmStaticInst::sveAccessTrap(ExceptionLevel el) const
|
||||
{
|
||||
switch (el) {
|
||||
case EL1:
|
||||
return std::make_shared<SupervisorTrap>(machInst, 0, EC_TRAPPED_SVE);
|
||||
case EL2:
|
||||
return std::make_shared<HypervisorTrap>(machInst, 0, EC_TRAPPED_SVE);
|
||||
case EL3:
|
||||
return std::make_shared<SecureMonitorTrap>(machInst, 0,
|
||||
EC_TRAPPED_SVE);
|
||||
|
||||
default:
|
||||
panic("Illegal EL in sveAccessTrap\n");
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
ArmStaticInst::checkSveTrap(ThreadContext *tc, CPSR cpsr) const
|
||||
{
|
||||
const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
|
||||
|
||||
if (ArmSystem::haveVirtualization(tc) && el <= EL2) {
|
||||
CPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
|
||||
if (cptrEnCheck.tz)
|
||||
return sveAccessTrap(EL2);
|
||||
}
|
||||
|
||||
if (ArmSystem::haveSecurity(tc)) {
|
||||
CPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||
if (!cptrEnCheck.ez)
|
||||
return sveAccessTrap(EL3);
|
||||
}
|
||||
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault
|
||||
ArmStaticInst::checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
|
||||
{
|
||||
const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
|
||||
if ((el == EL0 && cpacr.zen != 0x3) ||
|
||||
(el == EL1 && !(cpacr.zen & 0x1)))
|
||||
return sveAccessTrap(EL1);
|
||||
|
||||
return checkSveTrap(tc, cpsr);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
getRestoredITBits(ThreadContext *tc, CPSR spsr)
|
||||
{
|
||||
@@ -1100,5 +1160,10 @@ ArmStaticInst::generalExceptionsToAArch64(ThreadContext *tc,
|
||||
!ELIs32(tc, EL2) && hcr.tge);
|
||||
}
|
||||
|
||||
unsigned
|
||||
ArmStaticInst::getCurSveVecLenInBits(ThreadContext *tc)
|
||||
{
|
||||
return tc->getIsaPtr()->getCurSveVecLenInBits(tc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -156,9 +156,12 @@ class ArmStaticInst : public StaticInst
|
||||
|
||||
/// Print a register name for disassembly given the unique
|
||||
/// dependence tag number (FP or int).
|
||||
void printIntReg(std::ostream &os, RegIndex reg_idx) const;
|
||||
void printIntReg(std::ostream &os, RegIndex reg_idx,
|
||||
uint8_t opWidth = 0) const;
|
||||
void printFloatReg(std::ostream &os, RegIndex reg_idx) const;
|
||||
void printVecReg(std::ostream &os, RegIndex reg_idx) const;
|
||||
void printVecReg(std::ostream &os, RegIndex reg_idx,
|
||||
bool isSveVecReg = false) const;
|
||||
void printVecPredReg(std::ostream &os, RegIndex reg_idx) const;
|
||||
void printCCReg(std::ostream &os, RegIndex reg_idx) const;
|
||||
void printMiscReg(std::ostream &os, RegIndex reg_idx) const;
|
||||
void printMnemonic(std::ostream &os,
|
||||
@@ -466,6 +469,23 @@ class ArmStaticInst : public StaticInst
|
||||
*/
|
||||
Fault undefinedFault64(ThreadContext *tc, ExceptionLevel el) const;
|
||||
|
||||
/**
|
||||
* Trap an access to SVE registers due to access control bits.
|
||||
*
|
||||
* @param el Target EL for the trap.
|
||||
*/
|
||||
Fault sveAccessTrap(ExceptionLevel el) const;
|
||||
|
||||
/**
|
||||
* Check an SVE access against CPTR_EL2 and CPTR_EL3.
|
||||
*/
|
||||
Fault checkSveTrap(ThreadContext *tc, CPSR cpsr) const;
|
||||
|
||||
/**
|
||||
* Check an SVE access against CPACR_EL1, CPTR_EL2, and CPTR_EL3.
|
||||
*/
|
||||
Fault checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const;
|
||||
|
||||
/**
|
||||
* Get the new PSTATE from a SPSR register in preparation for an
|
||||
* exception return.
|
||||
@@ -520,6 +540,21 @@ class ArmStaticInst : public StaticInst
|
||||
{
|
||||
return simpleAsBytes(buf, max_size, machInst);
|
||||
}
|
||||
|
||||
static unsigned getCurSveVecLenInBits(ThreadContext *tc);
|
||||
|
||||
static unsigned
|
||||
getCurSveVecLenInQWords(ThreadContext *tc)
|
||||
{
|
||||
return getCurSveVecLenInBits(tc) >> 6;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static unsigned
|
||||
getCurSveVecLen(ThreadContext *tc)
|
||||
{
|
||||
return getCurSveVecLenInBits(tc) / (8 * sizeof(T));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
957
src/arch/arm/insts/sve.cc
Normal file
957
src/arch/arm/insts/sve.cc
Normal file
@@ -0,0 +1,957 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019 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
|
||||
*/
|
||||
|
||||
// TODO: add support for suffixes of register specifiers in disasm strings.
|
||||
|
||||
#include "arch/arm/insts/sve.hh"
|
||||
|
||||
namespace ArmISA {
|
||||
|
||||
const char*
|
||||
svePredTypeToStr(SvePredType pt)
|
||||
{
|
||||
switch (pt) {
|
||||
case SvePredType::MERGE:
|
||||
return "m";
|
||||
case SvePredType::ZERO:
|
||||
return "z";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredCountPredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printIntReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op1);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredCountOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
if (destIsVec) {
|
||||
printVecReg(ss, dest, true);
|
||||
} else {
|
||||
printIntReg(ss, dest);
|
||||
}
|
||||
ccprintf(ss, ", ");
|
||||
uint8_t opWidth = 64;
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, ", ");
|
||||
if (srcIs32b)
|
||||
opWidth = 32;
|
||||
printIntReg(ss, dest, opWidth);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveIndexIIOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", #%d, #%d", imm1, imm2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveIndexIROp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", #%d, ", imm1);
|
||||
printIntReg(ss, op2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveIndexRIOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printIntReg(ss, op1);
|
||||
ccprintf(ss, ", #%d", imm2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveIndexRROp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printIntReg(ss, op1);
|
||||
ccprintf(ss, ", ");
|
||||
printIntReg(ss, op2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveWhileOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
uint8_t opWidth;
|
||||
if (srcIs32b)
|
||||
opWidth = 32;
|
||||
else
|
||||
opWidth = 64;
|
||||
printIntReg(ss, op1, opWidth);
|
||||
ccprintf(ss, ", ");
|
||||
printIntReg(ss, op2, opWidth);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveCompTermOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printIntReg(ss, op1);
|
||||
ccprintf(ss, ", ");
|
||||
printIntReg(ss, op2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveUnaryPredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/m, ");
|
||||
printVecReg(ss, op1, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveUnaryUnpredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveUnaryWideImmUnpredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveUnaryWideImmPredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, (isMerging ? "/m" : "/z"));
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinImmUnpredConstrOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op1);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinImmPredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/m, ");
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinWideImmUnpredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinDestrPredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/m, ");
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinConstrPredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
if (predType == SvePredType::MERGE || predType == SvePredType::ZERO) {
|
||||
ccprintf(ss, "/%s", svePredTypeToStr(predType));
|
||||
}
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinUnpredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinIdxUnpredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
ccprintf(ss, "[");
|
||||
ss << (uint64_t)index;
|
||||
ccprintf(ss, "]");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredLogicalOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
if (isSel) {
|
||||
ccprintf(ss, ", ");
|
||||
} else {
|
||||
ccprintf(ss, "/z, ");
|
||||
}
|
||||
printVecPredReg(ss, op1);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredBinPermOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op1);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveCmpOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/z, ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveCmpImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/z, ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveTerPredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/m, ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveTerImmUnpredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveReducOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printFloatReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveOrdReducOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printFloatReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, ", ");
|
||||
printFloatReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePtrueOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
if (imm != 0x1f) {
|
||||
ccprintf(ss, ", ");
|
||||
ss << sveDisasmPredCountImm(imm);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveIntCmpOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/z, ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
if (op2IsWide) {
|
||||
printVecReg(ss, op2, true);
|
||||
} else {
|
||||
printVecReg(ss, op2, true);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveIntCmpImmOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, "/z, ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveAdrOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", [");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
if (offsetFormat == SveAdrOffsetUnpackedSigned) {
|
||||
ccprintf(ss, ", sxtw");
|
||||
} else if (offsetFormat == SveAdrOffsetUnpackedUnsigned) {
|
||||
ccprintf(ss, ", uxtw");
|
||||
} else if (mult != 1) {
|
||||
ccprintf(ss, ", lsl");
|
||||
}
|
||||
if (mult != 1) {
|
||||
ss << __builtin_ctz(mult);
|
||||
}
|
||||
ccprintf(ss, "]");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveElemCountOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
static const char suffix[9] =
|
||||
{'\0', 'b', 'h', '\0', 'w', '\0', '\0', '\0', 'd'};
|
||||
std::stringstream ss;
|
||||
ss << " " << mnemonic << suffix[esize] << " ";
|
||||
if (dstIsVec) {
|
||||
printVecReg(ss, dest, true);
|
||||
} else {
|
||||
if (dstIs32b) {
|
||||
printIntReg(ss, dest, 32);
|
||||
} else {
|
||||
printIntReg(ss, dest, 64);
|
||||
}
|
||||
}
|
||||
if (pattern != 0x1f) {
|
||||
ccprintf(ss, ", ");
|
||||
ss << sveDisasmPredCountImm(pattern);
|
||||
if (imm != 1) {
|
||||
ccprintf(ss, ", mul #");
|
||||
ss << std::to_string(imm);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePartBrkOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, isMerging ? "/m, " : "/z, ");
|
||||
printVecPredReg(ss, op1);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePartBrkPropOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/z, ");
|
||||
printVecPredReg(ss, op1);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveSelectOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
if (scalar)
|
||||
printIntReg(ss, dest, scalar_width);
|
||||
else if (simdFp)
|
||||
printFloatReg(ss, dest);
|
||||
else
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
if (conditional) {
|
||||
ccprintf(ss, ", ");
|
||||
if (scalar)
|
||||
printIntReg(ss, dest, scalar_width);
|
||||
else
|
||||
printVecReg(ss, dest, true);
|
||||
}
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveUnaryPredPredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op1);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveTblOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", { ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, " }, ");
|
||||
printVecReg(ss, op2, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveUnpackOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op1);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredTestOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op1);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredUnaryWImplicitSrcOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredUnaryWImplicitSrcPredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/z, ");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SvePredUnaryWImplicitDstOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, op1);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveWImplicitSrcDstOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinImmUnpredDestrOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", #");
|
||||
ss << imm;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveBinImmIdxUnpredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, "[");
|
||||
ss << imm;
|
||||
ccprintf(ss, "]");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveUnarySca2VecUnpredOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
if (simdFp) {
|
||||
printFloatReg(ss, op1);
|
||||
} else {
|
||||
printIntReg(ss, op1);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveDotProdIdxOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
ccprintf(ss, "[");
|
||||
ccprintf(ss, "%lu", imm);
|
||||
ccprintf(ss, "]");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveDotProdOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecReg(ss, dest, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op1, true);
|
||||
ccprintf(ss, ", ");
|
||||
printVecReg(ss, op2, true);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveComplexOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, gp);
|
||||
ccprintf(ss, "/m, ");
|
||||
printVecPredReg(ss, op1);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op2);
|
||||
ccprintf(ss, ", #");
|
||||
const char* rotstr[4] = {"0", "90", "180", "270"};
|
||||
ccprintf(ss, rotstr[rot]);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
SveComplexIdxOp::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss, "", false);
|
||||
printVecPredReg(ss, dest);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op1);
|
||||
ccprintf(ss, ", ");
|
||||
printVecPredReg(ss, op2);
|
||||
ccprintf(ss, "[");
|
||||
ss << imm;
|
||||
ccprintf(ss, "], #");
|
||||
const char* rotstr[4] = {"0", "90", "180", "270"};
|
||||
ccprintf(ss, rotstr[rot]);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
sveDisasmPredCountImm(uint8_t imm)
|
||||
{
|
||||
switch (imm) {
|
||||
case 0x0:
|
||||
return "POW2";
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
case 0x7:
|
||||
return "VL" + std::to_string(imm);
|
||||
case 0x8:
|
||||
case 0x9:
|
||||
case 0xa:
|
||||
case 0xb:
|
||||
case 0xc:
|
||||
case 0xd:
|
||||
return "VL" + std::to_string(1 << ((imm & 0x7) + 3));
|
||||
case 0x1d:
|
||||
return "MUL4";
|
||||
case 0x1e:
|
||||
return "MUL3";
|
||||
case 0x1f:
|
||||
return "ALL";
|
||||
default:
|
||||
return "#" + std::to_string(imm);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
sveDecodePredCount(uint8_t imm, unsigned int num_elems)
|
||||
{
|
||||
assert(num_elems > 0);
|
||||
|
||||
switch (imm) {
|
||||
case 0x0:
|
||||
// POW2
|
||||
return 1 << (31 - __builtin_clz((uint32_t) num_elems));
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
case 0x7:
|
||||
// VL1, VL2, VL3, VL4, VL5, VL6, VL7
|
||||
return (num_elems >= imm) ? imm : 0;
|
||||
case 0x8:
|
||||
case 0x9:
|
||||
case 0xa:
|
||||
case 0xb:
|
||||
case 0xc:
|
||||
case 0xd:
|
||||
// VL8, VL16, VL32, VL64, VL128, VL256
|
||||
{
|
||||
unsigned int pcount = 1 << ((imm & 0x7) + 3);
|
||||
return (num_elems >= pcount) ? pcount : 0;
|
||||
}
|
||||
case 0x1d:
|
||||
// MUL4
|
||||
return num_elems - (num_elems % 4);
|
||||
case 0x1e:
|
||||
// MUL3
|
||||
return num_elems - (num_elems % 3);
|
||||
case 0x1f:
|
||||
// ALL
|
||||
return num_elems;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
sveExpandFpImmAddSub(uint8_t imm, uint8_t size)
|
||||
{
|
||||
static constexpr uint16_t fpOne16 = 0x3c00;
|
||||
static constexpr uint16_t fpPointFive16 = 0x3800;
|
||||
static constexpr uint32_t fpOne32 = 0x3f800000;
|
||||
static constexpr uint32_t fpPointFive32 = 0x3f000000;
|
||||
static constexpr uint64_t fpOne64 = 0x3ff0000000000000;
|
||||
static constexpr uint64_t fpPointFive64 = 0x3fe0000000000000;
|
||||
|
||||
switch (size) {
|
||||
case 0x1:
|
||||
return imm ? fpOne16 : fpPointFive16;
|
||||
case 0x2:
|
||||
return imm ? fpOne32 : fpPointFive32;
|
||||
case 0x3:
|
||||
return imm ? fpOne64 : fpPointFive64;
|
||||
default:
|
||||
panic("Unsupported size");
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
sveExpandFpImmMaxMin(uint8_t imm, uint8_t size)
|
||||
{
|
||||
static constexpr uint16_t fpOne16 = 0x3c00;
|
||||
static constexpr uint32_t fpOne32 = 0x3f800000;
|
||||
static constexpr uint64_t fpOne64 = 0x3ff0000000000000;
|
||||
|
||||
switch (size) {
|
||||
case 0x1:
|
||||
return imm ? fpOne16 : 0x0;
|
||||
case 0x2:
|
||||
return imm ? fpOne32 : 0x0;
|
||||
case 0x3:
|
||||
return imm ? fpOne64 : 0x0;
|
||||
default:
|
||||
panic("Unsupported size");
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
sveExpandFpImmMul(uint8_t imm, uint8_t size)
|
||||
{
|
||||
static constexpr uint16_t fpTwo16 = 0x4000;
|
||||
static constexpr uint16_t fpPointFive16 = 0x3800;
|
||||
static constexpr uint32_t fpTwo32 = 0x40000000;
|
||||
static constexpr uint32_t fpPointFive32 = 0x3f000000;
|
||||
static constexpr uint64_t fpTwo64 = 0x4000000000000000;
|
||||
static constexpr uint64_t fpPointFive64 = 0x3fe0000000000000;
|
||||
|
||||
switch (size) {
|
||||
case 0x1:
|
||||
return imm ? fpTwo16 : fpPointFive16;
|
||||
case 0x2:
|
||||
return imm ? fpTwo32 : fpPointFive32;
|
||||
case 0x3:
|
||||
return imm ? fpTwo64 : fpPointFive64;
|
||||
default:
|
||||
panic("Unsupported size");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ArmISA
|
||||
883
src/arch/arm/insts/sve.hh
Normal file
883
src/arch/arm/insts/sve.hh
Normal file
@@ -0,0 +1,883 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019 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_INSTS_SVE_HH__
|
||||
#define __ARCH_ARM_INSTS_SVE_HH__
|
||||
|
||||
#include "arch/arm/insts/static_inst.hh"
|
||||
|
||||
namespace ArmISA {
|
||||
|
||||
enum class SvePredType {
|
||||
NONE,
|
||||
MERGE,
|
||||
ZERO,
|
||||
SELECT
|
||||
};
|
||||
|
||||
/// Returns the specifier for the predication type `pt` as a string.
|
||||
const char* svePredTypeToStr(SvePredType pt);
|
||||
|
||||
/// Index generation instruction, immediate operands
|
||||
class SveIndexIIOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
int8_t imm1;
|
||||
int8_t imm2;
|
||||
|
||||
SveIndexIIOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
int8_t _imm1, int8_t _imm2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), imm1(_imm1), imm2(_imm2)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class SveIndexIROp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
int8_t imm1;
|
||||
IntRegIndex op2;
|
||||
|
||||
SveIndexIROp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
int8_t _imm1, IntRegIndex _op2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), imm1(_imm1), op2(_op2)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class SveIndexRIOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
int8_t imm2;
|
||||
|
||||
SveIndexRIOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
IntRegIndex _op1, int8_t _imm2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), imm2(_imm2)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class SveIndexRROp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
IntRegIndex op2;
|
||||
|
||||
SveIndexRROp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
IntRegIndex _op1, IntRegIndex _op2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
// Predicate count SVE instruction.
|
||||
class SvePredCountOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex gp;
|
||||
bool srcIs32b;
|
||||
bool destIsVec;
|
||||
|
||||
SvePredCountOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp,
|
||||
bool _srcIs32b = false, bool _destIsVec = false) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), gp(_gp),
|
||||
srcIs32b(_srcIs32b), destIsVec(_destIsVec)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
// Predicate count SVE instruction (predicated).
|
||||
class SvePredCountPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
IntRegIndex gp;
|
||||
|
||||
SvePredCountPredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), gp(_gp)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// While predicate generation SVE instruction.
|
||||
class SveWhileOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
bool srcIs32b;
|
||||
|
||||
SveWhileOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
|
||||
bool _srcIs32b) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), srcIs32b(_srcIs32b)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Compare and terminate loop SVE instruction.
|
||||
class SveCompTermOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex op1, op2;
|
||||
|
||||
SveCompTermOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _op1, IntRegIndex _op2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
op1(_op1), op2(_op2)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Unary, constructive, predicated (merging) SVE instruction.
|
||||
class SveUnaryPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, gp;
|
||||
|
||||
SveUnaryPredOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), gp(_gp)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Unary, constructive, unpredicated SVE instruction.
|
||||
class SveUnaryUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1;
|
||||
|
||||
SveUnaryUnpredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Unary with wide immediate, constructive, unpredicated SVE instruction.
|
||||
class SveUnaryWideImmUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
uint64_t imm;
|
||||
|
||||
SveUnaryWideImmUnpredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
uint64_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Unary with wide immediate, constructive, predicated SVE instruction.
|
||||
class SveUnaryWideImmPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
uint64_t imm;
|
||||
IntRegIndex gp;
|
||||
|
||||
bool isMerging;
|
||||
|
||||
SveUnaryWideImmPredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
uint64_t _imm, IntRegIndex _gp, bool _isMerging) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), imm(_imm), gp(_gp), isMerging(_isMerging)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary with immediate, destructive, unpredicated SVE instruction.
|
||||
class SveBinImmUnpredConstrOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1;
|
||||
uint64_t imm;
|
||||
|
||||
SveBinImmUnpredConstrOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
uint64_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary with immediate, destructive, predicated (merging) SVE instruction.
|
||||
class SveBinImmPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, gp;
|
||||
uint64_t imm;
|
||||
|
||||
SveBinImmPredOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, uint64_t _imm, IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), gp(_gp), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary with wide immediate, destructive, unpredicated SVE instruction.
|
||||
class SveBinWideImmUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
uint64_t imm;
|
||||
|
||||
SveBinWideImmUnpredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
uint64_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary, destructive, predicated (merging) SVE instruction.
|
||||
class SveBinDestrPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op2, gp;
|
||||
|
||||
SveBinDestrPredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op2,
|
||||
IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op2(_op2), gp(_gp)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary, constructive, predicated SVE instruction.
|
||||
class SveBinConstrPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2, gp;
|
||||
SvePredType predType;
|
||||
|
||||
SveBinConstrPredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2, IntRegIndex _gp,
|
||||
SvePredType _predType) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), gp(_gp), predType(_predType)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary, unpredicated SVE instruction with indexed operand
|
||||
class SveBinUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
|
||||
SveBinUnpredOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary, unpredicated SVE instruction
|
||||
class SveBinIdxUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
uint8_t index;
|
||||
|
||||
SveBinIdxUnpredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2, uint8_t _index) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), index(_index)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Predicate logical instruction.
|
||||
class SvePredLogicalOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2, gp;
|
||||
bool isSel;
|
||||
|
||||
SvePredLogicalOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2, IntRegIndex _gp, bool _isSel = false) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), gp(_gp), isSel(_isSel)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Predicate binary permute instruction.
|
||||
class SvePredBinPermOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
|
||||
SvePredBinPermOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE compare instructions, predicated (zeroing).
|
||||
class SveCmpOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, gp, op1, op2;
|
||||
|
||||
SveCmpOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
|
||||
IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), gp(_gp), op1(_op1), op2(_op2)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE compare-with-immediate instructions, predicated (zeroing).
|
||||
class SveCmpImmOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, gp, op1;
|
||||
uint64_t imm;
|
||||
|
||||
SveCmpImmOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, uint64_t _imm,
|
||||
IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), gp(_gp), op1(_op1), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Ternary, destructive, predicated (merging) SVE instruction.
|
||||
class SveTerPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2, gp;
|
||||
|
||||
SveTerPredOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
|
||||
IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), gp(_gp)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Ternary with immediate, destructive, unpredicated SVE instruction.
|
||||
class SveTerImmUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op2;
|
||||
uint64_t imm;
|
||||
|
||||
SveTerImmUnpredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op2,
|
||||
uint64_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op2(_op2), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE reductions.
|
||||
class SveReducOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, gp;
|
||||
|
||||
SveReducOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), gp(_gp)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE ordered reductions.
|
||||
class SveOrdReducOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, gp;
|
||||
|
||||
SveOrdReducOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), gp(_gp)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// PTRUE, PTRUES.
|
||||
class SvePtrueOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
uint8_t imm;
|
||||
|
||||
SvePtrueOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, uint8_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Integer compare SVE instruction.
|
||||
class SveIntCmpOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1, op2;
|
||||
IntRegIndex gp;
|
||||
bool op2IsWide;
|
||||
|
||||
SveIntCmpOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
|
||||
IntRegIndex _gp, bool _op2IsWide = false) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), gp(_gp), op2IsWide(_op2IsWide)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Integer compare with immediate SVE instruction.
|
||||
class SveIntCmpImmOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
int64_t imm;
|
||||
IntRegIndex gp;
|
||||
|
||||
SveIntCmpImmOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, int64_t _imm,
|
||||
IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), imm(_imm), gp(_gp)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// ADR.
|
||||
class SveAdrOp : public ArmStaticInst {
|
||||
public:
|
||||
enum SveAdrOffsetFormat {
|
||||
SveAdrOffsetPacked,
|
||||
SveAdrOffsetUnpackedSigned,
|
||||
SveAdrOffsetUnpackedUnsigned
|
||||
};
|
||||
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
uint8_t mult;
|
||||
SveAdrOffsetFormat offsetFormat;
|
||||
|
||||
SveAdrOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2, uint8_t _mult,
|
||||
SveAdrOffsetFormat _offsetFormat) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), mult(_mult),
|
||||
offsetFormat(_offsetFormat)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Element count SVE instruction.
|
||||
class SveElemCountOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
uint8_t pattern;
|
||||
uint8_t imm;
|
||||
bool dstIsVec;
|
||||
bool dstIs32b;
|
||||
uint8_t esize;
|
||||
|
||||
SveElemCountOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, uint8_t _pattern, uint8_t _imm,
|
||||
bool _dstIsVec, bool _dstIs32b) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), pattern(_pattern), imm(_imm), dstIsVec(_dstIsVec),
|
||||
dstIs32b(_dstIs32b)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Partition break SVE instruction.
|
||||
class SvePartBrkOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex gp;
|
||||
IntRegIndex op1;
|
||||
bool isMerging;
|
||||
|
||||
SvePartBrkOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _op1,
|
||||
bool _isMerging) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), gp(_gp), op1(_op1), isMerging(_isMerging)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Partition break with propagation SVE instruction.
|
||||
class SvePartBrkPropOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
IntRegIndex op2;
|
||||
IntRegIndex gp;
|
||||
|
||||
SvePartBrkPropOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
IntRegIndex _op1, IntRegIndex _op2, IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), gp(_gp)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Scalar element select SVE instruction.
|
||||
class SveSelectOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
IntRegIndex gp;
|
||||
bool conditional;
|
||||
bool scalar;
|
||||
bool simdFp;
|
||||
size_t scalar_width;
|
||||
|
||||
SveSelectOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
IntRegIndex _op1, IntRegIndex _gp,
|
||||
bool _conditional, bool _scalar,
|
||||
bool _simdFp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), gp(_gp), conditional(_conditional),
|
||||
scalar(_scalar), simdFp(_simdFp)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE unary operation on predicate (predicated)
|
||||
class SveUnaryPredPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
IntRegIndex gp;
|
||||
|
||||
SveUnaryPredPredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
IntRegIndex _op1, IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), gp(_gp)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE table lookup/permute using vector of element indices (TBL)
|
||||
class SveTblOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
IntRegIndex op2;
|
||||
|
||||
SveTblOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE unpack and widen predicate
|
||||
class SveUnpackOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
|
||||
SveUnpackOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _dest, IntRegIndex _op1) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE predicate test
|
||||
class SvePredTestOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex op1;
|
||||
IntRegIndex gp;
|
||||
|
||||
SvePredTestOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _op1, IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
op1(_op1), gp(_gp)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE unary predicate instructions with implicit source operand
|
||||
class SvePredUnaryWImplicitSrcOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
|
||||
SvePredUnaryWImplicitSrcOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE unary predicate instructions, predicated, with implicit source operand
|
||||
class SvePredUnaryWImplicitSrcPredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex gp;
|
||||
|
||||
SvePredUnaryWImplicitSrcPredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest,
|
||||
IntRegIndex _gp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), gp(_gp)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE unary predicate instructions with implicit destination operand
|
||||
class SvePredUnaryWImplicitDstOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex op1;
|
||||
|
||||
SvePredUnaryWImplicitDstOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _op1) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
op1(_op1)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE unary predicate instructions with implicit destination operand
|
||||
class SveWImplicitSrcDstOp : public ArmStaticInst {
|
||||
protected:
|
||||
SveWImplicitSrcDstOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE vector - immediate binary operation
|
||||
class SveBinImmUnpredDestrOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest;
|
||||
IntRegIndex op1;
|
||||
uint64_t imm;
|
||||
|
||||
SveBinImmUnpredDestrOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
uint64_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), imm(_imm)
|
||||
{}
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Binary with immediate index, destructive, unpredicated SVE instruction.
|
||||
class SveBinImmIdxUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1;
|
||||
uint64_t imm;
|
||||
|
||||
SveBinImmIdxUnpredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
uint64_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// Unary unpredicated scalar to vector instruction
|
||||
class SveUnarySca2VecUnpredOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1;
|
||||
bool simdFp;
|
||||
|
||||
SveUnarySca2VecUnpredOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
bool _simdFp) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), simdFp(_simdFp)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE dot product instruction (indexed)
|
||||
class SveDotProdIdxOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
uint64_t imm;
|
||||
uint8_t esize;
|
||||
|
||||
public:
|
||||
SveDotProdIdxOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2, uint64_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE dot product instruction (vectors)
|
||||
class SveDotProdOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
uint8_t esize;
|
||||
|
||||
public:
|
||||
SveDotProdOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE Complex Instructions (vectors)
|
||||
class SveComplexOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2, gp;
|
||||
uint8_t rot;
|
||||
|
||||
public:
|
||||
SveComplexOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2, IntRegIndex _gp, uint8_t _rot) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), gp(_gp), rot(_rot)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/// SVE Complex Instructions (indexed)
|
||||
class SveComplexIdxOp : public ArmStaticInst {
|
||||
protected:
|
||||
IntRegIndex dest, op1, op2;
|
||||
uint8_t rot, imm;
|
||||
|
||||
public:
|
||||
SveComplexIdxOp(const char* mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||
IntRegIndex _op2, uint8_t _rot, uint8_t _imm) :
|
||||
ArmStaticInst(mnem, _machInst, __opClass),
|
||||
dest(_dest), op1(_op1), op2(_op2), rot(_rot), imm(_imm)
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
|
||||
/// Returns the symbolic name associated with pattern `imm` for PTRUE(S)
|
||||
/// instructions.
|
||||
std::string sveDisasmPredCountImm(uint8_t imm);
|
||||
|
||||
/// Returns the actual number of elements active for PTRUE(S) instructions.
|
||||
/// @param imm 5-bit immediate encoding the predicate pattern.
|
||||
/// @param num_elems Current number of elements per vector (depending on
|
||||
/// current vector length and element size).
|
||||
unsigned int sveDecodePredCount(uint8_t imm, unsigned int num_elems);
|
||||
|
||||
/// Expand 1-bit floating-point immediate to 0.5 or 1.0 (FADD, FSUB, FSUBR).
|
||||
/// @param imm 1-bit immediate.
|
||||
/// @param size Encoding of the vector element size.
|
||||
/// @return Encoding of the expanded value.
|
||||
uint64_t sveExpandFpImmAddSub(uint8_t imm, uint8_t size);
|
||||
|
||||
/// Expand 1-bit floating-point immediate to 0.0 or 1.0 (FMAX, FMAXNM, FMIN,
|
||||
/// FMINNM).
|
||||
/// @param imm 1-bit immediate.
|
||||
/// @param size Encoding of the vector element size.
|
||||
/// @return Encoding of the expanded value.
|
||||
uint64_t sveExpandFpImmMaxMin(uint8_t imm, uint8_t size);
|
||||
|
||||
/// Expand 1-bit floating-point immediate to 0.5 or 2.0 (FMUL).
|
||||
/// @param imm 1-bit immediate.
|
||||
/// @param size Encoding of the vector element size.
|
||||
/// @return Encoding of the expanded value.
|
||||
uint64_t sveExpandFpImmMul(uint8_t imm, uint8_t size);
|
||||
|
||||
} // namespace ArmISA
|
||||
|
||||
#endif // __ARCH_ARM_INSTS_SVE_HH__
|
||||
@@ -89,12 +89,16 @@ ISA::ISA(Params *p)
|
||||
haveVirtualization = system->haveVirtualization();
|
||||
haveLargeAsid64 = system->haveLargeAsid64();
|
||||
physAddrRange = system->physAddrRange();
|
||||
haveSVE = system->haveSVE();
|
||||
sveVL = system->sveVL();
|
||||
} else {
|
||||
highestELIs64 = true; // ArmSystem::highestELIs64 does the same
|
||||
haveSecurity = haveLPAE = haveVirtualization = false;
|
||||
haveCrypto = true;
|
||||
haveLargeAsid64 = false;
|
||||
physAddrRange = 32; // dummy value
|
||||
haveSVE = true;
|
||||
sveVL = p->sve_vl_se;
|
||||
}
|
||||
|
||||
// Initial rename mode depends on highestEL
|
||||
@@ -350,6 +354,16 @@ ISA::initID64(const ArmISAParams *p)
|
||||
|
||||
miscRegs[MISCREG_ID_DFR0] = miscRegs[MISCREG_ID_DFR0_EL1];
|
||||
|
||||
// SVE
|
||||
miscRegs[MISCREG_ID_AA64ZFR0_EL1] = 0; // SVEver 0
|
||||
if (haveSecurity) {
|
||||
miscRegs[MISCREG_ZCR_EL3] = sveVL - 1;
|
||||
} else if (haveVirtualization) {
|
||||
miscRegs[MISCREG_ZCR_EL2] = sveVL - 1;
|
||||
} else {
|
||||
miscRegs[MISCREG_ZCR_EL1] = sveVL - 1;
|
||||
}
|
||||
|
||||
// Enforce consistency with system-level settings...
|
||||
|
||||
// EL3
|
||||
@@ -360,6 +374,10 @@ ISA::initID64(const ArmISAParams *p)
|
||||
miscRegs[MISCREG_ID_AA64PFR0_EL1] = insertBits(
|
||||
miscRegs[MISCREG_ID_AA64PFR0_EL1], 11, 8,
|
||||
haveVirtualization ? 0x2 : 0x0);
|
||||
// SVE
|
||||
miscRegs[MISCREG_ID_AA64PFR0_EL1] = insertBits(
|
||||
miscRegs[MISCREG_ID_AA64PFR0_EL1], 35, 32,
|
||||
haveSVE ? 0x1 : 0x0);
|
||||
// Large ASID support
|
||||
miscRegs[MISCREG_ID_AA64MMFR0_EL1] = insertBits(
|
||||
miscRegs[MISCREG_ID_AA64MMFR0_EL1], 7, 4,
|
||||
@@ -576,6 +594,7 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
|
||||
const uint32_t ones = (uint32_t)(-1);
|
||||
FPSCR fpscrMask = 0;
|
||||
fpscrMask.len = ones;
|
||||
fpscrMask.fz16 = ones;
|
||||
fpscrMask.stride = ones;
|
||||
fpscrMask.rMode = ones;
|
||||
fpscrMask.fz = ones;
|
||||
@@ -683,6 +702,7 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
|
||||
0x0000000000000020 | // EL1
|
||||
(haveVirtualization ? 0x0000000000000200 : 0) | // EL2
|
||||
(haveSecurity ? 0x0000000000002000 : 0) | // EL3
|
||||
(haveSVE ? 0x0000000100000000 : 0) | // SVE
|
||||
(haveGICv3CPUInterface ? 0x0000000001000000 : 0);
|
||||
case MISCREG_ID_AA64PFR1_EL1:
|
||||
return 0; // bits [63:0] RES0 (reserved for future use)
|
||||
@@ -757,6 +777,8 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
|
||||
pc.nextJazelle(cpsr.j);
|
||||
pc.illegalExec(cpsr.il == 1);
|
||||
|
||||
tc->getDecoderPtr()->setSveLen((getCurSveVecLenInBits(tc) >> 7) - 1);
|
||||
|
||||
// Follow slightly different semantics if a CheckerCPU object
|
||||
// is connected
|
||||
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
||||
@@ -807,6 +829,20 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
|
||||
miscRegName[misc_reg], newVal);
|
||||
}
|
||||
break;
|
||||
case MISCREG_CPACR_EL1:
|
||||
{
|
||||
const uint32_t ones = (uint32_t)(-1);
|
||||
CPACR cpacrMask = 0;
|
||||
cpacrMask.tta = ones;
|
||||
cpacrMask.fpen = ones;
|
||||
if (haveSVE) {
|
||||
cpacrMask.zen = ones;
|
||||
}
|
||||
newVal &= cpacrMask;
|
||||
DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n",
|
||||
miscRegName[misc_reg], newVal);
|
||||
}
|
||||
break;
|
||||
case MISCREG_CPTR_EL2:
|
||||
{
|
||||
const uint32_t ones = (uint32_t)(-1);
|
||||
@@ -814,10 +850,17 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
|
||||
cptrMask.tcpac = ones;
|
||||
cptrMask.tta = ones;
|
||||
cptrMask.tfp = ones;
|
||||
if (haveSVE) {
|
||||
cptrMask.tz = ones;
|
||||
}
|
||||
newVal &= cptrMask;
|
||||
cptrMask = 0;
|
||||
cptrMask.res1_13_12_el2 = ones;
|
||||
cptrMask.res1_9_0_el2 = ones;
|
||||
cptrMask.res1_7_0_el2 = ones;
|
||||
if (!haveSVE) {
|
||||
cptrMask.res1_8_el2 = ones;
|
||||
}
|
||||
cptrMask.res1_9_el2 = ones;
|
||||
newVal |= cptrMask;
|
||||
DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n",
|
||||
miscRegName[misc_reg], newVal);
|
||||
@@ -830,6 +873,9 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
|
||||
cptrMask.tcpac = ones;
|
||||
cptrMask.tta = ones;
|
||||
cptrMask.tfp = ones;
|
||||
if (haveSVE) {
|
||||
cptrMask.ez = ones;
|
||||
}
|
||||
newVal &= cptrMask;
|
||||
DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n",
|
||||
miscRegName[misc_reg], newVal);
|
||||
@@ -860,6 +906,7 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
|
||||
fpscrMask.ixe = ones;
|
||||
fpscrMask.ide = ones;
|
||||
fpscrMask.len = ones;
|
||||
fpscrMask.fz16 = ones;
|
||||
fpscrMask.stride = ones;
|
||||
fpscrMask.rMode = ones;
|
||||
fpscrMask.fz = ones;
|
||||
@@ -902,6 +949,7 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
|
||||
const uint32_t ones = (uint32_t)(-1);
|
||||
FPSCR fpscrMask = 0;
|
||||
fpscrMask.len = ones;
|
||||
fpscrMask.fz16 = ones;
|
||||
fpscrMask.stride = ones;
|
||||
fpscrMask.rMode = ones;
|
||||
fpscrMask.fz = ones;
|
||||
@@ -1986,11 +2034,16 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
|
||||
case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
|
||||
getGenericTimer(tc).setMiscReg(misc_reg, newVal);
|
||||
break;
|
||||
|
||||
case MISCREG_ICC_PMR_EL1 ... MISCREG_ICC_IGRPEN1_EL3:
|
||||
case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_LR15_EL2:
|
||||
getGICv3CPUInterface(tc).setMiscReg(misc_reg, newVal);
|
||||
return;
|
||||
case MISCREG_ZCR_EL3:
|
||||
case MISCREG_ZCR_EL2:
|
||||
case MISCREG_ZCR_EL1:
|
||||
tc->getDecoderPtr()->setSveLen(
|
||||
(getCurSveVecLenInBits(tc) >> 7) - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
setMiscRegNoEffect(misc_reg, newVal);
|
||||
@@ -2024,8 +2077,61 @@ ISA::getGICv3CPUInterface(ThreadContext *tc)
|
||||
return *gicv3CpuInterface.get();
|
||||
}
|
||||
|
||||
unsigned
|
||||
ISA::getCurSveVecLenInBits(ThreadContext *tc) const
|
||||
{
|
||||
if (!FullSystem) {
|
||||
return sveVL * 128;
|
||||
}
|
||||
|
||||
panic_if(!tc,
|
||||
"A ThreadContext is needed to determine the SVE vector length "
|
||||
"in full-system mode");
|
||||
|
||||
CPSR cpsr = miscRegs[MISCREG_CPSR];
|
||||
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
|
||||
|
||||
unsigned len = 0;
|
||||
|
||||
if (el == EL1 || (el == EL0 && !ELIsInHost(tc, el))) {
|
||||
len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL1]).len;
|
||||
}
|
||||
|
||||
if (el == EL2 || (el == EL0 && ELIsInHost(tc, el))) {
|
||||
len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL2]).len;
|
||||
} else if (haveVirtualization && !inSecureState(tc) &&
|
||||
(el == EL0 || el == EL1)) {
|
||||
len = std::min(
|
||||
len,
|
||||
static_cast<unsigned>(
|
||||
static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL2]).len));
|
||||
}
|
||||
|
||||
if (el == EL3) {
|
||||
len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL3]).len;
|
||||
} else if (haveSecurity) {
|
||||
len = std::min(
|
||||
len,
|
||||
static_cast<unsigned>(
|
||||
static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL3]).len));
|
||||
}
|
||||
|
||||
len = std::min(len, sveVL - 1);
|
||||
|
||||
return (len + 1) * 128;
|
||||
}
|
||||
|
||||
void
|
||||
ISA::zeroSveVecRegUpperPart(VecRegContainer &vc, unsigned eCount)
|
||||
{
|
||||
auto vv = vc.as<uint64_t>();
|
||||
for (int i = 2; i < eCount; ++i) {
|
||||
vv[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ArmISA
|
||||
|
||||
ArmISA::ISA *
|
||||
ArmISAParams::create()
|
||||
{
|
||||
|
||||
@@ -94,6 +94,10 @@ namespace ArmISA
|
||||
bool haveLargeAsid64;
|
||||
bool haveGICv3CPUInterface;
|
||||
uint8_t physAddrRange;
|
||||
bool haveSVE;
|
||||
|
||||
/** SVE vector length in quadwords */
|
||||
unsigned sveVL;
|
||||
|
||||
/**
|
||||
* If true, accesses to IMPLEMENTATION DEFINED registers are treated
|
||||
@@ -660,6 +664,13 @@ namespace ArmISA
|
||||
return std::make_pair(lower, upper);
|
||||
}
|
||||
|
||||
unsigned getCurSveVecLenInBits(ThreadContext *tc) const;
|
||||
|
||||
unsigned getCurSveVecLenInBitsAtReset() const { return sveVL * 128; }
|
||||
|
||||
static void zeroSveVecRegUpperPart(VecRegContainer &vc,
|
||||
unsigned eCount);
|
||||
|
||||
void serialize(CheckpointOut &cp) const
|
||||
{
|
||||
DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
|
||||
@@ -671,6 +682,8 @@ namespace ArmISA
|
||||
SERIALIZE_SCALAR(haveVirtualization);
|
||||
SERIALIZE_SCALAR(haveLargeAsid64);
|
||||
SERIALIZE_SCALAR(physAddrRange);
|
||||
SERIALIZE_SCALAR(haveSVE);
|
||||
SERIALIZE_SCALAR(sveVL);
|
||||
}
|
||||
void unserialize(CheckpointIn &cp)
|
||||
{
|
||||
@@ -685,6 +698,8 @@ namespace ArmISA
|
||||
UNSERIALIZE_SCALAR(haveVirtualization);
|
||||
UNSERIALIZE_SCALAR(haveLargeAsid64);
|
||||
UNSERIALIZE_SCALAR(physAddrRange);
|
||||
UNSERIALIZE_SCALAR(haveSVE);
|
||||
UNSERIALIZE_SCALAR(sveVL);
|
||||
}
|
||||
|
||||
void startup(ThreadContext *tc);
|
||||
|
||||
@@ -53,6 +53,10 @@ namespace Aarch64
|
||||
StaticInstPtr decodeAdvSIMD(ExtMachInst machInst);
|
||||
StaticInstPtr decodeAdvSIMDScalar(ExtMachInst machInst);
|
||||
|
||||
StaticInstPtr decodeSveInt(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFp(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveMem(ExtMachInst machInst);
|
||||
|
||||
StaticInstPtr decodeGem5Ops(ExtMachInst machInst);
|
||||
}
|
||||
}};
|
||||
@@ -2280,9 +2284,23 @@ def format Aarch64() {{
|
||||
{
|
||||
using namespace Aarch64;
|
||||
if (bits(machInst, 27) == 0x0) {
|
||||
if (bits(machInst, 28) == 0x0)
|
||||
return new Unknown64(machInst);
|
||||
else if (bits(machInst, 26) == 0)
|
||||
if (bits(machInst, 28) == 0x0) {
|
||||
if (bits(machInst, 26, 25) != 0x2) {
|
||||
return new Unknown64(machInst);
|
||||
}
|
||||
if (bits(machInst, 31) == 0x0) {
|
||||
switch (bits(machInst, 30, 29)) {
|
||||
case 0x0:
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
return decodeSveInt(machInst);
|
||||
case 0x3:
|
||||
return decodeSveFp(machInst);
|
||||
}
|
||||
} else {
|
||||
return decodeSveMem(machInst);
|
||||
}
|
||||
} else if (bits(machInst, 26) == 0)
|
||||
// bit 28:26=100
|
||||
return decodeDataProcImm(machInst);
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2010-2011 ARM Limited
|
||||
// Copyright (c) 2010-2011, 2017 ARM Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// The license below extends only to copyright in the software and shall
|
||||
@@ -50,6 +50,10 @@
|
||||
//Include support for decoding AArch64 NEON instructions
|
||||
##include "neon64.isa"
|
||||
|
||||
//Include support for decoding SVE instructions (AArch64-only)
|
||||
##include "sve_top_level.isa"
|
||||
##include "sve_2nd_level.isa"
|
||||
|
||||
//Include support for predicated instructions
|
||||
##include "pred.isa"
|
||||
|
||||
|
||||
2917
src/arch/arm/isa/formats/sve_2nd_level.isa
Normal file
2917
src/arch/arm/isa/formats/sve_2nd_level.isa
Normal file
File diff suppressed because it is too large
Load Diff
314
src/arch/arm/isa/formats/sve_top_level.isa
Normal file
314
src/arch/arm/isa/formats/sve_top_level.isa
Normal file
@@ -0,0 +1,314 @@
|
||||
// Copyright (c) 2017-2019 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
|
||||
/// SVE top-level decoder.
|
||||
|
||||
output header {{
|
||||
namespace Aarch64
|
||||
{
|
||||
StaticInstPtr decodeSveIntArithBinPred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntReduc(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveShiftByImmPred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntArithUnaryPred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntMulAdd(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntArithUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntLogUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIndexGen(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveStackAlloc(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveShiftByImmUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveCompVecAddr(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntMiscUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveElemCount(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveLogMaskImm(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntWideImmPred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSvePermExtract(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSvePermUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSvePermPredicates(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSvePermIntlv(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSvePermPred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveSelVec(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntCmpVec(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntCmpUImm(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntCmpSImm(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSvePredGen(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSvePredCount(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntCmpSca(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveIntWideImmUnpred(ExtMachInst machInst);
|
||||
|
||||
StaticInstPtr decodeSveMultiplyAddUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveMultiplyIndexed(ExtMachInst machInst);
|
||||
|
||||
StaticInstPtr decodeSveFpFastReduc(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpUnaryUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpCmpZero(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpAccumReduc(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpArithUnpred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpArithPred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpUnaryPred(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpCmpVec(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpFusedMulAdd(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpCplxAdd(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpCplxMulAddVec(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpMulAddIndexed(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpCplxMulAddIndexed(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveFpMulIndexed(ExtMachInst machInst);
|
||||
|
||||
StaticInstPtr decodeSveMemGather32(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveMemContigLoad(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveMemGather64(ExtMachInst machInst);
|
||||
StaticInstPtr decodeSveMemStore(ExtMachInst machInst);
|
||||
}
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
namespace Aarch64
|
||||
{
|
||||
|
||||
StaticInstPtr
|
||||
decodeSveInt(ExtMachInst machInst)
|
||||
{
|
||||
uint8_t b_29_24_21 = (bits(machInst, 29) << 2) |
|
||||
(bits(machInst, 24) << 1) |
|
||||
bits(machInst, 21);
|
||||
switch (b_29_24_21) {
|
||||
case 0x0:
|
||||
{
|
||||
if (bits(machInst, 14)) {
|
||||
return decodeSveIntMulAdd(machInst);
|
||||
} else {
|
||||
uint8_t b_15_13 = (bits(machInst, 15) << 1) |
|
||||
bits(machInst, 13);
|
||||
switch (b_15_13) {
|
||||
case 0x0:
|
||||
if (bits(machInst, 30)) {
|
||||
return decodeSveMultiplyAddUnpred(machInst);
|
||||
} else {
|
||||
return decodeSveIntArithBinPred(machInst);
|
||||
}
|
||||
case 0x1:
|
||||
return decodeSveIntReduc(machInst);
|
||||
case 0x2:
|
||||
return decodeSveShiftByImmPred(machInst);
|
||||
case 0x3:
|
||||
return decodeSveIntArithUnaryPred(machInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0x1:
|
||||
{
|
||||
uint8_t b_15_14 = bits(machInst, 15, 14);
|
||||
uint8_t b_13 = bits(machInst, 13);
|
||||
uint8_t b_12 = bits(machInst, 12);
|
||||
switch (b_15_14) {
|
||||
case 0x0:
|
||||
if (b_13) {
|
||||
return decodeSveIntLogUnpred(machInst);
|
||||
} else {
|
||||
if (bits(machInst, 30)) {
|
||||
return decodeSveMultiplyIndexed(machInst);
|
||||
} else {
|
||||
return decodeSveIntArithUnpred(machInst);
|
||||
}
|
||||
}
|
||||
case 0x1:
|
||||
if (b_13) {
|
||||
return new Unknown64(machInst);
|
||||
} else if (b_12) {
|
||||
return decodeSveStackAlloc(machInst);
|
||||
} else {
|
||||
return decodeSveIndexGen(machInst);
|
||||
}
|
||||
case 0x2:
|
||||
if (b_13) {
|
||||
if (b_12) {
|
||||
return decodeSveIntMiscUnpred(machInst);
|
||||
} else {
|
||||
return decodeSveCompVecAddr(machInst);
|
||||
}
|
||||
} else {
|
||||
return decodeSveShiftByImmUnpred(machInst);
|
||||
}
|
||||
case 0x3:
|
||||
return decodeSveElemCount(machInst);
|
||||
}
|
||||
}
|
||||
case 0x2:
|
||||
if (bits(machInst, 20)) {
|
||||
return decodeSveIntWideImmPred(machInst);
|
||||
} else {
|
||||
return decodeSveLogMaskImm(machInst);
|
||||
}
|
||||
case 0x3:
|
||||
{
|
||||
uint8_t b_15_14 = bits(machInst, 15, 14);
|
||||
uint8_t b_13 = bits(machInst, 13);
|
||||
switch (b_15_14) {
|
||||
case 0x0:
|
||||
if (b_13) {
|
||||
return decodeSvePermUnpred(machInst);
|
||||
} else {
|
||||
return decodeSvePermExtract(machInst);
|
||||
}
|
||||
case 0x1:
|
||||
if (b_13) {
|
||||
return decodeSvePermIntlv(machInst);
|
||||
} else {
|
||||
return decodeSvePermPredicates(machInst);
|
||||
}
|
||||
case 0x2:
|
||||
return decodeSvePermPred(machInst);
|
||||
case 0x3:
|
||||
return decodeSveSelVec(machInst);
|
||||
}
|
||||
}
|
||||
case 0x4:
|
||||
return decodeSveIntCmpVec(machInst);
|
||||
case 0x5:
|
||||
return decodeSveIntCmpUImm(machInst);
|
||||
case 0x6:
|
||||
if (bits(machInst, 14)) {
|
||||
return decodeSvePredGen(machInst);
|
||||
} else {
|
||||
return decodeSveIntCmpSImm(machInst);
|
||||
}
|
||||
case 0x7:
|
||||
{
|
||||
uint8_t b_15_14 = bits(machInst, 15, 14);
|
||||
switch (b_15_14) {
|
||||
case 0x0:
|
||||
return decodeSveIntCmpSca(machInst);
|
||||
case 0x1:
|
||||
return new Unknown64(machInst);
|
||||
case 0x2:
|
||||
return decodeSvePredCount(machInst);
|
||||
case 0x3:
|
||||
return decodeSveIntWideImmUnpred(machInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Unknown64(machInst);
|
||||
}
|
||||
|
||||
StaticInstPtr
|
||||
decodeSveFp(ExtMachInst machInst)
|
||||
{
|
||||
uint8_t b_24_21 = (bits(machInst, 24) << 1) |
|
||||
bits(machInst, 21);
|
||||
switch (b_24_21) {
|
||||
case 0x0:
|
||||
if (!bits(machInst, 15)) {
|
||||
return decodeSveFpCplxMulAddVec(machInst);
|
||||
} else if((bits(machInst, 20, 17) | bits(machInst, 14, 13)) == 0) {
|
||||
return decodeSveFpCplxAdd(machInst);
|
||||
}
|
||||
return new Unknown64(machInst);
|
||||
case 0x1:
|
||||
if (bits(machInst, 15, 12) == 1) {
|
||||
return decodeSveFpCplxMulAddIndexed(machInst);
|
||||
}
|
||||
switch (bits(machInst, 13, 11)) {
|
||||
case 0:
|
||||
return decodeSveFpMulAddIndexed(machInst);
|
||||
case 4:
|
||||
if (!bits(machInst, 10))
|
||||
return decodeSveFpMulIndexed(machInst);
|
||||
M5_FALLTHROUGH;
|
||||
default:
|
||||
return new Unknown64(machInst);
|
||||
}
|
||||
case 0x2:
|
||||
{
|
||||
if (bits(machInst, 14)) {
|
||||
return decodeSveFpCmpVec(machInst);
|
||||
} else {
|
||||
uint8_t b_15_13 = (bits(machInst, 15) << 1) |
|
||||
bits(machInst, 13);
|
||||
switch (b_15_13) {
|
||||
case 0x0:
|
||||
return decodeSveFpArithUnpred(machInst);
|
||||
case 0x1:
|
||||
{
|
||||
uint8_t b_20_19 = (bits(machInst, 20) << 1) |
|
||||
bits(machInst, 19);
|
||||
switch (b_20_19) {
|
||||
case 0x0:
|
||||
return decodeSveFpFastReduc(machInst);
|
||||
case 0x1:
|
||||
if (bits(machInst, 12)) {
|
||||
return decodeSveFpUnaryUnpred(machInst);
|
||||
} else {
|
||||
return new Unknown64(machInst);
|
||||
}
|
||||
case 0x2:
|
||||
return decodeSveFpCmpZero(machInst);
|
||||
case 0x3:
|
||||
return decodeSveFpAccumReduc(machInst);
|
||||
}
|
||||
}
|
||||
case 0x2:
|
||||
return decodeSveFpArithPred(machInst);
|
||||
case 0x3:
|
||||
return decodeSveFpUnaryPred(machInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0x3:
|
||||
return decodeSveFpFusedMulAdd(machInst);
|
||||
}
|
||||
return new Unknown64(machInst);
|
||||
}
|
||||
|
||||
StaticInstPtr
|
||||
decodeSveMem(ExtMachInst machInst)
|
||||
{
|
||||
uint8_t b_30_29 = bits(machInst, 30, 29);
|
||||
switch (b_30_29) {
|
||||
case 0x0:
|
||||
return decodeSveMemGather32(machInst);
|
||||
case 0x1:
|
||||
return decodeSveMemContigLoad(machInst);
|
||||
case 0x2:
|
||||
return decodeSveMemGather64(machInst);
|
||||
case 0x3:
|
||||
return decodeSveMemStore(machInst);
|
||||
}
|
||||
return new Unknown64(machInst);
|
||||
}
|
||||
|
||||
} // namespace Aarch64
|
||||
}};
|
||||
@@ -64,6 +64,7 @@ output header {{
|
||||
#include "arch/arm/insts/pred_inst.hh"
|
||||
#include "arch/arm/insts/pseudo.hh"
|
||||
#include "arch/arm/insts/static_inst.hh"
|
||||
#include "arch/arm/insts/sve.hh"
|
||||
#include "arch/arm/insts/vfp.hh"
|
||||
#include "arch/arm/isa_traits.hh"
|
||||
#include "mem/packet.hh"
|
||||
@@ -92,6 +93,7 @@ output exec {{
|
||||
#include <cmath>
|
||||
|
||||
#include "arch/arm/faults.hh"
|
||||
#include "arch/arm/isa.hh"
|
||||
#include "arch/arm/isa_traits.hh"
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "arch/generic/memhelpers.hh"
|
||||
|
||||
@@ -44,6 +44,11 @@ let {{
|
||||
decoder_output = ""
|
||||
exec_output = ""
|
||||
|
||||
zeroSveVecRegUpperPartCode = '''
|
||||
TheISA::ISA::zeroSveVecRegUpperPart(%s,
|
||||
ArmStaticInst::getCurSveVecLen<uint64_t>(xc->tcBase()));
|
||||
'''
|
||||
|
||||
fmovImmSCode = vfp64EnabledCheckCode + '''
|
||||
AA64FpDestP0_uw = bits(imm, 31, 0);
|
||||
AA64FpDestP1_uw = 0;
|
||||
@@ -53,6 +58,7 @@ let {{
|
||||
fmovImmSIop = InstObjParams("fmov", "FmovImmS", "FpRegImmOp",
|
||||
{ "code": fmovImmSCode,
|
||||
"op_class": "FloatMiscOp" }, [])
|
||||
fmovImmSIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += FpRegImmOpDeclare.subst(fmovImmSIop);
|
||||
decoder_output += FpRegImmOpConstructor.subst(fmovImmSIop);
|
||||
exec_output += BasicExecute.subst(fmovImmSIop);
|
||||
@@ -66,6 +72,7 @@ let {{
|
||||
fmovImmDIop = InstObjParams("fmov", "FmovImmD", "FpRegImmOp",
|
||||
{ "code": fmovImmDCode,
|
||||
"op_class": "FloatMiscOp" }, [])
|
||||
fmovImmDIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += FpRegImmOpDeclare.subst(fmovImmDIop);
|
||||
decoder_output += AA64FpRegImmOpConstructor.subst(fmovImmDIop);
|
||||
exec_output += BasicExecute.subst(fmovImmDIop);
|
||||
@@ -79,6 +86,7 @@ let {{
|
||||
fmovRegSIop = InstObjParams("fmov", "FmovRegS", "FpRegRegOp",
|
||||
{ "code": fmovRegSCode,
|
||||
"op_class": "FloatMiscOp" }, [])
|
||||
fmovRegSIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fmovRegSIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegSIop);
|
||||
exec_output += BasicExecute.subst(fmovRegSIop);
|
||||
@@ -92,6 +100,7 @@ let {{
|
||||
fmovRegDIop = InstObjParams("fmov", "FmovRegD", "FpRegRegOp",
|
||||
{ "code": fmovRegDCode,
|
||||
"op_class": "FloatMiscOp" }, [])
|
||||
fmovRegDIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fmovRegDIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fmovRegDIop);
|
||||
exec_output += BasicExecute.subst(fmovRegDIop);
|
||||
@@ -105,6 +114,8 @@ let {{
|
||||
fmovCoreRegWIop = InstObjParams("fmov", "FmovCoreRegW", "FpRegRegOp",
|
||||
{ "code": fmovCoreRegWCode,
|
||||
"op_class": "FloatMiscOp" }, [])
|
||||
fmovCoreRegWIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
|
||||
"AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fmovCoreRegWIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fmovCoreRegWIop);
|
||||
exec_output += BasicExecute.subst(fmovCoreRegWIop);
|
||||
@@ -118,6 +129,8 @@ let {{
|
||||
fmovCoreRegXIop = InstObjParams("fmov", "FmovCoreRegX", "FpRegRegOp",
|
||||
{ "code": fmovCoreRegXCode,
|
||||
"op_class": "FloatMiscOp" }, [])
|
||||
fmovCoreRegXIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
|
||||
"AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fmovCoreRegXIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fmovCoreRegXIop);
|
||||
exec_output += BasicExecute.subst(fmovCoreRegXIop);
|
||||
@@ -131,6 +144,8 @@ let {{
|
||||
fmovUCoreRegXIop = InstObjParams("fmov", "FmovUCoreRegX", "FpRegRegOp",
|
||||
{ "code": fmovUCoreRegXCode,
|
||||
"op_class": "FloatMiscOp" }, [])
|
||||
fmovUCoreRegXIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
|
||||
"AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fmovUCoreRegXIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fmovUCoreRegXIop);
|
||||
exec_output += BasicExecute.subst(fmovUCoreRegXIop);
|
||||
@@ -305,6 +320,7 @@ let {{
|
||||
iop = InstObjParams(name.lower(), name + suffix,
|
||||
"FpRegRegRegRegOp",
|
||||
{ "code": code, "op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
|
||||
header_output += AA64FpRegRegRegRegOpDeclare.subst(iop)
|
||||
decoder_output += AA64FpRegRegRegRegOpConstructor.subst(iop)
|
||||
@@ -337,16 +353,19 @@ let {{
|
||||
hIop = InstObjParams(name, Name + "H", base,
|
||||
{ "code": code,
|
||||
"op_class": opClass }, [])
|
||||
hIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
|
||||
code = singleIntConvCode2 % { "op": singleOp }
|
||||
sIop = InstObjParams(name, Name + "S", base,
|
||||
{ "code": code,
|
||||
"op_class": opClass }, [])
|
||||
sIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
|
||||
code = doubleIntConvCode2 % { "op": doubleOp }
|
||||
dIop = InstObjParams(name, Name + "D", base,
|
||||
{ "code": code,
|
||||
"op_class": opClass }, [])
|
||||
dIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
|
||||
declareTempl = eval( base + "Declare");
|
||||
constructorTempl = eval("AA64" + base + "Constructor");
|
||||
@@ -403,14 +422,17 @@ let {{
|
||||
hIop = InstObjParams(name, Name + "H", base,
|
||||
{ "code": code,
|
||||
"op_class": opClass }, [])
|
||||
hIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
code = singleIntConvCode % { "op": singleOp }
|
||||
sIop = InstObjParams(name, Name + "S", base,
|
||||
{ "code": code,
|
||||
"op_class": opClass }, [])
|
||||
sIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
code = doubleIntConvCode % { "op": doubleOp }
|
||||
dIop = InstObjParams(name, Name + "D", base,
|
||||
{ "code": code,
|
||||
"op_class": opClass }, [])
|
||||
dIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
|
||||
declareTempl = eval( base + "Declare");
|
||||
constructorTempl = eval("AA64" + base + "Constructor");
|
||||
@@ -446,6 +468,7 @@ let {{
|
||||
iop = InstObjParams(name, Name + suffix, base,
|
||||
{ "code": code % { "op": op },
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
|
||||
declareTempl = eval( base + "Declare");
|
||||
constructorTempl = eval("AA64" + base + "Constructor");
|
||||
@@ -535,6 +558,9 @@ let {{
|
||||
fcvtIntFpDIop = InstObjParams(mnem, instName, "FpRegRegOp",
|
||||
{ "code": fcvtIntFpDCode,
|
||||
"op_class": "FloatCvtOp" }, [])
|
||||
fcvtIntFpDIop.snippets["code"] += \
|
||||
zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
|
||||
header_output += FpRegRegOpDeclare.subst(fcvtIntFpDIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fcvtIntFpDIop);
|
||||
exec_output += BasicExecute.subst(fcvtIntFpDIop);
|
||||
@@ -597,6 +623,7 @@ let {{
|
||||
fcvtFpSFpDIop = InstObjParams("fcvt", "FCvtFpSFpD", "FpRegRegOp",
|
||||
{ "code": fcvtFpSFpDCode,
|
||||
"op_class": "FloatCvtOp" }, [])
|
||||
fcvtFpSFpDIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fcvtFpSFpDIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpSFpDIop);
|
||||
exec_output += BasicExecute.subst(fcvtFpSFpDIop);
|
||||
@@ -614,6 +641,7 @@ let {{
|
||||
fcvtFpDFpSIop = InstObjParams("fcvt", "FcvtFpDFpS", "FpRegRegOp",
|
||||
{"code": fcvtFpDFpSCode,
|
||||
"op_class": "FloatCvtOp" }, [])
|
||||
fcvtFpDFpSIop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fcvtFpDFpSIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpDFpSIop);
|
||||
exec_output += BasicExecute.subst(fcvtFpDFpSIop);
|
||||
@@ -646,6 +674,8 @@ let {{
|
||||
fcvtFpHFpIop = InstObjParams("fcvt", instName, "FpRegRegOp",
|
||||
{ "code": code,
|
||||
"op_class": "FloatCvtOp" }, [])
|
||||
fcvtFpHFpIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
|
||||
"AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fcvtFpHFpIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpHFpIop);
|
||||
exec_output += BasicExecute.subst(fcvtFpHFpIop);
|
||||
@@ -669,6 +699,8 @@ let {{
|
||||
fcvtFpFpHIop = InstObjParams("fcvt", instName, "FpRegRegOp",
|
||||
{ "code": code,
|
||||
"op_class": "FloatCvtOp" }, [])
|
||||
fcvtFpFpHIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
|
||||
"AA64FpDest"
|
||||
header_output += FpRegRegOpDeclare.subst(fcvtFpFpHIop);
|
||||
decoder_output += AA64FpRegRegOpConstructor.subst(fcvtFpFpHIop);
|
||||
exec_output += BasicExecute.subst(fcvtFpFpHIop);
|
||||
@@ -842,6 +874,8 @@ let {{
|
||||
fcvtFixedFpIop = InstObjParams(mnem, instName, "FpRegRegImmOp",
|
||||
{ "code": fcvtFixedFpCode,
|
||||
"op_class": "FloatCvtOp" }, [])
|
||||
fcvtFixedFpIop.snippets["code"] += zeroSveVecRegUpperPartCode % \
|
||||
"AA64FpDest"
|
||||
header_output += FpRegRegImmOpDeclare.subst(fcvtFixedFpIop);
|
||||
decoder_output += FpRegRegImmOpConstructor.subst(fcvtFixedFpIop);
|
||||
exec_output += BasicExecute.subst(fcvtFixedFpIop);
|
||||
@@ -888,6 +922,7 @@ let {{
|
||||
iop = InstObjParams("fcsel", "FCSel%s" %("D" if isDouble else "S"),
|
||||
"FpCondSelOp", { "code": code,
|
||||
"op_class": "FloatCvtOp" })
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += DataXCondSelDeclare.subst(iop)
|
||||
decoder_output += DataXCondSelConstructor.subst(iop)
|
||||
exec_output += BasicExecute.subst(iop)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2010-2014 ARM Limited
|
||||
// Copyright (c) 2010-2014, 2017 ARM Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// The license below extends only to copyright in the software and shall
|
||||
@@ -97,6 +97,9 @@ split exec;
|
||||
split decoder;
|
||||
##include "neon64_mem.isa"
|
||||
|
||||
//SVE
|
||||
##include "sve.isa"
|
||||
|
||||
//m5 Pseudo-ops
|
||||
##include "m5ops.isa"
|
||||
|
||||
|
||||
@@ -179,10 +179,16 @@ let {{
|
||||
def emit(self):
|
||||
self.buildEACode()
|
||||
|
||||
accEpilogCode = None
|
||||
# Code that actually handles the access
|
||||
if self.flavor in ("dprefetch", "iprefetch", "mprefetch"):
|
||||
accCode = 'uint64_t temp M5_VAR_USED = Mem%s;'
|
||||
elif self.flavor == "fp":
|
||||
accEpilogCode = '''
|
||||
TheISA::ISA::zeroSveVecRegUpperPart(AA64FpDest,
|
||||
ArmStaticInst::getCurSveVecLen<uint64_t>(
|
||||
xc->tcBase()));
|
||||
'''
|
||||
if self.size in (1, 2, 4):
|
||||
accCode = '''
|
||||
AA64FpDestP0_uw = cSwap(Mem%s,
|
||||
@@ -216,6 +222,8 @@ let {{
|
||||
accCode = accCode % buildMemSuffix(self.sign, self.size)
|
||||
|
||||
self.codeBlobs["memacc_code"] = accCode
|
||||
if accEpilogCode:
|
||||
self.codeBlobs["memacc_epilog_code"] = accEpilogCode
|
||||
|
||||
# Push it out to the output files
|
||||
wbDecl = None
|
||||
@@ -227,8 +235,17 @@ let {{
|
||||
def emit(self):
|
||||
self.buildEACode()
|
||||
|
||||
accEpilogCode = None
|
||||
# Code that actually handles the access
|
||||
if self.flavor == "fp":
|
||||
accEpilogCode = '''
|
||||
TheISA::ISA::zeroSveVecRegUpperPart(AA64FpDest,
|
||||
ArmStaticInst::getCurSveVecLen<uint64_t>(
|
||||
xc->tcBase()));
|
||||
TheISA::ISA::zeroSveVecRegUpperPart(AA64FpDest2,
|
||||
ArmStaticInst::getCurSveVecLen<uint64_t>(
|
||||
xc->tcBase()));
|
||||
'''
|
||||
if self.size == 4:
|
||||
accCode = '''
|
||||
uint64_t data = cSwap(Mem_ud, isBigEndian64(xc->tcBase()));
|
||||
@@ -300,6 +317,8 @@ let {{
|
||||
isBigEndian64(xc->tcBase()));
|
||||
'''
|
||||
self.codeBlobs["memacc_code"] = accCode
|
||||
if accEpilogCode:
|
||||
self.codeBlobs["memacc_epilog_code"] = accEpilogCode
|
||||
|
||||
# Push it out to the output files
|
||||
wbDecl = None
|
||||
|
||||
@@ -106,10 +106,13 @@ let {{
|
||||
if rasPop:
|
||||
is_ras_pop = "1"
|
||||
codeBlobsCopy['is_ras_pop'] = is_ras_pop
|
||||
if 'memacc_epilog_code' in codeBlobsCopy:
|
||||
del codeBlobsCopy['memacc_epilog_code']
|
||||
|
||||
iop = InstObjParams(name, Name, base,
|
||||
codeBlobsCopy, instFlagsCopy)
|
||||
|
||||
if 'memacc_epilog_code' in codeBlobs:
|
||||
iop.snippets['memacc_code'] += codeBlobs['memacc_epilog_code']
|
||||
header_output = self.declareTemplate.subst(iop)
|
||||
decoder_output = self.constructTemplate.subst(iop)
|
||||
exec_output = self.fullExecTemplate.subst(iop) + \
|
||||
|
||||
@@ -48,6 +48,11 @@ let {{
|
||||
floatTypes = ("uint16_t", "uint32_t", "uint64_t")
|
||||
smallFloatTypes = ("uint32_t",)
|
||||
|
||||
zeroSveVecRegUpperPartCode = '''
|
||||
TheISA::ISA::zeroSveVecRegUpperPart(%s,
|
||||
ArmStaticInst::getCurSveVecLen<uint64_t>(xc->tcBase()));
|
||||
'''
|
||||
|
||||
def threeEqualRegInstX(name, Name, opClass, types, rCount, op,
|
||||
readDest=False, pairwise=False, scalar=False,
|
||||
byElem=False, decoder='Generic'):
|
||||
@@ -132,6 +137,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
if byElem:
|
||||
header_output += NeonX2RegImmOpDeclare.subst(iop)
|
||||
else:
|
||||
@@ -240,6 +246,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": 2,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
if byElem:
|
||||
header_output += NeonX2RegImmOpDeclare.subst(iop)
|
||||
else:
|
||||
@@ -327,6 +334,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
if hasImm:
|
||||
header_output += NeonX1RegImmOpDeclare.subst(iop)
|
||||
else:
|
||||
@@ -378,6 +386,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": 2,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
if hasImm:
|
||||
header_output += NeonX1RegImmOpDeclare.subst(iop)
|
||||
else:
|
||||
@@ -449,6 +458,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": 2,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
if hasImm:
|
||||
header_output += NeonX1RegImmOpDeclare.subst(iop)
|
||||
else:
|
||||
@@ -484,6 +494,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX2RegOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -519,6 +530,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX1Reg2ImmOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -556,6 +568,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX1RegOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -602,6 +615,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX1RegOpDeclare.subst(iop)
|
||||
if long:
|
||||
exec_output += NeonXUnequalRegOpExecute.subst(iop)
|
||||
@@ -654,6 +668,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX1RegOpDeclare.subst(iop)
|
||||
exec_output += NeonXUnequalRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -696,6 +711,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX1RegImmOnlyOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -725,6 +741,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX1RegOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -757,6 +774,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX2RegImmOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -785,6 +803,7 @@ let {{
|
||||
{ "code": eWalkCode,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX1RegImmOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
@@ -880,6 +899,7 @@ let {{
|
||||
{ "code": code,
|
||||
"r_count": rCount,
|
||||
"op_class": opClass }, [])
|
||||
iop.snippets["code"] += zeroSveVecRegUpperPartCode % "AA64FpDest"
|
||||
header_output += NeonX2RegOpDeclare.subst(iop)
|
||||
exec_output += NeonXEqualRegOpExecute.subst(iop)
|
||||
for type in types:
|
||||
|
||||
@@ -44,6 +44,11 @@ let {{
|
||||
decoder_output = ''
|
||||
exec_output = ''
|
||||
|
||||
zeroSveVecRegUpperPartCode = '''
|
||||
TheISA::ISA::zeroSveVecRegUpperPart(%s,
|
||||
ArmStaticInst::getCurSveVecLen<uint64_t>(xc->tcBase()));
|
||||
'''
|
||||
|
||||
def mkMemAccMicroOp(name):
|
||||
global header_output, decoder_output, exec_output
|
||||
SPAlignmentCheckCodeNeon = '''
|
||||
@@ -145,6 +150,8 @@ let {{
|
||||
'ea_code' : simd64EnabledCheckCode + eaCode,
|
||||
},
|
||||
[ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
|
||||
loadIop.snippets["memacc_code"] += zeroSveVecRegUpperPartCode % \
|
||||
"AA64FpDest"
|
||||
storeIop = InstObjParams(name + 'st',
|
||||
'MicroNeonStore64',
|
||||
'MicroNeonMemOp',
|
||||
|
||||
4798
src/arch/arm/isa/insts/sve.isa
Normal file
4798
src/arch/arm/isa/insts/sve.isa
Normal file
File diff suppressed because it is too large
Load Diff
@@ -46,6 +46,7 @@ def operand_types {{
|
||||
'uh' : 'uint16_t',
|
||||
'sw' : 'int32_t',
|
||||
'uw' : 'uint32_t',
|
||||
'sd' : 'int64_t',
|
||||
'ud' : 'uint64_t',
|
||||
'tud' : 'std::array<uint64_t, 2>',
|
||||
'sf' : 'float',
|
||||
@@ -53,6 +54,10 @@ def operand_types {{
|
||||
'vc' : 'TheISA::VecRegContainer',
|
||||
# For operations that are implemented as a template
|
||||
'x' : 'TPElem',
|
||||
'xs' : 'TPSElem',
|
||||
'xd' : 'TPDElem',
|
||||
'pc' : 'TheISA::VecPredRegContainer',
|
||||
'pb' : 'uint8_t'
|
||||
}};
|
||||
|
||||
let {{
|
||||
@@ -129,6 +134,9 @@ let {{
|
||||
def vectorRegElem(elem, ext = 'sf', zeroing = False):
|
||||
return (elem, ext, zeroing)
|
||||
|
||||
def vecPredReg(idx):
|
||||
return ('VecPredReg', 'pc', idx, None, srtNormal)
|
||||
|
||||
def intReg(idx):
|
||||
return ('IntReg', 'uw', idx, 'IsInteger', srtNormal,
|
||||
maybePCRead, maybePCWrite)
|
||||
@@ -522,6 +530,25 @@ def operands {{
|
||||
'AA64FpDestQV1L': vectorRegElem('0', 'tud', zeroing = True)
|
||||
}),
|
||||
|
||||
'AA64FpDestMerge': vectorReg('dest',
|
||||
{
|
||||
'AA64FpDestMergeP0': vectorRegElem('0'),
|
||||
'AA64FpDestMergeP1': vectorRegElem('1'),
|
||||
'AA64FpDestMergeP2': vectorRegElem('2'),
|
||||
'AA64FpDestMergeP3': vectorRegElem('3'),
|
||||
'AA64FpDestMergeS': vectorRegElem('0', 'sf', zeroing = True),
|
||||
'AA64FpDestMergeD': vectorRegElem('0', 'df', zeroing = True),
|
||||
'AA64FpDestMergeQ': vectorRegElem('0', 'tud', zeroing = True)
|
||||
}),
|
||||
|
||||
# Predicate register operands
|
||||
'GpOp': vecPredReg('gp'),
|
||||
'POp1': vecPredReg('op1'),
|
||||
'POp2': vecPredReg('op2'),
|
||||
'PDest': vecPredReg('dest'),
|
||||
'PDestMerge': vecPredReg('dest'),
|
||||
'Ffr': vecPredReg('PREDREG_FFR'),
|
||||
|
||||
#Abstracted control reg operands
|
||||
'MiscDest': cntrlReg('dest'),
|
||||
'MiscOp1': cntrlReg('op1'),
|
||||
|
||||
1034
src/arch/arm/isa/templates/sve.isa
Normal file
1034
src/arch/arm/isa/templates/sve.isa
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2010-2011,2018 ARM Limited
|
||||
// Copyright (c) 2010-2011, 2017-2018 ARM Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// The license below extends only to copyright in the software and shall
|
||||
@@ -80,3 +80,6 @@
|
||||
##include "crypto.isa"
|
||||
|
||||
##include "neon64.isa"
|
||||
|
||||
//Templates for SVE instructions
|
||||
##include "sve.isa"
|
||||
|
||||
@@ -1695,7 +1695,11 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_ID_AA64PFR0_EL1;
|
||||
case 1:
|
||||
return MISCREG_ID_AA64PFR1_EL1;
|
||||
case 2 ... 7:
|
||||
case 2 ... 3:
|
||||
return MISCREG_RAZ;
|
||||
case 4:
|
||||
return MISCREG_ID_AA64ZFR0_EL1;
|
||||
case 5 ... 7:
|
||||
return MISCREG_RAZ;
|
||||
}
|
||||
break;
|
||||
@@ -1804,6 +1808,12 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_CPACR_EL1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ZCR_EL1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -1830,6 +1840,22 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_HACR_EL2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ZCR_EL2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (crm) {
|
||||
case 2:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ZCR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -1852,6 +1878,12 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_CPTR_EL3;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ZCR_EL3;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (op2) {
|
||||
case 1:
|
||||
@@ -4923,6 +4955,18 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_CNTHV_TVAL_EL2)
|
||||
.mon().hyp();
|
||||
|
||||
// SVE
|
||||
InitReg(MISCREG_ID_AA64ZFR0_EL1)
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_ZCR_EL3)
|
||||
.mon();
|
||||
InitReg(MISCREG_ZCR_EL2)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ZCR_EL12)
|
||||
.unimplemented().warnNotFail();
|
||||
InitReg(MISCREG_ZCR_EL1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
|
||||
// Dummy registers
|
||||
InitReg(MISCREG_NOP)
|
||||
.allPrivileges();
|
||||
|
||||
@@ -891,9 +891,12 @@ namespace ArmISA
|
||||
MISCREG_ICH_LRC14,
|
||||
MISCREG_ICH_LRC15,
|
||||
|
||||
// These MISCREG_FREESLOT are available Misc Register
|
||||
// slots for future registers to be implemented.
|
||||
MISCREG_FREESLOT_1,
|
||||
// SVE
|
||||
MISCREG_ID_AA64ZFR0_EL1,
|
||||
MISCREG_ZCR_EL3,
|
||||
MISCREG_ZCR_EL2,
|
||||
MISCREG_ZCR_EL12,
|
||||
MISCREG_ZCR_EL1,
|
||||
|
||||
// NUM_PHYS_MISCREGS specifies the number of actual physical
|
||||
// registers, not considering the following pseudo-registers
|
||||
@@ -1825,7 +1828,11 @@ namespace ArmISA
|
||||
"ich_lrc14",
|
||||
"ich_lrc15",
|
||||
|
||||
"freeslot2",
|
||||
"id_aa64zfr0_el1",
|
||||
"zcr_el3",
|
||||
"zcr_el2",
|
||||
"zcr_el12",
|
||||
"zcr_el1",
|
||||
|
||||
"num_phys_regs",
|
||||
|
||||
|
||||
@@ -201,6 +201,7 @@ namespace ArmISA
|
||||
Bitfield<10> tfp; // AArch64
|
||||
Bitfield<9> tcp9;
|
||||
Bitfield<8> tcp8;
|
||||
Bitfield<8> tz; // SVE
|
||||
Bitfield<7> tcp7;
|
||||
Bitfield<6> tcp6;
|
||||
Bitfield<5> tcp5;
|
||||
@@ -375,6 +376,7 @@ namespace ArmISA
|
||||
Bitfield<13, 12> cp6;
|
||||
Bitfield<15, 14> cp7;
|
||||
Bitfield<17, 16> cp8;
|
||||
Bitfield<17, 16> zen; // SVE
|
||||
Bitfield<19, 18> cp9;
|
||||
Bitfield<21, 20> cp10;
|
||||
Bitfield<21, 20> fpen; // AArch64
|
||||
@@ -636,9 +638,17 @@ namespace ArmISA
|
||||
Bitfield<20> tta;
|
||||
Bitfield<13, 12> res1_13_12_el2;
|
||||
Bitfield<10> tfp;
|
||||
Bitfield<9, 0> res1_9_0_el2;
|
||||
Bitfield<9> res1_9_el2;
|
||||
Bitfield<8> res1_8_el2;
|
||||
Bitfield<8> ez; // SVE (CPTR_EL3)
|
||||
Bitfield<8> tz; // SVE (CPTR_EL2)
|
||||
Bitfield<7, 0> res1_7_0_el2;
|
||||
EndBitUnion(CPTR)
|
||||
|
||||
BitUnion64(ZCR)
|
||||
Bitfield<3, 0> len;
|
||||
EndBitUnion(ZCR)
|
||||
|
||||
}
|
||||
|
||||
#endif // __ARCH_ARM_MISCREGS_TYPES_HH__
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011, 2014, 2016 ARM Limited
|
||||
* Copyright (c) 2010-2011, 2014, 2016-2017 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -126,7 +126,8 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc)
|
||||
changed[STATE_CPSR] = (newState[STATE_CPSR] != oldState[STATE_CPSR]);
|
||||
|
||||
for (int i = 0; i < NumVecV7ArchRegs; i++) {
|
||||
auto vec(tc->readVecReg(RegId(VecRegClass,i)).as<uint64_t, 2>());
|
||||
auto vec(tc->readVecReg(RegId(VecRegClass,i))
|
||||
.as<uint64_t, MaxSveVecLenInDWords>());
|
||||
newState[STATE_F0 + 2*i] = vec[0];
|
||||
newState[STATE_F0 + 2*i + 1] = vec[1];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012, 2018 ARM Limited
|
||||
* Copyright (c) 2010, 2012, 2017-2018 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -134,6 +134,8 @@ ArmProcess64::initState()
|
||||
// Enable the floating point coprocessors.
|
||||
cpacr.cp10 = 0x3;
|
||||
cpacr.cp11 = 0x3;
|
||||
// Enable SVE.
|
||||
cpacr.zen = 0x3;
|
||||
tc->setMiscReg(MISCREG_CPACR_EL1, cpacr);
|
||||
// Generically enable floating point support.
|
||||
FPEXC fpexc = tc->readMiscReg(MISCREG_FPEXC);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011, 2014, 2016 ARM Limited
|
||||
* Copyright (c) 2010-2011, 2014, 2016-2017 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -62,20 +62,18 @@ using ArmISAInst::MaxInstDestRegs;
|
||||
using ArmISAInst::MaxMiscDestRegs;
|
||||
|
||||
// Number of VecElem per Vector Register, computed based on the vector length
|
||||
constexpr unsigned NumVecElemPerVecReg = 4;
|
||||
constexpr unsigned NumVecElemPerVecReg = MaxSveVecLenInWords;
|
||||
|
||||
using VecElem = uint32_t;
|
||||
using VecReg = ::VecRegT<VecElem, NumVecElemPerVecReg, false>;
|
||||
using ConstVecReg = ::VecRegT<VecElem, NumVecElemPerVecReg, true>;
|
||||
using VecRegContainer = VecReg::Container;
|
||||
|
||||
constexpr size_t VecRegSizeBytes = NumVecElemPerVecReg * sizeof(VecElem);
|
||||
|
||||
// Dummy typedefs
|
||||
using VecPredReg = ::DummyVecPredReg;
|
||||
using ConstVecPredReg = ::DummyConstVecPredReg;
|
||||
using VecPredRegContainer = ::DummyVecPredRegContainer;
|
||||
constexpr size_t VecPredRegSizeBits = ::DummyVecPredRegSizeBits;
|
||||
constexpr bool VecPredRegHasPackedRepr = ::DummyVecPredRegHasPackedRepr;
|
||||
using VecPredReg = ::VecPredRegT<VecElem, NumVecElemPerVecReg,
|
||||
VecPredRegHasPackedRepr, false>;
|
||||
using ConstVecPredReg = ::VecPredRegT<VecElem, NumVecElemPerVecReg,
|
||||
VecPredRegHasPackedRepr, true>;
|
||||
using VecPredRegContainer = VecPredReg::Container;
|
||||
|
||||
// Constants Related to the number of registers
|
||||
const int NumIntArchRegs = NUM_ARCH_INTREGS;
|
||||
@@ -90,7 +88,8 @@ const int NumVecSpecialRegs = 8;
|
||||
const int NumIntRegs = NUM_INTREGS;
|
||||
const int NumFloatRegs = NumFloatV8ArchRegs + NumFloatSpecialRegs;
|
||||
const int NumVecRegs = NumVecV8ArchRegs + NumVecSpecialRegs;
|
||||
const int NumVecPredRegs = 1;
|
||||
const int NumVecPredRegs = 17; // P0-P15, FFR
|
||||
const int PREDREG_FFR = 16;
|
||||
const int NumCCRegs = NUM_CCREGS;
|
||||
const int NumMiscRegs = NUM_MISCREGS;
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ ArmSystem::ArmSystem(Params *p)
|
||||
_highestELIs64(p->highest_el_is_64),
|
||||
_physAddrRange64(p->phys_addr_range_64),
|
||||
_haveLargeAsid64(p->have_large_asid_64),
|
||||
_haveSVE(p->have_sve),
|
||||
_sveVL(p->sve_vl),
|
||||
_m5opRange(p->m5ops_base ?
|
||||
RangeSize(p->m5ops_base, 0x10000) :
|
||||
AddrRange(1, 0)), // Create an empty range if disabled
|
||||
|
||||
@@ -122,6 +122,14 @@ class ArmSystem : public System
|
||||
*/
|
||||
const bool _haveLargeAsid64;
|
||||
|
||||
/**
|
||||
* True if SVE is implemented (ARMv8)
|
||||
*/
|
||||
const bool _haveSVE;
|
||||
|
||||
/** SVE vector length at reset, in quadwords */
|
||||
const unsigned _sveVL;
|
||||
|
||||
/**
|
||||
* Range for memory-mapped m5 pseudo ops. The range will be
|
||||
* invalid/empty if disabled.
|
||||
@@ -227,6 +235,12 @@ class ArmSystem : public System
|
||||
/** Returns true if ASID is 16 bits in AArch64 (ARMv8) */
|
||||
bool haveLargeAsid64() const { return _haveLargeAsid64; }
|
||||
|
||||
/** Returns true if SVE is implemented (ARMv8) */
|
||||
bool haveSVE() const { return _haveSVE; }
|
||||
|
||||
/** Returns the SVE vector length at reset, in quadwords */
|
||||
unsigned sveVL() const { return _sveVL; }
|
||||
|
||||
/** Returns the supported physical address range in bits if the highest
|
||||
* implemented exception level is 64 bits (ARMv8) */
|
||||
uint8_t physAddrRange64() const { return _physAddrRange64; }
|
||||
|
||||
@@ -72,6 +72,10 @@ namespace ArmISA
|
||||
Bitfield<63, 62> decoderFault; // See DecoderFault
|
||||
Bitfield<61> illegalExecution;
|
||||
|
||||
// SVE vector length, encoded in the same format as the ZCR_EL<x>.LEN
|
||||
// bitfields
|
||||
Bitfield<59, 56> sveLen;
|
||||
|
||||
// ITSTATE bits
|
||||
Bitfield<55, 48> itstate;
|
||||
Bitfield<55, 52> itstateCond;
|
||||
@@ -628,6 +632,7 @@ namespace ArmISA
|
||||
EC_HVC_64 = 0x16,
|
||||
EC_SMC_64 = 0x17,
|
||||
EC_TRAPPED_MSR_MRS_64 = 0x18,
|
||||
EC_TRAPPED_SVE = 0x19,
|
||||
EC_PREFETCH_ABORT_TO_HYP = 0x20,
|
||||
EC_PREFETCH_ABORT_LOWER_EL = 0x20, // AArch64 alias
|
||||
EC_PREFETCH_ABORT_FROM_HYP = 0x21,
|
||||
@@ -754,6 +759,18 @@ namespace ArmISA
|
||||
}
|
||||
}
|
||||
|
||||
constexpr unsigned MaxSveVecLenInBits = 2048;
|
||||
static_assert(MaxSveVecLenInBits >= 128 &&
|
||||
MaxSveVecLenInBits <= 2048 &&
|
||||
MaxSveVecLenInBits % 128 == 0,
|
||||
"Unsupported max. SVE vector length");
|
||||
constexpr unsigned MaxSveVecLenInBytes = MaxSveVecLenInBits >> 3;
|
||||
constexpr unsigned MaxSveVecLenInWords = MaxSveVecLenInBits >> 5;
|
||||
constexpr unsigned MaxSveVecLenInDWords = MaxSveVecLenInBits >> 6;
|
||||
|
||||
constexpr unsigned VecRegSizeBytes = MaxSveVecLenInBytes;
|
||||
constexpr unsigned VecPredRegSizeBits = MaxSveVecLenInBytes;
|
||||
constexpr unsigned VecPredRegHasPackedRepr = false;
|
||||
} // namespace ArmISA
|
||||
|
||||
#endif
|
||||
|
||||
@@ -297,6 +297,17 @@ ELIs32(ThreadContext *tc, ExceptionLevel el)
|
||||
return aarch32;
|
||||
}
|
||||
|
||||
bool
|
||||
ELIsInHost(ThreadContext *tc, ExceptionLevel el)
|
||||
{
|
||||
if (!ArmSystem::haveVirtualization(tc)) {
|
||||
return false;
|
||||
}
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
return (!isSecureBelowEL3(tc) && !ELIs32(tc, EL2) && hcr.e2h == 1 &&
|
||||
(el == EL2 || (el == EL0 && hcr.tge == 1)));
|
||||
}
|
||||
|
||||
std::pair<bool, bool>
|
||||
ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
|
||||
{
|
||||
|
||||
@@ -179,6 +179,12 @@ bool ELIs32(ThreadContext *tc, ExceptionLevel el);
|
||||
|
||||
bool ELIs64(ThreadContext *tc, ExceptionLevel el);
|
||||
|
||||
/**
|
||||
* Returns true if the current exception level `el` is executing a Host OS or
|
||||
* an application of a Host OS (Armv8.1 Virtualization Host Extensions).
|
||||
*/
|
||||
bool ELIsInHost(ThreadContext *tc, ExceptionLevel el);
|
||||
|
||||
bool isBigEndian64(ThreadContext *tc);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016, 2018 ARM Limited
|
||||
* Copyright (c) 2015-2018 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -154,6 +154,8 @@
|
||||
#include "base/cprintf.hh"
|
||||
#include "base/logging.hh"
|
||||
|
||||
constexpr unsigned MaxVecRegLenInBytes = 256;
|
||||
|
||||
template <size_t Sz>
|
||||
class VecRegContainer;
|
||||
|
||||
@@ -271,6 +273,8 @@ class VecRegContainer
|
||||
{
|
||||
static_assert(Sz > 0,
|
||||
"Cannot create Vector Register Container of zero size");
|
||||
static_assert(Sz <= MaxVecRegLenInBytes,
|
||||
"Vector Register size limit exceeded");
|
||||
public:
|
||||
static constexpr size_t SIZE = Sz;
|
||||
using Container = std::array<uint8_t,Sz>;
|
||||
@@ -519,6 +523,7 @@ class VecLaneT
|
||||
friend class VecRegContainer<32>;
|
||||
friend class VecRegContainer<64>;
|
||||
friend class VecRegContainer<128>;
|
||||
friend class VecRegContainer<MaxVecRegLenInBytes>;
|
||||
|
||||
/** My type alias. */
|
||||
using MyClass = VecLaneT<VecElem, Const>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2010,2018 ARM Limited
|
||||
# Copyright (c) 2010, 2017-2018 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
@@ -47,13 +47,16 @@ class OpClass(Enum):
|
||||
'FloatMisc', 'FloatSqrt',
|
||||
'SimdAdd', 'SimdAddAcc', 'SimdAlu', 'SimdCmp', 'SimdCvt',
|
||||
'SimdMisc', 'SimdMult', 'SimdMultAcc', 'SimdShift', 'SimdShiftAcc',
|
||||
'SimdSqrt', 'SimdFloatAdd', 'SimdFloatAlu', 'SimdFloatCmp',
|
||||
'SimdFloatCvt', 'SimdFloatDiv', 'SimdFloatMisc', 'SimdFloatMult',
|
||||
'SimdFloatMultAcc', 'SimdFloatSqrt',
|
||||
'SimdDiv', 'SimdSqrt', 'SimdFloatAdd', 'SimdFloatAlu',
|
||||
'SimdFloatCmp', 'SimdFloatCvt', 'SimdFloatDiv', 'SimdFloatMisc',
|
||||
'SimdFloatMult', 'SimdFloatMultAcc', 'SimdFloatSqrt',
|
||||
'SimdReduceAdd', 'SimdReduceAlu', 'SimdReduceCmp',
|
||||
'SimdFloatReduceAdd', 'SimdFloatReduceCmp',
|
||||
'SimdAes', 'SimdAesMix', 'SimdSha1Hash', 'SimdSha1Hash2',
|
||||
'SimdSha256Hash', 'SimdSha256Hash2', 'SimdShaSigma2',
|
||||
'SimdShaSigma3', 'MemRead', 'MemWrite',
|
||||
'FloatMemRead', 'FloatMemWrite',
|
||||
'SimdShaSigma3',
|
||||
'SimdPredAlu',
|
||||
'MemRead', 'MemWrite', 'FloatMemRead', 'FloatMemWrite',
|
||||
'IprAccess', 'InstPrefetch']
|
||||
|
||||
class OpDesc(SimObject):
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (c) 2001-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -118,7 +130,38 @@ Trace::ExeTracerRecord::traceInst(const StaticInstPtr &inst, bool ran)
|
||||
}
|
||||
|
||||
if (Debug::ExecResult && data_status != DataInvalid) {
|
||||
ccprintf(outs, " D=%#018x", data.as_int);
|
||||
switch (data_status) {
|
||||
case DataVec:
|
||||
{
|
||||
ccprintf(outs, " D=0x[");
|
||||
auto dv = data.as_vec->as<uint32_t>();
|
||||
for (int i = TheISA::VecRegSizeBytes / 4 - 1; i >= 0;
|
||||
i--) {
|
||||
ccprintf(outs, "%08x", dv[i]);
|
||||
if (i != 0) {
|
||||
ccprintf(outs, "_");
|
||||
}
|
||||
}
|
||||
ccprintf(outs, "]");
|
||||
}
|
||||
break;
|
||||
case DataVecPred:
|
||||
{
|
||||
ccprintf(outs, " D=0b[");
|
||||
auto pv = data.as_pred->as<uint8_t>();
|
||||
for (int i = TheISA::VecPredRegSizeBits - 1; i >= 0; i--) {
|
||||
ccprintf(outs, pv[i] ? "1" : "0");
|
||||
if (i != 0 && i % 4 == 0) {
|
||||
ccprintf(outs, "_");
|
||||
}
|
||||
}
|
||||
ccprintf(outs, "]");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ccprintf(outs, " D=%#018x", data.as_int);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Debug::ExecEffAddr && getMemValid())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2012-2014,2018 ARM Limited
|
||||
# Copyright (c) 2012-2014, 2017-2018 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
@@ -148,15 +148,24 @@ class MinorDefaultFloatSimdFU(MinorFU):
|
||||
'FloatMultAcc', 'FloatDiv', 'FloatSqrt',
|
||||
'SimdAdd', 'SimdAddAcc', 'SimdAlu', 'SimdCmp', 'SimdCvt',
|
||||
'SimdMisc', 'SimdMult', 'SimdMultAcc', 'SimdShift', 'SimdShiftAcc',
|
||||
'SimdSqrt', 'SimdFloatAdd', 'SimdFloatAlu', 'SimdFloatCmp',
|
||||
'SimdDiv', 'SimdSqrt', 'SimdFloatAdd', 'SimdFloatAlu', 'SimdFloatCmp',
|
||||
'SimdFloatCvt', 'SimdFloatDiv', 'SimdFloatMisc', 'SimdFloatMult',
|
||||
'SimdFloatMultAcc', 'SimdFloatSqrt', 'SimdAes', 'SimdAesMix',
|
||||
'SimdFloatMultAcc', 'SimdFloatSqrt', 'SimdReduceAdd', 'SimdReduceAlu',
|
||||
'SimdReduceCmp', 'SimdFloatReduceAdd', 'SimdFloatReduceCmp',
|
||||
'SimdAes', 'SimdAesMix',
|
||||
'SimdSha1Hash', 'SimdSha1Hash2', 'SimdSha256Hash',
|
||||
'SimdSha256Hash2', 'SimdShaSigma2', 'SimdShaSigma3'])
|
||||
|
||||
timings = [MinorFUTiming(description='FloatSimd',
|
||||
srcRegsRelativeLats=[2])]
|
||||
opLat = 6
|
||||
|
||||
class MinorDefaultPredFU(MinorFU):
|
||||
opClasses = minorMakeOpClassSet(['SimdPredAlu'])
|
||||
timings = [MinorFUTiming(description="Pred",
|
||||
srcRegsRelativeLats=[2])]
|
||||
opLat = 3
|
||||
|
||||
class MinorDefaultMemFU(MinorFU):
|
||||
opClasses = minorMakeOpClassSet(['MemRead', 'MemWrite', 'FloatMemRead',
|
||||
'FloatMemWrite'])
|
||||
@@ -171,8 +180,8 @@ class MinorDefaultMiscFU(MinorFU):
|
||||
class MinorDefaultFUPool(MinorFUPool):
|
||||
funcUnits = [MinorDefaultIntFU(), MinorDefaultIntFU(),
|
||||
MinorDefaultIntMulFU(), MinorDefaultIntDivFU(),
|
||||
MinorDefaultFloatSimdFU(), MinorDefaultMemFU(),
|
||||
MinorDefaultMiscFU()]
|
||||
MinorDefaultFloatSimdFU(), MinorDefaultPredFU(),
|
||||
MinorDefaultMemFU(), MinorDefaultMiscFU()]
|
||||
|
||||
class ThreadPolicy(Enum): vals = ['SingleThreaded', 'RoundRobin', 'Random']
|
||||
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
# 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.
|
||||
#
|
||||
# Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -38,4 +50,4 @@ class FUPool(SimObject):
|
||||
|
||||
class DefaultFUPool(FUPool):
|
||||
FUList = [ IntALU(), IntMultDiv(), FP_ALU(), FP_MultDiv(), ReadPort(),
|
||||
SIMD_Unit(), WritePort(), RdWrPort(), IprPort() ]
|
||||
SIMD_Unit(), PredALU(), WritePort(), RdWrPort(), IprPort() ]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2010 ARM Limited
|
||||
# Copyright (c) 2010, 2017 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
@@ -86,6 +86,7 @@ class SIMD_Unit(FUDesc):
|
||||
OpDesc(opClass='SimdMultAcc'),
|
||||
OpDesc(opClass='SimdShift'),
|
||||
OpDesc(opClass='SimdShiftAcc'),
|
||||
OpDesc(opClass='SimdDiv'),
|
||||
OpDesc(opClass='SimdSqrt'),
|
||||
OpDesc(opClass='SimdFloatAdd'),
|
||||
OpDesc(opClass='SimdFloatAlu'),
|
||||
@@ -95,9 +96,18 @@ class SIMD_Unit(FUDesc):
|
||||
OpDesc(opClass='SimdFloatMisc'),
|
||||
OpDesc(opClass='SimdFloatMult'),
|
||||
OpDesc(opClass='SimdFloatMultAcc'),
|
||||
OpDesc(opClass='SimdFloatSqrt') ]
|
||||
OpDesc(opClass='SimdFloatSqrt'),
|
||||
OpDesc(opClass='SimdReduceAdd'),
|
||||
OpDesc(opClass='SimdReduceAlu'),
|
||||
OpDesc(opClass='SimdReduceCmp'),
|
||||
OpDesc(opClass='SimdFloatReduceAdd'),
|
||||
OpDesc(opClass='SimdFloatReduceCmp') ]
|
||||
count = 4
|
||||
|
||||
class PredALU(FUDesc):
|
||||
opList = [ OpDesc(opClass='SimdPredAlu') ]
|
||||
count = 1
|
||||
|
||||
class ReadPort(FUDesc):
|
||||
opList = [ OpDesc(opClass='MemRead'),
|
||||
OpDesc(opClass='FloatMemRead') ]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010,2018 ARM Limited
|
||||
* Copyright (c) 2010, 2017-2018 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -73,7 +73,11 @@ static const OpClass SimdMultOp = Enums::SimdMult;
|
||||
static const OpClass SimdMultAccOp = Enums::SimdMultAcc;
|
||||
static const OpClass SimdShiftOp = Enums::SimdShift;
|
||||
static const OpClass SimdShiftAccOp = Enums::SimdShiftAcc;
|
||||
static const OpClass SimdDivOp = Enums::SimdDiv;
|
||||
static const OpClass SimdSqrtOp = Enums::SimdSqrt;
|
||||
static const OpClass SimdReduceAddOp = Enums::SimdReduceAdd;
|
||||
static const OpClass SimdReduceAluOp = Enums::SimdReduceAlu;
|
||||
static const OpClass SimdReduceCmpOp = Enums::SimdReduceCmp;
|
||||
static const OpClass SimdFloatAddOp = Enums::SimdFloatAdd;
|
||||
static const OpClass SimdFloatAluOp = Enums::SimdFloatAlu;
|
||||
static const OpClass SimdFloatCmpOp = Enums::SimdFloatCmp;
|
||||
@@ -83,6 +87,8 @@ static const OpClass SimdFloatMiscOp = Enums::SimdFloatMisc;
|
||||
static const OpClass SimdFloatMultOp = Enums::SimdFloatMult;
|
||||
static const OpClass SimdFloatMultAccOp = Enums::SimdFloatMultAcc;
|
||||
static const OpClass SimdFloatSqrtOp = Enums::SimdFloatSqrt;
|
||||
static const OpClass SimdFloatReduceCmpOp = Enums::SimdFloatReduceCmp;
|
||||
static const OpClass SimdFloatReduceAddOp = Enums::SimdFloatReduceAdd;
|
||||
static const OpClass SimdAesOp = Enums::SimdAes;
|
||||
static const OpClass SimdAesMixOp = Enums::SimdAesMix;
|
||||
static const OpClass SimdSha1HashOp = Enums::SimdSha1Hash;
|
||||
@@ -91,6 +97,7 @@ static const OpClass SimdSha256HashOp = Enums::SimdSha256Hash;
|
||||
static const OpClass SimdSha256Hash2Op = Enums::SimdSha256Hash2;
|
||||
static const OpClass SimdShaSigma2Op = Enums::SimdShaSigma2;
|
||||
static const OpClass SimdShaSigma3Op = Enums::SimdShaSigma3;
|
||||
static const OpClass SimdPredAluOp = Enums::SimdPredAlu;
|
||||
static const OpClass MemReadOp = Enums::MemRead;
|
||||
static const OpClass MemWriteOp = Enums::MemWrite;
|
||||
static const OpClass FloatMemReadOp = Enums::FloatMemRead;
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2001-2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -66,7 +78,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
|
||||
BaseTLB *_dtb, TheISA::ISA *_isa)
|
||||
: ThreadState(_cpu, _thread_num, _process), isa(_isa),
|
||||
predicate(false), system(_sys),
|
||||
itb(_itb), dtb(_dtb)
|
||||
itb(_itb), dtb(_dtb), decoder(TheISA::Decoder(_isa))
|
||||
{
|
||||
clearArchRegs();
|
||||
tc = new ProxyThreadContext<SimpleThread>(this);
|
||||
@@ -77,7 +89,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
|
||||
BaseTLB *_itb, BaseTLB *_dtb,
|
||||
TheISA::ISA *_isa, bool use_kernel_stats)
|
||||
: ThreadState(_cpu, _thread_num, NULL), isa(_isa), system(_sys), itb(_itb),
|
||||
dtb(_dtb)
|
||||
dtb(_dtb), decoder(TheISA::Decoder(_isa))
|
||||
{
|
||||
tc = new ProxyThreadContext<SimpleThread>(this);
|
||||
|
||||
|
||||
37
util/cpt_upgraders/arm-sve.py
Normal file
37
util/cpt_upgraders/arm-sve.py
Normal file
@@ -0,0 +1,37 @@
|
||||
def upgrader(cpt):
|
||||
"""
|
||||
Update the checkpoint to support initial SVE implemtation.
|
||||
The updater is taking the following steps.
|
||||
|
||||
1) Set isa.haveSVE to false
|
||||
2) Set isa.sveVL to 1
|
||||
3) Add SVE misc registers in the checkpoint
|
||||
"""
|
||||
if cpt.get('root','isa') == 'arm':
|
||||
for sec in cpt.sections():
|
||||
import re
|
||||
# Search for all ISA sections
|
||||
if re.search('.*sys.*\.cpu.*\.isa$', sec):
|
||||
|
||||
# haveSVE = false
|
||||
cpt.set(sec, 'haveSVE', 'false')
|
||||
|
||||
# sveVL (sve Vector Length in quadword) = 1
|
||||
# (This is a dummy value since haveSVE is set to false)
|
||||
cpt.set(sec, 'sveVL', '1')
|
||||
|
||||
# Updating SVE misc registers (dummy values)
|
||||
mr = cpt.get(sec, 'miscRegs').split()
|
||||
if len(mr) == 820:
|
||||
print "MISCREG_SVE registers already seems to be inserted."
|
||||
else:
|
||||
# Replace MISCREG_FREESLOT_1 with MISCREG_ID_AA64ZFR0_EL1
|
||||
mr[-1] = 0;
|
||||
|
||||
mr.append(0); # Add dummy value for MISCREG_ZCR_EL3
|
||||
mr.append(0); # Add dummy value for MISCREG_ZCR_EL2
|
||||
mr.append(0); # Add dummy value for MISCREG_ZCR_EL12
|
||||
mr.append(0); # Add dummy value for MISCREG_ZCR_EL1
|
||||
cpt.set(sec, 'miscRegs', ' '.join(str(x) for x in mr))
|
||||
|
||||
legacy_version = 15
|
||||
Reference in New Issue
Block a user