From fd652df8b36a9d3e6b09ae2b9f7bcb07e88fdfaa Mon Sep 17 00:00:00 2001 From: Jiangning Liu Date: Thu, 2 Aug 2012 08:29:50 +0000 Subject: [PATCH] Fix #13035, a bug around Thumb instruction LDRD/STRD with negative #0 offset index issue. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161162 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 3 +- .../ARM/Disassembler/ARMDisassembler.cpp | 11 +++++-- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 31 ++++++++++++------- test/MC/ARM/basic-thumb2-instructions.s | 12 +++++++ test/MC/Disassembler/ARM/thumb2.txt | 12 ++++++- 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 89f7ec227eb..c3610c81a61 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -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) diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 6f36dcc1ef3..e47bf66e3af 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -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; } diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index ad99c14ceed..8b9109ec986 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -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, diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s index 31ada98d330..23d9f5977a2 100644 --- a/test/MC/ARM/basic-thumb2-instructions.s +++ b/test/MC/ARM/basic-thumb2-instructions.s @@ -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] @------------------------------------------------------------------------------ diff --git a/test/MC/Disassembler/ARM/thumb2.txt b/test/MC/Disassembler/ARM/thumb2.txt index 2c363feb085..42ebe58207b 100644 --- a/test/MC/Disassembler/ARM/thumb2.txt +++ b/test/MC/Disassembler/ARM/thumb2.txt @@ -641,6 +641,9 @@ # 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 @@ -648,6 +651,9 @@ 0x76 0xe8 0x02 0x35 0xd6 0xe9 0x00 0x35 0xd3 0xe9 0x00 0x81 +0x72 0xe8 0x00 0x01 +0x72 0xe9 0x00 0x01 +0x52 0xe9 0x00 0x01 #------------------------------------------------------------------------------ @@ -1822,12 +1828,16 @@ # 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