diff options
-rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 20 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 16 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 2 |
3 files changed, 36 insertions, 2 deletions
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 43f1194897..f9969b9e6f 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -290,6 +290,26 @@ class InstThumb<AddrMode am, int sz, IndexMode im, let DecoderNamespace = "Thumb"; } +// Pseudo-instructions for alternate assembly syntax (never used by codegen). +// These are aliases that require C++ handling to convert to the target +// instruction, while InstAliases can be handled directly by tblgen. +class AsmPseudoInst<dag iops> + : InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain, + "", NoItinerary> { + let OutOperandList = (ops); + let InOperandList = iops; + let Pattern = []; + let isCodeGenOnly = 0; // So we get asm matcher for it. + let isPseudo = 1; +} + +class ARMAsmPseudo<dag iops> : AsmPseudoInst<iops>, Requires<[IsARM]>; +class tAsmPseudo<dag iops> : AsmPseudoInst<iops>, Requires<[IsThumb]>; +class t2AsmPseudo<dag iops> : AsmPseudoInst<iops>, Requires<[IsThumb2]>; +class VFP2AsmPseudo<dag iops> : AsmPseudoInst<iops>, Requires<[HasVFP2]>; +class NEONAsmPseudo<dag iops> : AsmPseudoInst<iops>, Requires<[HasNEON]>; + +// Pseudo instructions for the code generator. class PseudoInst<dag oops, dag iops, InstrItinClass itin, list<dag> pattern> : InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain, "", itin> { diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 0732060c88..46ea29f192 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -761,6 +761,11 @@ public: return (Val > -256 && Val < 256) || Val == INT32_MIN; } bool isAddrMode5() const { + // If we have an immediate that's not a constant, treat it as a label + // reference needing a fixup. If it is a constant, it's something else + // and we reject it. + if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm())) + return true; if (!isMemory() || Memory.Alignment != 0) return false; // Check for register offset. if (Memory.OffsetRegNum) return false; @@ -768,7 +773,7 @@ public: if (!Memory.OffsetImm) return true; int64_t Val = Memory.OffsetImm->getValue(); return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || - Val == INT32_MIN; + Val == INT32_MIN; } bool isMemTBB() const { if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || @@ -1375,6 +1380,15 @@ public: void addAddrMode5Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); + // If we have an immediate that's not a constant, treat it as a label + // reference needing a fixup. If it is a constant, it's something else + // and we reject it. + if (isImm()) { + Inst.addOperand(MCOperand::CreateExpr(getImm())); + Inst.addOperand(MCOperand::CreateImm(0)); + return; + } + // The lower two bits are always zero and as such are not encoded. int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index c31c5e6b84..1bc585b46d 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -63,7 +63,7 @@ public: { "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, -{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, { "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel | |