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:
committed by
Prajwal Rathnakar Hegde
parent
2579bacf06
commit
dfa3c073cf
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user