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
28namespace nv50_ir {
29
30struct RelocInfo;
31
32struct 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
50struct 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
61class CodeEmitter
62{
63public:
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);
72   inline void *getCodeLocation() const { return code; }
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
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
86protected:
87   const Target *targ;
88
89   uint32_t *code;
90   uint32_t codeSize;
91   uint32_t codeSizeLimit;
92
93   RelocInfo *relocInfo;
94};
95
96
97enum 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
116class Target
117{
118public:
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
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
134   virtual void parseDriverInfo(const struct nv50_ir_prog_info *info) { }
135
136   virtual bool runLegalizePass(Program *, CGStage stage) const = 0;
137
138public:
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;
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)
179   virtual bool canDualIssue(const Instruction *insn,
180                             const Instruction *next) const { return false; }
181   virtual int getLatency(const Instruction *) const { return 1; }
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
189public:
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
196   static inline uint8_t getOpSrcNr(operation op)
197   {
198      return operationSrcNr[op];
199   }
200   static inline OpClass getOpClass(operation op)
201   {
202      return operationClass[op];
203   }
204
205protected:
206   uint32_t chipset;
207
208   DataFile nativeFileMap[DATA_FILE_COUNT];
209
210   OpInfo opInfo[OP_LAST + 1];
211};
212
213const Target::OpInfo& Target::getOpInfo(const Instruction *insn) const
214{
215   return opInfo[MIN2(insn->op, OP_LAST)];
216}
217
218const Target::OpInfo& Target::getOpInfo(const operation op) const
219{
220   return opInfo[op];
221}
222
223inline 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