Fix #13035, a bug around Thumb instruction LDRD/STRD with negative #0 offset index...
authorJiangning Liu <jiangning.liu@arm.com>
Thu, 2 Aug 2012 08:29:50 +0000 (08:29 +0000)
committerJiangning Liu <jiangning.liu@arm.com>
Thu, 2 Aug 2012 08:29:50 +0000 (08:29 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161162 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/Disassembler/ARMDisassembler.cpp
lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
test/MC/ARM/basic-thumb2-instructions.s
test/MC/Disassembler/ARM/thumb2.txt

index 89f7ec227ebf08ff8388ffc99dee73e152a0be03..c3610c81a61533e638fbd1239a98ea715b91157c 100644 (file)
@@ -1040,7 +1040,8 @@ public:
     // Immediate offset a multiple of 4 in range [-1020, 1020].
     if (!Memory.OffsetImm) return true;
     int64_t Val = Memory.OffsetImm->getValue();
-    return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
+    // Special case, #-0 is INT32_MIN.
+    return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || Val == INT32_MIN;
   }
   bool isMemImm0_1020s4Offset() const {
     if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
index 6f36dcc1ef37bbbb6bb81dd3888a7b3309a52861..e47bf66e3afe8761a8a1e37a8d118751993e50b5 100644 (file)
@@ -3151,9 +3151,14 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
 
 static DecodeStatus DecodeT2Imm8S4(MCInst &Inst, unsigned Val,
                            uint64_t Address, const void *Decoder) {
-  int imm = Val & 0xFF;
-  if (!(Val & 0x100)) imm *= -1;
-  Inst.addOperand(MCOperand::CreateImm(imm << 2));
+  if (Val == 0)
+    Inst.addOperand(MCOperand::CreateImm(INT32_MIN));
+  else {
+    int imm = Val & 0xFF;
+
+    if (!(Val & 0x100)) imm *= -1;
+    Inst.addOperand(MCOperand::CreateImm(imm << 2));
+  }
 
   return MCDisassembler::Success;
 }
index ad99c14ceed2ec338f72acc9684c2ac61839770c..8b9109ec9868130fbc362265cbd3e5d554adf955 100644 (file)
@@ -972,12 +972,17 @@ void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
 
   O << "[" << getRegisterName(MO1.getReg());
 
-  int32_t OffImm = (int32_t)MO2.getImm() / 4;
+  int32_t OffImm = (int32_t)MO2.getImm();
+
+  assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
+
   // Don't print +0.
-  if (OffImm < 0)
-    O << ", #-" << -OffImm * 4;
+  if (OffImm == INT32_MIN)
+    O << ", #-0";
+  else if (OffImm < 0)
+    O << ", #-" << -OffImm;
   else if (OffImm > 0)
-    O << ", #" << OffImm * 4;
+    O << ", #" << OffImm;
   O << "]";
 }
 
@@ -1009,15 +1014,17 @@ void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
                                                         unsigned OpNum,
                                                         raw_ostream &O) {
   const MCOperand &MO1 = MI->getOperand(OpNum);
-  int32_t OffImm = (int32_t)MO1.getImm() / 4;
+  int32_t OffImm = (int32_t)MO1.getImm();
+
+  assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
+
   // Don't print +0.
-  if (OffImm != 0) {
-    O << ", ";
-    if (OffImm < 0)
-      O << "#-" << -OffImm * 4;
-    else if (OffImm > 0)
-      O << "#" << OffImm * 4;
-  }
+  if (OffImm == INT32_MIN)
+    O << ", #-0";
+  else if (OffImm < 0)
+    O << ", #-" << -OffImm;
+  else if (OffImm > 0)
+    O << ", #" << OffImm;
 }
 
 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
