isa,arm: Add missing AArch32 FP instructions
This commit adds missing non-predicated, scalar floating point instructions. Specifically VRINT* floating point integer rounding instructions and VSEL* floating point conditional selects. Change-Id: I23cbd1389f151389ac8beb28a7d18d5f93d000e7 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-by: Nathanael Premillieu <nathanael.premillieu@arm.com>
This commit is contained in:
parent
68fdccb30b
commit
bd0c2d5b0b
5 changed files with 220 additions and 3 deletions
|
@ -122,6 +122,21 @@ FpRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
FpRegRegRegCondOp::generateDisassembly(Addr pc, const SymbolTable *symtab)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
printMnemonic(ss);
|
||||||
|
printCondition(ss, cond);
|
||||||
|
printReg(ss, dest + FP_Reg_Base);
|
||||||
|
ss << ", ";
|
||||||
|
printReg(ss, op1 + FP_Reg_Base);
|
||||||
|
ss << ", ";
|
||||||
|
printReg(ss, op2 + FP_Reg_Base);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
FpRegRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
FpRegRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -979,6 +979,27 @@ class FpRegRegRegOp : public FpOp
|
||||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FpRegRegRegCondOp : public FpOp
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
IntRegIndex dest;
|
||||||
|
IntRegIndex op1;
|
||||||
|
IntRegIndex op2;
|
||||||
|
ConditionCode cond;
|
||||||
|
|
||||||
|
FpRegRegRegCondOp(const char *mnem, ExtMachInst _machInst,
|
||||||
|
OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
|
||||||
|
IntRegIndex _op2, ConditionCode _cond,
|
||||||
|
VfpMicroMode mode = VfpNotAMicroop) :
|
||||||
|
FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2),
|
||||||
|
cond(_cond)
|
||||||
|
{
|
||||||
|
setVfpMicroFlags(mode, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||||
|
};
|
||||||
|
|
||||||
class FpRegRegRegRegOp : public FpOp
|
class FpRegRegRegRegOp : public FpOp
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- mode:c++ -*-
|
// -*- mode:c++ -*-
|
||||||
|
|
||||||
// Copyright (c) 2010-2011 ARM Limited
|
// Copyright (c) 2010-2011,2016 ARM Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// The license below extends only to copyright in the software and shall
|
// The license below extends only to copyright in the software and shall
|
||||||
|
@ -1950,8 +1950,102 @@ let {{
|
||||||
const uint32_t b = bits(machInst, 6, 5);
|
const uint32_t b = bits(machInst, 6, 5);
|
||||||
if ((machInst.thumb == 1 && bits(machInst, 28) == 1) ||
|
if ((machInst.thumb == 1 && bits(machInst, 28) == 1) ||
|
||||||
(machInst.thumb == 0 && machInst.condCode == 0xf)) {
|
(machInst.thumb == 0 && machInst.condCode == 0xf)) {
|
||||||
|
// Determine if this is backported aarch64 FP instruction
|
||||||
|
const bool b31_b24 = bits(machInst, 31, 24) == 0xFE;
|
||||||
|
const bool b23 = bits(machInst, 23);
|
||||||
|
const bool b21_b18 = bits(machInst, 21, 18) == 0xE;
|
||||||
|
const bool b11_b9 = bits(machInst, 11, 9) == 0x5;
|
||||||
|
const bool sz = bits(machInst, 8);
|
||||||
|
const bool b7_b6 = bits(machInst, 7, 6) == 0x1;
|
||||||
|
const bool b6 = bits(machInst, 6) == 0x0;
|
||||||
|
const bool b4 = bits(machInst, 4) == 0x0;
|
||||||
|
if (b31_b24 && b23 && b21_b18 && b11_b9 && b7_b6 && b4) {
|
||||||
|
// VINT* Integer Rounding Instructon
|
||||||
|
const uint32_t rm = bits(machInst, 17, 16);
|
||||||
|
|
||||||
|
if (sz) {
|
||||||
|
const IntRegIndex vd =
|
||||||
|
(IntRegIndex)((bits(machInst, 22) << 5) |
|
||||||
|
(bits(machInst, 15, 12) << 1));
|
||||||
|
const IntRegIndex vm =
|
||||||
|
(IntRegIndex)((bits(machInst, 5) << 5) |
|
||||||
|
(bits(machInst, 3, 0) << 1));
|
||||||
|
switch(rm) {
|
||||||
|
case 0x0:
|
||||||
|
return decodeVfpRegRegOp<VRIntAD>(machInst, vd, vm,
|
||||||
|
true);
|
||||||
|
case 0x1:
|
||||||
|
return decodeVfpRegRegOp<VRIntND>(machInst, vd, vm,
|
||||||
|
true);
|
||||||
|
case 0x2:
|
||||||
|
return decodeVfpRegRegOp<VRIntPD>(machInst, vd, vm,
|
||||||
|
true);
|
||||||
|
case 0x3:
|
||||||
|
return decodeVfpRegRegOp<VRIntMD>(machInst, vd, vm,
|
||||||
|
true);
|
||||||
|
default: return new Unknown(machInst);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const IntRegIndex vd =
|
||||||
|
(IntRegIndex)(bits(machInst, 22) |
|
||||||
|
(bits(machInst, 15, 12) << 1));
|
||||||
|
const IntRegIndex vm =
|
||||||
|
(IntRegIndex)(bits(machInst, 5) |
|
||||||
|
(bits(machInst, 3, 0) << 1));
|
||||||
|
switch(rm) {
|
||||||
|
case 0x0:
|
||||||
|
return decodeVfpRegRegOp<VRIntAS>(machInst, vd, vm,
|
||||||
|
false);
|
||||||
|
case 0x1:
|
||||||
|
return decodeVfpRegRegOp<VRIntNS>(machInst, vd, vm,
|
||||||
|
false);
|
||||||
|
case 0x2:
|
||||||
|
return decodeVfpRegRegOp<VRIntPS>(machInst, vd, vm,
|
||||||
|
false);
|
||||||
|
case 0x3:
|
||||||
|
return decodeVfpRegRegOp<VRIntMS>(machInst, vd, vm,
|
||||||
|
false);
|
||||||
|
default: return new Unknown(machInst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (b31_b24 && !b23 && b11_b9 && b6 && b4){
|
||||||
|
// VSEL* floating point conditional select
|
||||||
|
|
||||||
|
ConditionCode cond;
|
||||||
|
switch(bits(machInst, 21, 20)) {
|
||||||
|
case 0x0: cond = COND_EQ; break;
|
||||||
|
case 0x1: cond = COND_VS; break;
|
||||||
|
case 0x2: cond = COND_GE; break;
|
||||||
|
case 0x3: cond = COND_GT; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sz) {
|
||||||
|
const IntRegIndex vd =
|
||||||
|
(IntRegIndex)((bits(machInst, 22) << 5) |
|
||||||
|
(bits(machInst, 15, 12) << 1));
|
||||||
|
const IntRegIndex vm =
|
||||||
|
(IntRegIndex)((bits(machInst, 5) << 5) |
|
||||||
|
(bits(machInst, 3, 0) << 1));
|
||||||
|
const IntRegIndex vn =
|
||||||
|
(IntRegIndex)((bits(machInst, 7) << 5) |
|
||||||
|
(bits(machInst, 19, 16) << 1));
|
||||||
|
return new VselD(machInst, vd, vn, vm, cond);
|
||||||
|
} else {
|
||||||
|
const IntRegIndex vd =
|
||||||
|
(IntRegIndex)(bits(machInst, 22) |
|
||||||
|
(bits(machInst, 15, 12) << 1));
|
||||||
|
const IntRegIndex vm =
|
||||||
|
(IntRegIndex)(bits(machInst, 5) |
|
||||||
|
(bits(machInst, 3, 0) << 1));
|
||||||
|
const IntRegIndex vn =
|
||||||
|
(IntRegIndex)((bits(machInst, 19, 16) << 1) |
|
||||||
|
bits(machInst, 7));
|
||||||
|
return new VselS(machInst, vd, vn, vm, cond);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return new Unknown(machInst);
|
return new Unknown(machInst);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (l == 0 && c == 0) {
|
if (l == 0 && c == 0) {
|
||||||
if (a == 0) {
|
if (a == 0) {
|
||||||
const uint32_t vn = (bits(machInst, 19, 16) << 1) |
|
const uint32_t vn = (bits(machInst, 19, 16) << 1) |
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- mode:c++ -*-
|
// -*- mode:c++ -*-
|
||||||
|
|
||||||
// Copyright (c) 2010-2013 ARM Limited
|
// Copyright (c) 2010-2013,2016 ARM Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// The license below extends only to copyright in the software and shall
|
// The license below extends only to copyright in the software and shall
|
||||||
|
@ -642,6 +642,26 @@ let {{
|
||||||
"-FpOp1", "-dbl(FpOp1P0_uw, FpOp1P1_uw)")
|
"-FpOp1", "-dbl(FpOp1P0_uw, FpOp1P1_uw)")
|
||||||
buildSimpleUnaryFpOp("vabs", "Vabs", "FpRegRegOp", "SimdFloatMiscOp",
|
buildSimpleUnaryFpOp("vabs", "Vabs", "FpRegRegOp", "SimdFloatMiscOp",
|
||||||
"fabsf(FpOp1)", "fabs(dbl(FpOp1P0_uw, FpOp1P1_uw))")
|
"fabsf(FpOp1)", "fabs(dbl(FpOp1P0_uw, FpOp1P1_uw))")
|
||||||
|
buildSimpleUnaryFpOp("vrintp", "VRIntP", "FpRegRegOp", "SimdFloatMiscOp",
|
||||||
|
"fplibRoundInt<uint32_t>(FpOp1, FPRounding_POSINF, false, fpscr)",
|
||||||
|
"fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
|
||||||
|
"FPRounding_POSINF, false, fpscr)"
|
||||||
|
)
|
||||||
|
buildSimpleUnaryFpOp("vrintm", "VRIntM", "FpRegRegOp", "SimdFloatMiscOp",
|
||||||
|
"fplibRoundInt<uint32_t>(FpOp1, FPRounding_NEGINF, false, fpscr)",
|
||||||
|
"fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
|
||||||
|
"FPRounding_NEGINF, false, fpscr)"
|
||||||
|
)
|
||||||
|
buildSimpleUnaryFpOp("vrinta", "VRIntA", "FpRegRegOp", "SimdFloatMiscOp",
|
||||||
|
"fplibRoundInt<uint32_t>(FpOp1, FPRounding_TIEAWAY, false, fpscr)",
|
||||||
|
"fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
|
||||||
|
"FPRounding_TIEAWAY, false, fpscr)"
|
||||||
|
)
|
||||||
|
buildSimpleUnaryFpOp("vrintn", "VRIntN", "FpRegRegOp", "SimdFloatMiscOp",
|
||||||
|
"fplibRoundInt<uint32_t>(FpOp1, FPRounding_TIEEVEN, false, fpscr)",
|
||||||
|
"fplibRoundInt<uint64_t>(dbl(FpOp1P0_uw, FpOp1P1_uw), " \
|
||||||
|
"FPRounding_TIEEVEN, false, fpscr)"
|
||||||
|
)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
|
@ -1402,6 +1422,46 @@ let {{
|
||||||
exec_output += PredOpExecute.subst(vcmpeZeroDIop);
|
exec_output += PredOpExecute.subst(vcmpeZeroDIop);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
let {{
|
||||||
|
|
||||||
|
header_output = ""
|
||||||
|
decoder_output = ""
|
||||||
|
exec_output = ""
|
||||||
|
|
||||||
|
vselSCode = vfpEnabledCheckCode + '''
|
||||||
|
if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, cond)) {
|
||||||
|
FpDest = FpOp1;
|
||||||
|
} else {
|
||||||
|
FpDest = FpOp2;
|
||||||
|
} '''
|
||||||
|
|
||||||
|
vselSIop = InstObjParams("vsels", "VselS", "FpRegRegRegCondOp",
|
||||||
|
{ "code" : vselSCode,
|
||||||
|
"predicate_test" : predicateTest,
|
||||||
|
"op_class" : "SimdFloatCmpOp" }, [] )
|
||||||
|
header_output += FpRegRegRegCondOpDeclare.subst(vselSIop);
|
||||||
|
decoder_output += FpRegRegRegCondOpConstructor.subst(vselSIop);
|
||||||
|
exec_output += PredOpExecute.subst(vselSIop);
|
||||||
|
|
||||||
|
vselDCode = vfpEnabledCheckCode + '''
|
||||||
|
if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, cond)) {
|
||||||
|
FpDestP0_uw = FpOp1P0_uw;
|
||||||
|
FpDestP1_uw = FpOp1P1_uw;
|
||||||
|
} else {
|
||||||
|
FpDestP0_uw = FpOp2P0_uw;
|
||||||
|
FpDestP1_uw = FpOp2P1_uw;
|
||||||
|
} '''
|
||||||
|
|
||||||
|
vselDIop = InstObjParams("vseld", "VselD", "FpRegRegRegCondOp",
|
||||||
|
{ "code" : vselDCode,
|
||||||
|
"predicate_test" : predicateTest,
|
||||||
|
"op_class" : "SimdFloatCmpOp" }, [] )
|
||||||
|
header_output += FpRegRegRegCondOpDeclare.subst(vselDIop);
|
||||||
|
decoder_output += FpRegRegRegCondOpConstructor.subst(vselDIop);
|
||||||
|
exec_output += PredOpExecute.subst(vselDIop);
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
|
|
||||||
header_output = ""
|
header_output = ""
|
||||||
|
|
|
@ -210,3 +210,30 @@ def template FpRegRegRegOpConstructor {{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
def template FpRegRegRegCondOpDeclare {{
|
||||||
|
class %(class_name)s : public %(base_class)s
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
%(class_name)s(ExtMachInst machInst,
|
||||||
|
IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
|
||||||
|
ConditionCode _cond,
|
||||||
|
VfpMicroMode mode = VfpNotAMicroop);
|
||||||
|
%(BasicExecDeclare)s
|
||||||
|
};
|
||||||
|
}};
|
||||||
|
|
||||||
|
def template FpRegRegRegCondOpConstructor {{
|
||||||
|
%(class_name)s::%(class_name)s(ExtMachInst machInst,
|
||||||
|
IntRegIndex _dest,
|
||||||
|
IntRegIndex _op1,
|
||||||
|
IntRegIndex _op2,
|
||||||
|
ConditionCode _cond,
|
||||||
|
VfpMicroMode mode)
|
||||||
|
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
|
||||||
|
_dest, _op1, _op2, _cond, mode)
|
||||||
|
{
|
||||||
|
%(constructor)s;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
Loading…
Reference in a new issue