ARM assembly parsing and encoding for VMOV immediate.
authorJim Grosbach <grosbach@apple.com>
Mon, 3 Oct 2011 23:38:36 +0000 (23:38 +0000)
committerJim Grosbach <grosbach@apple.com>
Mon, 3 Oct 2011 23:38:36 +0000 (23:38 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141046 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstrVFP.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/simple-fp-encoding.s

index 7115db581fe02b26cbb171c376016cde3404e7a7..e746cf20d032a32a2484896399363759a16c3971 100644 (file)
@@ -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<f32>,
                  PatLeaf<(f32 fpimm), [{
       return ARM_AM::getFP32Imm(N->getValueAPF()) != -1;
@@ -40,6 +46,7 @@ def vfp_f32imm : Operand<f32>,
       return CurDAG->getTargetConstant(enc, MVT::i32);
     }]>> {
   let PrintMethod = "printFPImmOperand";
+  let ParserMatchClass = FPImmOperand;
 }
 
 def vfp_f64imm : Operand<f64>,
@@ -51,6 +58,7 @@ def vfp_f64imm : Operand<f64>,
       return CurDAG->getTargetConstant(enc, MVT::i32);
     }]>> {
   let PrintMethod = "printFPImmOperand";
+  let ParserMatchClass = FPImmOperand;
 }
 
 
index 81a67868049bb7d5fbb1716038b636755c203c07..56f9955cf536d9c6ccfad624564fce17bf45dd21 100644 (file)
@@ -158,6 +158,7 @@ class ARMAsmParser : public MCTargetAsmParser {
   OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
   OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
   OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
+  OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
 
   // 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 << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
+       << ") >";
+    break;
   case CondCode:
     OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
     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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &Operands,
index 969cc8aa2edfd82f06f49d4177ad8ee5832e3e32..e7d452a28495f1d3f159c4222470b6e8c5f640a2 100644 (file)
 @ 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]