[llvm] r188067 - Fix assembling of Thumb2 branch instructions.

Mihai Popa mihail.popa at gmail.com
Fri Aug 9 03:38:32 PDT 2013


Author: mpopa
Date: Fri Aug  9 05:38:32 2013
New Revision: 188067

URL: http://llvm.org/viewvc/llvm-project?rev=188067&view=rev
Log:
Fix assembling of Thumb2 branch instructions.

The long encoding for Thumb2 unconditional branches is broken.
Additionally, there is no range checking for target operands; as such 
for instructions originating in assembly code, only short Thumb encodings
are generated, regardless of the bitsize needed for the offset.

Adding range checking is non trivial due to the representation of Thumb
branch instructions. There is no true difference between conditional and
unconditional branches in terms of operands and syntax - even unconditional
branches have a predicate which is expected to match that of the IT block
they are in. Yet, the encodings and the permitted size of the offset differ.

Due to this, for any mnemonic there are really 4 encodings to choose for.

The problem cannot be handled in the parser alone or by manipulating td files.
Because the parser builds first a set of match candidates and then checks them
one by one, whatever tablegen-only solution might be found will ultimately be
dependent of the parser's evaluation order. What's worse is that due to the fact
that all branches have the same syntax and the same kinds of operands, that 
order is governed by the lexicographical ordering of the names of operand 
classes...

To circumvent all this, any necessary disambiguation is added to the instruction
validation pass.



Added:
    llvm/trunk/test/MC/ARM/thumb2-branches.s
Modified:
    llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
    llvm/trunk/test/MC/ARM/basic-thumb-instructions.s
    llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s
    llvm/trunk/test/MC/ARM/thumb-diagnostics.s
    llvm/trunk/test/MC/ARM/thumb2-b.w-encodingT4.s
    llvm/trunk/test/MC/ARM/thumb2-diagnostics.s

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Fri Aug  9 05:38:32 2013
@@ -491,7 +491,8 @@ let isBranch = 1, isTerminator = 1, isBa
              T1Encoding<{1,1,1,0,0,?}>, Sched<[WriteBr]> {
     bits<11> target;
     let Inst{10-0} = target;
-  }
+    let AsmMatchConverter = "cvtThumbBranches";
+ }
 
   // Far jump
   // Just a pseudo for a tBL instruction. Needed to let regalloc know about
@@ -521,6 +522,7 @@ let isBranch = 1, isTerminator = 1 in
   bits<8> target;
   let Inst{11-8} = p;
   let Inst{7-0} = target;
+  let AsmMatchConverter = "cvtThumbBranches";
 }
 
 

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Fri Aug  9 05:38:32 2013
@@ -3336,13 +3336,14 @@ def t2B   : T2I<(outs), (ins uncondbrtar
   let Inst{12} = 1;
 
   bits<24> target;
-  let Inst{26} = target{19};
-  let Inst{11} = target{18};
-  let Inst{13} = target{17};
+  let Inst{26} = target{23};
+  let Inst{13} = target{22};
+  let Inst{11} = target{21};
   let Inst{25-16} = target{20-11};
   let Inst{10-0} = target{10-0};
   let DecoderMethod = "DecodeT2BInstruction";
-}
+  let AsmMatchConverter = "cvtThumbBranches"; 
+} 
 
 let isNotDuplicable = 1, isIndirectBranch = 1 in {
 def t2BR_JT : t2PseudoInst<(outs),
@@ -3410,6 +3411,7 @@ def t2Bcc : T2I<(outs), (ins brtarget:$t
   let Inst{10-0} = target{11-1};
 
   let DecoderMethod = "DecodeThumb2BCCInstruction";
+  let AsmMatchConverter = "cvtThumbBranches";
 }
 
 // Tail calls. The IOS version of thumb tail calls uses a t2 branch, so

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Fri Aug  9 05:38:32 2013
@@ -221,6 +221,9 @@ class ARMAsmParser : public MCTargetAsmP
   // Asm Match Converter Methods
   void cvtThumbMultiply(MCInst &Inst,
                         const SmallVectorImpl<MCParsedAsmOperand*> &);
+  void cvtThumbBranches(MCInst &Inst,
+                        const SmallVectorImpl<MCParsedAsmOperand*> &);
+                        
   bool validateInstruction(MCInst &Inst,
                            const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
   bool processInstruction(MCInst &Inst,
@@ -601,7 +604,7 @@ public:
   template<unsigned width, unsigned scale>
   bool isUnsignedOffset() const {
     if (!isImm()) return false;
-    if (dyn_cast<MCSymbolRefExpr>(Imm.Val)) return true;
+    if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
       int64_t Val = CE->getValue();
       int64_t Align = 1LL << scale;
@@ -610,6 +613,22 @@ public:
     }
     return false;
   }
+  // checks whether this operand is an signed offset which fits is a field
+  // of specified width and scaled by a specific number of bits
+  template<unsigned width, unsigned scale>
+  bool isSignedOffset() const {
+    if (!isImm()) return false;
+    if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
+    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
+      int64_t Val = CE->getValue();
+      int64_t Align = 1LL << scale;
+      int64_t Max = Align * ((1LL << (width-1)) - 1);
+      int64_t Min = -Align * (1LL << (width-1));
+      return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max);
+    }
+    return false;
+  }
+
   // checks whether this operand is a memory operand computed as an offset
   // applied to PC. the offset may have 8 bits of magnitude and is represented
   // with two bits of shift. textually it may be either [pc, #imm], #imm or 
