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