From 6f9a0047387e9ca5a658a90355b49b8a55db03d6 Mon Sep 17 00:00:00 2001 From: David Peixotto Date: Tue, 7 Jan 2014 18:19:23 +0000 Subject: [PATCH] Add ARM fconsts/fconstd aliases for vmov.f32/vmov.f64 This commit adds the pre-UAL aliases of fconsts and fconstd for vmov.f32 and vmov.f64. They use an InstAlias rather than a MnemonicAlias to properly support the predicate operand. We need to support encoded 8-bit constants in order to implement the pre-UAL fconsts/fconstd aliases for vmov.f32/vmov.f64, so this commit also fixes parsing of encoded floating point constants used in vmov.f32/vmov.f64 instructions. Now we can support assembly code like this: fconsts s0, #0x70 which is equivalent to vmov.f32 s0, #1.0. Most of the code was already in place to support this feature. Previously the code was trying to accept encoded 8-bit float constants for the vmov.f32/vmov.f64 instructions. It looks like the support for parsing encoded floats was lost in a refactoring in commit r148556 and we did not have any tests in place to catch it. The change in this commit is to keep the parsed value as a 32-bit float instead of a 64-bit double because that is what the isFPImm() function expects to find. There is no loss of precision by using a 32-bit float here because we are still limited to an 8-bit encoded value in the end. Additionally, we explicitly reject encoded 8-bit floats for vmovf.32/64. This is the same as the current behavior, but we now do it explicitly rather than accidently. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198697 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrVFP.td | 11 ++++++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 19 ++++++---- test/MC/ARM/fconst.s | 22 ++++++++++++ test/MC/ARM/fp-const-errors.s | 22 ++++++++++++ test/MC/ARM/simple-fp-encoding.s | 43 +++++++++++++++++++++++ 5 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 test/MC/ARM/fconst.s create mode 100644 test/MC/ARM/fp-const-errors.s diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index a5494819d16..1d7802a2c7f 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -1762,3 +1762,14 @@ def : VFP2InstAlias<"vmov${p}.f64 $Dn, $Rt, $Rt2", // VMOVD does. def : VFP2InstAlias<"vmov${p} $Sd, $Sm", (VMOVS SPR:$Sd, SPR:$Sm, pred:$p)>; + +// FCONSTD/FCONSTS alias for vmov.f64/vmov.f32 +// These aliases provide added functionality over vmov.f instructions by +// allowing users to write assembly containing encoded floating point constants +// (e.g. #0x70 vs #1.0). Without these alises there is no way for the +// assembler to accept encoded fp constants (but the equivalent fp-literal is +// accepted directly by vmovf). +def : VFP3InstAlias<"fconstd${p} $Dd, $val", + (FCONSTD DPR:$Dd, vfp_f64imm:$val, pred:$p)>; +def : VFP3InstAlias<"fconsts${p} $Sd, $val", + (FCONSTS SPR:$Sd, vfp_f32imm:$val, pred:$p)>; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 1145fe70400..47f7eca09a1 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4620,8 +4620,12 @@ parseFPImm(SmallVectorImpl &Operands) { // for these: // vmov.i{8|16|32|64} , #imm ARMOperand *TyOp = static_cast(Operands[2]); - if (!TyOp->isToken() || (TyOp->getToken() != ".f32" && - TyOp->getToken() != ".f64")) + bool isVmovf = TyOp->isToken() && (TyOp->getToken() == ".f32" || + TyOp->getToken() == ".f64"); + ARMOperand *Mnemonic = static_cast(Operands[0]); + bool isFconst = Mnemonic->isToken() && (Mnemonic->getToken() == "fconstd" || + Mnemonic->getToken() == "fconsts"); + if (!(isVmovf || isFconst)) return MatchOperand_NoMatch; Parser.Lex(); // Eat '#' or '$'. @@ -4634,7 +4638,7 @@ parseFPImm(SmallVectorImpl &Operands) { } const AsmToken &Tok = Parser.getTok(); SMLoc Loc = Tok.getLoc(); - if (Tok.is(AsmToken::Real)) { + if (Tok.is(AsmToken::Real) && isVmovf) { APFloat RealVal(APFloat::IEEEsingle, Tok.getString()); uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); // If we had a '-' in front, toggle the sign bit. @@ -4647,15 +4651,16 @@ parseFPImm(SmallVectorImpl &Operands) { } // Also handle plain integers. Instructions which allow floating point // immediates also allow a raw encoded 8-bit value. - if (Tok.is(AsmToken::Integer)) { + if (Tok.is(AsmToken::Integer) && isFconst) { int64_t Val = Tok.getIntVal(); Parser.Lex(); // Eat the token. if (Val > 255 || Val < 0) { Error(Loc, "encoded floating point value out of range"); return MatchOperand_ParseFail; } - double RealVal = ARM_AM::getFPImmFloat(Val); - Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue(); + float RealVal = ARM_AM::getFPImmFloat(Val); + Val = APFloat(RealVal).bitcastToAPInt().getZExtValue(); + Operands.push_back(ARMOperand::CreateImm( MCConstantExpr::Create(Val, getContext()), S, Parser.getTok().getLoc())); @@ -4910,7 +4915,7 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" || Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" || Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" || - Mnemonic == "vfms" || Mnemonic == "vfnms" || + Mnemonic == "vfms" || Mnemonic == "vfnms" || Mnemonic == "fconsts" || (Mnemonic == "movs" && isThumb()))) { Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1); CarrySetting = true; diff --git a/test/MC/ARM/fconst.s b/test/MC/ARM/fconst.s new file mode 100644 index 00000000000..e2c1b3918ff --- /dev/null +++ b/test/MC/ARM/fconst.s @@ -0,0 +1,22 @@ +@ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7-apple-darwin -show-encoding < %s | FileCheck %s + +@ fconstd/fconsts aliases + fconsts s4, #0x0 + fconsts s4, #0x70 + fconstd d3, #0x0 + fconstd d3, #0x70 + + fconstsne s5, #0x1 + fconstsgt s5, #0x20 + fconstdlt d2, #0x3 + fconstdge d2, #0x40 + +@ CHECK: vmov.f32 s4, #2.000000e+00 @ encoding: [0x00,0x2a,0xb0,0xee] +@ CHECK: vmov.f32 s4, #1.000000e+00 @ encoding: [0x00,0x2a,0xb7,0xee] +@ CHECK: vmov.f64 d3, #2.000000e+00 @ encoding: [0x00,0x3b,0xb0,0xee] +@ CHECK: vmov.f64 d3, #1.000000e+00 @ encoding: [0x00,0x3b,0xb7,0xee] + +@ CHECK: vmovne.f32 s5, #2.125000e+00 @ encoding: [0x01,0x2a,0xf0,0x1e] +@ CHECK: vmovgt.f32 s5, #8.000000e+00 @ encoding: [0x00,0x2a,0xf2,0xce] +@ CHECK: vmovlt.f64 d2, #2.375000e+00 @ encoding: [0x03,0x2b,0xb0,0xbe] +@ CHECK: vmovge.f64 d2, #1.250000e-01 @ encoding: [0x00,0x2b,0xb4,0xae] diff --git a/test/MC/ARM/fp-const-errors.s b/test/MC/ARM/fp-const-errors.s new file mode 100644 index 00000000000..2a68ddbe727 --- /dev/null +++ b/test/MC/ARM/fp-const-errors.s @@ -0,0 +1,22 @@ +@ RUN: not llvm-mc -mcpu=cortex-a8 -triple armv7-none-linux-gnueabi < %s 2>&1 | FileCheck %s + +@ Test for floating point constants that are out of the 8-bit encoded value range +vmov.f32 s2, #32.0 +@ CHECK: error: invalid operand for instruction + +vmov.f64 d2, #32.0 +@ CHECK: error: invalid operand for instruction + +@ Test that vmov.f instructions do not accept an 8-bit encoded float as an operand +vmov.f32 s1, #0x70 +@ CHECK: error: invalid floating point immediate + +vmov.f64 d2, #0x70 +@ CHECK: error: invalid floating point immediate + +@ Test that fconst instructions do not accept a float constant as an operand +fconsts s1, #1.0 +@ CHECK: error: invalid floating point immediate + +fconstd d2, #1.0 +@ CHECK: error: invalid floating point immediate diff --git a/test/MC/ARM/simple-fp-encoding.s b/test/MC/ARM/simple-fp-encoding.s index d840e9cd798..539dd2c4d97 100644 --- a/test/MC/ARM/simple-fp-encoding.s +++ b/test/MC/ARM/simple-fp-encoding.s @@ -395,3 +395,46 @@ @ CHECK: vmov.i32 d4, #0x0 @ encoding: [0x10,0x40,0x80,0xf2] @ CHECK: vmov.i32 d4, #0x42000000 @ encoding: [0x12,0x46,0x84,0xf2] + +@ Test encoding of floating point constants for vmov functions +@ vfp3 + vmov.f32 s5, #1.0 + vmov.f32 s5, #0.125 + vmov.f32 s5, #-1.875 + vmov.f32 s5, #-0.59375 + + vmov.f64 d6, #1.0 + vmov.f64 d6, #0.125 + vmov.f64 d6, #-1.875 + vmov.f64 d6, #-0.59375 + +@ neon + vmov.f32 d7, #1.0 + vmov.f32 d7, #0.125 + vmov.f32 d7, #-1.875 + vmov.f32 d7, #-0.59375 + + vmov.f32 q8, #1.0 + vmov.f32 q8, #0.125 + vmov.f32 q8, #-1.875 + vmov.f32 q8, #-0.59375 + +@ CHECK: vmov.f32 s5, #1.000000e+00 @ encoding: [0x00,0x2a,0xf7,0xee] +@ CHECK: vmov.f32 s5, #1.250000e-01 @ encoding: [0x00,0x2a,0xf4,0xee] +@ CHECK: vmov.f32 s5, #-1.875000e+00 @ encoding: [0x0e,0x2a,0xff,0xee] +@ CHECK: vmov.f32 s5, #-5.937500e-01 @ encoding: [0x03,0x2a,0xfe,0xee] + +@ CHECK: vmov.f64 d6, #1.000000e+00 @ encoding: [0x00,0x6b,0xb7,0xee] +@ CHECK: vmov.f64 d6, #1.250000e-01 @ encoding: [0x00,0x6b,0xb4,0xee] +@ CHECK: vmov.f64 d6, #-1.875000e+00 @ encoding: [0x0e,0x6b,0xbf,0xee] +@ CHECK: vmov.f64 d6, #-5.937500e-01 @ encoding: [0x03,0x6b,0xbe,0xee] + +@ CHECK: vmov.f32 d7, #1.000000e+00 @ encoding: [0x10,0x7f,0x87,0xf2] +@ CHECK: vmov.f32 d7, #1.250000e-01 @ encoding: [0x10,0x7f,0x84,0xf2] +@ CHECK: vmov.f32 d7, #-1.875000e+00 @ encoding: [0x1e,0x7f,0x87,0xf3] +@ CHECK: vmov.f32 d7, #-5.937500e-01 @ encoding: [0x13,0x7f,0x86,0xf3] + +@ CHECK: vmov.f32 q8, #1.000000e+00 @ encoding: [0x50,0x0f,0xc7,0xf2] +@ CHECK: vmov.f32 q8, #1.250000e-01 @ encoding: [0x50,0x0f,0xc4,0xf2] +@ CHECK: vmov.f32 q8, #-1.875000e+00 @ encoding: [0x5e,0x0f,0xc7,0xf3] +@ CHECK: vmov.f32 q8, #-5.937500e-01 @ encoding: [0x53,0x0f,0xc6,0xf3] -- 2.34.1