summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitch Hayenga <mitch.hayenga@arm.com>2016-10-13 19:22:10 +0100
committerMitch Hayenga <mitch.hayenga@arm.com>2016-10-13 19:22:10 +0100
commitbd0c2d5b0bf512aa5c172fe5676e151913e5e97d (patch)
tree3aa61e0e7070664b605c216dff51f8d4d6847d8f
parent68fdccb30bd85cd99823fb411ec7ae67112062d7 (diff)
downloadgem5-bd0c2d5b0bf512aa5c172fe5676e151913e5e97d.tar.xz
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>
-rw-r--r--src/arch/arm/insts/vfp.cc15
-rw-r--r--src/arch/arm/insts/vfp.hh21
-rw-r--r--src/arch/arm/isa/formats/fp.isa98
-rw-r--r--src/arch/arm/isa/insts/fp.isa62
-rw-r--r--src/arch/arm/isa/templates/vfp.isa27
5 files changed, 220 insertions, 3 deletions
diff --git a/src/arch/arm/insts/vfp.cc b/src/arch/arm/insts/vfp.cc
index 03fdc83fa..c76f97ca6 100644
--- a/src/arch/arm/insts/vfp.cc
+++ b/src/arch/arm/insts/vfp.cc
@@ -123,6 +123,21 @@ FpRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
}
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
FpRegRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh
index f28ab9e1f..de0c62161 100644
--- a/src/arch/arm/insts/vfp.hh
+++ b/src/arch/arm/insts/vfp.hh
@@ -979,6 +979,27 @@ class FpRegRegRegOp : public FpOp
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
{
protected:
diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa
index ccd4589a3..82d351e6e 100644
--- a/src/arch/arm/isa/formats/fp.isa
+++ b/src/arch/arm/isa/formats/fp.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2010-2011 ARM Limited
+// Copyright (c) 2010-2011,2016 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -1950,7 +1950,101 @@ let {{
const uint32_t b = bits(machInst, 6, 5);
if ((machInst.thumb == 1 && bits(machInst, 28) == 1) ||
(machInst.thumb == 0 && machInst.condCode == 0xf)) {
- return new Unknown(machInst);
+ // 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);
+ }
}
if (l == 0 && c == 0) {
if (a == 0) {
diff --git a/src/arch/arm/isa/insts/fp.isa b/src/arch/arm/isa/insts/fp.isa
index 34dff5139..0f10a05af 100644
--- a/src/arch/arm/isa/insts/fp.isa
+++ b/src/arch/arm/isa/insts/fp.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2010-2013 ARM Limited
+// Copyright (c) 2010-2013,2016 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -642,6 +642,26 @@ let {{
"-FpOp1", "-dbl(FpOp1P0_uw, FpOp1P1_uw)")
buildSimpleUnaryFpOp("vabs", "Vabs", "FpRegRegOp", "SimdFloatMiscOp",
"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 {{
@@ -1408,6 +1428,46 @@ let {{
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 {{
+
+ header_output = ""
+ decoder_output = ""
+ exec_output = ""
+
vcvtFpSFixedSCode = vfpEnabledCheckCode + '''
FPSCR fpscr = (FPSCR) FpscrExc;
vfpFlushToZero(fpscr, FpOp1);
diff --git a/src/arch/arm/isa/templates/vfp.isa b/src/arch/arm/isa/templates/vfp.isa
index 1c945cddc..d94f4652a 100644
--- a/src/arch/arm/isa/templates/vfp.isa
+++ b/src/arch/arm/isa/templates/vfp.isa
@@ -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;
+ }
+}};