[llvm-commits] [PATCH] thumb t2b fix

Greg Fitzgerald garious at gmail.com
Wed Sep 19 15:21:23 PDT 2012


Okay, here's my first shot.  It starts with Christopher's patch and
tests, adds a couple more tests, removes the bit-clearing code, and I
believe fixes a bug in the fixup encoding.

Can you please have a look?  Feedback much appreciated.

Thanks,
Greg


On Wed, Sep 19, 2012 at 2:35 AM, Tim Northover <t.p.northover at gmail.com> wrote:
>> 1) Why do you need to clear bits during fixup resolution?  The intended
>> design is for the MCCodeEmitter to leave fixup bits as zero if it could not
>> determine the correct value for them.
>
> /me sidles off to fix another backend quickly.
>
> Thanks for your explanations.
>
> Tim.
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
From 13bb7c8c04f8ff4fd853f2e2ef6ec734e9351c9b Mon Sep 17 00:00:00 2001
From: Greg Fitzgerald <gregf at codeaurora.org>
Date: Wed, 19 Sep 2012 15:02:32 -0700
Subject: [PATCH] Bug 13039: Fixed branch encoding in Thumb2 code generation

http://llvm.org/bugs/show_bug.cgi?id=13039
---
 lib/Target/ARM/ARMInstrThumb2.td                 |   12 ++++----
 lib/Target/ARM/Disassembler/ARMDisassembler.cpp  |   17 +++++++-----
 lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp    |   18 ++++++-------
 lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp |   30 +++++++++++----------
 test/MC/ARM/basic-thumb2-instructions.s          |    4 ++-
 test/MC/ARM/thumb-t2b.txt                        |    7 +++++
 test/MC/Disassembler/ARM/thumb2.txt              |    2 +
 7 files changed, 52 insertions(+), 38 deletions(-)
 create mode 100644 test/MC/ARM/thumb-t2b.txt

diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index f1a6cce..1821a72 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -3239,15 +3239,15 @@ let isPredicable = 1 in
 def t2B   : T2I<(outs), (ins uncondbrtarget:$target), IIC_Br,
                  "b", ".w\t$target",
                  [(br bb:$target)]> {
+
+  bits<24> target;
   let Inst{31-27} = 0b11110;
+  let Inst{26} = target{23};
+  let Inst{25-16} = target{20-11};
   let Inst{15-14} = 0b10;
+  let Inst{13} = target{22};
   let Inst{12} = 1;
-
-  bits<20> target;
-  let Inst{26} = target{19};
-  let Inst{11} = target{18};
-  let Inst{13} = target{17};
-  let Inst{21-16} = target{16-11};
+  let Inst{11} = target{21};
   let Inst{10-0} = target{10-0};
   let DecoderMethod = "DecodeT2BInstruction";
 }
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 57642e1..c9e3b01 100644
--- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -2090,14 +2090,17 @@ static DecodeStatus
 DecodeT2BInstruction(MCInst &Inst, unsigned Insn,
                      uint64_t Address, const void *Decoder) {
   DecodeStatus S = MCDisassembler::Success;
-  unsigned imm = (fieldFromInstruction(Insn, 0, 11) << 0) |
-                 (fieldFromInstruction(Insn, 11, 1) << 18) |
-                 (fieldFromInstruction(Insn, 13, 1) << 17) |
-                 (fieldFromInstruction(Insn, 16, 6) << 11) |
-                 (fieldFromInstruction(Insn, 26, 1) << 19);
-  if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<20>(imm<<1) + 4,
+
+  unsigned s = fieldFromInstruction(Insn, 26, 1);
+  unsigned i1 = !(fieldFromInstruction(Insn, 13, 1) ^ s) ? 1 << 22 : 0;
+  unsigned i2 = !(fieldFromInstruction(Insn, 11, 1) ^ s) ? 1 << 21 : 0;
+  unsigned imm = (fieldFromInstruction(Insn, 0, 11)  << 0 ) |
+                 (fieldFromInstruction(Insn, 16, 10) << 11) |
+                 (s << 23) | i1 | i2;
+
+  if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<25>(imm<<1) + 4,
                                 true, 4, Inst, Decoder))
-    Inst.addOperand(MCOperand::CreateImm(SignExtend32<20>(imm << 1)));
+    Inst.addOperand(MCOperand::CreateImm(SignExtend32<25>(imm << 1)));
   return S;
 }
 
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 68c47ac..79198c4 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -362,16 +362,14 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
     Value >>= 1; // Low bit is not encoded.
 
     uint32_t out = 0;
