1 //===-- SystemZMCAsmBackend.cpp - SystemZ assembler backend ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "MCTargetDesc/SystemZMCTargetDesc.h"
11 #include "MCTargetDesc/SystemZMCFixups.h"
12 #include "llvm/MC/MCAsmBackend.h"
13 #include "llvm/MC/MCELFObjectWriter.h"
14 #include "llvm/MC/MCFixupKindInfo.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCObjectWriter.h"
20 // Value is a fully-resolved relocation value: Symbol + Addend [- Pivot].
21 // Return the bits that should be installed in a relocation field for
23 static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value) {
24 if (Kind < FirstTargetFixupKind)
27 switch (unsigned(Kind)) {
28 case SystemZ::FK_390_PC16DBL:
29 case SystemZ::FK_390_PC32DBL:
30 case SystemZ::FK_390_PLT16DBL:
31 case SystemZ::FK_390_PLT32DBL:
32 return (int64_t)Value / 2;
35 llvm_unreachable("Unknown fixup kind!");
38 // If Opcode is a relaxable interprocedural reference, return the relaxed form,
39 // otherwise return 0.
40 static unsigned getRelaxedOpcode(unsigned Opcode) {
42 case SystemZ::BRAS: return SystemZ::BRASL;
48 class SystemZMCAsmBackend : public MCAsmBackend {
51 SystemZMCAsmBackend(uint8_t osABI)
54 // Override MCAsmBackend
55 virtual unsigned getNumFixupKinds() const LLVM_OVERRIDE {
56 return SystemZ::NumTargetFixupKinds;
58 virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const
60 virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
61 uint64_t Value) const LLVM_OVERRIDE;
62 virtual bool mayNeedRelaxation(const MCInst &Inst) const LLVM_OVERRIDE;
63 virtual bool fixupNeedsRelaxation(const MCFixup &Fixup,
65 const MCRelaxableFragment *Fragment,
66 const MCAsmLayout &Layout) const
68 virtual void relaxInstruction(const MCInst &Inst,
69 MCInst &Res) const LLVM_OVERRIDE;
70 virtual bool writeNopData(uint64_t Count,
71 MCObjectWriter *OW) const LLVM_OVERRIDE;
72 virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const
74 return createSystemZObjectWriter(OS, OSABI);
76 virtual bool doesSectionRequireSymbols(const MCSection &Section) const
81 } // end anonymous namespace
83 const MCFixupKindInfo &
84 SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
85 const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = {
86 { "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
87 { "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
88 { "FK_390_PLT16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
89 { "FK_390_PLT32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel }
92 if (Kind < FirstTargetFixupKind)
93 return MCAsmBackend::getFixupKindInfo(Kind);
95 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
97 return Infos[Kind - FirstTargetFixupKind];
100 void SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
101 unsigned DataSize, uint64_t Value) const {
102 MCFixupKind Kind = Fixup.getKind();
103 unsigned Offset = Fixup.getOffset();
104 unsigned Size = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
106 assert(Offset + Size <= DataSize && "Invalid fixup offset!");
108 // Big-endian insertion of Size bytes.
109 Value = extractBitsForFixup(Kind, Value);
110 unsigned ShiftValue = (Size * 8) - 8;
111 for (unsigned I = 0; I != Size; ++I) {
112 Data[Offset + I] |= uint8_t(Value >> ShiftValue);
117 bool SystemZMCAsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
118 return getRelaxedOpcode(Inst.getOpcode()) != 0;
122 SystemZMCAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
124 const MCRelaxableFragment *Fragment,
125 const MCAsmLayout &Layout) const {
126 // At the moment we just need to relax 16-bit fields to wider fields.
127 Value = extractBitsForFixup(Fixup.getKind(), Value);
128 return (int16_t)Value != (int64_t)Value;
131 void SystemZMCAsmBackend::relaxInstruction(const MCInst &Inst,
133 unsigned Opcode = getRelaxedOpcode(Inst.getOpcode());
134 assert(Opcode && "Unexpected insn to relax");
136 Res.setOpcode(Opcode);
139 bool SystemZMCAsmBackend::writeNopData(uint64_t Count,
140 MCObjectWriter *OW) const {
141 for (uint64_t I = 0; I != Count; ++I)
146 MCAsmBackend *llvm::createSystemZMCAsmBackend(const Target &T, StringRef TT,
148 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS());
149 return new SystemZMCAsmBackend(OSABI);