diff options
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 12 | ||||
-rw-r--r-- | lib/MC/MachObjectWriter.cpp | 3 | ||||
-rw-r--r-- | lib/Target/ARM/ARMAsmBackend.cpp | 9 | ||||
-rw-r--r-- | lib/Target/ARM/ARMCodeEmitter.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMFixupKinds.h | 9 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 22 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 38 | ||||
-rw-r--r-- | test/MC/ARM/arm_fixups.s | 2 | ||||
-rw-r--r-- | utils/TableGen/EDEmitter.cpp | 7 |
9 files changed, 88 insertions, 16 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 4dbb538..629d746 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -1503,7 +1503,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, break; } break; - case ARM::fixup_arm_branch: + case ARM::fixup_arm_uncondbranch: switch (Modifier) { case MCSymbolRefExpr::VK_ARM_PLT: Type = ELF::R_ARM_PLT32; @@ -1513,6 +1513,9 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, break; } break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; case ARM::fixup_arm_movt_hi16: case ARM::fixup_arm_movt_hi16_pcrel: Type = ELF::R_ARM_MOVT_PREL; @@ -1565,11 +1568,12 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, case ARM::fixup_arm_thumb_br: assert(0 && "Unimplemented"); break; - case ARM::fixup_arm_branch: - // FIXME: Differentiate between R_ARM_CALL and - // R_ARM_JUMP24 (latter used for conditional jumps) + case ARM::fixup_arm_uncondbranch: Type = ELF::R_ARM_CALL; break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; case ARM::fixup_arm_movt_hi16: Type = ELF::R_ARM_MOVT_ABS; break; diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 1fb0f99..8af07c7 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -940,7 +940,8 @@ public: case ARM::fixup_arm_ldst_pcrel_12: case ARM::fixup_arm_pcrel_10: case ARM::fixup_arm_adr_pcrel_12: - case ARM::fixup_arm_branch: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: RelocType = unsigned(macho::RIT_ARM_Branch24Bit); // Report as 'long', even though that is not quite accurate. Log2Size = llvm::Log2_32(4); diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index fa8809d..ec23449 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -67,7 +67,8 @@ public: { "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, -{ "fixup_arm_branch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_uncondbranch", 0, 24, 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 }, @@ -254,7 +255,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { return swapped; } - case ARM::fixup_arm_branch: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: // 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); @@ -454,7 +456,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { case ARM::fixup_arm_ldst_pcrel_12: case ARM::fixup_arm_pcrel_10: case ARM::fixup_arm_adr_pcrel_12: - case ARM::fixup_arm_branch: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: return 3; case FK_Data_4: diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index fc12ddc..9bbf6a03 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -187,6 +187,8 @@ namespace { const { return 0; } unsigned getUnconditionalBranchTargetOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getARMBranchTargetOpValue(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 9425f22..3d175e3 100644 --- a/lib/Target/ARM/ARMFixupKinds.h +++ b/lib/Target/ARM/ARMFixupKinds.h @@ -40,9 +40,12 @@ enum Fixups { // fixup_t2_adr_pcrel_12 - 12-bit PC relative relocation for the ADR // instruction. fixup_t2_adr_pcrel_12, - // fixup_arm_branch - 24-bit PC relative relocation for direct branch - // instructions. - fixup_arm_branch, + // fixup_arm_condbranch - 24-bit PC relative relocation for conditional branch + // instructions. + fixup_arm_condbranch, + // fixup_arm_uncondbranch - 24-bit PC relative relocation for + // branch instructions. (unconditional) + fixup_arm_uncondbranch, // fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct // uconditional branch instructions. fixup_t2_condbranch, diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index e6addfe..bd58fcc 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -293,20 +293,36 @@ def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{ // // Branch target. +// FIXME: rename brtarget to t2_brtarget def brtarget : Operand<OtherVT> { let EncoderMethod = "getBranchTargetOpValue"; } +// FIXME: get rid of this one? def uncondbrtarget : Operand<OtherVT> { let EncoderMethod = "getUnconditionalBranchTargetOpValue"; } +// Branch target for ARM. Handles conditional/unconditional +def br_target : Operand<OtherVT> { + let EncoderMethod = "getARMBranchTargetOpValue"; +} + // Call target. +// FIXME: rename bltarget to t2_bl_target? def bltarget : Operand<i32> { // Encoded the same as branch targets. let EncoderMethod = "getBranchTargetOpValue"; } +// Call target for ARM. Handles conditional/unconditional +// FIXME: rename bl_target to t2_bltarget? +def bl_target : Operand<i32> { + // Encoded the same as branch targets. + let EncoderMethod = "getARMBranchTargetOpValue"; +} + + // A list of registers separated by comma. Used by load/store multiple. def RegListAsmOperand : AsmOperandClass { let Name = "RegList"; @@ -1271,7 +1287,7 @@ let isCall = 1, D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR], Uses = [SP] in { - def BL : ABXI<0b1011, (outs), (ins bltarget:$func, variable_ops), + def BL : ABXI<0b1011, (outs), (ins bl_target:$func, variable_ops), IIC_Br, "bl\t$func", [(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsNotDarwin]> { @@ -1280,7 +1296,7 @@ let isCall = 1, let Inst{23-0} = func; } - def BL_pred : ABI<0b1011, (outs), (ins bltarget:$func, variable_ops), + def BL_pred : ABI<0b1011, (outs), (ins bl_target:$func, variable_ops), IIC_Br, "bl", "\t$func", [(ARMcall_pred tglobaladdr:$func)]>, Requires<[IsARM, IsNotDarwin]> { @@ -1456,7 +1472,7 @@ let isBranch = 1, isTerminator = 1 in { // FIXME: should be able to write a pattern for ARMBrcond, but can't use // a two-value operand where a dag node expects two operands. :( - def Bcc : ABI<0b1010, (outs), (ins brtarget:$target), + def Bcc : ABI<0b1010, (outs), (ins br_target:$target), IIC_Br, "b", "\t$target", [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> { bits<24> target; diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index a309122..94321ad 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -99,6 +99,10 @@ public: uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const; + /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate + /// branch target. + uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const; /// getAdrLabelOpValue - Return encoding info for 12-bit immediate /// ADR label target. @@ -473,6 +477,23 @@ getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups); } +/// Return true if this branch has a non-always predication +static bool HasConditionalBranch(const MCInst &MI) { + int NumOp = MI.getNumOperands(); + if (NumOp >= 2) { + for (int i = 0; i < NumOp-1; ++i) { + const MCOperand &MCOp1 = MI.getOperand(i); + const MCOperand &MCOp2 = MI.getOperand(i + 1); + if (MCOp1.isImm() && MCOp2.isReg() && + (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) { + if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL) + return true; + } + } + } + return false; +} + /// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch /// target. uint32_t ARMMCCodeEmitter:: @@ -483,9 +504,24 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, if (Subtarget->isThumb2()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups); - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups); + return getARMBranchTargetOpValue(MI, OpIdx, Fixups); } +/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch +/// target. +uint32_t ARMMCCodeEmitter:: +getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const { + if (HasConditionalBranch(MI)) + return ::getBranchTargetOpValue(MI, OpIdx, + ARM::fixup_arm_condbranch, Fixups); + return ::getBranchTargetOpValue(MI, OpIdx, + ARM::fixup_arm_uncondbranch, Fixups); +} + + + + /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit /// immediate branch target. uint32_t ARMMCCodeEmitter:: diff --git a/test/MC/ARM/arm_fixups.s b/test/MC/ARM/arm_fixups.s index 146de9c..0dceb83 100644 --- a/test/MC/ARM/arm_fixups.s +++ b/test/MC/ARM/arm_fixups.s @@ -2,6 +2,6 @@ // RUN: FileCheck < %t %s // CHECK: bl _printf @ encoding: [A,A,A,0xeb] -// CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_branch +// CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_uncondbranch bl _printf
\ No newline at end of file diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 7051f2e..f00f79d 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -325,6 +325,9 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, PCR("uncondbrtarget"); PCR("bltarget"); + // all I, ARM mode only, conditional/unconditional + PCR("br_target"); + PCR("bl_target"); return 1; } @@ -600,6 +603,10 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ? MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ? MISC("bltarget", "kOperandTypeARMBranchTarget"); // ? + + MISC("br_target", "kOperandTypeARMBranchTarget"); // ? + MISC("bl_target", "kOperandTypeARMBranchTarget"); // ? + MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ? MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ? MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I |