arch-arm: Add support for the SVE CLAST[A|B] (vectors) instructions
Change-Id: I5ce54832ac19054b0cacc4887eac8707d1f46cbd
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 d16c47e..6074ce0 100644
--- a/src/arch/arm/insts/sve.cc
+++ b/src/arch/arm/insts/sve.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited
+ * Copyright (c) 2017-2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -547,17 +547,23 @@
}
std::string
-SveScalarSelectOp::generateDisassembly(Addr pc,
+SveSelectOp::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, "", false);
- printIntReg(ss, dest, scalar_width);
+ if (scalar)
+ printIntReg(ss, dest, scalar_width);
+ else
+ printVecReg(ss, dest, true);
ccprintf(ss, ", ");
printPredReg(ss, gp);
if (conditional) {
ccprintf(ss, ", ");
- printIntReg(ss, dest, scalar_width);
+ if (scalar)
+ printIntReg(ss, dest, scalar_width);
+ else
+ printVecReg(ss, dest, true);
}
ccprintf(ss, ", ");
printVecReg(ss, op1, true);
diff --git a/src/arch/arm/insts/sve.hh b/src/arch/arm/insts/sve.hh
index 3344e8c..9062b4f 100644
--- a/src/arch/arm/insts/sve.hh
+++ b/src/arch/arm/insts/sve.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited
+ * Copyright (c) 2017-2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -569,20 +569,22 @@
};
/// Scalar element select SVE instruction.
-class SveScalarSelectOp : public ArmStaticInst {
+class SveSelectOp : public ArmStaticInst {
protected:
IntRegIndex dest;
IntRegIndex op1;
IntRegIndex gp;
bool conditional;
+ bool scalar;
size_t scalar_width;
- SveScalarSelectOp(const char* mnem, ExtMachInst _machInst,
+ SveSelectOp(const char* mnem, ExtMachInst _machInst,
OpClass __opClass, IntRegIndex _dest,
IntRegIndex _op1, IntRegIndex _gp,
- bool _conditional) :
+ bool _conditional, bool _scalar) :
ArmStaticInst(mnem, _machInst, __opClass),
- dest(_dest), op1(_op1), gp(_gp), conditional(_conditional)
+ dest(_dest), op1(_op1), gp(_gp), conditional(_conditional),
+ scalar(_scalar)
{}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
diff --git a/src/arch/arm/isa/formats/sve_2nd_level.isa b/src/arch/arm/isa/formats/sve_2nd_level.isa
index 2276cd6..8ba83d9 100644
--- a/src/arch/arm/isa/formats/sve_2nd_level.isa
+++ b/src/arch/arm/isa/formats/sve_2nd_level.isa
@@ -1185,7 +1185,6 @@
break;
case 0xC:
if (!b13) {
- // sve_int_perm_splice
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);
@@ -1219,12 +1218,25 @@
break;
case 0x4:
if (!b13) {
- // sve_int_perm_clast_zz
+ 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<SveClastav>(size,
+ machInst, zdn, zm, pg);
+ } else {
+ return decodeSveUnaryPredU<SveClastbv>(size,
+ machInst, zdn, zm, pg);
+ }
}
break;
case 0x5:
if (!b13) {
// sve_int_perm_clast_vz
+ // uint8_t AB = bits(machInst, 16);
+ // uint8_t size = bits(machInst, 23, 22);
}
break;
case 0x8:
@@ -1245,7 +1257,6 @@
break;
}
if (bits(machInst, 20, 18) == 0x1 && !b13) {
- // sve_int_perm_rev
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);
diff --git a/src/arch/arm/isa/insts/sve.isa b/src/arch/arm/isa/insts/sve.isa
index 0182da3..a782af5 100644
--- a/src/arch/arm/isa/insts/sve.isa
+++ b/src/arch/arm/isa/insts/sve.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 ARM Limited
+// Copyright (c) 2017-2018 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -2267,7 +2267,7 @@
# Generate definitions for scalar select instructions
def sveSelectInst(name, Name, opClass, types, op, isCond,
- decoder = 'Generic'):
+ destType = DestType.Scalar, decoder = 'Generic'):
global header_output, exec_output, decoders
code = sveEnabledCheckCode + '''
unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
@@ -2278,13 +2278,34 @@
break;
}
}
- Element destElem;
- %(op)s
- XDest = destElem;'''%{'op': op}
- iop = InstObjParams(name, 'Sve' + Name, 'SveScalarSelectOp',
+ '''
+ if isCond:
+ code += '''
+ if (last >= 0) {'''
+ code += '''
+ Element destElem;
+ %(op)s'''%{'op': op}
+ if destType == DestType.Vector:
+ code += '''
+ for (unsigned i = 0; i < eCount; ++i)
+ AA64FpDest_x[i] = destElem;'''
+ elif destType == DestType.Scalar:
+ code += '''
+ XDest = destElem;'''
+ if isCond:
+ code += '''
+ }'''
+ if destType == DestType.Scalar:
+ code += ''' else {
+ XDest = (Element) XDest;
+ }'''
+ iop = InstObjParams(name, 'Sve' + Name, 'SveSelectOp',
{'code': code, 'op_class': opClass,
- 'isCond': 'true' if isCond else 'false'}, [])
- header_output += SveScalarSelectOpDeclare.subst(iop)
+ 'isCond': 'true' if isCond else 'false',
+ 'isScalar': 'true' if destType == DestType.Scalar
+ else 'false'},
+ [])
+ header_output += SveSelectOpDeclare.subst(iop)
exec_output += SveOpExecute.subst(iop)
for type in types:
substDict = {'targs' : type,
@@ -2812,25 +2833,23 @@
isFlagSetting = True, whenBrk = Break.Before)
# CLASTA (scalar)
clastaCode = '''
- if (last < 0) {
- destElem = XDest;
- } else {
- last++;
- if (last >= eCount)
- last = 0;
- destElem = AA64FpOp1_x[last];
- }'''
+ last++;
+ if (last >= eCount)
+ last = 0;
+ destElem = AA64FpOp1_x[last];'''
sveSelectInst('clasta', 'Clasta', 'SimdAluOp', unsignedTypes, clastaCode,
- isCond = True)
+ isCond = True, destType = DestType.Scalar)
+ # CLASTA (vector)
+ sveSelectInst('clasta', 'Clastav', 'SimdAluOp', unsignedTypes, clastaCode,
+ isCond = True, destType = DestType.Vector)
# CLASTB (scalar)
clastbCode = '''
- if (last < 0) {
- destElem = XDest;
- } else {
- destElem = AA64FpOp1_x[last];
- }'''
+ destElem = AA64FpOp1_x[last];'''
sveSelectInst('clastb', 'Clastb', 'SimdAluOp', unsignedTypes, clastbCode,
- isCond = True)
+ isCond = True, destType = DestType.Scalar)
+ # CLASTB (vector)
+ sveSelectInst('clastb', 'Clastbv', 'SimdAluOp', unsignedTypes, clastbCode,
+ isCond = True, destType = DestType.Vector)
# CLS
clsCode = '''
destElem = 0;
diff --git a/src/arch/arm/isa/templates/sve.isa b/src/arch/arm/isa/templates/sve.isa
index 6626b70..27fcf7e 100644
--- a/src/arch/arm/isa/templates/sve.isa
+++ b/src/arch/arm/isa/templates/sve.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 ARM Limited
+// Copyright (c) 2018 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -719,7 +719,7 @@
};
}};
-def template SveScalarSelectOpDeclare {{
+def template SveSelectOpDeclare {{
template <class _Element>
class %(class_name)s : public %(base_class)s
{
@@ -730,7 +730,7 @@
%(class_name)s(ExtMachInst machInst, IntRegIndex _dest,
IntRegIndex _op1, IntRegIndex _gp)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest,
- _op1, _gp, %(isCond)s)
+ _op1, _gp, %(isCond)s, %(isScalar)s)
{
%(constructor)s;
scalar_width = (sizeof(Element) == 8) ? 64 : 32;