-    bool I =  Value & 0x800000;
-    bool J1 = Value & 0x400000;
-    bool J2 = Value & 0x200000;
-    J1 ^= I;
-    J2 ^= I;
-
-    out |= I  << 26; // S bit
-    out |= !J1 << 13; // J1 bit
-    out |= !J2 << 11; // J2 bit
-    out |= (Value & 0x1FF800)  << 5; // imm6 field
+    bool S =  Value & 0x800000;
+    bool I1 = Value & 0x400000;
+    bool I2 = Value & 0x200000;
+
+    out |= S  << 26; // S bit
+    out |= !(I1 ^ S) << 13; // J1 bit
+    out |= !(I2 ^ S) << 11; // J2 bit
+    out |= (Value & 0x1FF800)  << 5;  // imm10 field
     out |= (Value & 0x0007FF);        // imm11 field
 
     uint64_t swapped = (out & 0xFFFF0000) >> 16;
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
index dde7285..f52576b 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
@@ -625,20 +625,22 @@ getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
 uint32_t ARMMCCodeEmitter::
 getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
                        SmallVectorImpl<MCFixup> &Fixups) const {
-  unsigned Val =
-    ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
-  bool I  = (Val & 0x800000);
-  bool J1 = (Val & 0x400000);
-  bool J2 = (Val & 0x200000);
-  if (I ^ J1)
-    Val &= ~0x400000;
-  else
-    Val |= 0x400000;
+  const MCOperand MO = MI.getOperand(OpIdx);
+  if (MO.isExpr())
+    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
 
-  if (I ^ J2)
-    Val &= ~0x200000;
-  else
-    Val |= 0x200000;
+  uint32_t Val = MO.getImm() >> 1;
+
+  bool S  = Val & 0x800000;
+  bool I1 = Val & 0x400000;
+  bool I2 = Val & 0x200000;
+
+  bool J1 = !I1 ^ S;
+  bool J2 = !I2 ^ S;
+
+  Val &= ~0x600000; // Clear J1 and J2 bits
+  Val |= J1 ? 0x400000 : 0;
+  Val |= J2 ? 0x200000 : 0;
 
   return Val;
 }
diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s
index 23d9f59..9b6c1d8 100644
--- a/test/MC/ARM/basic-thumb2-instructions.s
+++ b/test/MC/ARM/basic-thumb2-instructions.s
@@ -211,12 +211,14 @@ _func:
 @------------------------------------------------------------------------------
 @ B
 @------------------------------------------------------------------------------
+        b.w     #4194304
         b.w   _bar
         beq.w   _bar
         it eq
         beq.w _bar
         bmi.w   #-183396
-
+ 
+@ CHECK: b.w #4194304                    @ encoding: [0x00,0xf0,0x00,0xb0]
 @ CHECK: b.w	_bar                    @ encoding: [A,0xf0'A',A,0x90'A']
           @   fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
 @ CHECK: beq.w	_bar                    @ encoding: [A,0xf0'A',A,0x80'A']
diff --git a/test/MC/ARM/thumb-t2b.txt b/test/MC/ARM/thumb-t2b.txt
new file mode 100644
index 0000000..166c660
--- /dev/null
+++ b/test/MC/ARM/thumb-t2b.txt
@@ -0,0 +1,7 @@
+@ RUN: llvm-mc -triple thumbv7 -filetype=obj %s | llvm-objdump -disassemble -triple thumbv7 - | FileCheck %s
+
+b.w _bar
+.zero 12582912
+_bar:
+
+@ CHECK: 00 f0 00 90 b.w #12582912
diff --git a/test/MC/Disassembler/ARM/thumb2.txt b/test/MC/Disassembler/ARM/thumb2.txt
index 42ebe58..c866321 100644
--- a/test/MC/Disassembler/ARM/thumb2.txt
+++ b/test/MC/Disassembler/ARM/thumb2.txt
@@ -166,8 +166,10 @@
 # B
 #------------------------------------------------------------------------------
 # CHECK: bmi.w   #-183396
+# CHECK: b.w     #4194304
 
 0x13 0xf5 0xce 0xa9
+0x00 0xf0 0x00 0xb0
 
 
 #------------------------------------------------------------------------------
-- 
1.7.5.4



More information about the llvm-commits mailing list