arch-arm,cpu: Add four Arm SVE2 int instructions

This changeset adds ARM SVE2 integer instructions
- ADCLB, ADCLT, SBCLB, SBCLT
- Decoding logic as per sve encoding of Version: 2023-03

Change-Id: I1bd3fe24b33677baa0b6da3c1dd7423f2b13b2c6
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70137
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
Prajwal Hegde
2023-04-27 14:38:36 -05:00
committed by Prajwal Rathnakar Hegde
parent 2579bacf06
commit dfa3c073cf
6 changed files with 179 additions and 4 deletions

View File

@@ -435,6 +435,20 @@ SveTerPredOp::generateDisassembly(
return ss.str();
}
std::string
SveTerUnpredOp::generateDisassembly(
Addr pc, const loader::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
SveTerImmUnpredOp::generateDisassembly(
Addr pc, const loader::SymbolTable *symtab) const

View File

@@ -498,6 +498,23 @@ class SveTerPredOp : public ArmStaticInst
Addr pc, const loader::SymbolTable *symtab) const override;
};
///SVE2 Accumulate instructions
class SveTerUnpredOp : public ArmStaticInst
{
protected:
RegIndex dest, op1, op2;
SveTerUnpredOp(const char* mnem, ExtMachInst _machInst,
OpClass __opClass, RegIndex _dest,
RegIndex _op1, RegIndex _op2) :
ArmStaticInst(mnem, _machInst, __opClass),
dest(_dest), op1(_op1), op2(_op2)
{}
std::string generateDisassembly(
Addr pc, const loader::SymbolTable *symtab) const override;
};
/// Ternary with immediate, destructive, unpredicated SVE instruction.
class SveTerImmUnpredOp : public ArmStaticInst
{

View File

@@ -2283,6 +2283,52 @@ namespace Aarch64
return new Unknown64(machInst);
} // decodeSveMultiplyIndexed
StaticInstPtr
decodeSve2ArithCarry(ExtMachInst machInst)
{
RegIndex zn = (RegIndex) (uint8_t) bits(machInst, 9, 5);
RegIndex zm = (RegIndex) (uint8_t) bits(machInst, 20, 16);
RegIndex zda = (RegIndex) (uint8_t) bits(machInst, 4, 0);
uint8_t size = bits(machInst, 23, 22);
if (size & 0x2) {
if (bits(machInst, 10)){
return decodeSveTerUnpred<Sve2Sbclt>(
size, machInst, zda, zn, zm);
} else {
return decodeSveTerUnpred<Sve2Sbclb>(
size, machInst, zda, zn, zm);
}
} else {
if (bits(machInst, 10)){
return decodeSveTerUnpred<Sve2Adclt>(
size, machInst, zda, zn, zm);
} else {
return decodeSveTerUnpred<Sve2Adclb>(
size, machInst, zda, zn, zm);
}
}
return new Unknown64(machInst);
} //decodeSve2ArithCarry
StaticInstPtr
decodeSve2Accum(ExtMachInst machInst)
{
uint8_t op0 = bits(machInst, 20, 17);
uint8_t op1 = bits(machInst, 13, 11);
if (op0 != 0 && op1 == 3) {
return new Unknown64(machInst);
}
switch (op1) {
case 2:
return decodeSve2ArithCarry(machInst);
default:
break;
}
return new Unknown64(machInst);
} //decodeSve2Accum
StaticInstPtr
decodeSveFpFastReduc(ExtMachInst machInst)
{

View File

@@ -69,6 +69,7 @@ namespace Aarch64
StaticInstPtr decodeSvePsel(ExtMachInst machInst);
StaticInstPtr decodeSveIntWideImmUnpred(ExtMachInst machInst);
StaticInstPtr decodeSveClamp(ExtMachInst machInst);
StaticInstPtr decodeSve2Accum(ExtMachInst machInst);
StaticInstPtr decodeSveMultiplyAddUnpred(ExtMachInst machInst);
StaticInstPtr decodeSveMultiplyIndexed(ExtMachInst machInst);
@@ -173,10 +174,23 @@ namespace Aarch64
break;
}
case 0x2:
if (bits(machInst, 20)) {
return decodeSveIntWideImmPred(machInst);
} else {
return decodeSveLogMaskImm(machInst);
{
if (bits(machInst, 30) == 0) {
if (bits(machInst, 20)) {
return decodeSveIntWideImmPred(machInst);
} else {
return decodeSveLogMaskImm(machInst);
}
} else {
uint8_t b_15_14 = bits(machInst, 15, 14);
switch (b_15_14) {
case 3:
return decodeSve2Accum(machInst);
default :
break;
}
}
break;
}
case 0x3:
{

View File

@@ -926,6 +926,19 @@ output header {{
}
}
// Decodes ternary, unpredicated SVE2 instructions
template <template <typename T> class Base>
StaticInstPtr
decodeSveTerUnpred(unsigned size, ExtMachInst machInst,
RegIndex dest, RegIndex op1, RegIndex op2)
{
if (bits(size, 0) == 0) {
return new Base<uint32_t>(machInst, dest, op1, op2);
} else {
return new Base<uint64_t>(machInst, dest, op1, op2);
}
}
// Decodes ternary with immediate operand, destructive, unpredicated SVE
// instructions handling floating-point variants only.
template <template <typename T> class Base>
@@ -2085,6 +2098,35 @@ let {{
'class_name' : 'Sve' + Name}
exec_output += SveOpExecDeclare.subst(substDict)
# Generates definitions for ternary SVE2 intructions (unpredicated)
def sveTerInstUnpred(name, Name, opClass, types, op,
isTop=False, isAdd=True, decoder='Generic'):
global header_output, exec_output, decoders
code = sveEnabledCheckCode + '''
unsigned const pairs = ArmStaticInst::getCurSveVecLen<Element>(
xc->tcBase()) / 2;
for (unsigned p = 0; p < pairs; p++) {
const Element& srcElem1 = AA64FpDestMerge_x[2 * p + 0];
const Element& srcElem2 = AA64FpOp1_x[%(src_top_elem)s];
int carryIn = bits(AA64FpOp2_x[2 * p + 1], 0);
Element %(op)s
int carryOut = findCarry(
sizeof(Element) * 8, res, srcElem1,
%(src_elem2)s) & 1;
AA64FpDest_x[2 * p + 0] = res;
AA64FpDest_x[2 * p + 1] = (Element)0x0 + carryOut;
}''' % {'op': op,
'src_top_elem' : '2 * p + 1' if isTop else '2 * p + 0',
'src_elem2' : 'srcElem2' if isAdd else '~(srcElem2)'}
iop = ArmInstObjParams(name, 'Sve2' + Name, 'SveTerUnpredOp',
{'code': code, 'op_class': opClass}, [])
header_output += sveTerUnpredOpDeclare.subst(iop)
exec_output += SveOpExecute.subst(iop)
for type in types:
substDict = {'targs' : type,
'class_name' : 'Sve2' + Name}
exec_output += SveOpExecDeclare.subst(substDict)
# Generates definitions for ternary SVE instructions with indexed operand
def sveTerIdxInst(name, Name, opClass, types, op, decoder='Generic'):
global header_output, exec_output, decoders
@@ -4052,6 +4094,22 @@ let {{
# MLS
mlsCode = 'destElem -= srcElem1 * srcElem2;'
sveTerInst('mls', 'Mls', 'SimdMultAccOp', signedTypes, mlsCode)
# ADCLT
adcltCode = 'res = srcElem1 + srcElem2 + carryIn;'
sveTerInstUnpred('adclt', 'Adclt', 'VectorIntegerArithOp', unsignedTypes,
adcltCode, isTop=True, isAdd=True)
# ADCLB
adclbCode = 'res = srcElem1 + srcElem2 + carryIn;'
sveTerInstUnpred('adclb', 'Adclb', 'VectorIntegerArithOp', unsignedTypes,
adclbCode, isTop=False, isAdd=True)
# SBCLT
sbcltCode = 'res = srcElem1 + ~(srcElem2) + carryIn;'
sveTerInstUnpred('sbclt', 'Sbclt', 'VectorIntegerArithOp', unsignedTypes,
sbcltCode, isTop=True, isAdd=False)
# SBCLB
sbclbCode = 'res = srcElem1 + ~(srcElem2) + carryIn;'
sveTerInstUnpred('sbclb', 'Sbclb', 'VectorIntegerArithOp', unsignedTypes,
sbclbCode, isTop=False, isAdd=False)
# MOVPRFX (predicated)
movCode = 'destElem = srcElem1;'
sveUnaryInst('movprfx', 'MovprfxPredM', 'SimdMiscOp', unsignedTypes,

View File

@@ -489,6 +489,32 @@ class %(class_name)s : public %(base_class)s
};
}};
def template sveTerUnpredOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
protected:
typedef _Element Element;
typedef _Element TPElem;
public:
// Constructor
%(class_name)s(ExtMachInst machInst, RegIndex _dest,
RegIndex _op1, RegIndex _op2) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _op2)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
Fault execute(ExecContext *, trace::InstRecord *) const override;
};
}};
def template SveTerImmUnpredOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s