• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2012-2013 LunarG, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Chia-I Wu <olv@lunarg.com>
26  */
27 
28 #ifndef TOY_COMPILER_H
29 #define TOY_COMPILER_H
30 
31 #include "genhw/genhw.h"
32 #include "util/slab.h"
33 
34 #include "ilo_common.h"
35 #include "toy_compiler_reg.h"
36 
37 /**
38  * Toy opcodes.
39  */
40 enum toy_opcode {
41    /* 0..127 are reserved for GEN6_OPCODE_x */
42    TOY_OPCODE_LAST_HW = 127,
43 
44    TOY_OPCODE_DO,
45 
46    /* TGSI register functions */
47    TOY_OPCODE_TGSI_IN,
48    TOY_OPCODE_TGSI_CONST,
49    TOY_OPCODE_TGSI_SV,
50    TOY_OPCODE_TGSI_IMM,
51    TOY_OPCODE_TGSI_INDIRECT_FETCH,
52    TOY_OPCODE_TGSI_INDIRECT_STORE,
53 
54    /* TGSI sampling functions */
55    TOY_OPCODE_TGSI_TEX,
56    TOY_OPCODE_TGSI_TXB,
57    TOY_OPCODE_TGSI_TXD,
58    TOY_OPCODE_TGSI_TXL,
59    TOY_OPCODE_TGSI_TXP,
60    TOY_OPCODE_TGSI_TXF,
61    TOY_OPCODE_TGSI_TXQ,
62    TOY_OPCODE_TGSI_TXQ_LZ,
63    TOY_OPCODE_TGSI_TEX2,
64    TOY_OPCODE_TGSI_TXB2,
65    TOY_OPCODE_TGSI_TXL2,
66    TOY_OPCODE_TGSI_SAMPLE,
67    TOY_OPCODE_TGSI_SAMPLE_I,
68    TOY_OPCODE_TGSI_SAMPLE_I_MS,
69    TOY_OPCODE_TGSI_SAMPLE_B,
70    TOY_OPCODE_TGSI_SAMPLE_C,
71    TOY_OPCODE_TGSI_SAMPLE_C_LZ,
72    TOY_OPCODE_TGSI_SAMPLE_D,
73    TOY_OPCODE_TGSI_SAMPLE_L,
74    TOY_OPCODE_TGSI_GATHER4,
75    TOY_OPCODE_TGSI_SVIEWINFO,
76    TOY_OPCODE_TGSI_SAMPLE_POS,
77    TOY_OPCODE_TGSI_SAMPLE_INFO,
78 
79    /* math functions */
80    TOY_OPCODE_INV,
81    TOY_OPCODE_LOG,
82    TOY_OPCODE_EXP,
83    TOY_OPCODE_SQRT,
84    TOY_OPCODE_RSQ,
85    TOY_OPCODE_SIN,
86    TOY_OPCODE_COS,
87    TOY_OPCODE_FDIV,
88    TOY_OPCODE_POW,
89    TOY_OPCODE_INT_DIV_QUOTIENT,
90    TOY_OPCODE_INT_DIV_REMAINDER,
91 
92    /* URB functions */
93    TOY_OPCODE_URB_WRITE,
94 
95    /* GS-specific functions */
96    TOY_OPCODE_EMIT,
97    TOY_OPCODE_ENDPRIM,
98 
99    /* FS-specific functions */
100    TOY_OPCODE_DDX,
101    TOY_OPCODE_DDY,
102    TOY_OPCODE_FB_WRITE,
103    TOY_OPCODE_KIL,
104 };
105 
106 /**
107  * Toy instruction.
108  */
109 struct toy_inst {
110    unsigned opcode:8;            /* enum toy_opcode      */
111    unsigned access_mode:1;       /* GEN6_ALIGN_x          */
112    unsigned mask_ctrl:1;         /* GEN6_MASKCTRL_x           */
113    unsigned dep_ctrl:2;          /* GEN6_DEPCTRL_x     */
114    unsigned qtr_ctrl:2;          /* GEN6_QTRCTRL_x   */
115    unsigned thread_ctrl:2;       /* GEN6_THREADCTRL_x         */
116    unsigned pred_ctrl:4;         /* GEN6_PREDCTRL_x      */
117    unsigned pred_inv:1;          /* true or false        */
118    unsigned exec_size:3;         /* GEN6_EXECSIZE_x        */
119    unsigned cond_modifier:4;     /* GEN6_COND_x    */
120    unsigned acc_wr_ctrl:1;       /* true or false        */
121    unsigned saturate:1;          /* true or false        */
122 
123    /* true if the instruction should be ignored for instruction iteration */
124    unsigned marker:1;
125 
126    unsigned pad:1;
127 
128    struct toy_dst dst;
129    struct toy_src src[5];        /* match TGSI_FULL_MAX_SRC_REGISTERS */
130 
131    struct {
132       int target;                /* TGSI_TEXTURE_x */
133       struct toy_src offsets[1]; /* need to be 4 when GATHER4 is supported */
134    } tex;
135 
136    struct list_head list;
137 };
138 
139 struct toy_compaction_table {
140    uint32_t control[32];
141    uint32_t datatype[32];
142    uint32_t subreg[32];
143    uint32_t src[32];
144 
145    uint32_t control_3src[4];
146    uint64_t source_3src[4];
147 };
148 
149 /**
150  * Toy compiler.
151  */
152 struct toy_compiler {
153    const struct ilo_dev *dev;
154 
155    struct toy_inst templ;
156    struct slab_mempool mempool;
157    struct list_head instructions;
158    struct list_head *iter, *iter_next;
159 
160    /* this is not set until toy_compiler_legalize_for_asm() */
161    int num_instructions;
162 
163    int rect_linear_width;
164    int next_vrf;
165 
166    bool fail;
167    const char *reason;
168 };
169 
170 /**
171  * Allocate the given number of VRF registers.
172  */
173 static inline int
tc_alloc_vrf(struct toy_compiler * tc,int count)174 tc_alloc_vrf(struct toy_compiler *tc, int count)
175 {
176    const int vrf = tc->next_vrf;
177 
178    tc->next_vrf += count;
179 
180    return vrf;
181 }
182 
183 /**
184  * Allocate a temporary register.
185  */
186 static inline struct toy_dst
tc_alloc_tmp(struct toy_compiler * tc)187 tc_alloc_tmp(struct toy_compiler *tc)
188 {
189    return tdst(TOY_FILE_VRF, tc_alloc_vrf(tc, 1), 0);
190 }
191 
192 /**
193  * Allocate four temporary registers.
194  */
195 static inline void
tc_alloc_tmp4(struct toy_compiler * tc,struct toy_dst * tmp)196 tc_alloc_tmp4(struct toy_compiler *tc, struct toy_dst *tmp)
197 {
198    tmp[0] = tc_alloc_tmp(tc);
199    tmp[1] = tc_alloc_tmp(tc);
200    tmp[2] = tc_alloc_tmp(tc);
201    tmp[3] = tc_alloc_tmp(tc);
202 }
203 
204 /**
205  * Duplicate an instruction at the current location.
206  */
207 static inline struct toy_inst *
tc_duplicate_inst(struct toy_compiler * tc,const struct toy_inst * inst)208 tc_duplicate_inst(struct toy_compiler *tc, const struct toy_inst *inst)
209 {
210    struct toy_inst *new_inst;
211 
212    new_inst = slab_alloc_st(&tc->mempool);
213    if (!new_inst)
214       return NULL;
215 
216    *new_inst = *inst;
217    list_addtail(&new_inst->list, tc->iter_next);
218 
219    return new_inst;
220 }
221 
222 /**
223  * Move an instruction to the current location.
224  */
225 static inline void
tc_move_inst(struct toy_compiler * tc,struct toy_inst * inst)226 tc_move_inst(struct toy_compiler *tc, struct toy_inst *inst)
227 {
228    list_del(&inst->list);
229    list_addtail(&inst->list, tc->iter_next);
230 }
231 
232 /**
233  * Discard an instruction.
234  */
235 static inline void
tc_discard_inst(struct toy_compiler * tc,struct toy_inst * inst)236 tc_discard_inst(struct toy_compiler *tc, struct toy_inst *inst)
237 {
238    list_del(&inst->list);
239    slab_free_st(&tc->mempool, inst);
240 }
241 
242 /**
243  * Add a new instruction at the current location, using tc->templ as the
244  * template.
245  */
246 static inline struct toy_inst *
tc_add(struct toy_compiler * tc)247 tc_add(struct toy_compiler *tc)
248 {
249    return tc_duplicate_inst(tc, &tc->templ);
250 }
251 
252 /**
253  * A convenient version of tc_add() for instructions with 3 source operands.
254  */
255 static inline struct toy_inst *
tc_add3(struct toy_compiler * tc,unsigned opcode,struct toy_dst dst,struct toy_src src0,struct toy_src src1,struct toy_src src2)256 tc_add3(struct toy_compiler *tc, unsigned opcode,
257         struct toy_dst dst,
258         struct toy_src src0,
259         struct toy_src src1,
260         struct toy_src src2)
261 {
262    struct toy_inst *inst;
263 
264    inst = tc_add(tc);
265    if (!inst)
266       return NULL;
267 
268    inst->opcode = opcode;
269    inst->dst = dst;
270    inst->src[0] = src0;
271    inst->src[1] = src1;
272    inst->src[2] = src2;
273 
274    return inst;
275 }
276 
277 /**
278  * A convenient version of tc_add() for instructions with 2 source operands.
279  */
280 static inline struct toy_inst *
tc_add2(struct toy_compiler * tc,int opcode,struct toy_dst dst,struct toy_src src0,struct toy_src src1)281 tc_add2(struct toy_compiler *tc, int opcode,
282             struct toy_dst dst,
283             struct toy_src src0,
284             struct toy_src src1)
285 {
286    return tc_add3(tc, opcode, dst, src0, src1, tsrc_null());
287 }
288 
289 /**
290  * A convenient version of tc_add() for instructions with 1 source operand.
291  */
292 static inline struct toy_inst *
tc_add1(struct toy_compiler * tc,unsigned opcode,struct toy_dst dst,struct toy_src src0)293 tc_add1(struct toy_compiler *tc, unsigned opcode,
294         struct toy_dst dst,
295         struct toy_src src0)
296 {
297    return tc_add2(tc, opcode, dst, src0, tsrc_null());
298 }
299 
300 /**
301  * A convenient version of tc_add() for instructions without source or
302  * destination operands.
303  */
304 static inline struct toy_inst *
tc_add0(struct toy_compiler * tc,unsigned opcode)305 tc_add0(struct toy_compiler *tc, unsigned opcode)
306 {
307    return tc_add1(tc, opcode, tdst_null(), tsrc_null());
308 }
309 
310 #define TC_ALU0(func, opcode)             \
311 static inline struct toy_inst *           \
312 func(struct toy_compiler *tc)             \
313 {                                         \
314    return tc_add0(tc, opcode);            \
315 }
316 
317 #define TC_ALU1(func, opcode)             \
318 static inline struct toy_inst *           \
319 func(struct toy_compiler *tc,             \
320      struct toy_dst dst,                  \
321      struct toy_src src)                  \
322 {                                         \
323    return tc_add1(tc, opcode, dst, src);  \
324 }
325 
326 #define TC_ALU2(func, opcode)             \
327 static inline struct toy_inst *           \
328 func(struct toy_compiler *tc,             \
329      struct toy_dst dst,                  \
330      struct toy_src src0,                 \
331      struct toy_src src1)                 \
332 {                                         \
333    return tc_add2(tc, opcode,             \
334          dst, src0, src1);                \
335 }
336 
337 #define TC_ALU3(func, opcode)             \
338 static inline struct toy_inst *           \
339 func(struct toy_compiler *tc,             \
340      struct toy_dst dst,                  \
341      struct toy_src src0,                 \
342      struct toy_src src1,                 \
343      struct toy_src src2)                 \
344 {                                         \
345    return tc_add3(tc, opcode,             \
346          dst, src0, src1, src2);          \
347 }
348 
349 #define TC_CND2(func, opcode)             \
350 static inline struct toy_inst *           \
351 func(struct toy_compiler *tc,             \
352      struct toy_dst dst,                  \
353      struct toy_src src0,                 \
354      struct toy_src src1,                 \
355      unsigned cond_modifier)              \
356 {                                         \
357    struct toy_inst *inst;                 \
358    inst = tc_add2(tc, opcode,             \
359          dst, src0, src1);                \
360    inst->cond_modifier = cond_modifier;   \
361    return inst;                           \
362 }
363 
TC_ALU0(tc_NOP,GEN6_OPCODE_NOP)364 TC_ALU0(tc_NOP, GEN6_OPCODE_NOP)
365 TC_ALU0(tc_ELSE, GEN6_OPCODE_ELSE)
366 TC_ALU0(tc_ENDIF, GEN6_OPCODE_ENDIF)
367 TC_ALU1(tc_MOV, GEN6_OPCODE_MOV)
368 TC_ALU1(tc_RNDD, GEN6_OPCODE_RNDD)
369 TC_ALU1(tc_INV, TOY_OPCODE_INV)
370 TC_ALU1(tc_FRC, GEN6_OPCODE_FRC)
371 TC_ALU1(tc_EXP, TOY_OPCODE_EXP)
372 TC_ALU1(tc_LOG, TOY_OPCODE_LOG)
373 TC_ALU2(tc_ADD, GEN6_OPCODE_ADD)
374 TC_ALU2(tc_MUL, GEN6_OPCODE_MUL)
375 TC_ALU2(tc_AND, GEN6_OPCODE_AND)
376 TC_ALU2(tc_OR, GEN6_OPCODE_OR)
377 TC_ALU2(tc_DP2, GEN6_OPCODE_DP2)
378 TC_ALU2(tc_DP3, GEN6_OPCODE_DP3)
379 TC_ALU2(tc_DP4, GEN6_OPCODE_DP4)
380 TC_ALU2(tc_SHL, GEN6_OPCODE_SHL)
381 TC_ALU2(tc_SHR, GEN6_OPCODE_SHR)
382 TC_ALU2(tc_POW, TOY_OPCODE_POW)
383 TC_ALU3(tc_MAC, GEN6_OPCODE_MAC)
384 TC_CND2(tc_SEL, GEN6_OPCODE_SEL)
385 TC_CND2(tc_CMP, GEN6_OPCODE_CMP)
386 TC_CND2(tc_IF, GEN6_OPCODE_IF)
387 TC_CND2(tc_SEND, GEN6_OPCODE_SEND)
388 
389 /**
390  * Upcast a list_head to an instruction.
391  */
392 static inline struct toy_inst *
393 tc_list_to_inst(struct toy_compiler *tc, struct list_head *item)
394 {
395    return container_of(item, (struct toy_inst *) NULL, list);
396 }
397 
398 /**
399  * Return the instruction at the current location.
400  */
401 static inline struct toy_inst *
tc_current(struct toy_compiler * tc)402 tc_current(struct toy_compiler *tc)
403 {
404    return (tc->iter != &tc->instructions) ?
405       tc_list_to_inst(tc, tc->iter) : NULL;
406 }
407 
408 /**
409  * Set the current location to the head.
410  */
411 static inline void
tc_head(struct toy_compiler * tc)412 tc_head(struct toy_compiler *tc)
413 {
414    tc->iter = &tc->instructions;
415    tc->iter_next = tc->iter->next;
416 }
417 
418 /**
419  * Set the current location to the tail.
420  */
421 static inline void
tc_tail(struct toy_compiler * tc)422 tc_tail(struct toy_compiler *tc)
423 {
424    tc->iter = &tc->instructions;
425    tc->iter_next = tc->iter;
426 }
427 
428 /**
429  * Advance the current location.
430  */
431 static inline struct toy_inst *
tc_next_no_skip(struct toy_compiler * tc)432 tc_next_no_skip(struct toy_compiler *tc)
433 {
434    /* stay at the tail so that new instructions are added there */
435    if (tc->iter_next == &tc->instructions) {
436       tc_tail(tc);
437       return NULL;
438    }
439 
440    tc->iter = tc->iter_next;
441    tc->iter_next = tc->iter_next->next;
442 
443    return tc_list_to_inst(tc, tc->iter);
444 }
445 
446 /**
447  * Advance the current location, skipping markers.
448  */
449 static inline struct toy_inst *
tc_next(struct toy_compiler * tc)450 tc_next(struct toy_compiler *tc)
451 {
452    struct toy_inst *inst;
453 
454    do {
455       inst = tc_next_no_skip(tc);
456    } while (inst && inst->marker);
457 
458    return inst;
459 }
460 
461 static inline void
tc_fail(struct toy_compiler * tc,const char * reason)462 tc_fail(struct toy_compiler *tc, const char *reason)
463 {
464    if (!tc->fail) {
465       tc->fail = true;
466       tc->reason = reason;
467    }
468 }
469 
470 void
471 toy_compiler_init(struct toy_compiler *tc, const struct ilo_dev *dev);
472 
473 void
474 toy_compiler_cleanup(struct toy_compiler *tc);
475 
476 void
477 toy_compiler_dump(struct toy_compiler *tc);
478 
479 void *
480 toy_compiler_assemble(struct toy_compiler *tc, int *size);
481 
482 const struct toy_compaction_table *
483 toy_compiler_get_compaction_table(const struct ilo_dev *dev);
484 
485 void
486 toy_compiler_disassemble(const struct ilo_dev *dev,
487                          const void *kernel, int size,
488                          bool dump_hex);
489 
490 #endif /* TOY_COMPILER_H */
491