blob: 615ba6f0fd7f225d61cb2effe51192b118182ae6 [file] [log] [blame]
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001//===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly 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/// \file
11///
12/// The AMDGPUAsmPrinter is used to print both assembly string and also binary
13/// code. When passed an MCAsmStreamer it prints assembly and when passed
14/// an MCObjectStreamer it outputs binary code.
15//
16//===----------------------------------------------------------------------===//
17//
18
19
20#include "AMDGPUAsmPrinter.h"
21#include "AMDGPU.h"
Tom Stellard9a256302013-04-15 17:51:35 +000022#include "SIDefines.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000023#include "SIMachineFunctionInfo.h"
24#include "SIRegisterInfo.h"
Tom Stellardbf1efe62013-04-15 17:51:30 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCSectionELF.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000027#include "llvm/MC/MCStreamer.h"
Tom Stellardbf1efe62013-04-15 17:51:30 +000028#include "llvm/Support/ELF.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000029#include "llvm/Support/TargetRegistry.h"
Chandler Carruth58a2cbe2013-01-02 10:22:59 +000030#include "llvm/Target/TargetLoweringObjectFile.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000031
32using namespace llvm;
33
34
35static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
36 MCStreamer &Streamer) {
37 return new AMDGPUAsmPrinter(tm, Streamer);
38}
39
40extern "C" void LLVMInitializeR600AsmPrinter() {
41 TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
42}
43
44/// We need to override this function so we can avoid
45/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
46bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
47 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
48 if (STM.dumpCode()) {
49#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
50 MF.dump();
51#endif
52 }
53 SetupMachineFunction(MF);
Tom Stellard3ce2ec82013-02-05 17:09:11 +000054 if (OutStreamer.hasRawTextSupport()) {
55 OutStreamer.EmitRawText("@" + MF.getName() + ":");
56 }
Tom Stellardf98f2ce2012-12-11 21:25:42 +000057 if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
Tom Stellardbf1efe62013-04-15 17:51:30 +000058 const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
59 .getELFSection(".AMDGPU.config",
60 ELF::SHT_NULL, 0,
61 SectionKind::getReadOnly());
62 OutStreamer.SwitchSection(ConfigSection);
Tom Stellardf98f2ce2012-12-11 21:25:42 +000063 EmitProgramInfo(MF);
64 }
Tom Stellardbf1efe62013-04-15 17:51:30 +000065 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
Tom Stellardf98f2ce2012-12-11 21:25:42 +000066 EmitFunctionBody();
67 return false;
68}
69
70void AMDGPUAsmPrinter::EmitProgramInfo(MachineFunction &MF) {
71 unsigned MaxSGPR = 0;
72 unsigned MaxVGPR = 0;
73 bool VCCUsed = false;
74 const SIRegisterInfo * RI =
75 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
76
77 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
78 BB != BB_E; ++BB) {
79 MachineBasicBlock &MBB = *BB;
80 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
81 I != E; ++I) {
82 MachineInstr &MI = *I;
83
84 unsigned numOperands = MI.getNumOperands();
85 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
86 MachineOperand & MO = MI.getOperand(op_idx);
87 unsigned maxUsed;
88 unsigned width = 0;
89 bool isSGPR = false;
90 unsigned reg;
91 unsigned hwReg;
92 if (!MO.isReg()) {
93 continue;
94 }
95 reg = MO.getReg();
96 if (reg == AMDGPU::VCC) {
97 VCCUsed = true;
98 continue;
99 }
100 switch (reg) {
101 default: break;
102 case AMDGPU::EXEC:
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000103 case AMDGPU::M0:
104 continue;
105 }
106
107 if (AMDGPU::SReg_32RegClass.contains(reg)) {
108 isSGPR = true;
109 width = 1;
110 } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
111 isSGPR = false;
112 width = 1;
113 } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
114 isSGPR = true;
115 width = 2;
116 } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
117 isSGPR = false;
118 width = 2;
Christian Konig4d0e8a82013-04-10 08:39:16 +0000119 } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
120 isSGPR = false;
121 width = 3;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000122 } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
123 isSGPR = true;
124 width = 4;
125 } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
126 isSGPR = false;
127 width = 4;
128 } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
129 isSGPR = true;
130 width = 8;
Tom Stellard36ba9092013-02-07 17:02:09 +0000131 } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
132 isSGPR = false;
133 width = 8;
134 } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
135 isSGPR = false;
136 width = 16;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000137 } else {
138 assert(!"Unknown register class");
139 }
Tom Stellard184f5c12013-02-07 19:39:45 +0000140 hwReg = RI->getEncodingValue(reg) & 0xff;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000141 maxUsed = hwReg + width - 1;
142 if (isSGPR) {
143 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
144 } else {
145 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
146 }
147 }
148 }
149 }
150 if (VCCUsed) {
151 MaxSGPR += 2;
152 }
153 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
Tom Stellard9a256302013-04-15 17:51:35 +0000154 unsigned RsrcReg;
155 switch (MFI->ShaderType) {
156 default: // Fall through
157 case ShaderType::COMPUTE: RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
158 case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
159 case ShaderType::PIXEL: RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
160 case ShaderType::VERTEX: RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
161 }
162
163 OutStreamer.EmitIntValue(RsrcReg, 4);
164 OutStreamer.EmitIntValue(S_00B028_VGPRS(MaxVGPR / 4) | S_00B028_SGPRS(MaxSGPR / 8), 4);
165 if (MFI->ShaderType == ShaderType::PIXEL) {
166 OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
167 OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
168 }
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000169}