@@ -4102,6 +4121,65 @@ cvtThumbMultiply(MCInst &Inst,
   ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
 }
 
+void ARMAsmParser::
+cvtThumbBranches(MCInst &Inst,
+           const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+  int CondOp = -1, ImmOp = -1;
+  switch(Inst.getOpcode()) {
+    case ARM::tB:
+    case ARM::tBcc:  CondOp = 1; ImmOp = 2; break;
+
+    case ARM::t2B:
+    case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break;
+
+    default: llvm_unreachable("Unexpected instruction in cvtThumbBranches");
+  }
+  // first decide whether or not the branch should be conditional
+  // by looking at it's location relative to an IT block
+  if(inITBlock()) {
+    // inside an IT block we cannot have any conditional branches. any 
+    // such instructions needs to be converted to unconditional form
+    switch(Inst.getOpcode()) {
+      case ARM::tBcc: Inst.setOpcode(ARM::tB); break;
+      case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break;
+    }
+  } else {
+    // outside IT blocks we can only have unconditional branches with AL
+    // condition code or conditional branches with non-AL condition code
+    unsigned Cond = static_cast<ARMOperand*>(Operands[CondOp])->getCondCode();
+    switch(Inst.getOpcode()) {
+      case ARM::tB:
+      case ARM::tBcc: 
+        Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc); 
+        break;
+      case ARM::t2B:
+      case ARM::t2Bcc: 
+        Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc);
+        break;
+    }
+  }
+  
+  // now decide on encoding size based on branch target range
+  switch(Inst.getOpcode()) {
+    // classify tB as either t2B or t1B based on range of immediate operand
+    case ARM::tB: {
+      ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]);
+      if(!op->isSignedOffset<11, 1>() && isThumbTwo()) 
+        Inst.setOpcode(ARM::t2B);
+      break;
+    }
+    // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand
+    case ARM::tBcc: {
+      ARMOperand* op = static_cast<ARMOperand*>(Operands[ImmOp]);
+      if(!op->isSignedOffset<8, 1>() && isThumbTwo())
+        Inst.setOpcode(ARM::t2Bcc);
+      break;
+    }
+  }
+  ((ARMOperand*)Operands[ImmOp])->addImmOperands(Inst, 1);
+  ((ARMOperand*)Operands[CondOp])->addCondCodeOperands(Inst, 2);
+}
+
 /// Parse an ARM memory expression, return false if successful else return true
 /// or an error.  The first token must be a '[' when called.
 bool ARMAsmParser::
@@ -5216,6 +5294,7 @@ validateInstruction(MCInst &Inst,
                     const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
   const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
   SMLoc Loc = Operands[0]->getStartLoc();
+
   // Check the IT block state first.
   // NOTE: BKPT instruction has the interesting property of being
   // allowed in IT blocks, but not being predicable.  It just always
@@ -5247,8 +5326,8 @@ validateInstruction(MCInst &Inst,
   // Check for non-'al' condition codes outside of the IT block.
   } else if (isThumbTwo() && MCID.isPredicable() &&
              Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
-             ARMCC::AL && Inst.getOpcode() != ARM::tB &&
-             Inst.getOpcode() != ARM::t2B)
+             ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
+             Inst.getOpcode() != ARM::t2Bcc)
     return Error(Loc, "predicated instructions must be in IT block");
 
   switch (Inst.getOpcode()) {
@@ -5383,6 +5462,28 @@ validateInstruction(MCInst &Inst,
     }
     break;
   }
