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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * 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 class CodeEmitter
62 {
63 public:
64 CodeEmitter(const Target *);
65
66 // returns whether the instruction was encodable and written
67 virtual bool emitInstruction(Instruction *) = 0;
68
69 virtual uint32_t getMinEncodingSize(const Instruction *) const = 0;
70
71 void setCodeLocation(void *, uint32_t size);
getCodeLocation()72 inline void *getCodeLocation() const { return code; }
getCodeSize()73 inline uint32_t getCodeSize() const { return codeSize; }
74
75 bool addReloc(RelocEntry::Type, int w, uint32_t data, uint32_t m,
76 int s);
77
getRelocInfo()78 inline void *getRelocInfo() const { return relocInfo; }
79
80 void prepareEmission(Program *);
81 virtual void prepareEmission(Function *);
82 virtual void prepareEmission(BasicBlock *);
83
84 void printBinary() const;
85
86 protected:
87 const Target *targ;
88
89 uint32_t *code;
90 uint32_t codeSize;
91 uint32_t codeSizeLimit;
92
93 RelocInfo *relocInfo;
94 };
95
96
97 enum OpClass
98 {
99 OPCLASS_MOVE = 0,
100 OPCLASS_LOAD = 1,
101 OPCLASS_STORE = 2,
102 OPCLASS_ARITH = 3,
103 OPCLASS_SHIFT = 4,
104 OPCLASS_SFU = 5,
105 OPCLASS_LOGIC = 6,
106 OPCLASS_COMPARE = 7,
107 OPCLASS_CONVERT = 8,
108 OPCLASS_ATOMIC = 9,
109 OPCLASS_TEXTURE = 10,
110 OPCLASS_SURFACE = 11,
111 OPCLASS_FLOW = 12,
112 OPCLASS_PSEUDO = 14,
113 OPCLASS_OTHER = 15
114 };
115
116 class Target
117 {
118 public:
Target(bool j,bool s)119 Target(bool j, bool s) : joinAnterior(j), hasSWSched(s) { }
120
121 static Target *create(uint32_t chipset);
122 static void destroy(Target *);
123
124 // 0x50 and 0x84 to 0xaf for nv50
125 // 0xc0 to 0xdf for nvc0
getChipset()126 inline uint32_t getChipset() const { return chipset; }
127
128 virtual CodeEmitter *getCodeEmitter(Program::Type) = 0;
129
130 // Drivers should upload this so we can use it from all programs.
131 // The address chosen is supplied to the relocation routine.
132 virtual void getBuiltinCode(const uint32_t **code, uint32_t *size) const = 0;
133
parseDriverInfo(const struct nv50_ir_prog_info * info)134 virtual void parseDriverInfo(const struct nv50_ir_prog_info *info) { }
135
136 virtual bool runLegalizePass(Program *, CGStage stage) const = 0;
137
138 public:
139 struct OpInfo
140 {
141 OpInfo *variants;
142 operation op;
143 uint16_t srcTypes;
144 uint16_t dstTypes;
145 uint32_t immdBits;
146 uint8_t srcNr;
147 uint8_t srcMods[3];
148 uint8_t dstMods;
149 uint8_t srcFiles[3];
150 uint8_t dstFiles;
151 unsigned int minEncSize : 4;
152 unsigned int vector : 1;
153 unsigned int predicate : 1;
154 unsigned int commutative : 1;
155 unsigned int pseudo : 1;
156 unsigned int flow : 1;
157 unsigned int hasDest : 1;
158 unsigned int terminator : 1;
159 };
160
161 inline const OpInfo& getOpInfo(const Instruction *) const;
162 inline const OpInfo& getOpInfo(const operation) const;
163
164 inline DataFile nativeFile(DataFile f) const;
165
166 virtual bool insnCanLoad(const Instruction *insn, int s,
167 const Instruction *ld) const = 0;
168 virtual bool isOpSupported(operation, DataType) const = 0;
169 virtual bool isAccessSupported(DataFile, DataType) const = 0;
170 virtual bool isModSupported(const Instruction *,
171 int s, Modifier) const = 0;
172 virtual bool isSatSupported(const Instruction *) const = 0;
isPostMultiplySupported(operation op,float f,int & e)173 virtual bool isPostMultiplySupported(operation op, float f,
174 int& e) const { return false; }
175 virtual bool mayPredicate(const Instruction *,
176 const Value *) const = 0;
177
178 // whether @insn can be issued together with @next (order matters)
canDualIssue(const Instruction * insn,const Instruction * next)179 virtual bool canDualIssue(const Instruction *insn,
180 const Instruction *next) const { return false; }
getLatency(const Instruction *)181 virtual int getLatency(const Instruction *) const { return 1; }
getThroughput(const Instruction *)182 virtual int getThroughput(const Instruction *) const { return 1; }
183
184 virtual unsigned int getFileSize(DataFile) const = 0;
185 virtual unsigned int getFileUnit(DataFile) const = 0;
186
187 virtual uint32_t getSVAddress(DataFile, const Symbol *) const = 0;
188
189 public:
190 const bool joinAnterior; // true if join is executed before the op
191 const bool hasSWSched; // true if code should provide scheduling data
192
193 static const uint8_t operationSrcNr[OP_LAST + 1];
194 static const OpClass operationClass[OP_LAST + 1];
195
getOpSrcNr(operation op)196 static inline uint8_t getOpSrcNr(operation op)
197 {
198 return operationSrcNr[op];
199 }
getOpClass(operation op)200 static inline OpClass getOpClass(operation op)
201 {
202 return operationClass[op];
203 }
204
205 protected:
206 uint32_t chipset;
207
208 DataFile nativeFileMap[DATA_FILE_COUNT];
209
210 OpInfo opInfo[OP_LAST + 1];
211 };
212
getOpInfo(const Instruction * insn)213 const Target::OpInfo& Target::getOpInfo(const Instruction *insn) const
214 {
215 return opInfo[MIN2(insn->op, OP_LAST)];
216 }
217
getOpInfo(const operation op)218 const Target::OpInfo& Target::getOpInfo(const operation op) const
219 {
220 return opInfo[op];
221 }
222
nativeFile(DataFile f)223 inline DataFile Target::nativeFile(DataFile f) const
224 {
225 return nativeFileMap[f];
226 }
227
228 } // namespace nv50_ir
229
230 #endif // __NV50_IR_TARGET_H__
231