ARM parsing and encoding of SBFX and UBFX.
authorJim Grosbach <grosbach@apple.com>
Wed, 27 Jul 2011 21:09:25 +0000 (21:09 +0000)
committerJim Grosbach <grosbach@apple.com>
Wed, 27 Jul 2011 21:09:25 +0000 (21:09 +0000)
Encode the width operand as it encodes in the instruction, which simplifies
the disassembler and the encoder, by using the imm1_32 operand def. Add a
diagnostic for the context-sensitive constraint that the width must be in
the range [1,32-lsb].

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136264 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
test/MC/ARM/basic-arm-instructions.s
test/MC/ARM/diagnostics.s

index 6c10a431d9b6599e3fe0eeb87fbaff5f8b1aa624..e0720b3da8fcf2b4ceb7d15793d2ab954fa3f1d3 100644 (file)
@@ -215,8 +215,6 @@ namespace {
       const { return 0; }
     unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
-    unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
-      const { return 0; }
     unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
     unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op)
index 928e2efa72ffa9c63301713cdc3cc532dd3b7579..74d877a27fca33e80f3a2b0aad0b9caf8eedf27b 100644 (file)
@@ -2024,7 +2024,8 @@ SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
                                 Srl_imm)) {
         assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
 
-        unsigned Width = CountTrailingOnes_32(And_imm);
+        // Note: The width operand is encoded as width-1.
+        unsigned Width = CountTrailingOnes_32(And_imm) - 1;
         unsigned LSB = Srl_imm;
         SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
         SDValue Ops[] = { N->getOperand(0).getOperand(0),
@@ -2044,7 +2045,8 @@ SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
     unsigned Srl_imm = 0;
     if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
       assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
-      unsigned Width = 32 - Srl_imm;
+      // Note: The width operand is encoded as width-1.
+      unsigned Width = 32 - Srl_imm - 1;
       int LSB = Srl_imm - Shl_imm;
       if (LSB < 0)
         return NULL;
index 4c6bace639910c18c6ec05c231f4aefe742b9d61..7e9687a7cf19f93c1d0ff56574d79d594cac98f2 100644 (file)
@@ -513,14 +513,6 @@ def imm0_31 : Operand<i32>, ImmLeaf<i32, [{
   let ParserMatchClass = Imm0_31AsmOperand;
 }
 
-/// imm0_31_m1 - Matches and prints like imm0_31, but encodes as 'value - 1'.
-def imm0_31_m1 : Operand<i32>, ImmLeaf<i32, [{
-  return Imm >= 0 && Imm < 32;
-}]> {
-  let EncoderMethod = "getImmMinusOneOpValue";
-  let DecoderMethod = "DecodeImmMinusOneOperand";
-}
-
 // imm0_65535_expr - For movt/movw - 16-bit immediate that can also reference
 // a relocatable expression.
 //
@@ -2423,7 +2415,7 @@ def UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">;
 
 
 def SBFX  : I<(outs GPR:$Rd),
-              (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width),
+              (ins GPR:$Rn, imm0_31:$lsb, imm1_32:$width),
                AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
                "sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
                Requires<[IsARM, HasV6T2]> {
@@ -2440,7 +2432,7 @@ def SBFX  : I<(outs GPR:$Rd),
 }
 
 def UBFX  : I<(outs GPR:$Rd),
-              (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width),
+              (ins GPR:$Rn, imm0_31:$lsb, imm1_32:$width),
                AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
                "ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
                Requires<[IsARM, HasV6T2]> {
index 7e516b2ce7ca9aaae360ef783c09244eddfa1eca..b4ca828b26b1ba2541ef7e139449bb1169b220a1 100644 (file)
@@ -2024,7 +2024,7 @@ def t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm),
 }
 
 def t2SBFX: T2TwoRegBitFI<
-                (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm0_31_m1:$msb),
+                (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb),
                  IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $msb", []> {
   let Inst{31-27} = 0b11110;
   let Inst{25} = 1;
@@ -2033,7 +2033,7 @@ def t2SBFX: T2TwoRegBitFI<
 }
 
 def t2UBFX: T2TwoRegBitFI<
-                (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm0_31_m1:$msb),
+                (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb),
                  IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $msb", []> {
   let Inst{31-27} = 0b11110;
   let Inst{25} = 1;
index a2df19f8f49090e0a72f4b86c28396d7c478a819..352e90200981375378a9df0cb8677df79ad9e26b 100644 (file)
@@ -2605,6 +2605,15 @@ validateInstruction(MCInst &Inst,
                    "source operands must be sequential");
     return false;
   }
