From: Giacomo Gabrielli Date: Tue, 16 Oct 2018 15:09:02 +0000 (+0100) Subject: arch-arm,cpu: Add initial support for Arm SVE X-Git-Tag: v19.0.0.0~1060 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c4cc3145cd1eeed236b5cd3f7b2424bc0761878e;p=gem5.git 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 - Gabor Dozsa - Giacomo Travaglini Thanks to Pau Cabre for his contribution of bugfixes. Change-Id: I1808b5ff55b401777eeb9b99c9a1129e0d527709 Signed-off-by: Giacomo Gabrielli Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/13515 Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg --- diff --git a/src/arch/arm/ArmISA.py b/src/arch/arm/ArmISA.py index 70be40313..ea2927d5d 100644 --- a/src/arch/arm/ArmISA.py +++ b/src/arch/arm/ArmISA.py @@ -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") diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index 7ade1e695..ec30e0bf6 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -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") diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index a1063f039..58a13cd72 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -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') diff --git a/src/arch/arm/decoder.cc b/src/arch/arm/decoder.cc index ce039b731..4c86ee2c6 100644 --- a/src/arch/arm/decoder.cc +++ b/src/arch/arm/decoder.cc @@ -47,6 +47,7 @@ #include "arch/arm/utility.hh" #include "base/trace.hh" #include "debug/Decoder.hh" +#include "sim/full_system.hh" namespace ArmISA { @@ -54,11 +55,13 @@ namespace ArmISA GenericISA::BasicDecodeCache Decoder::defaultCache; Decoder::Decoder(ISA* isa) - : data(0), fpscrLen(0), fpscrStride(0), decoderFlavour(isa - ? isa->decoderFlavour() - : Enums::Generic) + : data(0), fpscrLen(0), fpscrStride(0), + decoderFlavour(isa->decoderFlavour()) { reset(); + + // Initialize SVE vector length + sveLen = (isa->getCurSveVecLenInBitsAtReset() >> 7) - 1; } void @@ -157,6 +160,7 @@ Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) emi.aarch64 = pc.aarch64(); emi.fpscrLen = fpscrLen; emi.fpscrStride = fpscrStride; + emi.sveLen = sveLen; const Addr alignment(pc.thumb() ? 0x1 : 0x3); emi.decoderFault = static_cast( diff --git a/src/arch/arm/decoder.hh b/src/arch/arm/decoder.hh index f8748ab5e..f44a981d9 100644 --- a/src/arch/arm/decoder.hh +++ b/src/arch/arm/decoder.hh @@ -72,6 +72,12 @@ class Decoder int fpscrLen; int fpscrStride; + /** + * SVE vector length, encoded in the same format as the ZCR_EL.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 diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index f245cd4f0..cc0e8f3f2 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -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(machInst, 0, EC_TRAPPED_SVE); + case EL2: + return std::make_shared(machInst, 0, EC_TRAPPED_SVE); + case EL3: + return std::make_shared(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); +} } diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index f4f3cbb6d..9caf016dd 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -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 + static unsigned + getCurSveVecLen(ThreadContext *tc) + { + return getCurSveVecLenInBits(tc) / (8 * sizeof(T)); + } }; } diff --git a/src/arch/arm/insts/sve.cc b/src/arch/arm/insts/sve.cc new file mode 100644 index 000000000..22ce47f93 --- /dev/null +++ b/src/arch/arm/insts/sve.cc @@ -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 diff --git a/src/arch/arm/insts/sve.hh b/src/arch/arm/insts/sve.hh new file mode 100644 index 000000000..f72e3ccd7 --- /dev/null +++ b/src/arch/arm/insts/sve.hh @@ -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__ diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 3b10f68a4..38fbae142 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -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(miscRegs[MISCREG_ZCR_EL1]).len; + } + + if (el == EL2 || (el == EL0 && ELIsInHost(tc, el))) { + len = static_cast(miscRegs[MISCREG_ZCR_EL2]).len; + } else if (haveVirtualization && !inSecureState(tc) && + (el == EL0 || el == EL1)) { + len = std::min( + len, + static_cast( + static_cast(miscRegs[MISCREG_ZCR_EL2]).len)); + } + + if (el == EL3) { + len = static_cast(miscRegs[MISCREG_ZCR_EL3]).len; + } else if (haveSecurity) { + len = std::min( + len, + static_cast( + static_cast(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(); + for (int i = 2; i < eCount; ++i) { + vv[i] = 0; + } } +} // namespace ArmISA + ArmISA::ISA * ArmISAParams::create() { diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh index b98610bfc..1931306f9 100644 --- a/src/arch/arm/isa.hh +++ b/src/arch/arm/isa.hh @@ -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); diff --git a/src/arch/arm/isa/formats/aarch64.isa b/src/arch/arm/isa/formats/aarch64.isa index 3f4e33711..15cbe90dc 100644 --- a/src/arch/arm/isa/formats/aarch64.isa +++ b/src/arch/arm/isa/formats/aarch64.isa @@ -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 diff --git a/src/arch/arm/isa/formats/formats.isa b/src/arch/arm/isa/formats/formats.isa index 25ace4be3..935500dc2 100644 --- a/src/arch/arm/isa/formats/formats.isa +++ b/src/arch/arm/isa/formats/formats.isa @@ -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" diff --git a/src/arch/arm/isa/formats/sve_2nd_level.isa b/src/arch/arm/isa/formats/sve_2nd_level.isa new file mode 100644 index 000000000..3c5e01c6b --- /dev/null +++ b/src/arch/arm/isa/formats/sve_2nd_level.isa @@ -0,0 +1,2917 @@ +// 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 2nd-level decoder. + +output decoder {{ +namespace Aarch64 +{ + + StaticInstPtr + decodeSveIntArithBinPred(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + switch (bits(machInst, 20, 19)) { + case 0x0: + { + uint8_t size = bits(machInst, 23, 22); + uint8_t opc = bits(machInst, 18, 16); + switch (opc) { + case 0x0: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 0x1: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 0x3: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + default: + return new Unknown64(machInst); + } + } + case 0x1: + { + uint8_t size = bits(machInst, 23, 22); + uint8_t u = bits(machInst, 16); + uint8_t opc = bits(machInst, 18, 17); + switch (opc) { + case 0x0: + return decodeSveBinDestrPred( + size, u, machInst, zdn, zm, pg); + case 0x1: + return decodeSveBinDestrPred( + size, u, machInst, zdn, zm, pg); + case 0x2: + return decodeSveBinDestrPred( + size, u, machInst, zdn, zm, pg); + default: + return new Unknown64(machInst); + } + } + case 0x2: + { + uint8_t size = bits(machInst, 23, 22); + uint8_t u = bits(machInst, 16); + uint8_t opc = bits(machInst, 18, 17); + switch (opc) { + case 0x0: + if (u == 0) { + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + } else { + return new Unknown64(machInst); + } + case 0x1: + return decodeSveBinDestrPred( + size, u, machInst, zdn, zm, pg); + case 0x2: + if (size == 0x2 || size == 0x3) { + return decodeSveBinDestrPred( + size, u, machInst, zdn, zm, pg); + } else { + return new Unknown64(machInst); + } + case 0x3: + if (size == 0x2 || size == 0x3) { + return decodeSveBinDestrPred( + size, u, machInst, zdn, zm, pg); + } else { + return new Unknown64(machInst); + } + } + } + case 0x3: + { + uint8_t size = bits(machInst, 23, 22); + uint8_t opc = bits(machInst, 18, 16); + + switch (opc) { + case 0x0: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 0x1: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 0x2: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 0x3: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + default: + return new Unknown64(machInst); + } + } + } + return new Unknown64(machInst); + } // decodeSveArithBinPred + + StaticInstPtr + decodeSveIntReduc(ExtMachInst machInst) + { + IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = bits(machInst, 23, 22); + + switch (bits(machInst, 20, 19)) { + case 0x0: + { + uint8_t u = bits(machInst, 16); + uint8_t opc = bits(machInst, 18, 17); + if (opc != 0x0 || (!u && size == 0x3)) { + return new Unknown64(machInst); + } else { + return decodeSveWideningReduc( + size, u, machInst, vd, zn, pg); + } + } + case 0x1: + { + uint8_t u = bits(machInst, 16); + uint8_t opc = bits(machInst, 18, 17); + switch (opc) { + case 0x0: + return decodeSveUnaryPred( + size, u, machInst, vd, zn, pg); + case 0x1: + return decodeSveUnaryPred( + size, u, machInst, vd, zn, pg); + default: + return new Unknown64(machInst); + } + } + case 0x2: + { + uint8_t opc = bits(machInst, 18, 17); + uint8_t merge = bits(machInst, 16); + switch (opc) { + case 0x0: + if (merge) { + return decodeSveUnaryPredU( + size, machInst, vd /* zd */, zn, pg); + } else { + return decodeSveUnaryPredU( + size, machInst, vd /* zd */, zn, pg); + } + default: + return new Unknown64(machInst); + } + } + case 0x3: + { + uint8_t opc = bits(machInst, 18, 16); + switch (opc) { + case 0x0: + return decodeSveUnaryPredU( + size, machInst, vd, zn, pg); + case 0x1: + return decodeSveUnaryPredU( + size, machInst, vd, zn, pg); + case 0x2: + return decodeSveUnaryPredU( + size, machInst, vd, zn, pg); + default: + return new Unknown64(machInst); + } + } + } + return new Unknown64(machInst); + } // decodeSveIntReduc + + StaticInstPtr + decodeSveIntMulAdd(ExtMachInst machInst) + { + IntRegIndex zda = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = bits(machInst, 23, 22); + uint8_t opc = (bits(machInst, 15) << 1) | bits(machInst, 13); + switch (opc) { + case 0x0: + return decodeSveTerPredS( + size, machInst, zda, zn, zm, pg); + case 0x1: + return decodeSveTerPredS( + size, machInst, zda, zn, zm, pg); + case 0x2: + return decodeSveTerPredS( + size, machInst, zda /* zdn */, zn /* za */, zm, pg); + case 0x3: + return decodeSveTerPredS( + size, machInst, zda /* zdn */, zn /* za */, zm, pg); + } + return new Unknown64(machInst); + } // decodeSveIntMulAdd + + StaticInstPtr + decodeSveShiftByImmPred0(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + uint8_t imm3 = (uint8_t) bits(machInst, 7, 5); + + uint8_t tsize = (bits(machInst, 23, 22) << 2) | bits(machInst, 9, 8); + uint8_t esize = 0; + uint8_t size = 0; + + if (tsize == 0x0) { + return new Unknown64(machInst); + } else if (tsize == 0x1) { + esize = 8; + } else if ((tsize & 0x0E) == 0x2) { + esize = 16; + size = 1; + } else if ((tsize & 0x0C) == 0x4) { + esize = 32; + size = 2; + } else if ((tsize & 0x08) == 0x8) { + esize = 64; + size = 3; + } + + uint8_t opc = bits(machInst, 18, 16); + switch (opc) { + case 0x0: + { + unsigned shiftAmt = 2 * esize - ((tsize << 3) | imm3); + return decodeSveBinImmPredU( + size, machInst, zdn, shiftAmt, pg); + } + case 0x01: + { + unsigned shiftAmt = 2 * esize - ((tsize << 3) | imm3); + return decodeSveBinImmPredU( + size, machInst, zdn, shiftAmt, pg); + } + case 0x03: + { + unsigned shiftAmt = ((tsize << 3) | imm3) - esize; + return decodeSveBinImmPredU( + size, machInst, zdn, shiftAmt, pg); + } + case 0x04: + { + unsigned shiftAmt = 2 * esize - ((tsize << 3) | imm3); + return decodeSveBinImmPredS( + size, machInst, zdn, shiftAmt, pg); + } + } + return new Unknown64(machInst); + } // decodeSveShiftByImmPred0 + + StaticInstPtr + decodeSveShiftByVectorPred(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + uint8_t size = bits(machInst, 23, 22); + uint8_t opc = bits(machInst, 18, 16); + switch (opc) { + case 0: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 1: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 3: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 4: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 5: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 7: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + } + return new Unknown64(machInst); + } // decodeSveShiftByVectorPred + + StaticInstPtr + decodeSveShiftByWideElemsPred(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + uint8_t size = bits(machInst, 23, 22); + uint8_t opc = bits(machInst, 18, 16); + switch (opc) { + case 0x0: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 0x1: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + case 0x3: + return decodeSveBinDestrPredU( + size, machInst, zdn, zm, pg); + } + return new Unknown64(machInst); + } // decodeSveShiftByWideElemsPred + + StaticInstPtr + decodeSveShiftByImmPred(ExtMachInst machInst) + { + uint8_t b20_19 = bits(machInst, 20, 19); + uint8_t b23_22 = bits(machInst, 23, 22); + + if (b20_19 == 0x0) { + return decodeSveShiftByImmPred0(machInst); + } else if (b20_19 == 0x2) { + return decodeSveShiftByVectorPred(machInst); + } else if (b20_19 == 0x3 && b23_22 != 0x3) { + return decodeSveShiftByWideElemsPred(machInst); + } + return new Unknown64(machInst); + } // decodeSveShiftByImmPred + + StaticInstPtr + decodeSveIntArithUnaryPred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + unsigned esize = bits(machInst, 23, 22); + uint8_t opg = bits(machInst, 20, 19); + uint8_t opc = bits(machInst, 18, 16); + if (opg == 0x2) { + bool unsig = static_cast(opc & 1); + switch (opc) { + case 0: + case 1: + if (esize == 0) break; + if (unsig) { + return decodeSveUnaryExtendFromBPredU( + esize, machInst, zd, zn, pg); + } else { + return decodeSveUnaryExtendFromBPredU( + esize, machInst, zd, zn, pg); + } + case 2: + case 3: + if (esize < 2) break; + if (unsig) { + return decodeSveUnaryExtendFromHPredU( + esize, machInst, zd, zn, pg); + } else { + return decodeSveUnaryExtendFromHPredU( + esize, machInst, zd, zn, pg); + } + case 4: + case 5: + if (esize != 3) break; + if (unsig) { + return new SveUxtw( + machInst, zd, zn, pg); + } else { + return new SveSxtw( + machInst, zd, zn, pg); + } + case 6: + return decodeSveUnaryPredS( + esize, machInst, zd, zn, pg); + case 7: + return decodeSveUnaryPredS( + esize, machInst, zd, zn, pg); + } + } else if (opg == 0x3) { + switch (opc) { + case 0: + return decodeSveUnaryPredS( + esize, machInst, zd, zn, pg); + case 1: + return decodeSveUnaryPredS( + esize, machInst, zd, zn, pg); + case 2: + return decodeSveUnaryPredU( + esize, machInst, zd, zn, pg); + case 3: + return decodeSveUnaryPredU( + esize, machInst, zd, zn, pg); + case 4: + return decodeSveUnaryPredF( + esize, machInst, zd, zn, pg); + case 5: + return decodeSveUnaryPredF( + esize, machInst, zd, zn, pg); + case 6: + return decodeSveUnaryPredU( + esize, machInst, zd, zn, pg); + break; + } + } + return new Unknown64(machInst); + } // decodeSveIntArithUnaryPred + + StaticInstPtr + decodeSveIntArithUnpred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + + uint8_t opc = (uint8_t) bits(machInst, 12, 10); + uint8_t size = (uint8_t) bits(machInst, 23, 22); + + switch (opc) { + case 0x0: + return decodeSveBinUnpredU(size, machInst, + zd, zn, zm); + case 0x1: + return decodeSveBinUnpredU(size, machInst, + zd, zn, zm); + case 0x4: + return decodeSveBinUnpredS(size, machInst, + zd, zn, zm); + case 0x5: + return decodeSveBinUnpredU(size, machInst, + zd, zn, zm); + case 0x6: + return decodeSveBinUnpredS(size, machInst, + zd, zn, zm); + case 0x7: + return decodeSveBinUnpredU(size, machInst, + zd, zn, zm); + } + + return new Unknown64(machInst); + } // decodeSveIntArithUnpred + + StaticInstPtr + decodeSveIntLogUnpred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + uint8_t opc = (uint8_t) (bits(machInst, 23, 22) << 3 + | bits(machInst, 12, 10)); + + switch (opc) { + case 0x4: + return new SveAndUnpred(machInst, zd, zn, zm); + case 0xc: + return new SveOrrUnpred(machInst, zd, zn, zm); + case 0x14: + return new SveEorUnpred(machInst, zd, zn, zm); + case 0x1c: + return new SveBicUnpred(machInst, zd, zn, zm); + } + + return new Unknown64(machInst); + } // decodeSveIntLogUnpred + + StaticInstPtr + decodeSveIndexGen(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + uint8_t size = (uint8_t) bits(machInst, 23, 22); + uint8_t grp = (uint8_t) bits(machInst, 11, 10); + + switch (grp) { + case 0: + { // INDEX (immediate) + int8_t imm5 = sext<5>(bits(machInst, 9, 5)); + int8_t imm5b = sext<5>(bits(machInst, 20, 16)); + switch (size) { + case 0: + return new SveIndexII(machInst, + zd, imm5, imm5b); + case 1: + return new SveIndexII(machInst, + zd, imm5, imm5b); + case 2: + return new SveIndexII(machInst, + zd, imm5, imm5b); + case 3: + return new SveIndexII(machInst, + zd, imm5, imm5b); + } + } + case 1: + { // INDEX (scalar, immediate) + int8_t imm5 = sext<5>(bits(machInst, 20, 16)); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits( + machInst, 9, 5); + switch (size) { + case 0: + return new SveIndexRI(machInst, + zd, zn, imm5); + case 1: + return new SveIndexRI(machInst, + zd, zn, imm5); + case 2: + return new SveIndexRI(machInst, + zd, zn, imm5); + case 3: + return new SveIndexRI(machInst, + zd, zn, imm5); + } + } + case 2: + { // INDEX (immediate, scalar) + int8_t imm5 = sext<5>(bits(machInst, 9, 5)); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits( + machInst, 20, 16); + switch (size) { + case 0: + return new SveIndexIR(machInst, + zd, imm5, zm); + case 1: + return new SveIndexIR(machInst, + zd, imm5, zm); + case 2: + return new SveIndexIR(machInst, + zd, imm5, zm); + case 3: + return new SveIndexIR(machInst, + zd, imm5, zm); + } + } + case 3: + { // INDEX (scalars) + IntRegIndex zn = (IntRegIndex) (uint8_t) bits( + machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits( + machInst, 20, 16); + switch (size) { + case 0: + return new SveIndexRR(machInst, + zd, zn, zm); + case 1: + return new SveIndexRR(machInst, + zd, zn, zm); + case 2: + return new SveIndexRR(machInst, + zd, zn, zm); + case 3: + return new SveIndexRR(machInst, + zd, zn, zm); + } + } + } + return new Unknown64(machInst); + } // decodeSveIndexGen + + StaticInstPtr + decodeSveStackAlloc(ExtMachInst machInst) + { + uint8_t b23_22 = bits(machInst, 23, 22); + uint8_t b11 = bits(machInst, 11); + if ((b23_22 & 0x2) == 0x0 && b11 == 0x0) { + IntRegIndex rd = makeSP( + (IntRegIndex) (uint8_t) bits(machInst, 4, 0)); + IntRegIndex rn = makeSP( + (IntRegIndex) (uint8_t) bits(machInst, 20, 16)); + uint64_t imm = sext<6>(bits(machInst, 10, 5)); + if ((b23_22 & 0x1) == 0x0) { + return new AddvlXImm(machInst, rd, rn, imm); + } else { + return new AddplXImm(machInst, rd, rn, imm); + } + } else if (b23_22 == 0x2 && b11 == 0x0) { + IntRegIndex rd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + uint64_t imm = sext<6>(bits(machInst, 10, 5)); + if (bits(machInst, 20, 16) == 0x1f) { + return new SveRdvl(machInst, rd, imm); + } + } + return new Unknown64(machInst); + } // decodeSveStackAlloc + + StaticInstPtr + decodeSveShiftByWideElemsUnpred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + uint8_t size = bits(machInst, 23, 22); + uint8_t opc = (uint8_t) bits(machInst, 11, 10); + switch (opc) { + case 0x0: + return decodeSveBinUnpredU( + size, machInst, zd, zn, zm); + case 0x1: + return decodeSveBinUnpredU( + size, machInst, zd, zn, zm); + case 0x3: + return decodeSveBinUnpredU( + size, machInst, zd, zn, zm); + } + return new Unknown64(machInst); + } // decodeSveShiftByWideElemsUnpred + + StaticInstPtr + decodeSveShiftByImmUnpredB(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + uint8_t imm3 = (uint8_t) bits(machInst, 18, 16); + + uint8_t tsize = (bits(machInst, 23, 22) << 2) | bits(machInst, 20, 19); + uint8_t esize = 0; + uint8_t size = 0; + if (tsize == 0x0) { + return new Unknown64(machInst); + } else if (tsize == 0x1) { + esize = 8; + } else if ((tsize & 0x0E) == 0x2) { + esize = 16; + size = 1; + } else if ((tsize & 0x0C) == 0x4) { + esize = 32; + size = 2; + } else if ((tsize & 0x08) == 0x8) { + esize = 64; + size = 3; + } + + uint8_t opc = bits(machInst, 11, 10); + switch (opc) { + case 0x00: + { + unsigned shiftAmt = 2 * esize - ((tsize << 3) | imm3); + return decodeSveBinImmUnpredU( + size, machInst, zd, zn, shiftAmt); + } + case 0x01: + { + unsigned shiftAmt = 2 * esize - ((tsize << 3) | imm3); + return decodeSveBinImmUnpredU( + size, machInst, zd, zn, shiftAmt); + } + case 0x03: + { + unsigned shiftAmt = ((tsize << 3) | imm3) - esize; + return decodeSveBinImmUnpredU( + size, machInst, zd, zn, shiftAmt); + } + } + + return new Unknown64(machInst); + } // decodeSveShiftByImmUnpredB + + StaticInstPtr + decodeSveShiftByImmUnpred(ExtMachInst machInst) + { + if (bits(machInst, 12)) { + return decodeSveShiftByImmUnpredB(machInst); + } else { + return decodeSveShiftByWideElemsUnpred(machInst); + } + return new Unknown64(machInst); + } // decodeSveShiftByImmUnpred + + StaticInstPtr + decodeSveCompVecAddr(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + uint8_t mult = 1 << bits(machInst, 11, 10); + + uint8_t opc = bits(machInst, 23, 22); + + switch (opc) { + case 0x0: + return new SveAdr(machInst, zd, zn, zm, mult, + SveAdr::SveAdrOffsetUnpackedSigned); + case 0x1: + return new SveAdr(machInst, zd, zn, zm, mult, + SveAdr::SveAdrOffsetUnpackedUnsigned); + case 0x2: + return new SveAdr(machInst, zd, zn, zm, mult, + SveAdr::SveAdrOffsetPacked); + case 0x3: + return new SveAdr(machInst, zd, zn, zm, mult, + SveAdr::SveAdrOffsetPacked); + } + return new Unknown64(machInst); + } // decodeSveCompVecAddr + + StaticInstPtr + decodeSveIntMiscUnpred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + + uint8_t size = bits(machInst, 23, 22); + uint8_t opc = bits(machInst, 11, 10); + switch (opc) { + case 0x0: + // SVE floating-point trig select coefficient + { + if (size == 0) { + break; + } + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, + 20, 16); + return decodeSveBinUnpredF( + size, machInst, zd, zn, zm); + } + case 0x2: + // SVE floating-point exponential accelerator + if (size == 0) { + break; + } + return decodeSveUnaryUnpredF(size, machInst, zd, zn); + case 0x3: + // SVE constructive prefix (unpredicated) + if (size == 0x0 && bits(machInst, 20, 16) == 0x0) { + return new SveMovprfxUnpred(machInst, zd, zn); + } + break; + } + return new Unknown64(machInst); + } // decodeSveIntMiscUnpred + + StaticInstPtr + decodeSveElemCount(ExtMachInst machInst) + { + uint8_t opc20 = (uint8_t) bits(machInst, 20); + uint8_t b13_12 = (uint8_t) bits(machInst, 13, 12); + uint8_t opc11 = (uint8_t) bits(machInst, 11); + uint8_t opc10 = (uint8_t) bits(machInst, 10); + uint8_t opc11_10 = (uint8_t) bits(machInst, 11, 10); + if (b13_12 == 0) { + uint8_t pattern = (uint8_t) bits(machInst, 9, 5); + uint8_t imm4 = (uint8_t) bits(machInst, 19, 16) + 1; + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + unsigned size = (unsigned) bits(machInst, 23, 22); + if (opc20) { + if (opc11 == 0) { + if (opc10) { + return decodeSveElemIntCountLU(size, + machInst, zdn, pattern, imm4); + } else { + return decodeSveElemIntCountLU(size, + machInst, zdn, pattern, imm4); + } + } + } else { + if (opc11) { + if (opc10) { + return decodeSveElemIntCountLU(size, + machInst, zdn, pattern, imm4); + } else { + return decodeSveElemIntCountLS(size, + machInst, zdn, pattern, imm4); + } + } else { + if (opc10) { + return decodeSveElemIntCountLU(size, + machInst, zdn, pattern, imm4); + } else { + return decodeSveElemIntCountLS(size, + machInst, zdn, pattern, imm4); + } + } + } + } else if (b13_12 == 3) { + uint8_t pattern = (uint8_t) bits(machInst, 9, 5); + uint8_t imm4 = (uint8_t) bits(machInst, 19, 16) + 1; + IntRegIndex rdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + unsigned size = (unsigned) bits(machInst, 23, 22); + switch (opc11_10) { + case 0: + if (opc20) { + return decodeSveElemIntCountS(size, + machInst, rdn, pattern, imm4); + } else { + return decodeSveElemIntCountS(size, + machInst, rdn, pattern, imm4); + } + case 1: + if (opc20) { + return decodeSveElemIntCountU(size, + machInst, rdn, pattern, imm4); + } else { + return decodeSveElemIntCountU(size, + machInst, rdn, pattern, imm4); + } + case 2: + if (opc20) { + return decodeSveElemIntCountS(size, + machInst, rdn, pattern, imm4); + } else { + return decodeSveElemIntCountS(size, + machInst, rdn, pattern, imm4); + } + case 3: + if (opc20) { + return decodeSveElemIntCountU(size, + machInst, rdn, pattern, imm4); + } else { + return decodeSveElemIntCountU(size, + machInst, rdn, pattern, imm4); + } + } + } else if (opc20 && b13_12 == 2 && !(opc11_10 & 0x2)) { + uint8_t pattern = (uint8_t) bits(machInst, 9, 5); + uint8_t imm4 = (uint8_t) bits(machInst, 19, 16) + 1; + IntRegIndex rdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + unsigned size = (unsigned) bits(machInst, 23, 22); + if (opc11_10 & 0x1) { + return decodeSveElemIntCountU(size, machInst, + rdn, pattern, imm4); + } else { + return decodeSveElemIntCountU(size, machInst, + rdn, pattern, imm4); + } + } else if (!opc20 && b13_12 == 2 && opc11_10 == 0) { + uint8_t pattern = (uint8_t) bits(machInst, 9, 5); + uint8_t imm4 = (uint8_t) bits(machInst, 19, 16) + 1; + IntRegIndex rd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + unsigned size = (unsigned) bits(machInst, 23, 22); + return decodeSveElemIntCountU(size, machInst, + rd, pattern, imm4); + } + return new Unknown64(machInst); + } // decodeSveElemCount + + StaticInstPtr + decodeSveLogMaskImm(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + bool n = bits(machInst, 17); + uint8_t immr = bits(machInst, 16, 11); + uint8_t imms = bits(machInst, 10, 5); + + // Decode bitmask + // len = MSB(n:NOT(imms)), len < 1 is undefined + uint8_t len = 0; + if (n) { + len = 6; + } else if (imms == 0x3f || imms == 0x3e) { + return new Unknown64(machInst); + } else { + len = findMsbSet(imms ^ 0x3f); + } + // Generate r, s, and size + uint64_t r = bits(immr, len - 1, 0); + uint64_t s = bits(imms, len - 1, 0); + uint8_t size = 1 << len; + if (s == size - 1) + return new Unknown64(machInst); + // Generate the pattern with s 1s, rotated by r, with size bits + uint64_t pattern = mask(s + 1); + if (r) { + pattern = (pattern >> r) | (pattern << (size - r)); + pattern &= mask(size); + } + // Replicate that to fill up the immediate + for (unsigned i = 1; i < (64 / size); i *= 2) + pattern |= (pattern << (i * size)); + uint64_t imm = pattern; + + if (bits(machInst, 19, 18) == 0x0) { + if (bits(machInst, 23, 22) == 0x3) { + return new SveDupm(machInst, zd, imm); + } else { + switch (bits(machInst, 23, 22)) { + case 0x0: + return new SveOrrImm(machInst, zd, imm); + case 0x1: + return new SveEorImm(machInst, zd, imm); + case 0x2: + return new SveAndImm(machInst, zd, imm); + } + } + } + + return new Unknown64(machInst); + } // decodeSveLogMaskImm + + StaticInstPtr + decodeSveIntWideImmPred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 19, 16); + uint8_t size = bits(machInst, 23, 22); + + if (bits(machInst, 15) == 0x0) { + uint64_t imm = bits(machInst, 12, 5); + uint8_t sh = bits(machInst, 13); + uint8_t m = bits(machInst, 14); + if (sh) { + if (size == 0x0) { + return new Unknown64(machInst); + } + imm <<= 8; + } + if (m) { + if (sh) { + return decodeSveWideImmPredU( + size, machInst, zd, sext<16>(imm), pg); + } else { + return decodeSveWideImmPredU( + size, machInst, zd, sext<8>(imm), pg); + } + } else { + if (sh) { + return decodeSveWideImmPredU( + size, machInst, zd, sext<16>(imm), pg, + false /* isMerging */); + } else { + return decodeSveWideImmPredU( + size, machInst, zd, sext<8>(imm), pg, + false /* isMerging */); + } + } + } else if (bits(machInst, 15, 13) == 0x6 && size != 0x0) { + uint64_t imm = vfp_modified_imm(bits(machInst, 12, 5), + decode_fp_data_type(size)); + return decodeSveWideImmPredF( + size, machInst, zd, imm, pg); + } + + return new Unknown64(machInst); + } // decodeSveIntWideImmPred + + StaticInstPtr + decodeSvePermExtract(ExtMachInst machInst) + { + uint8_t b23_22 = (unsigned) bits(machInst, 23, 22); + if (!b23_22) { + uint8_t position = + bits(machInst, 20, 16) << 3 | bits(machInst, 12, 10); + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + return new SveExt(machInst, zdn, zm, position); + } + return new Unknown64(machInst); + } // decodeSvePermExtract + + StaticInstPtr + decodeSvePermUnpred(ExtMachInst machInst) + { + uint8_t b12_10 = bits(machInst, 12, 10); + if (b12_10 == 0x4) { + unsigned size = (unsigned) bits(machInst, 23, 22); + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + return decodeSveBinUnpredU(size, machInst, zd, zn, zm); + } else if (bits(machInst, 20, 16) == 0x0 && b12_10 == 0x6) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex rn = makeSP( + (IntRegIndex) (uint8_t) bits(machInst, 9, 5)); + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + return decodeSveUnaryUnpredU(size, machInst, zd, rn); + } else if (bits(machInst, 20, 16) == 0x4 && b12_10 == 0x6) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex rm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + return decodeSveUnaryUnpredU(size, machInst, zdn, rm); + } else if (bits(machInst, 20, 16) == 0x14 && b12_10 == 0x6) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + return decodeSveUnaryUnpredU(size, machInst, zdn, vm); + } else if (bits(machInst, 20, 16) == 0x18 && b12_10 == 0x6) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + return decodeSveUnaryUnpredU(size, machInst, zd, zn); + } else if (b12_10 == 0x0 && bits(machInst, 20, 16) != 0x0) { + uint8_t imm = + bits(machInst, 23, 22) << 5 | // imm3h + bits(machInst, 20) << 4 | // imm3l + bits(machInst, 19, 16); // tsz + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + if (imm & 0x1) { + imm >>= 1; + return new SveDupIdx(machInst, zd, zn, imm); + } else if (imm & 0x2) { + imm >>= 2; + return new SveDupIdx(machInst, zd, zn, imm); + } else if (imm & 0x4) { + imm >>= 3; + return new SveDupIdx(machInst, zd, zn, imm); + } else if (imm & 0x8) { + imm >>= 4; + return new SveDupIdx(machInst, zd, zn, imm); + } else if (imm & 0x10) { + imm >>= 5; + return new SveDupIdx<__uint128_t>(machInst, zd, zn, imm); + } + return new Unknown64(machInst); + } else if (bits(machInst, 23, 22) != 0x0 && + bits(machInst, 20, 18) == 0x4 && b12_10 == 0x6) { + unsigned size = (unsigned) bits(machInst, 23, 22); + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + if (bits(machInst, 17)) { + if (bits(machInst, 16)) { + return decodeSveUnpackU(size, machInst, + zd, zn); + } else { + return decodeSveUnpackU(size, machInst, + zd, zn); + } + } else { + if (bits(machInst, 16)) { + return decodeSveUnpackS(size, machInst, + zd, zn); + } else { + return decodeSveUnpackS(size, machInst, + zd, zn); + } + } + } + return new Unknown64(machInst); + } // decodeSvePermUnpred + + StaticInstPtr + decodeSvePermPredicates(ExtMachInst machInst) + { + if (bits(machInst, 20) == 0x0 && bits(machInst, 12, 11) != 0x3 && + bits(machInst, 9) == 0x0 && bits(machInst, 4) == 0x0) { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + + uint8_t size = bits(machInst, 23, 22); + + uint8_t opc = bits(machInst, 12, 10); + + switch (opc) { + case 0x0: + return decodeSveBinUnpredU(size, + machInst, zd, zn, zm); + case 0x1: + return decodeSveBinUnpredU(size, + machInst, zd, zn, zm); + case 0x2: + return decodeSveBinUnpredU(size, + machInst, zd, zn, zm); + case 0x3: + return decodeSveBinUnpredU(size, + machInst, zd, zn, zm); + case 0x4: + return decodeSveBinUnpredU(size, + machInst, zd, zn, zm); + case 0x5: + return decodeSveBinUnpredU(size, + machInst, zd, zn, zm); + } + } else if (bits(machInst, 23, 22) == 0x0 && + bits(machInst, 20, 17) == 0x8 && bits(machInst, 12, 9) == 0x0 + && bits(machInst, 4) == 0x0) { + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + IntRegIndex pn = (IntRegIndex) (uint8_t) bits(machInst, 8, 5); + if (bits(machInst, 16)) { + return new SvePunpkhi(machInst, pd, pn); + } else { + return new SvePunpklo(machInst, pd, pn); + } + } else if (bits(machInst, 20, 16) == 0x14 && + bits(machInst, 12, 9) == 0x00 && bits(machInst, 4) == 0) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + IntRegIndex pn = (IntRegIndex) (uint8_t) bits(machInst, 8, 5); + return decodeSveUnaryUnpredU(size, machInst, pd, pn); + } + return new Unknown64(machInst); + } // decodeSvePermPredicates + + StaticInstPtr + decodeSvePermIntlv(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + + uint8_t size = bits(machInst, 23, 22); + + uint8_t opc = bits(machInst, 12, 10); + + switch (opc) { + case 0x0: + return decodeSveBinUnpredU(size, machInst, zd, zn, zm); + case 0x1: + return decodeSveBinUnpredU(size, machInst, zd, zn, zm); + case 0x2: + return decodeSveBinUnpredU(size, machInst, zd, zn, zm); + case 0x3: + return decodeSveBinUnpredU(size, machInst, zd, zn, zm); + case 0x4: + return decodeSveBinUnpredU(size, machInst, zd, zn, zm); + case 0x5: + return decodeSveBinUnpredU(size, machInst, zd, zn, zm); + } + return new Unknown64(machInst); + } // decodeSvePermIntlv + + StaticInstPtr + decodeSvePermPred(ExtMachInst machInst) + { + uint8_t b13 = bits(machInst, 13); + uint8_t b23 = bits(machInst, 23); + switch (bits(machInst, 20, 16)) { + case 0x0: + if (!b13) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex vn = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex zd = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + return decodeSveUnaryPredU(size, + machInst, zd, vn, pg); + } + break; + case 0x1: + if (!b13 && b23) { + // sve_int_perm_compact + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zn = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex zd = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + if (bits(machInst, 22)) { + return new SveCompact(machInst, zd, zn, pg); + } else { + return new SveCompact(machInst, zd, zn, pg); + } + } + break; + case 0x8: + if (b13) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex rn = makeSP( + (IntRegIndex)(uint8_t) bits(machInst, 9, 5)); + IntRegIndex zd = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + return decodeSveUnaryPredU(size, + machInst, zd, rn, pg); + } + break; + case 0xC: + if (!b13) { + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zdn = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + return decodeSveBinDestrPredU(size, machInst, + zdn, zm, pg); + } + break; + } + switch (bits(machInst, 20, 17)) { + case 0x0: + if (b13) { + uint8_t AB = bits(machInst, 16); + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zn = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex rd = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + if (!AB) { + return decodeSveUnaryPredU(size, + machInst, rd, zn, pg); + } else { + return decodeSveUnaryPredU(size, + machInst, rd, zn, pg); + } + } + break; + case 0x1: + if (!b13) { + uint8_t AB = bits(machInst, 16); + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zn = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex vd = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + if (!AB) { + return decodeSveUnaryPredU(size, + machInst, vd, zn, pg); + } else { + return decodeSveUnaryPredU(size, + machInst, vd, zn, pg); + } + } + break; + case 0x4: + if (!b13) { + uint8_t AB = bits(machInst, 16); + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zm = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex zdn = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + if (!AB) { + return decodeSveUnaryPredU(size, + machInst, zdn, zm, pg); + } else { + return decodeSveUnaryPredU(size, + machInst, zdn, zm, pg); + } + } + break; + case 0x5: + if (!b13) { + uint8_t AB = bits(machInst, 16); + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zm = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex zdn = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + if (!AB) { + return decodeSveUnaryPredU(size, + machInst, zdn, zm, pg); + } else { + return decodeSveUnaryPredU(size, + machInst, zdn, zm, pg); + } + } + break; + case 0x8: + if (b13) { + uint8_t AB = bits(machInst, 16); + uint8_t size = bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zm = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex rdn = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + if (!AB) { + return decodeSveUnaryPredU(size, + machInst, rdn, zm, pg); + } else { + return decodeSveUnaryPredU(size, + machInst, rdn, zm, pg); + } + } + break; + } + if (bits(machInst, 20, 18) == 0x1 && !b13) { + unsigned size = (unsigned) bits(machInst, 23, 22); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10); + IntRegIndex zn = (IntRegIndex)(uint8_t) bits(machInst, 9, 5); + IntRegIndex zd = (IntRegIndex)(uint8_t) bits(machInst, 4, 0); + uint8_t opc17_16 = bits(machInst, 17, 16); + switch (opc17_16) { + case 0x00: + switch (size) { + case 1: + return new SveRevb(machInst, zd, zn, pg); + case 2: + return new SveRevb(machInst, zd, zn, pg); + case 3: + return new SveRevb(machInst, zd, zn, pg); + } + break; + case 0x01: + switch (size) { + case 2: + return new SveRevh(machInst, zd, zn, pg); + case 3: + return new SveRevh(machInst, zd, zn, pg); + } + break; + case 0x02: + if (size == 3) { + return new SveRevw(machInst, zd, zn, pg); + } + break; + case 0x03: + return decodeSveUnaryPredU( + size, machInst, zd, zn, pg); + } + } + return new Unknown64(machInst); + } // decodeSvePermPred + + StaticInstPtr + decodeSveSelVec(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 13, 10); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + + uint8_t size = bits(machInst, 23, 22); + + return decodeSveBinConstrPredU(size, + machInst, zd, zn, zm, pg, SvePredType::SELECT); + } // decodeSveSelVec + + StaticInstPtr + decodeSveIntCmpVec(ExtMachInst machInst) + { + uint8_t size = bits(machInst, 23, 22); + uint8_t b14 = bits(machInst, 14); + uint8_t opc = + bits(machInst, 15) << 2 | + bits(machInst, 13) << 1 | + bits(machInst, 4); + IntRegIndex pd = (IntRegIndex) (uint8_t)bits(machInst, 3, 0); + IntRegIndex pg = (IntRegIndex) (uint8_t)bits(machInst, 12, 10); + IntRegIndex zn = (IntRegIndex) (uint8_t)bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t)bits(machInst, 20, 16); + if (b14 && size != 3) { + // sve_int_cmp_1 + switch (opc) { + case 0: + return decodeSveTerPredWS(size, + machInst, pd, zn, zm, pg); + case 1: + return decodeSveTerPredWS(size, + machInst, pd, zn, zm, pg); + case 2: + return decodeSveTerPredWS(size, + machInst, pd, zn, zm, pg); + case 3: + return decodeSveTerPredWS(size, + machInst, pd, zn, zm, pg); + case 4: + return decodeSveTerPredWU(size, + machInst, pd, zn, zm, pg); + case 5: + return decodeSveTerPredWU(size, + machInst, pd, zn, zm, pg); + case 6: + return decodeSveTerPredWU(size, + machInst, pd, zn, zm, pg); + case 7: + return decodeSveTerPredWU(size, + machInst, pd, zn, zm, pg); + } + } else if (!b14) { + switch (opc) { + case 0: + return decodeSveTerPredU(size, + machInst, pd, zn, zm, pg); + case 1: + return decodeSveTerPredU(size, + machInst, pd, zn, zm, pg); + case 2: + if (size != 3) { + return decodeSveTerPredWU(size, + machInst, pd, zn, zm, pg); + } + break; + case 3: + if (size != 3) { + return decodeSveTerPredWU(size, + machInst, pd, zn, zm, pg); + } + break; + case 4: + return decodeSveTerPredS(size, + machInst, pd, zn, zm, pg); + case 5: + return decodeSveTerPredS(size, + machInst, pd, zn, zm, pg); + case 6: + return decodeSveTerPredU(size, + machInst, pd, zn, zm, pg); + case 7: + return decodeSveTerPredU(size, + machInst, pd, zn, zm, pg); + } + } + return new Unknown64(machInst); + } // decodeSveIntCmpVec + + StaticInstPtr + decodeSveIntCmpUImm(ExtMachInst machInst) + { + uint8_t cmp = bits(machInst, 13) << 1 | bits(machInst, 4); + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + int64_t imm = (int64_t) bits(machInst, 20, 14); + uint8_t size = bits(machInst, 23, 22); + switch (cmp) { + case 0: + return decodeSveTerImmPredU(size, + machInst, pd, zn, imm, pg); + case 1: + return decodeSveTerImmPredU(size, + machInst, pd, zn, imm, pg); + case 2: + return decodeSveTerImmPredU(size, + machInst, pd, zn, imm, pg); + case 3: + return decodeSveTerImmPredU(size, + machInst, pd, zn, imm, pg); + } + return new Unknown64(machInst); + } // decodeSveIntCmpUImm + + StaticInstPtr + decodeSveIntCmpSImm(ExtMachInst machInst) + { + uint8_t opc = bits(machInst, 15) << 2 | bits(machInst, 13) << 1 | + bits(machInst, 4); + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + int64_t imm = sext<5>(bits(machInst, 20, 16)); + uint8_t size = bits(machInst, 23, 22); + switch (opc) { + case 0: + return decodeSveTerImmPredS(size, + machInst, pd, zn, imm, pg); + case 1: + return decodeSveTerImmPredS(size, + machInst, pd, zn, imm, pg); + case 2: + return decodeSveTerImmPredS(size, + machInst, pd, zn, imm, pg); + case 3: + return decodeSveTerImmPredS(size, + machInst, pd, zn, imm, pg); + case 4: + return decodeSveTerImmPredU(size, + machInst, pd, zn, imm, pg); + case 5: + return decodeSveTerImmPredU(size, + machInst, pd, zn, imm, pg); + default: + return new Unknown64(machInst); + } + return new Unknown64(machInst); + } // decodeSveIntCmpSImm + + StaticInstPtr + decodeSvePredLogicalOps(ExtMachInst machInst) + { + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + IntRegIndex pn = (IntRegIndex) (uint8_t) bits(machInst, 8, 5); + IntRegIndex pm = (IntRegIndex) (uint8_t) bits(machInst, 19, 16); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 13, 10); + uint8_t opc = (bits(machInst, 23, 22) << 2) | + (bits(machInst, 9) << 1) | + bits(machInst, 4); + switch (opc) { + case 0x0: + return new SvePredAnd(machInst, pd, pn, pm, pg); + case 0x1: + return new SvePredBic(machInst, pd, pn, pm, pg); + case 0x2: + return new SvePredEor(machInst, pd, pn, pm, pg); + case 0x3: + return new SvePredSel(machInst, pd, pn, pm, pg, true); + case 0x4: + return new SvePredAnds(machInst, pd, pn, pm, pg); + case 0x5: + return new SvePredBics(machInst, pd, pn, pm, pg); + case 0x6: + return new SvePredEors(machInst, pd, pn, pm, pg); + case 0x8: + return new SvePredOrr(machInst, pd, pn, pm, pg); + case 0x9: + return new SvePredOrn(machInst, pd, pn, pm, pg); + case 0xa: + return new SvePredNor(machInst, pd, pn, pm, pg); + case 0xb: + return new SvePredNand(machInst, pd, pn, pm, pg); + case 0xc: + return new SvePredOrrs(machInst, pd, pn, pm, pg); + case 0xd: + return new SvePredOrns(machInst, pd, pn, pm, pg); + case 0xe: + return new SvePredNors(machInst, pd, pn, pm, pg); + case 0xf: + return new SvePredNands(machInst, pd, pn, pm, pg); + } + + return new Unknown64(machInst); + } // decodeSvePredLogicalOps + + StaticInstPtr + decodeSvePropBreakFromPrevPartition(ExtMachInst machInst) + { + if (bits(machInst, 23) == 0x0 && bits(machInst, 9) == 0x0) { + uint8_t opc = (bits(machInst, 22) << 1) | bits(machInst, 4); + IntRegIndex pm = (IntRegIndex)(uint8_t) bits(machInst, 19, 16); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 13, 10); + IntRegIndex pn = (IntRegIndex)(uint8_t) bits(machInst, 8, 5); + IntRegIndex pd = (IntRegIndex)(uint8_t) bits(machInst, 3, 0); + switch (opc) { + case 0x0: + // BRKPA + return new SveBrkpa(machInst, pd, pn, pm, pg); + case 0x1: + // BRKPB + return new SveBrkpb(machInst, pd, pn, pm, pg); + case 0x2: + // BRKPAS + return new SveBrkpas(machInst, pd, pn, pm, pg); + case 0x3: + // BRKPBS + return new SveBrkpbs(machInst, pd, pn, pm, pg); + } + } + return new Unknown64(machInst); + } // decodeSvePropBreakFromPrevPartition + + StaticInstPtr + decodeSvePartitionBreakCond(ExtMachInst machInst) + { + if (bits(machInst, 18, 16) == 0x0 && bits(machInst, 9) == 0x0) { + bool flagset = bits(machInst, 22); + bool merging = bits(machInst, 4); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 13, 10); + IntRegIndex pn = (IntRegIndex)(uint8_t) bits(machInst, 8, 5); + IntRegIndex pd = (IntRegIndex)(uint8_t) bits(machInst, 3, 0); + if (bits(machInst, 23)) { + if (flagset) { + if (!merging) { + return new SveBrkbs(machInst, pd, pg, pn); + } + } else { + if (merging) { + return new SveBrkbm(machInst, pd, pg, pn); + } else { + return new SveBrkbz(machInst, pd, pg, pn); + } + } + } else { + if (flagset) { + if (!merging) { + return new SveBrkas(machInst, pd, pg, pn); + } + } else { + if (merging) { + return new SveBrkam(machInst, pd, pg, pn); + } else { + return new SveBrkaz(machInst, pd, pg, pn); + } + } + } + return new Unknown64(machInst); + } + return new Unknown64(machInst); + } // decodeSvePartitionBreakCond + + StaticInstPtr + decodeSvePredTest(ExtMachInst machInst) + { + if (bits(machInst, 23, 22) == 0x1 && + bits(machInst, 18, 16) == 0x0 && + bits(machInst, 9) == 0x0) { + IntRegIndex pn = (IntRegIndex) (uint8_t) bits(machInst, 8, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 13, 10); + return new SvePtest(machInst, pn, pg); + } + return new Unknown64(machInst); + } // decodeSvePredTest + + StaticInstPtr + decodeSvePredIteration(ExtMachInst machInst) + { + uint8_t size = bits(machInst, 23, 22); + uint8_t opc18_16 = bits(machInst, 18, 16); + uint8_t opc10_9 = bits(machInst, 10, 9); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 8, 5); + IntRegIndex pdn = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + if (opc18_16 == 0x1 && opc10_9 == 0x2) { + return decodeSveUnaryPredU(size, + machInst, pdn, pdn, pg); + } else if (size == 0x1 && opc18_16 == 0x0 && opc10_9 == 0) { + return new SvePfirst(machInst, pdn, pdn, pg); + } + return new Unknown64(machInst); + } // decodeSvePredIteration + + StaticInstPtr + decodeSveInitPred(ExtMachInst machInst) + { + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + unsigned size = bits(machInst, 23, 22); + uint8_t imm = bits(machInst, 9, 5); + + if (bits(machInst, 16) == 0x0) { + return decodeSvePtrue(size, machInst, pd, imm); + } else { + return decodeSvePtrue(size, machInst, pd, imm); + } + return new Unknown64(machInst); + } // decodeSveInitPred + + StaticInstPtr + decodeSveZeroPredReg(ExtMachInst machInst) + { + if (bits(machInst, 23, 22) == 0x0 && bits(machInst, 18, 16) == 0x0) { + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + return new SvePfalse(machInst, pd); + } + return new Unknown64(machInst); + } // decodeSveZeroPredReg + + StaticInstPtr + decodeSvePropBreakToNextPartition(ExtMachInst machInst) + { + if (bits(machInst, 23) == 0x0 && + bits(machInst, 18, 16) == 0x0 && + bits(machInst, 9) == 0x0 && + bits(machInst, 4) == 0x0) { + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 13, 10); + IntRegIndex pn = (IntRegIndex)(uint8_t) bits(machInst, 8, 5); + IntRegIndex pdm = (IntRegIndex)(uint8_t) bits(machInst, 3, 0); + if (bits(machInst, 22) == 0x0) { + return new SveBrkn(machInst, pdm, pn, pdm, pg); + } else { + return new SveBrkns(machInst, pdm, pn, pdm, pg); + } + return new Unknown64(machInst); + } + return new Unknown64(machInst); + } // decodeSvePropBreakToNextPartition + + StaticInstPtr + decodeSveReadPredFromFFRPred(ExtMachInst machInst) + { + if (bits(machInst, 23)) { + return new Unknown64(machInst); + } + IntRegIndex pd = (IntRegIndex)(uint8_t) bits(machInst, 3, 0); + IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 8, 5); + if (bits(machInst, 22)) { + return new SveRdffrsPred(machInst, pd, pg); + } else { + return new SveRdffrPred(machInst, pd, pg); + } + } // decodeSveReadPredFromFFRPred + + StaticInstPtr + decodeSveReadPredFromFFRUnpred(ExtMachInst machInst) + { + if (bits(machInst, 23, 22) != 0) { + return new Unknown64(machInst); + } + IntRegIndex pd = (IntRegIndex)(uint8_t) bits(machInst, 3, 0); + return new SveRdffrUnpred(machInst, pd); + } // decodeSveReadPredFromFFRUnpred + + StaticInstPtr + decodeSvePredGen(ExtMachInst machInst) + { + uint8_t b_20_15 = (bits(machInst, 20) << 1) | bits(machInst, 15); + switch (b_20_15) { + case 0x0: + return decodeSvePredLogicalOps(machInst); + case 0x1: + return decodeSvePropBreakFromPrevPartition(machInst); + case 0x2: + if (bits(machInst, 19) == 0x0) { + return decodeSvePartitionBreakCond(machInst); + } else { + return decodeSvePropBreakToNextPartition(machInst); + } + case 0x3: + if (bits(machInst, 19) == 0x0) { + if (bits(machInst, 4, 0) == 0x0) { + return decodeSvePredTest(machInst); + } else { + break; + } + } else { + switch (bits(machInst, 13, 12)) { + case 0x0: + if (bits(machInst, 11) == 0x0 && + bits(machInst, 4) == 0x0) { + return decodeSvePredIteration(machInst); + } else { + break; + } + case 0x1: + break; + case 0x2: + if (bits(machInst, 11, 10) == 0x0 && + bits(machInst, 4) == 0x0) { + return decodeSveInitPred(machInst); + } else if (bits(machInst, 11, 4) == 0x40) { + return decodeSveZeroPredReg(machInst); + } + break; + case 0x3: + if (bits(machInst, 11) == 0x0) { + if (bits(machInst, 16) == 0x0) { + return decodeSveReadPredFromFFRPred(machInst); + } else if (bits(machInst, 8, 4) == 0x0) { + return decodeSveReadPredFromFFRUnpred(machInst); + } + } + break; + } + } + break; + } + return new Unknown64(machInst); + } // decodeSvePredGen + + StaticInstPtr + decodeSvePredCount(ExtMachInst machInst) + { + uint8_t b19 = bits(machInst, 19); + if (b19) { + uint8_t b13_11 = bits(machInst, 13, 11); + switch (b13_11) { + case 0x0: + { + if (bits(machInst, 10, 9) != 0x0) { + return new Unknown64(machInst); + } + IntRegIndex zdn = (IntRegIndex) (uint8_t) + bits(machInst, 4, 0); + IntRegIndex pg = (IntRegIndex) (uint8_t) + bits(machInst, 8, 5); + uint8_t esize = bits(machInst, 23, 22); + if (esize == 0x0) { + return new Unknown64(machInst); + } + uint8_t opc = bits(machInst, 18, 17); + if (opc == 0x0) { + uint8_t u = bits(machInst, 16); + if (u) { + return decodeSvePredCountVU(esize, + machInst, zdn, pg); + } else { + return decodeSvePredCountVS(esize, + machInst, zdn, pg); + } + } else if (opc == 0x1) { + uint8_t u = bits(machInst, 16); + if (u) { + return decodeSvePredCountVU(esize, + machInst, zdn, pg); + } else { + return decodeSvePredCountVS(esize, + machInst, zdn, pg); + } + } else if (opc == 0x2) { + uint8_t d = bits(machInst, 16); + if (d) { + return decodeSvePredCountVU(esize, + machInst, zdn, pg); + } else { + return decodeSvePredCountVU(esize, + machInst, zdn, pg); + } + } + } + break; + case 0x1: + { + IntRegIndex rdn = (IntRegIndex) (uint8_t) + bits(machInst, 4, 0); + IntRegIndex pg = (IntRegIndex) (uint8_t) + bits(machInst, 8, 5); + uint8_t esize = bits(machInst, 23, 22); + uint8_t opc = bits(machInst, 18, 17); + uint8_t opc2 = bits(machInst, 10, 9); + if (opc == 0x0) { + uint8_t u = bits(machInst, 16); + if (opc2 == 0x0) { + if (u) { + return decodeSvePredCountU(esize, + machInst, rdn, pg); + } else { + return decodeSvePredCountS(esize, + machInst, rdn, pg); + } + } else if (opc2 == 0x2) { + if (u) { + return decodeSvePredCountU(esize, + machInst, rdn, pg); + } else { + return decodeSvePredCountS(esize, + machInst, rdn, pg); + } + } + } else if (opc == 0x1) { + uint8_t u = bits(machInst, 16); + if (opc2 == 0x0) { + if (u) { + return decodeSvePredCountU(esize, + machInst, rdn, pg); + } else { + return decodeSvePredCountS(esize, + machInst, rdn, pg); + } + } else if (opc2 == 0x2) { + if (u) { + return decodeSvePredCountU(esize, + machInst, rdn, pg); + } else { + return decodeSvePredCountS(esize, + machInst, rdn, pg); + } + } + } else if (opc == 0x2) { + if (opc2 == 0x0) { + if (bits(machInst, 16)) { + return decodeSvePredCountU(esize, + machInst, rdn, pg); + } else { + return decodeSvePredCountU(esize, + machInst, rdn, pg); + } + } + } + } + break; + case 0x2: + if (bits(machInst, 23, 22) == 0x0 && + bits(machInst, 10, 9) == 0x0 && + bits(machInst, 4, 0) == 0x0) { + uint8_t opc = bits(machInst, 18, 16); + if (opc == 0x0) { + IntRegIndex pn = (IntRegIndex)(uint8_t) + bits(machInst, 8, 5); + return new SveWrffr(machInst, pn); + } else if (opc == 0x4 && bits(machInst, 8, 5) == 0x0) { + return new SveSetffr(machInst); + } + } + break; + } + } else { + uint8_t opc = bits(machInst, 18, 16); + if (opc == 0 && bits(machInst, 9) == 0) { + IntRegIndex rd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex pn = (IntRegIndex) (uint8_t) bits(machInst, 8, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 13, + 10); + uint8_t esize = bits(machInst, 23, 22); + return decodeSveUnaryPredU(esize, + machInst, rd, pn, pg); + } + } + return new Unknown64(machInst); + } // decodeSvePredCount + + StaticInstPtr + decodeSveIntCmpSca(ExtMachInst machInst) + { + uint16_t b23_13_12_11_10_3_2_1_0 = (uint16_t) + (bits(machInst, 23) << 8) | (bits(machInst, 13, 10) << 4) | + bits(machInst, 3, 0); + uint8_t b10 = (uint8_t) bits(machInst, 10); + IntRegIndex rn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex rm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + if (b23_13_12_11_10_3_2_1_0 == 0x180) { + uint8_t s64b = bits(machInst, 22); + uint8_t ne = bits(machInst, 4); + if (ne) { + if (s64b) { + return new SveCtermne(machInst, rn, rm); + } else { + return new SveCtermne(machInst, rn, rm); + } + } else { + if (s64b) { + return new SveCtermeq(machInst, rn, rm); + } else { + return new SveCtermeq(machInst, rn, rm); + } + } + } else if (b10) { + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + uint8_t size = (uint8_t) bits(machInst, 23, 22); + uint8_t s64b = (uint8_t) bits(machInst, 12); + uint8_t opc = (uint8_t) bits(machInst, 11) << 1 | + bits(machInst, 4); + if (s64b) { + switch (opc) { + case 0: + return decodeSveBinUnpredS(size, + machInst, pd, rn, rm); + case 1: + return decodeSveBinUnpredS(size, + machInst, pd, rn, rm); + case 2: + return decodeSveBinUnpredU(size, + machInst, pd, rn, rm); + case 3: + return decodeSveBinUnpredU(size, + machInst, pd, rn, rm); + } + } else { + switch (opc) { + case 0: + return decodeSveBinUnpredS(size, + machInst, pd, rn, rm); + case 1: + return decodeSveBinUnpredS(size, + machInst, pd, rn, rm); + case 2: + return decodeSveBinUnpredU(size, + machInst, pd, rn, rm); + case 3: + return decodeSveBinUnpredU(size, + machInst, pd, rn, rm); + } + } + } + return new Unknown64(machInst); + } // decodeSveIntCmpSca + + StaticInstPtr + decodeSveIntWideImmUnpred0(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + uint64_t imm = bits(machInst, 12, 5); + uint8_t sh = bits(machInst, 13); + uint8_t size = bits(machInst, 23, 22); + + if (sh) { + if (size == 0x0) { + return new Unknown64(machInst); + } + imm <<= 8; + } + + switch (bits(machInst, 18, 16)) { + case 0x0: + return decodeSveWideImmUnpredU( + size, machInst, zdn, imm); + case 0x1: + return decodeSveWideImmUnpredU( + size, machInst, zdn, imm); + case 0x3: + return decodeSveWideImmUnpredU( + size, machInst, zdn, imm); + case 0x4: + return decodeSveWideImmUnpredS( + size, machInst, zdn, imm); + case 0x5: + return decodeSveWideImmUnpredU( + size, machInst, zdn, imm); + case 0x6: + return decodeSveWideImmUnpredS( + size, machInst, zdn, imm); + case 0x7: + return decodeSveWideImmUnpredU( + size, machInst, zdn, imm); + } + + return new Unknown64(machInst); + } // decodeSveIntWideImmUnpred0 + + StaticInstPtr + decodeSveIntWideImmUnpred1(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + uint64_t imm = bits(machInst, 12, 5); + uint8_t size = bits(machInst, 23, 22); + + switch (bits(machInst, 18, 16)) { + case 0x0: + return decodeSveWideImmUnpredS( + size, machInst, zdn, sext<8>(imm)); + case 0x1: + return decodeSveWideImmUnpredU( + size, machInst, zdn, imm); + case 0x2: + return decodeSveWideImmUnpredS( + size, machInst, zdn, sext<8>(imm)); + case 0x3: + return decodeSveWideImmUnpredU( + size, machInst, zdn, imm); + } + + return new Unknown64(machInst); + } // decodeSveIntWideImmUnpred1 + + StaticInstPtr + decodeSveIntWideImmUnpred2(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + uint64_t imm = bits(machInst, 12, 5); + uint8_t size = bits(machInst, 23, 22); + + if (bits(machInst, 18, 16) == 0x0) { + return decodeSveWideImmUnpredU( + size, machInst, zdn, sext<8>(imm)); + } + + return new Unknown64(machInst); + } // decodeSveIntWideImmUnpred2 + + StaticInstPtr + decodeSveIntWideImmUnpred3(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + uint64_t imm = bits(machInst, 12, 5); + uint8_t sh = bits(machInst, 13); + uint8_t size = bits(machInst, 23, 22); + + if (sh) { + if (size == 0x0) { + return new Unknown64(machInst); + } + imm <<= 8; + } + + if (bits(machInst, 18, 17) == 0x0) { + if (sh) { + return decodeSveWideImmUnpredU( + size, machInst, zd, sext<16>(imm)); + } else { + return decodeSveWideImmUnpredU( + size, machInst, zd, sext<8>(imm)); + } + } + + return new Unknown64(machInst); + } // decodeSveIntWideImmUnpred3 + + StaticInstPtr + decodeSveIntWideImmUnpred4(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + uint8_t size = bits(machInst, 23, 22); + + if (bits(machInst, 18, 17) == 0x0 && size != 0x0) { + uint64_t imm = vfp_modified_imm(bits(machInst, 12, 5), + decode_fp_data_type(size)); + return decodeSveWideImmUnpredF(size, machInst, zd, imm); + } + + return new Unknown64(machInst); + } // decodeSveIntWideImmUnpred4 + + StaticInstPtr + decodeSveIntWideImmUnpred(ExtMachInst machInst) + { + switch (bits(machInst, 20, 19)) { + case 0x0: + if (bits(machInst, 18, 16) != 0x2) { + return decodeSveIntWideImmUnpred0(machInst); + } + break; + case 0x1: + if (bits(machInst, 13) == 0x0) { + return decodeSveIntWideImmUnpred1(machInst); + } + break; + case 0x2: + if (bits(machInst, 13) == 0x0) { + return decodeSveIntWideImmUnpred2(machInst); + } + break; + case 0x3: + if (bits(machInst, 16) == 0x0) { + return decodeSveIntWideImmUnpred3(machInst); + } else if (bits(machInst, 13) == 0x0) { + return decodeSveIntWideImmUnpred4(machInst); + } + break; + } + return new Unknown64(machInst); + } // decodeSveIntWideImmUnpred + + StaticInstPtr + decodeSveMultiplyAddUnpred(ExtMachInst machInst) + { + IntRegIndex zda = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + + uint8_t size = (uint8_t) bits(machInst, 23, 22); + + if (bits(machInst, 12, 11) != 0 || !(size & 0x2)) { + return new Unknown64(machInst); + } + + uint8_t usig = (uint8_t) bits(machInst, 10); + if (size & 0x1) { + if (usig) { + return new SveUdotv(machInst, + zda, zn, zm); + } else { + return new SveSdotv(machInst, + zda, zn, zm); + } + } else { + if (usig) { + return new SveUdotv(machInst, + zda, zn, zm); + } else { + return new SveSdotv(machInst, + zda, zn, zm); + } + } + + return new Unknown64(machInst); + } // decodeSveMultiplyAddUnpred + + StaticInstPtr + decodeSveMultiplyIndexed(ExtMachInst machInst) + { + IntRegIndex zda = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + + uint8_t size = (uint8_t) bits(machInst, 23, 22); + + if (bits(machInst, 12, 11) != 0 || !(size & 0x2)) { + return new Unknown64(machInst); + } + + uint8_t usig = (uint8_t) bits(machInst, 10); + if (size & 0x1) { + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 19, 16); + uint8_t i1 = (uint8_t) bits(machInst, 20); + if (usig) { + return new SveUdoti(machInst, + zda, zn, zm, i1); + } else { + return new SveSdoti(machInst, + zda, zn, zm, i1); + } + } else { + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 18, 16); + uint8_t i2 = (uint8_t) bits(machInst, 20, 19); + if (usig) { + return new SveUdoti(machInst, + zda, zn, zm, i2); + } else { + return new SveSdoti(machInst, + zda, zn, zm, i2); + } + } + return new Unknown64(machInst); + } // decodeSveMultiplyIndexed + + StaticInstPtr + decodeSveFpFastReduc(ExtMachInst machInst) + { + IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = bits(machInst, 23, 22); + + if (size == 0x0) { + return new Unknown64(machInst); + } + + switch (bits(machInst, 18, 16)) { + case 0x0: + return decodeSveUnaryPredF(size, machInst, vd, zn, pg); + case 0x4: + return decodeSveUnaryPredF(size, machInst, vd, zn, pg); + case 0x5: + return decodeSveUnaryPredF(size, machInst, vd, zn, pg); + case 0x6: + return decodeSveUnaryPredF(size, machInst, vd, zn, pg); + case 0x7: + return decodeSveUnaryPredF(size, machInst, vd, zn, pg); + } + + return new Unknown64(machInst); + } // decodeSveFpFastReduc + + StaticInstPtr + decodeSveFpUnaryUnpred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + + uint8_t size = (uint8_t) bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + uint8_t opc = (uint8_t) bits(machInst, 18, 16); + + switch (opc) { + case 0x6: + return decodeSveUnaryUnpredF( + size, machInst, zd, zn); + case 0x7: + return decodeSveUnaryUnpredF( + size, machInst, zd, zn); + } + return new Unknown64(machInst); + } // decodeSveFpUnaryUnpred + + StaticInstPtr + decodeSveFpCmpZero(ExtMachInst machInst) + { + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + uint8_t opc = (bits(machInst, 17, 16) << 1) | bits(machInst, 4); + + switch (opc) { + case 0x0: + return decodeSveCmpImmF( + size, machInst, pd, zn, 0x0, pg); + case 0x1: + return decodeSveCmpImmF( + size, machInst, pd, zn, 0x0, pg); + case 0x2: + return decodeSveCmpImmF( + size, machInst, pd, zn, 0x0, pg); + case 0x3: + return decodeSveCmpImmF( + size, machInst, pd, zn, 0x0, pg); + case 0x4: + return decodeSveCmpImmF( + size, machInst, pd, zn, 0x0, pg); + case 0x6: + return decodeSveCmpImmF( + size, machInst, pd, zn, 0x0, pg); + } + return new Unknown64(machInst); + } // decodeSveFpCmpZero + + StaticInstPtr + decodeSveFpAccumReduc(ExtMachInst machInst) + { + uint8_t opc = bits(machInst, 18, 16); + uint8_t size = bits(machInst, 23, 22); + if (opc != 0 || size == 0) { + return new Unknown64(machInst); + } + + IntRegIndex vdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + return decodeSveUnaryPredF(size, machInst, vdn, zm, pg); + } // decodeSveFpAccumReduc + + StaticInstPtr + decodeSveFpArithUnpred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + + uint8_t size = bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + uint8_t opc = (uint8_t) bits(machInst, 12, 10); + + switch (opc) { + case 0x0: + return decodeSveBinUnpredF( + size, machInst, zd, zn, zm); + case 0x1: + return decodeSveBinUnpredF( + size, machInst, zd, zn, zm); + case 0x2: + return decodeSveBinUnpredF( + size, machInst, zd, zn, zm); + case 0x3: + return decodeSveBinUnpredF( + size, machInst, zd, zn, zm); + case 0x6: + return decodeSveBinUnpredF( + size, machInst, zd, zn, zm); + case 0x7: + return decodeSveBinUnpredF( + size, machInst, zd, zn, zm); + } + return new Unknown64(machInst); + } // decodeSveFpArithUnpred + + StaticInstPtr + decodeSveFpArithPred0(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = (uint8_t) bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + uint8_t opc = (uint8_t) bits(machInst, 19, 16); + + switch (opc) { + case 0x0: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x1: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x2: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x3: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x4: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x5: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x6: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x7: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x8: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0x9: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0xa: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0xc: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + case 0xd: + return decodeSveBinDestrPredF( + size, machInst, zdn, zm, pg); + } + return new Unknown64(machInst); + } // decodeSveFpArithPred0 + + StaticInstPtr + decodeSveFpTrigMAddCoeff(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + uint8_t imm = (uint8_t) bits(machInst, 18, 16); + + uint8_t size = (uint8_t) bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + + return decodeSveTerImmUnpredF(size, machInst, zdn, zm, imm); + } // decodeSveFpTrigMAddCoeff + + StaticInstPtr + decodeSveFpArithImmPred(ExtMachInst machInst) + { + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + uint64_t imm; + + uint8_t size = (uint8_t) bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + + uint8_t opc = (uint8_t) bits(machInst, 18, 16); + + switch (opc) { + case 0x0: + imm = sveExpandFpImmAddSub((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + case 0x1: + imm = sveExpandFpImmAddSub((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + case 0x2: + imm = sveExpandFpImmMul((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + case 0x3: + imm = sveExpandFpImmAddSub((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + case 0x4: + imm = sveExpandFpImmMaxMin((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + case 0x5: + imm = sveExpandFpImmMaxMin((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + case 0x6: + imm = sveExpandFpImmMaxMin((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + case 0x7: + imm = sveExpandFpImmMaxMin((uint8_t) bits(machInst, 5), size); + return decodeSveBinImmPredF( + size, machInst, zdn, imm, pg); + } + return new Unknown64(machInst); + } // decodeSveFpArithImmPred + + StaticInstPtr + decodeSveFpArithPred(ExtMachInst machInst) + { + if (bits(machInst, 20) == 0) { + return decodeSveFpArithPred0(machInst); + } else if (bits(machInst, 19) == 0) { + return decodeSveFpTrigMAddCoeff(machInst); + } else { + return decodeSveFpArithImmPred(machInst); + } + } // decodeSveFpArithPred + + StaticInstPtr + decodeSveFpUnaryPred(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = (uint8_t) bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + + uint8_t b20_19 = bits(machInst, 20, 19); + switch (b20_19) { + case 0x0: + { + if (bits(machInst, 18, 16) == 0x5) { + return new Unknown64(machInst); + } + // SVE floating-point round to integral value + uint8_t opc = (uint8_t) bits(machInst, 18, 16); + switch (opc) { + case 0x0: + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + case 0x1: + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + case 0x2: + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + case 0x3: + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + case 0x4: + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + case 0x6: + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + case 0x7: + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + } + } + break; + case 0x1: + { + // SVE floating-point unary operations (predicated) + uint8_t b18_16 = bits(machInst, 18, 16); + switch (b18_16) { + case 0x0: + if (size == 0x2) { + return new SveFcvtNarrow( + machInst, zd, zn, pg); + } else if (size == 0x3) { + return new SveFcvtNarrow( + machInst, zd, zn, pg); + } + break; + case 0x1: + if (size == 0x2) { + return new SveFcvtWiden( + machInst, zd, zn, pg); + } else if (size == 0x3) { + return new SveFcvtWiden( + machInst, zd, zn, pg); + } + break; + case 0x2: + if (size == 0x3) { + return new SveFcvtNarrow( + machInst, zd, zn, pg); + } + break; + case 0x3: + if (size == 0x3) { + return new SveFcvtWiden( + machInst, zd, zn, pg); + } + break; + case 0x4: + if (size != 0x0) { + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + } + break; + case 0x5: + if (size != 0x0) { + return decodeSveUnaryPredF( + size, machInst, zd, zn, pg); + } + break; + } + } + break; + case 0x2: + { + // SVE integer convert to floating-point + uint8_t opc = (size << 3) | bits(machInst, 18, 16); + switch (opc) { + case 0xa: + return new SveScvtfNarrow( + machInst, zd, zn, pg); + case 0xb: + return new SveUcvtfNarrow( + machInst, zd, zn, pg); + case 0xc: + return new SveScvtfNarrow( + machInst, zd, zn, pg); + case 0xd: + return new SveUcvtfNarrow( + machInst, zd, zn, pg); + case 0xe: + return new SveScvtfNarrow( + machInst, zd, zn, pg); + case 0xf: + return new SveUcvtfNarrow( + machInst, zd, zn, pg); + case 0x14: + return new SveScvtfNarrow( + machInst, zd, zn, pg); + case 0x15: + return new SveUcvtfNarrow( + machInst, zd, zn, pg); + case 0x18: + return new SveScvtfWiden( + machInst, zd, zn, pg); + case 0x19: + return new SveUcvtfWiden( + machInst, zd, zn, pg); + case 0x1c: + return new SveScvtfNarrow( + machInst, zd, zn, pg); + case 0x1d: + return new SveUcvtfNarrow( + machInst, zd, zn, pg); + case 0x1e: + return new SveScvtfNarrow( + machInst, zd, zn, pg); + case 0x1f: + return new SveUcvtfNarrow( + machInst, zd, zn, pg); + } + } + break; + case 0x3: + { + // SVE floating-point convert to integer + uint8_t opc = (size << 3) | bits(machInst, 18, 16); + switch (opc) { + case 0xa: + return new SveFcvtzsNarrow( + machInst, zd, zn, pg); + case 0xb: + return new SveFcvtzuNarrow( + machInst, zd, zn, pg); + case 0xc: + return new SveFcvtzsWiden( + machInst, zd, zn, pg); + case 0xd: + return new SveFcvtzuWiden( + machInst, zd, zn, pg); + case 0xe: + return new SveFcvtzsWiden( + machInst, zd, zn, pg); + case 0xf: + return new SveFcvtzuWiden( + machInst, zd, zn, pg); + case 0x14: + return new SveFcvtzsNarrow( + machInst, zd, zn, pg); + case 0x15: + return new SveFcvtzuNarrow( + machInst, zd, zn, pg); + case 0x18: + return new SveFcvtzsNarrow( + machInst, zd, zn, pg); + case 0x19: + return new SveFcvtzuNarrow( + machInst, zd, zn, pg); + case 0x1c: + return new SveFcvtzsWiden( + machInst, zd, zn, pg); + case 0x1d: + return new SveFcvtzuWiden( + machInst, zd, zn, pg); + case 0x1e: + return new SveFcvtzsNarrow( + machInst, zd, zn, pg); + case 0x1f: + return new SveFcvtzuNarrow( + machInst, zd, zn, pg); + } + } + break; + } + return new Unknown64(machInst); + } // decodeSveFpUnaryPred + + StaticInstPtr + decodeSveFpCmpVec(ExtMachInst machInst) + { + IntRegIndex pd = (IntRegIndex) (uint8_t) bits(machInst, 3, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + uint8_t opc = (bits(machInst, 15) << 2) | + (bits(machInst, 13) << 1) | + bits(machInst, 4); + + switch (opc) { + case 0x0: + return decodeSveCmpF(size, machInst, pd, zn, zm, pg); + case 0x1: + return decodeSveCmpF(size, machInst, pd, zn, zm, pg); + case 0x2: + return decodeSveCmpF(size, machInst, pd, zn, zm, pg); + case 0x3: + return decodeSveCmpF(size, machInst, pd, zn, zm, pg); + case 0x4: + return decodeSveCmpF(size, machInst, pd, zn, zm, pg); + case 0x5: + return decodeSveCmpF(size, machInst, pd, zn, zm, pg); + case 0x7: + return decodeSveCmpF(size, machInst, pd, zn, zm, pg); + } + return new Unknown64(machInst); + } // decodeSveFpCmpVec + + StaticInstPtr + decodeSveFpFusedMulAdd(ExtMachInst machInst) + { + IntRegIndex zda = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + + uint8_t size = bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + uint8_t opc = bits(machInst, 15, 13); + + switch (opc) { + case 0x0: + return decodeSveTerPredF( + size, machInst, zda, zn, zm, pg); + case 0x1: + return decodeSveTerPredF( + size, machInst, zda, zn, zm, pg); + case 0x2: + return decodeSveTerPredF( + size, machInst, zda, zn, zm, pg); + case 0x3: + return decodeSveTerPredF( + size, machInst, zda, zn, zm, pg); + case 0x4: + return decodeSveTerPredF( + size, machInst, zda /* zdn */, zm /* za */, zn, pg); + case 0x5: + return decodeSveTerPredF( + size, machInst, zda /* zdn */, zm /* za */, zn, pg); + case 0x6: + return decodeSveTerPredF( + size, machInst, zda /* zdn */, zm /* za */, zn, pg); + case 0x7: + return decodeSveTerPredF( + size, machInst, zda /* zdn */, zm /* za */, zn, pg); + } + return new Unknown64(machInst); + } // decodeSveFpFusedMulAdd + + StaticInstPtr + decodeSveFpCplxAdd(ExtMachInst machInst) + { + uint8_t size = bits(machInst, 23, 22); + uint8_t rot = bits(machInst, 16) << 1 | 0x01; + IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + switch (size) { + case 1: + return new SveFcadd(machInst, + zdn, zdn, zm, pg, rot); + case 2: + return new SveFcadd(machInst, + zdn, zdn, zm, pg, rot); + case 3: + return new SveFcadd(machInst, + zdn, zdn, zm, pg, rot); + } + return new Unknown64(machInst); + } + + StaticInstPtr + decodeSveFpCplxMulAddVec(ExtMachInst machInst) + { + uint8_t size = bits(machInst, 23, 22); + if (size == 0) { + return new Unknown64(machInst); + } + + IntRegIndex zda = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10); + IntRegIndex zm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); + uint8_t rot = bits(machInst, 14, 13); + switch (size) { + case 1: + return new SveFcmlav(machInst, + zda, zn, zm, pg, rot); + case 2: + return new SveFcmlav(machInst, + zda, zn, zm, pg, rot); + case 3: + return new SveFcmlav(machInst, + zda, zn, zm, pg, rot); + } + + return new Unknown64(machInst); + } // decodeSveFpCplxMulAddVec + + StaticInstPtr + decodeSveFpCplxMulAddIndexed(ExtMachInst machInst) + { + uint8_t size = bits(machInst, 23, 22); + if (size < 2) { + return new Unknown64(machInst); + } + + IntRegIndex zda = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + IntRegIndex zm; + uint8_t rot = bits(machInst, 11, 10); + uint8_t imm; + + switch (size) { + case 2: + zm = (IntRegIndex) (uint8_t) bits(machInst, 18, 16); + imm = bits(machInst, 20, 19); + return new SveFcmlai(machInst, + zda, zn, zm, rot, imm); + case 3: + zm = (IntRegIndex) (uint8_t) bits(machInst, 19, 16); + imm = bits(machInst, 20); + return new SveFcmlai(machInst, + zda, zn, zm, rot, imm); + } + return new Unknown64(machInst); + } // decodeSveFpCplxMulAddIndexed + + StaticInstPtr + decodeSveFpMulIndexed(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + + uint8_t size = bits(machInst, 23, 22); + switch (size) { + case 0x0: + case 0x1: + return new SveFmulIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 18, 16), + bits(machInst, 20, 19) | (bits(machInst, 22) << 2)); + case 0x2: + return new SveFmulIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 18, 16), + bits(machInst, 20, 19)); + case 0x3: + return new SveFmulIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 19, 16), + bits(machInst, 20)); + default: + return new Unknown64(machInst); + } + + } // decodeSveFpMulIndexed + + StaticInstPtr + decodeSveFpMulAddIndexed(ExtMachInst machInst) + { + IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); + IntRegIndex zn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); + const uint8_t op = bits(machInst, 10); + + uint8_t size = bits(machInst, 23, 22); + switch (size) { + case 0x0: + case 0x1: + if (op) { + return new SveFmlsIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 18, 16), + bits(machInst, 20, 19) | (bits(machInst, 22) << 2)); + } else { + return new SveFmlaIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 18, 16), + bits(machInst, 20, 19) | (bits(machInst, 22) << 2)); + } + case 0x2: + if (op) { + return new SveFmlsIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 18, 16), + bits(machInst, 20, 19)); + } else { + return new SveFmlaIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 18, 16), + bits(machInst, 20, 19)); + } + case 0x3: + if (op) { + return new SveFmlsIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 19, 16), + bits(machInst, 20)); + } else { + return new SveFmlaIdx( + machInst, zd, zn, + (IntRegIndex) (uint8_t) bits(machInst, 19, 16), + bits(machInst, 20)); + } + default: + return new Unknown64(machInst); + } + } // decodeSveFpMulAddIndexed + + StaticInstPtr + decodeSveMemGather32(ExtMachInst machInst) + { + return new Unknown64(machInst); + } // decodeSveMemGather32 + + StaticInstPtr + decodeSveMemContigLoad(ExtMachInst machInst) + { + return new Unknown64(machInst); + } // decodeSveMemContigLoad + + StaticInstPtr + decodeSveMemGather64(ExtMachInst machInst) + { + return new Unknown64(machInst); + } // decodeSveMemGather64 + + StaticInstPtr + decodeSveMemStore(ExtMachInst machInst) + { + return new Unknown64(machInst); + } // decodeSveMemStore + +} // namespace Aarch64 +}}; diff --git a/src/arch/arm/isa/formats/sve_top_level.isa b/src/arch/arm/isa/formats/sve_top_level.isa new file mode 100644 index 000000000..f4f1ab531 --- /dev/null +++ b/src/arch/arm/isa/formats/sve_top_level.isa @@ -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 +}}; diff --git a/src/arch/arm/isa/includes.isa b/src/arch/arm/isa/includes.isa index 37578f6ce..b89a67432 100644 --- a/src/arch/arm/isa/includes.isa +++ b/src/arch/arm/isa/includes.isa @@ -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 #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" diff --git a/src/arch/arm/isa/insts/fp64.isa b/src/arch/arm/isa/insts/fp64.isa index 6c0c6b808..26803e7e5 100644 --- a/src/arch/arm/isa/insts/fp64.isa +++ b/src/arch/arm/isa/insts/fp64.isa @@ -44,6 +44,11 @@ let {{ decoder_output = "" exec_output = "" + zeroSveVecRegUpperPartCode = ''' + TheISA::ISA::zeroSveVecRegUpperPart(%s, + ArmStaticInst::getCurSveVecLen(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) diff --git a/src/arch/arm/isa/insts/insts.isa b/src/arch/arm/isa/insts/insts.isa index 007d99ff2..623657efc 100644 --- a/src/arch/arm/isa/insts/insts.isa +++ b/src/arch/arm/isa/insts/insts.isa @@ -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" diff --git a/src/arch/arm/isa/insts/ldr64.isa b/src/arch/arm/isa/insts/ldr64.isa index 54e50d73e..fe7eaf0f8 100644 --- a/src/arch/arm/isa/insts/ldr64.isa +++ b/src/arch/arm/isa/insts/ldr64.isa @@ -179,10 +179,16 @@ let {{ def emit(self): self.buildEACode() + accEpilogCode = None # Code that actually handles the access if self.flavor in ("dprefetch", "iprefetch", "mprefetch"): accCode = 'uint64_t temp M5_VAR_USED = Mem%s;' elif self.flavor == "fp": + accEpilogCode = ''' + TheISA::ISA::zeroSveVecRegUpperPart(AA64FpDest, + ArmStaticInst::getCurSveVecLen( + 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( + xc->tcBase())); + TheISA::ISA::zeroSveVecRegUpperPart(AA64FpDest2, + ArmStaticInst::getCurSveVecLen( + 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 diff --git a/src/arch/arm/isa/insts/mem.isa b/src/arch/arm/isa/insts/mem.isa index 7323b02c9..5510c6c72 100644 --- a/src/arch/arm/isa/insts/mem.isa +++ b/src/arch/arm/isa/insts/mem.isa @@ -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) + \ diff --git a/src/arch/arm/isa/insts/neon64.isa b/src/arch/arm/isa/insts/neon64.isa index 855952d9e..2e0ec4495 100644 --- a/src/arch/arm/isa/insts/neon64.isa +++ b/src/arch/arm/isa/insts/neon64.isa @@ -48,6 +48,11 @@ let {{ floatTypes = ("uint16_t", "uint32_t", "uint64_t") smallFloatTypes = ("uint32_t",) + zeroSveVecRegUpperPartCode = ''' + TheISA::ISA::zeroSveVecRegUpperPart(%s, + ArmStaticInst::getCurSveVecLen(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: diff --git a/src/arch/arm/isa/insts/neon64_mem.isa b/src/arch/arm/isa/insts/neon64_mem.isa index 4511ad105..8f53369e9 100644 --- a/src/arch/arm/isa/insts/neon64_mem.isa +++ b/src/arch/arm/isa/insts/neon64_mem.isa @@ -44,6 +44,11 @@ let {{ decoder_output = '' exec_output = '' + zeroSveVecRegUpperPartCode = ''' + TheISA::ISA::zeroSveVecRegUpperPart(%s, + ArmStaticInst::getCurSveVecLen(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', diff --git a/src/arch/arm/isa/insts/sve.isa b/src/arch/arm/isa/insts/sve.isa new file mode 100644 index 000000000..b1b946f63 --- /dev/null +++ b/src/arch/arm/isa/insts/sve.isa @@ -0,0 +1,4798 @@ +// 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 Definition of SVE instructions. + +output header {{ + + // Decodes unary, constructive, predicated (merging) SVE instructions, + // handling signed and unsigned variants. + template