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:
Giacomo Gabrielli
2018-10-16 16:09:02 +01:00
parent 91195ae7f6
commit c4cc3145cd
46 changed files with 11605 additions and 61 deletions

View File

@@ -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")

View File

@@ -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")

View File

@@ -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')

View File

@@ -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>(

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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
View 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
View 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__

View File

@@ -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()
{

View File

@@ -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);

View File

@@ -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

View File

@@ -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"

File diff suppressed because it is too large Load Diff

View 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
}};

View File

@@ -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"

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -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) + \

View File

@@ -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:

View File

@@ -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',

File diff suppressed because it is too large Load Diff

View File

@@ -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'),

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -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();

View File

@@ -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",

View File

@@ -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__

View File

@@ -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];
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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; }

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);
/**

View File

@@ -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>;

View File

@@ -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):

View File

@@ -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())

View File

@@ -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']

View File

@@ -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() ]

View File

@@ -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') ]

View File

@@ -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;

View File

@@ -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);

View 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