+  case ARM::SBFX:
+  case ARM::UBFX: {
+    // width must be in range [1, 32-lsb]
+    unsigned lsb = Inst.getOperand(2).getImm();
+    unsigned widthm1 = Inst.getOperand(3).getImm();
+    if (widthm1 >= 32 - lsb)
+      return Error(Operands[5]->getStartLoc(),
+                   "bitfield width must be in range [1,32-lsb]");
+  }
   }
 
   return false;
index f16870054e142afa4eb0b994c6f15c5ac269b238..1f3920bd8cf21e54eed677639e1f53d65597afaf 100644 (file)
@@ -1026,7 +1026,7 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
     MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
                                                        decodeRm(insn))));
     MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 7)));
-    MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16) + 1));
+    MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16)));
     OpIdx += 3;
     return true;
   }
index e534e21375aea442f2c37a6c6cbbb32ea7c40dd5..66a62ef5a56bffe2e5585af22ef6467289a3ebb2 100644 (file)
@@ -1698,7 +1698,7 @@ static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode,
     assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX)
             && "Unexpected opcode");
     MI.addOperand(MCOperand::CreateImm(getLsb(insn)));
-    MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn) + 1));
+    MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn)));
 
     ++OpIdx;
   }
index 9482a6db1aef65be6be9d04dba34b55d79be4a71..4c5e9945139a56fa9b18dc848064f326d1a402e4 100644 (file)
@@ -259,11 +259,6 @@ public:
   unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
                              SmallVectorImpl<MCFixup> &Fixups) const;
 
-  unsigned getImmMinusOneOpValue(const MCInst &MI, unsigned Op,
-                                 SmallVectorImpl<MCFixup> &Fixups) const {
-    return MI.getOperand(Op).getImm() - 1;
-  }
-
   unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op,
                                    SmallVectorImpl<MCFixup> &Fixups) const {
     return 64 - MI.getOperand(Op).getImm();
index 02ccb9deb05ab7c778023ef712073db0b92ef384..c08bb83c096cd4b9e6df37ceadcf74fb7d73bda7 100644 (file)
@@ -1308,6 +1308,16 @@ _func:
 @ CHECK: sbc   r6, r6, r7, ror r9      @ encoding: [0x77,0x69,0xc6,0xe0]
 
 
+@------------------------------------------------------------------------------
+@ SBFX
+@------------------------------------------------------------------------------
+        sbfx r4, r5, #16, #1
+        sbfxgt r4, r5, #16, #16
+
+@ CHECK: sbfx  r4, r5, #16, #1         @ encoding: [0x55,0x48,0xa0,0xe7]
+@ CHECK: sbfxgt        r4, r5, #16, #16        @ encoding: [0x55,0x48,0xaf,0xc7]
+
+
 @------------------------------------------------------------------------------
 @ SEL
 @------------------------------------------------------------------------------
@@ -2001,3 +2011,11 @@ _func:
 @ CHECK: uasxeq        r9, r12, r0             @ encoding: [0x30,0x9f,0x5c,0x06]
 
 
+@------------------------------------------------------------------------------
+@ UBFX
+@------------------------------------------------------------------------------
+        ubfx r4, r5, #16, #1
+        ubfxgt r4, r5, #16, #16
+
+@ CHECK: ubfx  r4, r5, #16, #1         @ encoding: [0x55,0x48,0xe0,0xe7]
+@ CHECK: ubfxgt        r4, r5, #16, #16        @ encoding: [0x55,0x48,0xef,0xc7]
index e086128f420d6611f061bde8ed947118ee4f3742..cc244164a48f3eb3bbdb4437396be03f80f5888e 100644 (file)
 @ CHECK-ERRORS: error: rotate operator 'ror' expected
 @ CHECK-ERRORS:         sxtb16ge r2, r3, lsr #24
 @ CHECK-ERRORS:                          ^
+
+        @ Out of range width for SBFX/UBFX
+        sbfx r4, r5, #31, #2
+        ubfxgt r4, r5, #16, #17
+
+@ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb]
+@ CHECK-ERRORS:         sbfx r4, r5, #31, #2
+@ CHECK-ERRORS:                           ^
+@ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb]
+@ CHECK-ERRORS:         ubfxgt r4, r5, #16, #17
+@ CHECK-ERRORS:                             ^