nvc0/ir: be careful about propagating very large offsets into const load
[mesa.git] / src / gallium / drivers / nouveau / codegen / nv50_ir_target.h
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 "codegen/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 InterpEntry
62 {
63 InterpEntry(int ipa, int reg, int loc) : ipa(ipa), reg(reg), loc(loc) {}
64 uint32_t ipa:4; // SC mode used to identify colors
65 uint32_t reg:8; // The reg used for perspective division
66 uint32_t loc:20; // Let's hope we don't have more than 1M-sized shaders
67 };
68
69 typedef void (*InterpApply)(const InterpEntry*, uint32_t*, bool, bool);
70
71 struct InterpInfo
72 {
73 uint32_t count;
74 InterpApply apply;
75 InterpEntry entry[0];
76 };
77
78 class CodeEmitter
79 {
80 public:
81 CodeEmitter(const Target *);
82 virtual ~CodeEmitter() { }
83
84 // returns whether the instruction was encodable and written
85 virtual bool emitInstruction(Instruction *) = 0;
86
87 virtual uint32_t getMinEncodingSize(const Instruction *) const = 0;
88
89 void setCodeLocation(void *, uint32_t size);
90 inline void *getCodeLocation() const { return code; }
91 inline uint32_t getCodeSize() const { return codeSize; }
92
93 bool addReloc(RelocEntry::Type, int w, uint32_t data, uint32_t m,
94 int s);
95
96 inline void *getRelocInfo() const { return relocInfo; }
97
98 bool addInterp(int ipa, int reg, InterpApply apply);
99 inline void *getInterpInfo() const { return interpInfo; }
100
101 virtual void prepareEmission(Program *);
102 virtual void prepareEmission(Function *);
103 virtual void prepareEmission(BasicBlock *);
104
105 void printBinary() const;
106
107 protected:
108 const Target *targ;
109
110 uint32_t *code;
111 uint32_t codeSize;
112 uint32_t codeSizeLimit;
113
114 RelocInfo *relocInfo;
115 InterpInfo *interpInfo;
116 };
117
118
119 enum OpClass
120 {
121 OPCLASS_MOVE = 0,
122 OPCLASS_LOAD = 1,
123 OPCLASS_STORE = 2,
124 OPCLASS_ARITH = 3,
125 OPCLASS_SHIFT = 4,
126 OPCLASS_SFU = 5,
127 OPCLASS_LOGIC = 6,
128 OPCLASS_COMPARE = 7,
129 OPCLASS_CONVERT = 8,
130 OPCLASS_ATOMIC = 9,
131 OPCLASS_TEXTURE = 10,
132 OPCLASS_SURFACE = 11,
133 OPCLASS_FLOW = 12,
134 OPCLASS_PSEUDO = 14,
135 OPCLASS_VECTOR = 15,
136 OPCLASS_BITFIELD = 16,
137 OPCLASS_CONTROL = 17,
138 OPCLASS_OTHER = 18
139 };
140
141 class Target
142 {
143 public:
144 Target(bool m, bool j, bool s) : hasJoin(m), joinAnterior(j), hasSWSched(s) { }
145 virtual ~Target() { }
146
147 static Target *create(uint32_t chipset);
148 static void destroy(Target *);
149
150 // 0x50 and 0x84 to 0xaf for nv50
151 // 0xc0 to 0xdf for nvc0
152 inline uint32_t getChipset() const { return chipset; }
153
154 virtual CodeEmitter *getCodeEmitter(Program::Type) = 0;
155
156 // Drivers should upload this so we can use it from all programs.
157 // The address chosen is supplied to the relocation routine.
158 virtual void getBuiltinCode(const uint32_t **code, uint32_t *size) const = 0;
159
160 virtual void parseDriverInfo(const struct nv50_ir_prog_info *info) { }
161
162 virtual bool runLegalizePass(Program *, CGStage stage) const = 0;
163
164 public:
165 struct OpInfo
166 {
167 OpInfo *variants;
168 operation op;
169 uint16_t srcTypes;
170 uint16_t dstTypes;
171 uint32_t immdBits;
172 uint8_t srcNr;
173 uint8_t srcMods[3];
174 uint8_t dstMods;
175 uint16_t srcFiles[3];
176 uint16_t dstFiles;
177 unsigned int minEncSize : 4;
178 unsigned int vector : 1;
179 unsigned int predicate : 1;
180 unsigned int commutative : 1;
181 unsigned int pseudo : 1;
182 unsigned int flow : 1;
183 unsigned int hasDest : 1;
184 unsigned int terminator : 1;
185 };
186
187 inline const OpInfo& getOpInfo(const Instruction *) const;
188 inline const OpInfo& getOpInfo(const operation) const;
189
190 inline DataFile nativeFile(DataFile f) const;
191
192 virtual bool insnCanLoad(const Instruction *insn, int s,
193 const Instruction *ld) const = 0;
194 virtual bool insnCanLoadOffset(const Instruction *insn, int s,
195 int offset) const = 0;
196 virtual bool isOpSupported(operation, DataType) const = 0;
197 virtual bool isAccessSupported(DataFile, DataType) const = 0;
198 virtual bool isModSupported(const Instruction *,
199 int s, Modifier) const = 0;
200 virtual bool isSatSupported(const Instruction *) const = 0;
201 virtual bool isPostMultiplySupported(operation op, float f,
202 int& e) const { return false; }
203 virtual bool mayPredicate(const Instruction *,
204 const Value *) const = 0;
205
206 // whether @insn can be issued together with @next (order matters)
207 virtual bool canDualIssue(const Instruction *insn,
208 const Instruction *next) const { return false; }
209 virtual int getLatency(const Instruction *) const { return 1; }
210 virtual int getThroughput(const Instruction *) const { return 1; }
211
212 virtual unsigned int getFileSize(DataFile) const = 0;
213 virtual unsigned int getFileUnit(DataFile) const = 0;
214
215 virtual uint32_t getSVAddress(DataFile, const Symbol *) const = 0;
216
217 public:
218 const bool hasJoin; // true if instructions have a join modifier
219 const bool joinAnterior; // true if join is executed before the op
220 const bool hasSWSched; // true if code should provide scheduling data
221
222 static const uint8_t operationSrcNr[];
223 static const OpClass operationClass[];
224
225 static inline uint8_t getOpSrcNr(operation op)
226 {
227 return operationSrcNr[op];
228 }
229 static inline OpClass getOpClass(operation op)
230 {
231 return operationClass[op];
232 }
233
234 protected:
235 uint32_t chipset;
236
237 DataFile nativeFileMap[DATA_FILE_COUNT];
238
239 OpInfo opInfo[OP_LAST + 1];
240 };
241
242 const Target::OpInfo& Target::getOpInfo(const Instruction *insn) const
243 {
244 return opInfo[MIN2(insn->op, OP_LAST)];
245 }
246
247 const Target::OpInfo& Target::getOpInfo(const operation op) const
248 {
249 return opInfo[op];
250 }
251
252 inline DataFile Target::nativeFile(DataFile f) const
253 {
254 return nativeFileMap[f];
255 }
256
257 } // namespace nv50_ir
258
259 #endif // __NV50_IR_TARGET_H__