blob: 0a89a96862ecd8cb122b14131d162c8cacb25d29 [file] [log] [blame]
Ulrich Weigand5f613df2013-05-06 16:15:19 +00001//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Streams SystemZ assembly language and associated data, in the form of
11// MCInsts and MCExprs respectively.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SystemZAsmPrinter.h"
16#include "InstPrinter/SystemZInstPrinter.h"
17#include "SystemZConstantPoolValue.h"
18#include "SystemZMCInstLower.h"
19#include "llvm/CodeGen/MachineModuleInfoImpls.h"
20#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
21#include "llvm/MC/MCExpr.h"
Richard Sandiford9ab97cd2013-09-25 10:20:08 +000022#include "llvm/MC/MCInstBuilder.h"
Ulrich Weigand5f613df2013-05-06 16:15:19 +000023#include "llvm/MC/MCStreamer.h"
24#include "llvm/Support/TargetRegistry.h"
25#include "llvm/Target/Mangler.h"
26
27using namespace llvm;
28
Richard Sandiford652784e2013-09-25 11:11:53 +000029// Return an RI instruction like MI with opcode Opcode, but with the
30// GR64 register operands turned into GR32s.
31static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
32 return MCInstBuilder(Opcode)
33 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
34 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
35 .addImm(MI->getOperand(2).getImm());
36}
37
Richard Sandiford0755c932013-10-01 11:26:28 +000038// Return an RI instruction like MI with opcode Opcode, but with the
39// R2 register turned into a GR64.
40static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
41 return MCInstBuilder(Opcode)
42 .addReg(MI->getOperand(0).getReg())
43 .addReg(MI->getOperand(1).getReg())
44 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
45 .addImm(MI->getOperand(3).getImm())
46 .addImm(MI->getOperand(4).getImm())
47 .addImm(MI->getOperand(5).getImm());
48}
49
Ulrich Weigand5f613df2013-05-06 16:15:19 +000050void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
Richard Sandifordf348f832013-09-25 10:37:17 +000051 SystemZMCInstLower Lower(Mang, MF->getContext(), *this);
Ulrich Weigand5f613df2013-05-06 16:15:19 +000052 MCInst LoweredMI;
Richard Sandiford9ab97cd2013-09-25 10:20:08 +000053 switch (MI->getOpcode()) {
54 case SystemZ::Return:
55 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
56 break;
57
Richard Sandifordf348f832013-09-25 10:37:17 +000058 case SystemZ::CallBRASL:
59 LoweredMI = MCInstBuilder(SystemZ::BRASL)
60 .addReg(SystemZ::R14D)
61 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
62 break;
63
64 case SystemZ::CallBASR:
65 LoweredMI = MCInstBuilder(SystemZ::BASR)
66 .addReg(SystemZ::R14D)
67 .addReg(MI->getOperand(0).getReg());
68 break;
69
70 case SystemZ::CallJG:
71 LoweredMI = MCInstBuilder(SystemZ::JG)
72 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
73 break;
74
75 case SystemZ::CallBR:
76 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D);
77 break;
78
Richard Sandiford652784e2013-09-25 11:11:53 +000079 case SystemZ::IILF64:
80 LoweredMI = MCInstBuilder(SystemZ::IILF)
81 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
82 .addImm(MI->getOperand(2).getImm());
83 break;
84
Richard Sandiford01240232013-10-01 13:02:28 +000085 case SystemZ::IIHF64:
86 LoweredMI = MCInstBuilder(SystemZ::IIHF)
87 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
88 .addImm(MI->getOperand(2).getImm());
89 break;
90
Richard Sandiford0755c932013-10-01 11:26:28 +000091 case SystemZ::RISBHH:
92 case SystemZ::RISBHL:
93 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
94 break;
95
96 case SystemZ::RISBLH:
97 case SystemZ::RISBLL:
98 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
99 break;
100
Richard Sandiford652784e2013-09-25 11:11:53 +0000101#define LOWER_LOW(NAME) \
102 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
103
104 LOWER_LOW(IILL);
105 LOWER_LOW(IILH);
106 LOWER_LOW(NILL);
107 LOWER_LOW(NILH);
108 LOWER_LOW(NILF);
109 LOWER_LOW(OILL);
110 LOWER_LOW(OILH);
111 LOWER_LOW(OILF);
112 LOWER_LOW(XILF);
113
114#undef LOWER_LOW
115
Richard Sandiford9ab97cd2013-09-25 10:20:08 +0000116 default:
Richard Sandifordf348f832013-09-25 10:37:17 +0000117 Lower.lower(MI, LoweredMI);
Richard Sandiford9ab97cd2013-09-25 10:20:08 +0000118 break;
119 }
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000120 OutStreamer.EmitInstruction(LoweredMI);
121}
122
123// Convert a SystemZ-specific constant pool modifier into the associated
124// MCSymbolRefExpr variant kind.
125static MCSymbolRefExpr::VariantKind
126getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
127 switch (Modifier) {
128 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
129 }
130 llvm_unreachable("Invalid SystemCPModifier!");
131}
132
133void SystemZAsmPrinter::
134EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
135 SystemZConstantPoolValue *ZCPV =
136 static_cast<SystemZConstantPoolValue*>(MCPV);
137
138 const MCExpr *Expr =
139 MCSymbolRefExpr::Create(Mang->getSymbol(ZCPV->getGlobalValue()),
140 getModifierVariantKind(ZCPV->getModifier()),
141 OutContext);
142 uint64_t Size = TM.getDataLayout()->getTypeAllocSize(ZCPV->getType());
143
144 OutStreamer.EmitValue(Expr, Size);
145}
146
147bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
148 unsigned OpNo,
149 unsigned AsmVariant,
150 const char *ExtraCode,
151 raw_ostream &OS) {
152 if (ExtraCode && *ExtraCode == 'n') {
153 if (!MI->getOperand(OpNo).isImm())
154 return true;
155 OS << -int64_t(MI->getOperand(OpNo).getImm());
156 } else {
157 SystemZMCInstLower Lower(Mang, MF->getContext(), *this);
158 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo)));
159 SystemZInstPrinter::printOperand(MO, OS);
160 }
161 return false;
162}
163
164bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
165 unsigned OpNo,
166 unsigned AsmVariant,
167 const char *ExtraCode,
168 raw_ostream &OS) {
169 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(),
170 MI->getOperand(OpNo + 1).getImm(),
171 MI->getOperand(OpNo + 2).getReg(), OS);
172 return false;
173}
174
175void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) {
176 if (Subtarget->isTargetELF()) {
177 const TargetLoweringObjectFileELF &TLOFELF =
178 static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
179
180 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
181
182 // Output stubs for external and common global variables.
183 MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
184 if (!Stubs.empty()) {
185 OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
186 const DataLayout *TD = TM.getDataLayout();
187
188 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
189 OutStreamer.EmitLabel(Stubs[i].first);
190 OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
Rafael Espindola64e1af82013-07-02 15:49:13 +0000191 TD->getPointerSize(0));
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000192 }
193 Stubs.clear();
194 }
195 }
196}
197
198// Force static initialization.
199extern "C" void LLVMInitializeSystemZAsmPrinter() {
200 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
201}