arch-arm: Add support for SVE RDFFR(S), WRFFR and SETFFR Change-Id: I615723d82752c444e513d8917c2eeba9cdf75514 Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
diff --git a/src/arch/arm/insts/sve.cc b/src/arch/arm/insts/sve.cc index fb7218a..4d1bb6d 100644 --- a/src/arch/arm/insts/sve.cc +++ b/src/arch/arm/insts/sve.cc
@@ -617,7 +617,7 @@ } std::string -SvePredUnaryOp::generateDisassembly(Addr pc, +SvePredUnaryWImplicitSrcOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; @@ -627,6 +627,38 @@ } std::string +SvePredUnaryWImplicitSrcPredOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss, "", false); + printReg(ss, RegId(PredRegClass, dest)); + ccprintf(ss, ", "); + printReg(ss, RegId(PredRegClass, gp)); + ccprintf(ss, "/z, "); + return ss.str(); +} + +std::string +SvePredUnaryWImplicitDstOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + std::stringstream ss; + printMnemonic(ss, "", false); + printReg(ss, RegId(PredRegClass, 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 {
diff --git a/src/arch/arm/insts/sve.hh b/src/arch/arm/insts/sve.hh index b49a6d2..2417211 100644 --- a/src/arch/arm/insts/sve.hh +++ b/src/arch/arm/insts/sve.hh
@@ -646,19 +646,57 @@ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; -/// SVE unary predicate instructions -class SvePredUnaryOp : public ArmStaticInst { +/// SVE unary predicate instructions with implicit source operand +class SvePredUnaryWImplicitSrcOp : public ArmStaticInst { protected: IntRegIndex dest; - SvePredUnaryOp(const char* mnem, ExtMachInst _machInst, OpClass __opClass, - 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:
diff --git a/src/arch/arm/isa/formats/sve_2nd_level.isa b/src/arch/arm/isa/formats/sve_2nd_level.isa index b80b65d..b32ad38 100644 --- a/src/arch/arm/isa/formats/sve_2nd_level.isa +++ b/src/arch/arm/isa/formats/sve_2nd_level.isa
@@ -1,4 +1,3 @@ -// Copyright (c) 2017 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -1624,13 +1623,26 @@ StaticInstPtr decodeSveReadPredFromFFRPred(ExtMachInst machInst) { - return new Unknown64(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) { - return new Unknown64(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 @@ -1807,11 +1819,11 @@ bits(machInst, 4, 0) == 0x0) { uint8_t opc = bits(machInst, 18, 16); if (opc == 0x0) { - // TODO: WRFFR - return new NopInst(machInst); + IntRegIndex pn = (IntRegIndex)(uint8_t) + bits(machInst, 8, 5); + return new SveWrffr(machInst, pn); } else if (opc == 0x4 && bits(machInst, 8, 5) == 0x0) { - // TODO: SETFFR - return new NopInst(machInst); + return new SveSetffr(machInst); } } break;
diff --git a/src/arch/arm/isa/insts/sve.isa b/src/arch/arm/isa/insts/sve.isa index 9aaffc9..b5db2a9 100644 --- a/src/arch/arm/isa/insts/sve.isa +++ b/src/arch/arm/isa/insts/sve.isa
@@ -2459,18 +2459,48 @@ substDict = {'targs': type, 'class_name': 'Sve' + Name} exec_output += SveOpExecDeclare.subst(substDict) - # Generate definition for SVE PFALSE instruction - def svePfalseInst(name, Name, opClass, decoder = 'Generic'): + # Generate definition for unary SVE predicate instructions with implicit + # source operand (PFALSE, RDFFR(S)) + def svePredUnaryWImplicitSrcInst(name, Name, opClass, op, + predType=PredType.NONE, isFlagSetting=False, decoder='Generic'): global header_output, exec_output, decoders - code = sveEnabledCheckCode + ''' - PDest_ub[0] = 0; - destPred.reset();''' + code = sveEnabledCheckCode + op + if isFlagSetting: + code += ''' + CondCodesNZ = (destPred.firstActive(GpOp, eCount) << 1) | + destPred.noneActive(GpOp, eCount); + CondCodesC = !destPred.lastActive(GpOp, eCount); + CondCodesV = 0;''' extraPrologCode = ''' - auto& destPred = PDest;''' - iop = InstObjParams(name, 'Sve' + Name, 'SvePredUnaryOp', + auto& destPred M5_VAR_USED = PDest;''' + baseClass = ('SvePredUnaryWImplicitSrcOp' if predType == PredType.NONE + else 'SvePredUnaryWImplicitSrcPredOp') + iop = InstObjParams(name, 'Sve' + Name, baseClass, {'code': code, 'op_class': opClass}, []) iop.snippets['code'] = extraPrologCode + iop.snippets['code'] - header_output += SvePredicateUnaryOpDeclare.subst(iop) + if predType == PredType.NONE: + header_output += SvePredUnaryOpWImplicitSrcDeclare.subst(iop) + else: + header_output += SvePredUnaryPredOpWImplicitSrcDeclare.subst(iop) + exec_output += SveNonTemplatedOpExecute.subst(iop) + + # Generate definition for SVE instructions writing to the FFR (SETFFR, + # WRFFR) + def svePredWriteFfrInst(name, Name, opClass, op, isSetFfr, + decoder='Generic'): + global header_output, exec_output, decoders + code = sveEnabledCheckCode + op + extraPrologCode = ''' + auto& destPred M5_VAR_USED = Ffr;''' + baseClass = ('SveWImplicitSrcDstOp' if isSetFfr + else 'SvePredUnaryWImplicitDstOp') + iop = InstObjParams(name, 'Sve' + Name, baseClass, + {'code': code, 'op_class': opClass}, []) + iop.snippets['code'] = extraPrologCode + iop.snippets['code'] + if isSetFfr: + header_output += SveOpWImplicitSrcDstDeclare.subst(iop) + else: + header_output += SvePredUnaryOpWImplicitDstDeclare.subst(iop) exec_output += SveNonTemplatedOpExecute.subst(iop) # Generate definition for SVE Ext instruction @@ -3509,7 +3539,12 @@ sveAssocReducInst('orv', 'Orv', 'SimdReduceAluOp', unsignedTypes, orvCode, '0') # PFALSE - svePfalseInst('pfalse', 'Pfalse', 'SimdPredAluOp') + pfalseCode = ''' + PDest_ub[0] = 0; + destPred.reset(); + ''' + svePredUnaryWImplicitSrcInst('pfalse', 'Pfalse', 'SimdPredAluOp', + pfalseCode) # PFIRST svePFirstInst('pfirst', 'Pfirst', 'SimdPredAluOp') # PNEXT @@ -3531,6 +3566,30 @@ destElem = reverseBits(srcElem1);''' sveUnaryInst('rbit', 'Rbit', 'SimdAluOp', unsignedTypes, rbitCode, predType=PredType.MERGE, srcRegType=SrcRegType.Vector) + # RDFFR, RDFFRS (predicated) + rdffrPredCode = ''' + unsigned eCount = ArmStaticInst::getCurSveVecLen<uint8_t>( + xc->tcBase()); + for (unsigned i = 0; i < eCount; i++) { + if (GpOp_ub[i]) { + PDest_ub[i] = Ffr_ub[i]; + } else { + PDest_ub[i] = false; + } + }''' + svePredUnaryWImplicitSrcInst('rdffr', 'RdffrPred', 'SimdPredAluOp', + rdffrPredCode, PredType.ZERO, False) + svePredUnaryWImplicitSrcInst('rdffrs', 'RdffrsPred', 'SimdPredAluOp', + rdffrPredCode, PredType.ZERO, True) + # RDFFR (unpredicated) + rdffrUnpredCode = ''' + unsigned eCount = ArmStaticInst::getCurSveVecLen<uint8_t>( + xc->tcBase()); + for (unsigned i = 0; i < eCount; i++) { + PDest_ub[i] = Ffr_ub[i]; + }''' + svePredUnaryWImplicitSrcInst('rdffr', 'RdffrUnpred', 'SimdPredAluOp', + rdffrUnpredCode) # RDVL rdvlCode = sveEnabledCheckCode + ''' unsigned eCount = ArmStaticInst::getCurSveVecLen<uint8_t>( @@ -3618,6 +3677,11 @@ # SEL (vectors) sveBinInst('sel', 'Sel', 'SimdAluOp', unsignedTypes, selCode, PredType.SELECT, False) + # SETFFR + setffrCode = ''' + Ffr_ub[0] = true; + destPred.set();''' + svePredWriteFfrInst('setffr', 'Setffr', 'SimdPredAluOp', setffrCode, True) # SMAX (immediate) maxCode = 'destElem = (srcElem1 > srcElem2) ? srcElem1 : srcElem2;' sveWideImmInst('smax', 'SmaxImm', 'SimdCmpOp', signedTypes, maxCode) @@ -4169,6 +4233,14 @@ # WHILELT (64-bit) sveWhileInst('whilelt', 'Whilelt64', 'SimdCmpOp', signedTypes, whileLTCode, SrcSize.Src64bit) + # WRFFR + wrffrCode = ''' + unsigned eCount = ArmStaticInst::getCurSveVecLen<uint8_t>( + xc->tcBase()); + for (unsigned i = 0; i < eCount; i++) { + Ffr_ub[i] = POp1_ub[i]; + }''' + svePredWriteFfrInst('wrffr', 'Wrffr', 'SimdPredAluOp', wrffrCode, False) # ZIP1, ZIP2 (predicates) zipPredIterCode = ''' constexpr unsigned sz = sizeof(Element);
diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa index f4880fb..bc4d057 100644 --- a/src/arch/arm/isa/operands.isa +++ b/src/arch/arm/isa/operands.isa
@@ -531,6 +531,7 @@ 'POp1': predReg('op1'), 'POp2': predReg('op2'), 'PDest': predReg('dest'), + 'Ffr': predReg('PREDREG_FFR'), #Abstracted control reg operands 'MiscDest': cntrlReg('dest'),
diff --git a/src/arch/arm/isa/templates/sve.isa b/src/arch/arm/isa/templates/sve.isa index a27bfdc..6edcb8b 100644 --- a/src/arch/arm/isa/templates/sve.isa +++ b/src/arch/arm/isa/templates/sve.isa
@@ -778,7 +778,7 @@ }; }}; -def template SvePredicateUnaryOpDeclare {{ +def template SvePredUnaryOpWImplicitSrcDeclare {{ class %(class_name)s : public %(base_class)s { public: @@ -792,6 +792,48 @@ }; }}; +def template SvePredUnaryPredOpWImplicitSrcDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + %(class_name)s(ExtMachInst machInst, IntRegIndex _dest, IntRegIndex _gp) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest, _gp) + { + %(constructor)s; + } + + %(BasicExecDeclare)s +}; +}}; + +def template SvePredUnaryOpWImplicitDstDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + %(class_name)s(ExtMachInst machInst, IntRegIndex _op1) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _op1) + { + %(constructor)s; + } + + %(BasicExecDeclare)s +}; +}}; + +def template SveOpWImplicitSrcDstDeclare {{ +class %(class_name)s : public %(base_class)s +{ + public: + %(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } + + %(BasicExecDeclare)s +}; +}}; + def template SveWideningUnaryOpExecute {{ template <class SElement, class DElement> Fault %(class_name)s<SElement, DElement>::execute(CPU_EXEC_CONTEXT *xc,
diff --git a/src/arch/arm/registers.hh b/src/arch/arm/registers.hh index c23e51d..80bbfa8 100644 --- a/src/arch/arm/registers.hh +++ b/src/arch/arm/registers.hh
@@ -99,7 +99,8 @@ const int NumFloatRegs = NumFloatV8ArchRegs + NumFloatSpecialRegs; const int NumVecRegs = NumVecV8ArchRegs + NumVecSpecialRegs; const int NumCCRegs = NUM_CCREGS; -const int NumPredRegs = 16; +const int NumPredRegs = 17; // P0-P15, FFR +const int PREDREG_FFR = 16; const int NumMiscRegs = NUM_MISCREGS; #define ISA_HAS_CC_REGS
diff --git a/src/arch/generic/pred_reg.hh b/src/arch/generic/pred_reg.hh index 9c363ee..a67ba35 100644 --- a/src/arch/generic/pred_reg.hh +++ b/src/arch/generic/pred_reg.hh
@@ -94,6 +94,11 @@ typename std::enable_if<Condition, void>::type reset() { container.reset(); } + /// Reset the register to an all-true value. + template<bool Condition = !Const> + typename std::enable_if<Condition, void>::type + set() { container.set(); } + template<bool Condition = !Const> typename std::enable_if<Condition, MyClass&>::type operator=(const MyClass& that) @@ -268,6 +273,13 @@ container.fill(false); } + /// Sets the predicate register to an all-true value. + void + set() + { + container.fill(true); + } + /// Equality operator, required to compare thread contexts. template<size_t N2, bool P2> inline bool