From bd0c2d5b0bf512aa5c172fe5676e151913e5e97d Mon Sep 17 00:00:00 2001 From: Mitch Hayenga Date: Thu, 13 Oct 2016 19:22:10 +0100 Subject: [PATCH] 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 Reviewed-by: Nathanael Premillieu --- src/arch/arm/insts/vfp.cc | 15 +++++ src/arch/arm/insts/vfp.hh | 21 +++++++ src/arch/arm/isa/formats/fp.isa | 98 +++++++++++++++++++++++++++++- src/arch/arm/isa/insts/fp.isa | 62 ++++++++++++++++++- src/arch/arm/isa/templates/vfp.isa | 27 ++++++++ 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 @@ -122,6 +122,21 @@ FpRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 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 FpRegRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { 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(machInst, vd, vm, + true); + case 0x1: + return decodeVfpRegRegOp(machInst, vd, vm, + true); + case 0x2: + return decodeVfpRegRegOp(machInst, vd, vm, + true); + case 0x3: + return decodeVfpRegRegOp(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(machInst, vd, vm, + false); + case 0x1: + return decodeVfpRegRegOp(machInst, vd, vm, + false); + case 0x2: + return decodeVfpRegRegOp(machInst, vd, vm, + false); + case 0x3: + return decodeVfpRegRegOp(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(FpOp1, FPRounding_POSINF, false, fpscr)", + "fplibRoundInt(dbl(FpOp1P0_uw, FpOp1P1_uw), " \ + "FPRounding_POSINF, false, fpscr)" + ) + buildSimpleUnaryFpOp("vrintm", "VRIntM", "FpRegRegOp", "SimdFloatMiscOp", + "fplibRoundInt(FpOp1, FPRounding_NEGINF, false, fpscr)", + "fplibRoundInt(dbl(FpOp1P0_uw, FpOp1P1_uw), " \ + "FPRounding_NEGINF, false, fpscr)" + ) + buildSimpleUnaryFpOp("vrinta", "VRIntA", "FpRegRegOp", "SimdFloatMiscOp", + "fplibRoundInt(FpOp1, FPRounding_TIEAWAY, false, fpscr)", + "fplibRoundInt(dbl(FpOp1P0_uw, FpOp1P1_uw), " \ + "FPRounding_TIEAWAY, false, fpscr)" + ) + buildSimpleUnaryFpOp("vrintn", "VRIntN", "FpRegRegOp", "SimdFloatMiscOp", + "fplibRoundInt(FpOp1, FPRounding_TIEEVEN, false, fpscr)", + "fplibRoundInt(dbl(FpOp1P0_uw, FpOp1P1_uw), " \ + "FPRounding_TIEEVEN, false, fpscr)" + ) }}; let {{ @@ -1402,6 +1422,46 @@ let {{ 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 {{ header_output = "" 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; + } +}};