• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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