diff options
author | Giacomo Gabrielli <giacomo.gabrielli@arm.com> | 2018-10-16 16:09:02 +0100 |
---|---|---|
committer | Giacomo Gabrielli <giacomo.gabrielli@arm.com> | 2019-03-14 10:42:27 +0000 |
commit | c4cc3145cd1eeed236b5cd3f7b2424bc0761878e (patch) | |
tree | b38eab6f5f389dfc53c2cf74275a83bacd2e9b18 /src/arch/arm/insts/sve.cc | |
parent | 91195ae7f637d1d4879cc3bf0860147333846e75 (diff) | |
download | gem5-c4cc3145cd1eeed236b5cd3f7b2424bc0761878e.tar.xz |
arch-arm,cpu: Add initial support for Arm SVE
This changeset adds initial support for the Arm Scalable Vector Extension
(SVE) by implementing:
- support for most data-processing instructions (no loads/stores yet);
- basic system-level support.
Additional authors:
- Javier Setoain <javier.setoain@arm.com>
- Gabor Dozsa <gabor.dozsa@arm.com>
- Giacomo Travaglini <giacomo.travaglini@arm.com>
Thanks to Pau Cabre for his contribution of bugfixes.
Change-Id: I1808b5ff55b401777eeb9b99c9a1129e0d527709
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/13515
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'src/arch/arm/insts/sve.cc')
-rw-r--r-- | src/arch/arm/insts/sve.cc | 957 |
1 files changed, 957 insertions, 0 deletions
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 |