+  // final range checking for Thumb unconditional branch instructions
+  case ARM::tB:
+    if(!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<11, 1>())
+      return Error(Operands[2]->getStartLoc(), "Branch target out of range");
+    break;
+  case ARM::t2B: {
+    int op = (Operands[2]->isImm()) ? 2 : 3;
+    if(!(static_cast<ARMOperand*>(Operands[op]))->isSignedOffset<24, 1>())
+      return Error(Operands[op]->getStartLoc(), "Branch target out of range");
+    break;
+  }
+  // final range checking for Thumb conditional branch instructions
+  case ARM::tBcc:
+    if(!(static_cast<ARMOperand*>(Operands[2]))->isSignedOffset<8, 1>())
+      return Error(Operands[2]->getStartLoc(), "Branch target out of range");
+    break;
+  case ARM::t2Bcc: {
+    int op = (Operands[2]->isImm()) ? 2 : 3;
+    if(!(static_cast<ARMOperand*>(Operands[op]))->isSignedOffset<20, 1>())
+      return Error(Operands[op]->getStartLoc(), "Branch target out of range");
+    break;
+  }
   }
 
   StringRef DepInfo;

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp Fri Aug  9 05:38:32 2013
@@ -638,8 +638,14 @@ getARMBLXTargetOpValue(const MCInst &MI,
 uint32_t ARMMCCodeEmitter::
 getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
                        SmallVectorImpl<MCFixup> &Fixups) const {
-  unsigned Val =
-    ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
+  unsigned Val = 0;
+  const MCOperand MO = MI.getOperand(OpIdx);
+    
+  if(MO.isExpr())
+    Val = ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
+  else 
+    Val = MO.getImm() >> 1;
+
   bool I  = (Val & 0x800000);
   bool J1 = (Val & 0x400000);
   bool J2 = (Val & 0x200000);

Modified: llvm/trunk/test/MC/ARM/basic-thumb-instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/basic-thumb-instructions.s?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/basic-thumb-instructions.s (original)
+++ llvm/trunk/test/MC/ARM/basic-thumb-instructions.s Fri Aug  9 05:38:32 2013
@@ -128,7 +128,7 @@ _func:
         beq _bar
         b       #1838
         b       #-420
-        beq     #336
+        beq     #-256
         beq     #160
 
 @ CHECK: b	_baz                    @ encoding: [A,0xe0'A']
@@ -137,7 +137,7 @@ _func:
              @   fixup A - offset: 0, value: _bar, kind: fixup_arm_thumb_bcc
 @ CHECK: b       #1838                   @ encoding: [0x97,0xe3]
 @ CHECK: b       #-420                   @ encoding: [0x2e,0xe7]
-@ CHECK: beq     #336                    @ encoding: [0xa8,0xd0]
+@ CHECK: beq     #-256                   @ encoding: [0x80,0xd0]
 @ CHECK: beq     #160                    @ encoding: [0x50,0xd0]
 
 @------------------------------------------------------------------------------

Modified: llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s (original)
+++ llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s Fri Aug  9 05:38:32 2013
@@ -221,12 +221,12 @@ _func:
         beq.w _bar
         bmi.w   #-183396
 
-@ CHECK: b.w	_bar                    @ encoding: [A,0xf0'A',A,0x90'A']
+@ CHECK: b.w	_bar                    @ encoding: [A,0xf0'A',A,0xb8'A']
           @   fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
 @ CHECK: beq.w	_bar                    @ encoding: [A,0xf0'A',A,0x80'A']
           @   fixup A - offset: 0, value: _bar, kind: fixup_t2_condbranch
 @ CHECK: it	eq                      @ encoding: [0x08,0xbf]
-@ CHECK: beq.w	_bar                    @ encoding: [A,0xf0'A',A,0x90'A']
+@ CHECK: beq.w	_bar                    @ encoding: [A,0xf0'A',A,0xb8'A']
           @   fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
 @ CHECK: bmi.w   #-183396                @ encoding: [0x13,0xf5,0xce,0xa9]
 

Modified: llvm/trunk/test/MC/ARM/thumb-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb-diagnostics.s?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb-diagnostics.s (original)
+++ llvm/trunk/test/MC/ARM/thumb-diagnostics.s Fri Aug  9 05:38:32 2013
@@ -138,7 +138,26 @@ error: invalid operand for instruction
 @ CHECK-ERRORS: error: source register must be the same as destination
 @ CHECK-ERRORS:         add r2, sp, ip
 @ CHECK-ERRORS:                     ^
- 
+
+
+ at ------------------------------------------------------------------------------
+@ WFE/WFI/YIELD - out of range immediates for Thumb1 branches
+ at ------------------------------------------------------------------------------
+
+        beq    #-258
+        bne    #256
+        bgt    #13
+        b      #-1048578
+        b      #1048576
+        b      #10323
+
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+
 @------------------------------------------------------------------------------
 @ WFE/WFI/YIELD - are not supported pre v6T2
 @------------------------------------------------------------------------------

Modified: llvm/trunk/test/MC/ARM/thumb2-b.w-encodingT4.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb2-b.w-encodingT4.s?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb2-b.w-encodingT4.s (original)
+++ llvm/trunk/test/MC/ARM/thumb2-b.w-encodingT4.s Fri Aug  9 05:38:32 2013
@@ -9,4 +9,4 @@ _foo:
 @------------------------------------------------------------------------------
         b.w   0x3680c
 
-@ CHECK: b.w	#223244                    @ encoding: [0x6d,0xf0,0x0c,0xb0]
+@ CHECK: b.w	#223244                    @ encoding: [0x36,0xf0,0x06,0xbc]

Added: llvm/trunk/test/MC/ARM/thumb2-branches.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb2-branches.s?rev=188067&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb2-branches.s (added)
+++ llvm/trunk/test/MC/ARM/thumb2-branches.s Fri Aug  9 05:38:32 2013
@@ -0,0 +1,286 @@
+@ RUN: llvm-mc -triple=thumbv7-apple-darwin -mcpu=cortex-a8 -show-encoding < %s | FileCheck %s
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches accept narrow suffix and encode to short encodings
+ at ------------------------------------------------------------------------------
+
+         b.n    #-2048
+         b.n    #2046
+
+@ CHECK: b	#-2048                  @ encoding: [0x00,0xe4]
+@ CHECK: b	#2046                   @ encoding: [0xff,0xe3]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+ at ------------------------------------------------------------------------------
+
+         b.w    #-2048
+         b.w    #2046
+         b.w    #-1677216
+         b.w    #1677214
+
+@ CHECK: b.w	#-2048                  @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: b.w	#2046                   @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: b.w	#-1677216               @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w	#1677214                @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+ at ------------------------------------------------------------------------------
+
+         b      #-2048
+         b      #2046
+         b      #-2050
+         b      #2048
+         b      #-1677216
+         b      #1677214
+
+@ CHECK: b	#-2048                  @ encoding: [0x00,0xe4]
+@ CHECK: b	#2046                   @ encoding: [0xff,0xe3]
+@ CHECK: b.w	#-2050                  @ encoding: [0xff,0xf7,0xff,0xbb]
+@ CHECK: b.w	#2048                   @ encoding: [0x00,0xf0,0x00,0xbc]
+@ CHECK: b.w	#-1677216               @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w	#1677214                @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches with width narrow suffix in IT block 
+ at ------------------------------------------------------------------------------
+
+         it     eq
+         beq.n  #-2048
+         it     ne
+         bne.n  #-2046
+
+@ CHECK: it	eq                      @ encoding: [0x08,0xbf]
+@ CHECK: beq	#-2048                  @ encoding: [0x00,0xe4] 
+@ CHECK: it	ne                      @ encoding: [0x18,0xbf] 
+@ CHECK: bne	#-2046                  @ encoding: [0x01,0xe4]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches with wide suffix in IT block
+ at ------------------------------------------------------------------------------
+
+         it     gt
+         bgt.w  #-2048
+         it     le
+         ble.w  #2046
+         it     ge
+         bge.w  #-1677216
+         it     lt
+         blt.w  #1677214
+
+@ CHECK: it	gt                      @ encoding: [0xc8,0xbf]
+@ CHECK: bgt.w	#-2048                  @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: it	le                      @ encoding: [0xd8,0xbf]
+@ CHECK: ble.w	#2046                   @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: it	ge                      @ encoding: [0xa8,0xbf]
+@ CHECK: bge.w	#-1677216               @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: it	lt                      @ encoding: [0xb8,0xbf]
+@ CHECK: blt.w	#1677214                @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+ at ------------------------------------------------------------------------------
+@ conditional branches accept narrow suffix and encode to short encodings
+ at ------------------------------------------------------------------------------
+
+         beq.n    #-256
+         bne.n    #254
+
+@ CHECK: beq	#-256                   @ encoding: [0x80,0xd0]
+@ CHECK: bne	#254                    @ encoding: [0x7f,0xd1]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+ at ------------------------------------------------------------------------------
+
+         bmi.w    #-256
+         bne.w    #254
+         blt.w    #-1048576
+         bge.w    #1048574
+
+@ CHECK: bmi.w	#-256                   @ encoding: [0x3f,0xf5,0x80,0xaf]
+@ CHECK: bne.w	#254                    @ encoding: [0x40,0xf0,0x7f,0x80]
+@ CHECK: blt.w	#-1048576               @ encoding: [0xc0,0xf6,0x00,0x80]
+@ CHECK: bge.w	#1048574                @ encoding: [0xbf,0xf2,0xff,0xaf]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+ at ------------------------------------------------------------------------------
+
+         bne     #-256
+         bgt     #254
+         bne     #-258
+         bgt     #256
+         bne     #-1048576
+         bgt     #1048574
+
+@ CHECK: bne	#-256                   @ encoding: [0x80,0xd1]
+@ CHECK: bgt	#254                    @ encoding: [0x7f,0xdc]
+@ CHECK: bne.w	#-258                   @ encoding: [0x7f,0xf4,0x7f,0xaf]
+@ CHECK: bgt.w	#256                    @ encoding: [0x00,0xf3,0x80,0x80]
+@ CHECK: bne.w	#-1048576               @ encoding: [0x40,0xf4,0x00,0x80]
+@ CHECK: bgt.w	#1048574                @ encoding: [0x3f,0xf3,0xff,0xaf]
+
+ at ------------------------------------------------------------------------------
+@ same branch insturction encoding to conditional or unconditional depending
+@ on whether it is in an IT block or not
+ at ------------------------------------------------------------------------------
+
+         it     eq
+         addeq  r0, r1
+         bne    #128
+
+@ CHECK: it	eq                      @ encoding: [0x08,0xbf]
+@ CHECK: addeq	r0, r1                  @ encoding: [0x08,0x44]
+@ CHECK: bne	#128                    @ encoding: [0x40,0xd1]
+
+         ite    eq
+         addeq  r0, r1
+         bne    #128
+
+@ CHECK: ite	eq                      @ encoding: [0x0c,0xbf]
+@ CHECK: addeq	r0, r1                  @ encoding: [0x08,0x44]
+@ CHECK: bne	#128                    @ encoding: [0x40,0xe0]
+
+@ RUN: llvm-mc -triple=thumbv7-apple-darwin -mcpu=cortex-a8 -show-encoding < %s | FileCheck %s
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches accept narrow suffix and encode to short encodings
+ at ------------------------------------------------------------------------------
+
+         b.n    #-2048
+         b.n    #2046
+
+@ CHECK: b	#-2048                  @ encoding: [0x00,0xe4]
+@ CHECK: b	#2046                   @ encoding: [0xff,0xe3]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+ at ------------------------------------------------------------------------------
+
+         b.w    #-2048
+         b.w    #2046
+         b.w    #-1677216
+         b.w    #1677214
+
+@ CHECK: b.w	#-2048                  @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: b.w	#2046                   @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: b.w	#-1677216               @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w	#1677214                @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+ at ------------------------------------------------------------------------------
+
+         b      #-2048
+         b      #2046
+         b      #-2050
+         b      #2048
+         b      #-1677216
+         b      #1677214
+
+@ CHECK: b	#-2048                  @ encoding: [0x00,0xe4]
+@ CHECK: b	#2046                   @ encoding: [0xff,0xe3]
+@ CHECK: b.w	#-2050                  @ encoding: [0xff,0xf7,0xff,0xbb]
+@ CHECK: b.w	#2048                   @ encoding: [0x00,0xf0,0x00,0xbc]
+@ CHECK: b.w	#-1677216               @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: b.w	#1677214                @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches with width narrow suffix in IT block 
+ at ------------------------------------------------------------------------------
+
+         it     eq
+         beq.n  #-2048
+         it     ne
+         bne.n  #-2046
+
+@ CHECK: it	eq                      @ encoding: [0x08,0xbf]
+@ CHECK: beq	#-2048                  @ encoding: [0x00,0xe4] 
+@ CHECK: it	ne                      @ encoding: [0x18,0xbf] 
+@ CHECK: bne	#-2046                  @ encoding: [0x01,0xe4]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches with wide suffix in IT block
+ at ------------------------------------------------------------------------------
+
+         it     gt
+         bgt.w  #-2048
+         it     le
+         ble.w  #2046
+         it     ge
+         bge.w  #-1677216
+         it     lt
+         blt.w  #1677214
+
+@ CHECK: it	gt                      @ encoding: [0xc8,0xbf]
+@ CHECK: bgt.w	#-2048                  @ encoding: [0xff,0xf7,0x00,0xbc]
+@ CHECK: it	le                      @ encoding: [0xd8,0xbf]
+@ CHECK: ble.w	#2046                   @ encoding: [0x00,0xf0,0xff,0xbb]
+@ CHECK: it	ge                      @ encoding: [0xa8,0xbf]
+@ CHECK: bge.w	#-1677216               @ encoding: [0x66,0xf6,0x30,0xbc]
+@ CHECK: it	lt                      @ encoding: [0xb8,0xbf]
+@ CHECK: blt.w	#1677214                @ encoding: [0x99,0xf1,0xcf,0xbb]
+
+ at ------------------------------------------------------------------------------
+@ conditional branches accept narrow suffix and encode to short encodings
+ at ------------------------------------------------------------------------------
+
+         beq.n    #-256
+         bne.n    #254
+
+@ CHECK: beq	#-256                   @ encoding: [0x80,0xd0]
+@ CHECK: bne	#254                    @ encoding: [0x7f,0xd1]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches accept wide suffix and encode to wide encodings
+ at ------------------------------------------------------------------------------
+
+         bmi.w    #-256
+         bne.w    #254
+         blt.w    #-1048576
+         bge.w    #1048574
+
+@ CHECK: bmi.w	#-256                   @ encoding: [0x3f,0xf5,0x80,0xaf]
+@ CHECK: bne.w	#254                    @ encoding: [0x40,0xf0,0x7f,0x80]
+@ CHECK: blt.w	#-1048576               @ encoding: [0xc0,0xf6,0x00,0x80]
+@ CHECK: bge.w	#1048574                @ encoding: [0xbf,0xf2,0xff,0xaf]
+
+ at ------------------------------------------------------------------------------
+@ unconditional branches without width suffix encode depending of offset size
+ at ------------------------------------------------------------------------------
+
+         bne     #-256
+         bgt     #254
+         bne     #-258
+         bgt     #256
+         bne     #-1048576
+         bgt     #1048574
+
+@ CHECK: bne	#-256                   @ encoding: [0x80,0xd1]
+@ CHECK: bgt	#254                    @ encoding: [0x7f,0xdc]
+@ CHECK: bne.w	#-258                   @ encoding: [0x7f,0xf4,0x7f,0xaf]
+@ CHECK: bgt.w	#256                    @ encoding: [0x00,0xf3,0x80,0x80]
+@ CHECK: bne.w	#-1048576               @ encoding: [0x40,0xf4,0x00,0x80]
+@ CHECK: bgt.w	#1048574                @ encoding: [0x3f,0xf3,0xff,0xaf]
+
+ at ------------------------------------------------------------------------------
+@ same branch insturction encoding to conditional or unconditional depending
+@ on whether it is in an IT block or not
+ at ------------------------------------------------------------------------------
+
+         it     eq
+         addeq  r0, r1
+         bne    #128
+
+@ CHECK: it	eq                      @ encoding: [0x08,0xbf]
+@ CHECK: addeq	r0, r1                  @ encoding: [0x08,0x44]
+@ CHECK: bne	#128                    @ encoding: [0x40,0xd1]
+
+         ite    eq
+         addeq  r0, r1
+         bne    #128
+
+@ CHECK: ite	eq                      @ encoding: [0x0c,0xbf]
+@ CHECK: addeq	r0, r1                  @ encoding: [0x08,0x44]
+@ CHECK: bne	#128                    @ encoding: [0x40,0xe0]
+

Modified: llvm/trunk/test/MC/ARM/thumb2-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb2-diagnostics.s?rev=188067&r1=188066&r2=188067&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb2-diagnostics.s (original)
+++ llvm/trunk/test/MC/ARM/thumb2-diagnostics.s Fri Aug  9 05:38:32 2013
@@ -51,3 +51,22 @@
         itt eq
         bkpteq #1
 @ CHECK-ERRORS: error: instruction 'bkpt' is not predicable, but condition code specified
+
+        nopeq
+        nopeq
+
+@ out of range operands for Thumb2 targets
+
+        beq.w  #-1048578
+        bne.w  #1048576
+        blt.w  #1013411
+        b.w    #-16777218
+        b.w    #16777216
+        b.w    #1592313
+
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range
+@ CHECK-ERRORS: error: Branch target out of range





More information about the llvm-commits mailing list