1 /*
2 * Copyright 2011 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #ifndef __NV50_IR_TARGET_H__
24 #define __NV50_IR_TARGET_H__
25
26 #include "nv50_ir.h"
27
28 namespace nv50_ir {
29
30 struct RelocInfo;
31
32 struct RelocEntry
33 {
34 enum Type
35 {
36 TYPE_CODE,
37 TYPE_BUILTIN,
38 TYPE_DATA
39 };
40
41 uint32_t data;
42 uint32_t mask;
43 uint32_t offset;
44 int8_t bitPos;
45 Type type;
46
47 inline void apply(uint32_t *binary, const RelocInfo *info) const;
48 };
49
50 struct RelocInfo
51 {
52 uint32_t codePos;
53 uint32_t libPos;
54 uint32_t dataPos;
55
56 uint32_t count;
57
58 RelocEntry entry[0];
59 };
60
61 struct FixupData {
FixupDataFixupData62 FixupData(bool force, bool flat, uint8_t alphatest, bool msaa) :
63 force_persample_interp(force), flatshade(flat), alphatest(alphatest), msaa(msaa) {}
64 bool force_persample_interp;
65 bool flatshade;
66 uint8_t alphatest;
67 bool msaa;
68 };
69
70 struct FixupEntry;
71 typedef void (*FixupApply)(const FixupEntry*, uint32_t*, const FixupData&);
72
73 struct FixupEntry
74 {
FixupEntryFixupEntry75 FixupEntry(FixupApply apply, int ipa, int reg, int loc) :
76 apply(apply), ipa(ipa), reg(reg), loc(loc) {}
77
78 FixupApply apply;
79 union {
80 struct {
81 uint32_t ipa:4; // SC mode used to identify colors
82 uint32_t reg:8; // The reg used for perspective division
83 uint32_t loc:20; // Let's hope we don't have more than 1M-sized shaders
84 };
85 uint32_t val;
86 };
87 };
88
89 struct FixupInfo
90 {
91 uint32_t count;
92 FixupEntry entry[0];
93 };
94
95 class CodeEmitter
96 {
97 public:
98 CodeEmitter(const Target *);
~CodeEmitter()99 virtual ~CodeEmitter() { }
100
101 // returns whether the instruction was encodable and written
102 virtual bool emitInstruction(Instruction *) = 0;
103
104 virtual uint32_t getMinEncodingSize(const Instruction *) const = 0;
105
106 void setCodeLocation(void *, uint32_t size);
getCodeLocation()107 inline void *getCodeLocation() const { return code; }
getCodeSize()108 inline uint32_t getCodeSize() const { return codeSize; }
109
110 bool addReloc(RelocEntry::Type, int w, uint32_t data, uint32_t m,
111 int s);
112
getRelocInfo()113 inline void *getRelocInfo() const { return relocInfo; }
114
115 bool addInterp(int ipa, int reg, FixupApply apply);
getFixupInfo()116 inline void *getFixupInfo() const { return fixupInfo; }
117
118 virtual void prepareEmission(Program *);
119 virtual void prepareEmission(Function *);
120 virtual void prepareEmission(BasicBlock *);
121
122 void printBinary() const;
123
124 protected:
125 const Target *targ;
126
127 uint32_t *code;
128 uint32_t codeSize;
129 uint32_t codeSizeLimit;
130
131 RelocInfo *relocInfo;
132 FixupInfo *fixupInfo;
133 };
134
135
136 enum OpClass
137 {
138 OPCLASS_MOVE = 0,
139 OPCLASS_LOAD = 1,
140 OPCLASS_STORE = 2,
141 OPCLASS_ARITH = 3,
142 OPCLASS_SHIFT = 4,
143 OPCLASS_SFU = 5,
144 OPCLASS_LOGIC = 6,
145 OPCLASS_COMPARE = 7,
146 OPCLASS_CONVERT = 8,
147 OPCLASS_ATOMIC = 9,
148 OPCLASS_TEXTURE = 10,
149 OPCLASS_SURFACE = 11,
150 OPCLASS_FLOW = 12,
151 OPCLASS_PSEUDO = 14,
152 OPCLASS_VECTOR = 15,
153 OPCLASS_BITFIELD = 16,
154 OPCLASS_CONTROL = 17,
155 OPCLASS_OTHER = 18
156 };
157
158 class Target
159 {
160 public:
Target(bool m,bool j,bool s)161 Target(bool m, bool j, bool s) : hasJoin(m), joinAnterior(j), hasSWSched(s) { }
~Target()162 virtual ~Target() { }
163
164 static Target *create(uint32_t chipset);
165 static void destroy(Target *);
166
167 // 0x50 and 0x84 to 0xaf for nv50
168 // 0xc0 to 0xdf for nvc0
getChipset()169 inline uint32_t getChipset() const { return chipset; }
170
171 virtual CodeEmitter *getCodeEmitter(Program::Type) = 0;
172
173 // Drivers should upload this so we can use it from all programs.
174 // The address chosen is supplied to the relocation routine.
175 virtual void getBuiltinCode(const uint32_t **code, uint32_t *size) const = 0;
176
parseDriverInfo(const struct nv50_ir_prog_info * info,const struct nv50_ir_prog_info_out * info_out)177 virtual void parseDriverInfo(const struct nv50_ir_prog_info *info,
178 const struct nv50_ir_prog_info_out *info_out) {
179 if (info_out->type == PIPE_SHADER_COMPUTE) {
180 threads = info->prop.cp.numThreads[0] *
181 info->prop.cp.numThreads[1] *
182 info->prop.cp.numThreads[2];
183 if (threads == 0)
184 threads = info->target >= NVISA_GK104_CHIPSET ? 1024 : 512;
185 } else {
186 threads = 32; // doesn't matter, just not too big.
187 }
188 }
189
190 virtual bool runLegalizePass(Program *, CGStage stage) const = 0;
191
192 public:
193 struct OpInfo
194 {
195 OpInfo *variants;
196 operation op;
197 uint16_t srcTypes;
198 uint16_t dstTypes;
199 uint32_t immdBits;
200 uint8_t srcNr;
201 uint8_t srcMods[3];
202 uint8_t dstMods;
203 uint16_t srcFiles[3];
204 uint16_t dstFiles;
205 unsigned int minEncSize : 5;
206 unsigned int vector : 1;
207 unsigned int predicate : 1;
208 unsigned int commutative : 1;
209 unsigned int pseudo : 1;
210 unsigned int flow : 1;
211 unsigned int hasDest : 1;
212 unsigned int terminator : 1;
213 };
214
215 inline const OpInfo& getOpInfo(const Instruction *) const;
216 inline const OpInfo& getOpInfo(const operation) const;
217
218 inline DataFile nativeFile(DataFile f) const;
219
220 virtual bool insnCanLoad(const Instruction *insn, int s,
221 const Instruction *ld) const = 0;
222 virtual bool insnCanLoadOffset(const Instruction *insn, int s,
223 int offset) const = 0;
224 virtual bool isOpSupported(operation, DataType) const = 0;
225 virtual bool isAccessSupported(DataFile, DataType) const = 0;
226 virtual bool isModSupported(const Instruction *,
227 int s, Modifier) const = 0;
228 virtual bool isSatSupported(const Instruction *) const = 0;
isPostMultiplySupported(operation op,float f,int & e)229 virtual bool isPostMultiplySupported(operation op, float f,
230 int& e) const { return false; }
231 virtual bool mayPredicate(const Instruction *,
232 const Value *) const = 0;
233
234 // whether @insn can be issued together with @next (order matters)
canDualIssue(const Instruction * insn,const Instruction * next)235 virtual bool canDualIssue(const Instruction *insn,
236 const Instruction *next) const { return false; }
getLatency(const Instruction *)237 virtual int getLatency(const Instruction *) const { return 1; }
getThroughput(const Instruction *)238 virtual int getThroughput(const Instruction *) const { return 1; }
239
240 virtual unsigned int getFileSize(DataFile) const = 0;
241 virtual unsigned int getFileUnit(DataFile) const = 0;
242
243 virtual uint32_t getSVAddress(DataFile, const Symbol *) const = 0;
244
245 public:
246 const bool hasJoin; // true if instructions have a join modifier
247 const bool joinAnterior; // true if join is executed before the op
248 const bool hasSWSched; // true if code should provide scheduling data
249
250 static const uint8_t operationSrcNr[];
251 static const OpClass operationClass[];
252
getOpSrcNr(operation op)253 static inline uint8_t getOpSrcNr(operation op)
254 {
255 return operationSrcNr[op];
256 }
getOpClass(operation op)257 static inline OpClass getOpClass(operation op)
258 {
259 return operationClass[op];
260 }
261
262 protected:
263 uint32_t chipset;
264 uint32_t threads;
265
266 DataFile nativeFileMap[DATA_FILE_COUNT];
267
268 OpInfo opInfo[OP_LAST + 1];
269 };
270
getOpInfo(const Instruction * insn)271 const Target::OpInfo& Target::getOpInfo(const Instruction *insn) const
272 {
273 return opInfo[MIN2(insn->op, OP_LAST)];
274 }
275
getOpInfo(const operation op)276 const Target::OpInfo& Target::getOpInfo(const operation op) const
277 {
278 return opInfo[op];
279 }
280
nativeFile(DataFile f)281 inline DataFile Target::nativeFile(DataFile f) const
282 {
283 return nativeFileMap[f];
284 }
285
286 } // namespace nv50_ir
287
288 #endif // __NV50_IR_TARGET_H__
289