diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index ffa9307c9a7..cb0c54386ed 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -140,11 +140,32 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { // These values don't encode the low two bits since they're always zero. // Offset by 8 just as above. return 0xffffff & ((Value - 8) >> 2); - case ARM::fixup_t2_branch: { + case ARM::fixup_t2_uncondbranch: { Value = Value - 4; 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 + out |= (Value & 0x0007FF); // imm11 field + + uint64_t swapped = (out & 0xFFFF0000) >> 16; + swapped |= (out & 0x0000FFFF) << 16; + return swapped; + } + case ARM::fixup_t2_condbranch: { + Value = Value - 4; + Value >>= 1; // Low bit is not encoded. + + uint64_t out = 0; out |= (Value & 0x80000) << 7; // S bit out |= (Value & 0x40000) >> 7; // J2 bit out |= (Value & 0x20000) >> 4; // J1 bit @@ -332,7 +353,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { case FK_Data_4: case ARM::fixup_t2_ldst_pcrel_12: - case ARM::fixup_t2_branch: + case ARM::fixup_t2_condbranch: + case ARM::fixup_t2_uncondbranch: case ARM::fixup_t2_pcrel_10: case ARM::fixup_arm_thumb_bl: case ARM::fixup_arm_thumb_blx: diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 823947395f2..101c07b4db6 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -183,6 +183,8 @@ namespace { const { return 0; } unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getUnconditionalBranchTargetOpValue(const MachineInstr &MI, + unsigned Op) const { return 0; } unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op) diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h index d21a81a0fcb..48d495396e2 100644 --- a/lib/Target/ARM/ARMFixupKinds.h +++ b/lib/Target/ARM/ARMFixupKinds.h @@ -36,9 +36,12 @@ enum Fixups { // fixup_arm_branch - 24-bit PC relative relocation for direct branch // instructions. fixup_arm_branch, - // fixup_t2_branch - 20-bit PC relative relocation for Thumb2 direct branch - // instructions. - fixup_t2_branch, + // fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct + // uconditional branch instructions. + fixup_t2_condbranch, + // fixup_t2_uncondbranch - 20-bit PC relative relocation for Thumb2 direct + // branch unconditional branch instructions. + fixup_t2_uncondbranch, // fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions. fixup_arm_thumb_br, diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index f93d8ff2e30..71948e1b641 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -293,6 +293,10 @@ def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; } +def uncondbrtarget : Operand { + let EncoderMethod = "getUnconditionalBranchTargetOpValue"; +} + // Call target. def bltarget : Operand { // Encoded the same as branch targets. diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index c83f5bd06b1..2fedb5398eb 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -2961,7 +2961,7 @@ def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, let isBranch = 1, isTerminator = 1, isBarrier = 1 in { let isPredicable = 1 in -def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br, +def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br, "b.w\t$target", [(br bb:$target)]> { let Inst{31-27} = 0b11110; diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 833bd22c748..7f34ee96e37 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -57,7 +57,8 @@ public: MCFixupKindInfo::FKF_IsAligned}, { "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, -{ "fixup_t2_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_thumb_blx", 7, 21, MCFixupKindInfo::FKF_IsPCRel }, @@ -122,6 +123,12 @@ public: uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const; + /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit + /// immediate Thumb2 direct branch target. + uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const; + + /// getAdrLabelOpValue - Return encoding info for 12-bit immediate /// ADR label target. uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, @@ -499,10 +506,34 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, // coupling between MC and TM anywhere we can help it. const ARMSubtarget &Subtarget = TM.getSubtarget(); if (Subtarget.isThumb2()) - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_branch, Fixups); + return + ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups); return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups); } +/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit +/// immediate branch target. +uint32_t ARMMCCodeEmitter:: +getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &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; + + if (I ^ J2) + Val &= ~0x200000; + else + Val |= 0x200000; + + return Val; +} + /// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label /// target. uint32_t ARMMCCodeEmitter:: diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index be1ed8f792b..dede4b02446 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -322,6 +322,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, PCR("offset32"); PCR("offset64"); PCR("brtarget"); + PCR("uncondbrtarget"); PCR("bltarget"); return 1; @@ -587,6 +588,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("neon_vcvt_imm32"); MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ? MISC("t_brtarget", "kOperandTypeARMBranchTarget"); // ? MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ? MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ? diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index e3cad1aaa89..ccd3efd980a 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -857,6 +857,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32imm_pcrel", TYPE_REL32) TYPE("SSECC", TYPE_IMM3) TYPE("brtarget", TYPE_RELv) + TYPE("uncondbrtarget", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) TYPE("f80mem", TYPE_M80FP) TYPE("lea32mem", TYPE_LEA)