diff options
author | Jim Grosbach <grosbach@apple.com> | 2010-11-11 18:04:49 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2010-11-11 18:04:49 +0000 |
commit | c466b937dbdbaabeef0097fe340de1b8f49a3508 (patch) | |
tree | 818b2b9b8fcf077d6eb3c05032e47f51a86b6f72 | |
parent | 8a83d54528c197675ba0f21ebe95ac30fa3d8841 (diff) |
Encoding of destination fixup for ARM branch and conditional branch
instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118801 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/ARM/ARMAsmBackend.cpp | 14 | ||||
-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 | 14 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 31 |
5 files changed, 57 insertions, 13 deletions
diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index be3c711166..54cd1aefd4 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -138,12 +138,13 @@ public: } }; -static unsigned getFixupKindLog2Size(unsigned Kind) { +static unsigned getFixupKindNumBytes(unsigned Kind) { switch (Kind) { default: llvm_unreachable("Unknown fixup kind!"); - case FK_Data_4: return 2; + case FK_Data_4: return 4; case ARM::fixup_arm_pcrel_12: return 2; case ARM::fixup_arm_vfp_pcrel_12: return 1; + case ARM::fixup_arm_branch: return 3; } } @@ -156,16 +157,17 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case ARM::fixup_arm_pcrel_12: // ARM PC-relative values are offset by 8. return Value - 8; + case ARM::fixup_arm_branch: case ARM::fixup_arm_vfp_pcrel_12: - // The VFP ld/st immediate value doesn't encode the low two bits since - // they're always zero. Offset by 8 just as above. + // These values don't encode the low two bits since they're always zero. + // Offset by 8 just as above. return (Value - 8) >> 2; } } void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF, - uint64_t Value) const { - unsigned NumBytes = getFixupKindLog2Size(Fixup.getKind()); + uint64_t Value) const { + unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); Value = adjustFixupValue(Fixup.getKind(), Value); assert(Fixup.getOffset() + NumBytes <= DF.getContents().size() && diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 4aa73851a0..e85c7d9287 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -161,6 +161,8 @@ namespace { // are already handled elsewhere. They are placeholders to allow this // encoder to continue to function until the MC encoder is sufficiently // far along that this one can be eliminated entirely. + unsigned getBranchTargetOpValue(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 3d91d52a6b..8d26f213e6 100644 --- a/lib/Target/ARM/ARMFixupKinds.h +++ b/lib/Target/ARM/ARMFixupKinds.h @@ -20,7 +20,14 @@ enum Fixups { // fixup_arm_vfp_pcrel_12 - 12-bit PC relative relocation for symbol addresses // used in VFP instructions where the lower 2 bits are not encoded (so it's // encoded as an 8-bit immediate). - fixup_arm_vfp_pcrel_12 + fixup_arm_vfp_pcrel_12, + // fixup_arm_brnach - 24-bit PC relative relocation for direct branch + // instructions. + fixup_arm_branch, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind }; } } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 837a4fba0d..3465e9879e 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -274,7 +274,9 @@ def sube_live_carry : // // Branch target. -def brtarget : Operand<OtherVT>; +def brtarget : Operand<OtherVT> { + string EncoderMethod = "getBranchTargetOpValue"; +} // A list of registers separated by comma. Used by load/store multiple. def reglist : Operand<i32> { @@ -1363,7 +1365,10 @@ let isBranch = 1, isTerminator = 1 in { let isBarrier = 1 in { let isPredicable = 1 in def B : ABXI<0b1010, (outs), (ins brtarget:$target), IIC_Br, - "b\t$target", [(br bb:$target)]>; + "b\t$target", [(br bb:$target)]> { + bits<24> target; + let Inst{23-0} = target; + } let isNotDuplicable = 1, isIndirectBranch = 1, // FIXME: $imm field is not specified by asm string. Mark as cgonly. @@ -1406,7 +1411,10 @@ let isBranch = 1, isTerminator = 1 in { // a two-value operand where a dag node expects two operands. :( def Bcc : ABI<0b1010, (outs), (ins brtarget:$target), IIC_Br, "b", "\t$target", - [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]>; + [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> { + bits<24> target; + let Inst{23-0} = target; + } } // Branch and Exchange Jazelle -- for disassembly only diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 89c0d2d058..0207491970 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -41,12 +41,14 @@ public: ~ARMMCCodeEmitter() {} - unsigned getNumFixupKinds() const { return 2; } + unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[] = { - { "fixup_arm_pcrel_12", 2, 12, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_arm_vfp_pcrel_12", 3, 8, MCFixupKindInfo::FKF_IsPCRel }, + // name offset bits flags + { "fixup_arm_pcrel_12", 2, 12, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_arm_vfp_pcrel_12", 3, 8, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, }; if (Kind < FirstTargetFixupKind) @@ -72,6 +74,11 @@ public: unsigned &Reg, unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const; + /// getBranchTargetOpValue - Return encoding info for 24-bit immediate + /// branch target. + uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const; + /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' /// operand. uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, @@ -247,6 +254,24 @@ EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, return isAdd; } +/// getBranchTargetOpValue - Return encoding info for 24-bit immediate +/// branch target. +uint32_t ARMMCCodeEmitter:: +getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const { + const MCOperand &MO = MI.getOperand(OpIdx); + + // If the destination is an immediate, we have nothing to do. + if (MO.isImm()) return MO.getImm(); + assert (MO.isExpr() && "Unexpected branch target type!"); + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_branch); + Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + + // All of the information is in the fixup. + return 0; +} + /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand. uint32_t ARMMCCodeEmitter:: getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, |