index 31ada98d330bdb0d5c4916b3fe2b50e3cdde70d5..23d9f5977a296766dd48afe970ad63ea14d162af 100644 (file)
@@ -852,6 +852,9 @@ _func:
         ldrd r3, r5, [r6], #-8
         ldrd r3, r5, [r6]
         ldrd r8, r1, [r3, #0]
+        ldrd r0, r1, [r2, #-0]
+        ldrd r0, r1, [r2, #-0]!
+        ldrd r0, r1, [r2], #-0
 
 @ CHECK: ldrd  r3, r5, [r6, #24]       @ encoding: [0xd6,0xe9,0x06,0x35]
 @ CHECK: ldrd  r3, r5, [r6, #24]!      @ encoding: [0xf6,0xe9,0x06,0x35]
@@ -859,6 +862,9 @@ _func:
 @ CHECK: ldrd  r3, r5, [r6], #-8       @ encoding: [0x76,0xe8,0x02,0x35]
 @ CHECK: ldrd  r3, r5, [r6]            @ encoding: [0xd6,0xe9,0x00,0x35]
 @ CHECK: ldrd  r8, r1, [r3]            @ encoding: [0xd3,0xe9,0x00,0x81]
+@ CHECK: ldrd  r0, r1, [r2, #-0]       @ encoding: [0x52,0xe9,0x00,0x01]
+@ CHECK: ldrd  r0, r1, [r2, #-0]!      @ encoding: [0x72,0xe9,0x00,0x01]
+@ CHECK: ldrd  r0, r1, [r2], #-0       @ encoding: [0x72,0xe8,0x00,0x01]
 
 
 @------------------------------------------------------------------------------
@@ -2636,6 +2642,9 @@ _func:
         strd r3, r5, [r6], #-8
         strd r3, r5, [r6]
         strd r8, r1, [r3, #0]
+        strd r0, r1, [r2, #-0]
+        strd r0, r1, [r2, #-0]!
+        strd r0, r1, [r2], #-0
 
 @ CHECK: strd  r3, r5, [r6, #24]       @ encoding: [0xc6,0xe9,0x06,0x35]
 @ CHECK: strd  r3, r5, [r6, #24]!      @ encoding: [0xe6,0xe9,0x06,0x35]
@@ -2643,6 +2652,9 @@ _func:
 @ CHECK: strd  r3, r5, [r6], #-8       @ encoding: [0x66,0xe8,0x02,0x35]
 @ CHECK: strd  r3, r5, [r6]            @ encoding: [0xc6,0xe9,0x00,0x35]
 @ CHECK: strd  r8, r1, [r3]            @ encoding: [0xc3,0xe9,0x00,0x81]
+@ CHECK: strd   r0, r1, [r2, #-0]       @ encoding: [0x42,0xe9,0x00,0x01]
+@ CHECK: strd   r0, r1, [r2, #-0]!      @ encoding: [0x62,0xe9,0x00,0x01]
+@ CHECK: strd   r0, r1, [r2], #-0       @ encoding: [0x62,0xe8,0x00,0x01]
 
 
 @------------------------------------------------------------------------------
index 2c363feb0854729c6adb297d1a75c85d4a9beaa4..42ebe58207b3c39ea517bae0b0600f5355614e5f 100644 (file)
 # CHECK: ldrd r3, r5, [r6], #-8
 # CHECK: ldrd r3, r5, [r6]
 # CHECK: ldrd r8, r1, [r3]
+# CHECK: ldrd r0, r1, [r2], #-0
+# CHECK: ldrd r0, r1, [r2, #-0]!
+# CHECK: ldrd r0, r1, [r2, #-0]
 
 0xd6 0xe9 0x06 0x35
 0xf6 0xe9 0x06 0x35
 0x76 0xe8 0x02 0x35
 0xd6 0xe9 0x00 0x35
 0xd3 0xe9 0x00 0x81
+0x72 0xe8 0x00 0x01
+0x72 0xe9 0x00 0x01
+0x52 0xe9 0x00 0x01
 
 
 #------------------------------------------------------------------------------
 # STRD (immediate)
 #------------------------------------------------------------------------------
 # CHECK: strd r6, r3, [r5], #-8
-# CHECK: strd r8, r5, [r5]{{$}}
+# CHECK: strd r8, r5, [r5], #-0
 # CHECK: strd r7, r4, [r5], #-4
+# CHECK: strd r0, r1, [r2, #-0]!
+# CHECK: strd r0, r1, [r2, #-0]
 
 0x65 0xe8 0x02 0x63
 0x65 0xe8 0x00 0x85
 0x65 0xe8 0x01 0x74
+0x62 0xe9 0x00 0x01
+0x42 0xe9 0x00 0x01
 
 #------------------------------------------------------------------------------
 # STREX/STREXB/STREXH/STREXD