summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/ARMAsmBackend.cpp26
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp2
-rw-r--r--lib/Target/ARM/ARMFixupKinds.h9
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td4
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td2
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp35
-rw-r--r--utils/TableGen/EDEmitter.cpp2
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp1
8 files changed, 73 insertions, 8 deletions
diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp
index ffa9307c9a..cb0c54386e 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 823947395f..101c07b4db 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 d21a81a0fc..48d495396e 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 f93d8ff2e3..71948e1b64 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -293,6 +293,10 @@ def brtarget : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
}
+def uncondbrtarget : Operand<OtherVT> {
+ let EncoderMethod = "getUnconditionalBranchTargetOpValue";
+}
+
// Call target.
def bltarget : Operand<i32> {
// Encoded the same as branch targets.
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index c83f5bd06b..2fedb5398e 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 833bd22c74..7f34ee96e3 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<MCFixup> &Fixups) const;
+ /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
+ /// immediate Thumb2 direct branch target.
+ uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &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<ARMSubtarget>();
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<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;
+
+ 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 be1ed8f792..dede4b0244 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 e3cad1aaa8..ccd3efd980 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)