Index: test/MC/ARM/thumb-t2b.txt =================================================================== --- test/MC/ARM/thumb-t2b.txt (revision 0) +++ test/MC/ARM/thumb-t2b.txt (revision 0) @@ -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: a0 f0 00 90 b.w #12582912 Index: test/MC/ARM/basic-thumb2-instructions.s =================================================================== --- test/MC/ARM/basic-thumb2-instructions.s (revision 163390) +++ test/MC/ARM/basic-thumb2-instructions.s (working copy) @@ -217,12 +217,12 @@ 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] Index: test/MC/Disassembler/ARM/thumb-t2b-reencoding.txt =================================================================== --- test/MC/Disassembler/ARM/thumb-t2b-reencoding.txt (revision 0) +++ test/MC/Disassembler/ARM/thumb-t2b-reencoding.txt (revision 0) @@ -0,0 +1,21 @@ +# RUN: llvm-mc -triple thumbv7 -show-encoding -disassemble < %s | FileCheck %s + +0x00 0xf0 0x00 0x90 +0x00 0xf0 0x00 0x98 +0x00 0xf0 0x00 0xb0 +0x00 0xf0 0x00 0xb8 + +# CHECK: b.w #12582912 @ encoding: [0x00,0xf0,0x00,0x90] +# CHECK: b.w #8388608 @ encoding: [0x00,0xf0,0x00,0x98] +# CHECK: b.w #4194304 @ encoding: [0x00,0xf0,0x00,0xb0] +# CHECK: b.w #0 @ encoding: [0x00,0xf0,0x00,0xb8] + +0x00 0xf4 0x00 0x90 +0x00 0xf4 0x00 0x98 +0x00 0xf4 0x00 0xb0 +0x00 0xf4 0x00 0xb8 + +# CHECK: b.w #-16777216 @ encoding: [0x00,0xf4,0x00,0x90] +# CHECK: b.w #-12582912 @ encoding: [0x00,0xf4,0x00,0x98] +# CHECK: b.w #-8388608 @ encoding: [0x00,0xf4,0x00,0xb0] +# CHECK: b.w #-4194304 @ encoding: [0x00,0xf4,0x00,0xb8] Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td (revision 163390) +++ lib/Target/ARM/ARMInstrThumb2.td (working copy) @@ -3243,11 +3243,11 @@ let Inst{15-14} = 0b10; 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}; + bits<24> target; + 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"; } Index: lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp (revision 163390) +++ lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp (working copy) @@ -627,6 +627,8 @@ SmallVectorImpl &Fixups) const { unsigned Val = ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups); + Val >>= 1; // T4 branch immediate value has a '0' appended to the end. + bool I = (Val & 0x800000); bool J1 = (Val & 0x400000); bool J2 = (Val & 0x200000); Index: lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (revision 163390) +++ lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (working copy) @@ -247,7 +247,11 @@ } static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext *Ctx = NULL) { + uint64_t &Clear, MCContext *Ctx = NULL) { + // The number of fixups which can clear bits is very small. Default to no + // mask. + Clear = 0; + unsigned Kind = Fixup.getKind(); switch (Kind) { default: @@ -361,6 +365,9 @@ Value = Value - 4; Value >>= 1; // Low bit is not encoded. + // Clear all the bits that represent the immediate value. + Clear = ~0x9000f000; + uint32_t out = 0; bool I = Value & 0x800000; bool J1 = Value & 0x400000; @@ -549,7 +556,8 @@ // Try to get the encoded value for the fixup as-if we're mapping it into // the instruction. This allows adjustFixupValue() to issue a diagnostic // if the value aren't invalid. - (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); + uint64_t Clear; + (void)adjustFixupValue(Fixup, Value, Clear, &Asm.getContext()); } namespace { @@ -575,16 +583,19 @@ void ELFARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned NumBytes = 4; // FIXME: 2 for Thumb - Value = adjustFixupValue(Fixup, Value); - if (!Value) return; // Doesn't change encoding. + uint64_t Clear; + Value = adjustFixupValue(Fixup, Value, Clear); + if (!Value && !Clear) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); // For each byte of the fragment that the fixup touches, mask in the bits from // the fixup value. The Value has been "split up" into the appropriate // bitfields above. - for (unsigned i = 0; i != NumBytes; ++i) + for (unsigned i = 0; i != NumBytes; ++i) { + Data[Offset + i] &= ~uint8_t((Clear >> (i * 8)) & 0xff); Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); + } } // FIXME: This should be in a separate file. @@ -660,16 +671,19 @@ void DarwinARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); - Value = adjustFixupValue(Fixup, Value); - if (!Value) return; // Doesn't change encoding. + uint64_t Clear; + Value = adjustFixupValue(Fixup, Value, Clear); + if (!Value && !Clear) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); // For each byte of the fragment that the fixup touches, mask in the // bits from the fixup value. - for (unsigned i = 0; i != NumBytes; ++i) + for (unsigned i = 0; i != NumBytes; ++i) { + Data[Offset + i] &= ~uint8_t((Value >> (i * 8)) & 0xff); Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); + } } } // end anonymous namespace Index: lib/Target/ARM/Disassembler/ARMDisassembler.cpp =================================================================== --- lib/Target/ARM/Disassembler/ARMDisassembler.cpp (revision 163390) +++ lib/Target/ARM/Disassembler/ARMDisassembler.cpp (working copy) @@ -2090,14 +2090,17 @@ 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; }