From 9d39036f62674606565217a10db28171b9594bc7 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 3 Oct 2011 23:38:36 +0000 Subject: [PATCH] ARM assembly parsing and encoding for VMOV immediate. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141046 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrVFP.td | 8 +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 76 +++++++++++++++++++++++ test/MC/ARM/simple-fp-encoding.s | 14 +++-- 3 files changed, 93 insertions(+), 5 deletions(-) diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 7115db581fe..e746cf20d03 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -31,6 +31,12 @@ def arm_fmdrr : SDNode<"ARMISD::VMOVDRR", SDT_VMOVDRR>; // Operand Definitions. // +// 8-bit floating-point immediate encodings. +def FPImmOperand : AsmOperandClass { + let Name = "FPImm"; + let ParserMethod = "parseFPImm"; +} + def vfp_f32imm : Operand, PatLeaf<(f32 fpimm), [{ return ARM_AM::getFP32Imm(N->getValueAPF()) != -1; @@ -40,6 +46,7 @@ def vfp_f32imm : Operand, return CurDAG->getTargetConstant(enc, MVT::i32); }]>> { let PrintMethod = "printFPImmOperand"; + let ParserMatchClass = FPImmOperand; } def vfp_f64imm : Operand, @@ -51,6 +58,7 @@ def vfp_f64imm : Operand, return CurDAG->getTargetConstant(enc, MVT::i32); }]>> { let PrintMethod = "printFPImmOperand"; + let ParserMatchClass = FPImmOperand; } diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 81a67868049..56f9955cf53 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -158,6 +158,7 @@ class ARMAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseBitfield(SmallVectorImpl&); OperandMatchResultTy parsePostIdxReg(SmallVectorImpl&); OperandMatchResultTy parseAM3Offset(SmallVectorImpl&); + OperandMatchResultTy parseFPImm(SmallVectorImpl&); // Asm Match Converter Methods bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode, @@ -247,6 +248,7 @@ class ARMOperand : public MCParsedAsmOperand { CoprocNum, CoprocReg, Immediate, + FPImmediate, MemBarrierOpt, Memory, PostIndexRegister, @@ -305,6 +307,10 @@ class ARMOperand : public MCParsedAsmOperand { const MCExpr *Val; } Imm; + struct { + unsigned Val; // encoded 8-bit representation + } FPImm; + /// Combined record for all forms of ARM address expressions. struct { unsigned BaseRegNum; @@ -380,6 +386,9 @@ public: case Immediate: Imm = o.Imm; break; + case FPImmediate: + FPImm = o.FPImm; + break; case MemBarrierOpt: MBOpt = o.MBOpt; break; @@ -449,6 +458,11 @@ public: return Imm.Val; } + unsigned getFPImm() const { + assert(Kind == FPImmediate && "Invalid access!"); + return FPImm.Val; + } + ARM_MB::MemBOpt getMemBarrierOpt() const { assert(Kind == MemBarrierOpt && "Invalid access!"); return MBOpt.Val; @@ -471,6 +485,7 @@ public: bool isITMask() const { return Kind == ITCondMask; } bool isITCondCode() const { return Kind == CondCode; } bool isImm() const { return Kind == Immediate; } + bool isFPImm() const { return Kind == FPImmediate; } bool isImm8s4() const { if (Kind != Immediate) return false; @@ -952,6 +967,11 @@ public: addExpr(Inst, getImm()); } + void addFPImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getFPImm())); + } + void addImm8s4Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); // FIXME: We really want to scale the value here, but the LDRD/STRD @@ -1467,6 +1487,14 @@ public: return Op; } + static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) { + ARMOperand *Op = new ARMOperand(FPImmediate); + Op->FPImm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + static ARMOperand *CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm, unsigned OffsetRegNum, @@ -1529,6 +1557,10 @@ public: void ARMOperand::print(raw_ostream &OS) const { switch (Kind) { + case FPImmediate: + OS << ""; + break; case CondCode: OS << ""; break; @@ -3024,6 +3056,50 @@ bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, return false; } +/// parseFPImm - A floating point immediate expression operand. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseFPImm(SmallVectorImpl &Operands) { + SMLoc S = Parser.getTok().getLoc(); + + if (Parser.getTok().isNot(AsmToken::Hash)) + return MatchOperand_NoMatch; + Parser.Lex(); // Eat the '#'. + + // Handle negation, as that still comes through as a separate token. + bool isNegative = false; + if (Parser.getTok().is(AsmToken::Minus)) { + isNegative = true; + Parser.Lex(); + } + const AsmToken &Tok = Parser.getTok(); + if (Tok.is(AsmToken::Real)) { + APFloat RealVal(APFloat::IEEEdouble, Tok.getString()); + uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); + // If we had a '-' in front, toggle the sign bit. + IntVal ^= (uint64_t)isNegative << 63; + int Val = ARM_AM::getFP64Imm(APInt(64, IntVal)); + Parser.Lex(); // Eat the token. + if (Val == -1) { + TokError("floating point value out of range"); + return MatchOperand_ParseFail; + } + Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext())); + return MatchOperand_Success; + } + if (Tok.is(AsmToken::Integer)) { + int64_t Val = Tok.getIntVal(); + Parser.Lex(); // Eat the token. + if (Val > 255 || Val < 0) { + TokError("encoded floating point value out of range"); + return MatchOperand_ParseFail; + } + Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext())); + return MatchOperand_Success; + } + + TokError("invalid floating point immediate"); + return MatchOperand_ParseFail; +} /// Parse a arm instruction operand. For now this parses the operand regardless /// of the mnemonic. bool ARMAsmParser::parseOperand(SmallVectorImpl &Operands, diff --git a/test/MC/ARM/simple-fp-encoding.s b/test/MC/ARM/simple-fp-encoding.s index 969cc8aa2ed..e7d452a2849 100644 --- a/test/MC/ARM/simple-fp-encoding.s +++ b/test/MC/ARM/simple-fp-encoding.s @@ -141,11 +141,15 @@ @ CHECK: vmsr fpsid, r0 @ encoding: [0x10,0x0a,0xe0,0xee] vmsr fpsid, r0 -@ FIXME: vmov.f64 d16, #3.000000e+00 @ encoding: [0x08,0x0b,0xf0,0xee] -@ vmov.f64 d16, #3.000000e+00 - -@ FIXME: vmov.f32 s0, #3.000000e+00 @ encoding: [0x08,0x0a,0xb0,0xee] -@ vmov.f32 s0, #3.000000e+00 + vmov.f64 d16, #3.000000e+00 + vmov.f32 s0, #3.000000e+00 + vmov.f64 d16, #-3.000000e+00 + vmov.f32 s0, #-3.000000e+00 + +@ CHECK: vmov.f64 d16, #3.000000e+00 @ encoding: [0x08,0x0b,0xf0,0xee] +@ CHECK: vmov.f32 s0, #3.000000e+00 @ encoding: [0x08,0x0a,0xb0,0xee] +@ CHECK: vmov.f64 d16, #-3.000000e+00 @ encoding: [0x08,0x0b,0xf8,0xee] +@ CHECK: vmov.f32 s0, #-3.000000e+00 @ encoding: [0x08,0x0a,0xb8,0xee] @ CHECK: vmov s0, r0 @ encoding: [0x10,0x0a,0x00,0xee] @ CHECK: vmov s1, r1 @ encoding: [0x90,0x1a,0x00,0xee] -- 2.34.1