OSDN Git Service

a6413ead066e80b5e0afc9aab763e6cc06cbad6b
[android-x86/external-mesa.git] / src / gallium / drivers / ilo / shader / toy_compiler.h
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 "brw_defines.h"
32
33 #include "util/u_slab.h"
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 BRW_OPCODE_x */
42    TOY_OPCODE_LAST_HW = 127,
43
44    /* TGSI register functions */
45    TOY_OPCODE_TGSI_IN,
46    TOY_OPCODE_TGSI_CONST,
47    TOY_OPCODE_TGSI_SV,
48    TOY_OPCODE_TGSI_IMM,
49    TOY_OPCODE_TGSI_INDIRECT_FETCH,
50    TOY_OPCODE_TGSI_INDIRECT_STORE,
51
52    /* TGSI sampling functions */
53    TOY_OPCODE_TGSI_TEX,
54    TOY_OPCODE_TGSI_TXB,
55    TOY_OPCODE_TGSI_TXD,
56    TOY_OPCODE_TGSI_TXL,
57    TOY_OPCODE_TGSI_TXP,
58    TOY_OPCODE_TGSI_TXF,
59    TOY_OPCODE_TGSI_TXQ,
60    TOY_OPCODE_TGSI_TXQ_LZ,
61    TOY_OPCODE_TGSI_TEX2,
62    TOY_OPCODE_TGSI_TXB2,
63    TOY_OPCODE_TGSI_TXL2,
64    TOY_OPCODE_TGSI_SAMPLE,
65    TOY_OPCODE_TGSI_SAMPLE_I,
66    TOY_OPCODE_TGSI_SAMPLE_I_MS,
67    TOY_OPCODE_TGSI_SAMPLE_B,
68    TOY_OPCODE_TGSI_SAMPLE_C,
69    TOY_OPCODE_TGSI_SAMPLE_C_LZ,
70    TOY_OPCODE_TGSI_SAMPLE_D,
71    TOY_OPCODE_TGSI_SAMPLE_L,
72    TOY_OPCODE_TGSI_GATHER4,
73    TOY_OPCODE_TGSI_SVIEWINFO,
74    TOY_OPCODE_TGSI_SAMPLE_POS,
75    TOY_OPCODE_TGSI_SAMPLE_INFO,
76
77    /* math functions */
78    TOY_OPCODE_INV,
79    TOY_OPCODE_LOG,
80    TOY_OPCODE_EXP,
81    TOY_OPCODE_SQRT,
82    TOY_OPCODE_RSQ,
83    TOY_OPCODE_SIN,
84    TOY_OPCODE_COS,
85    TOY_OPCODE_FDIV,
86    TOY_OPCODE_POW,
87    TOY_OPCODE_INT_DIV_QUOTIENT,
88    TOY_OPCODE_INT_DIV_REMAINDER,
89
90    /* URB functions */
91    TOY_OPCODE_URB_WRITE,
92
93    /* GS-specific functions */
94    TOY_OPCODE_EMIT,
95    TOY_OPCODE_ENDPRIM,
96
97    /* FS-specific functions */
98    TOY_OPCODE_DDX,
99    TOY_OPCODE_DDY,
100    TOY_OPCODE_FB_WRITE,
101    TOY_OPCODE_KIL,
102 };
103
104 /**
105  * Toy instruction.
106  */
107 struct toy_inst {
108    unsigned opcode:8;            /* enum toy_opcode      */
109    unsigned access_mode:1;       /* BRW_ALIGN_x          */
110    unsigned mask_ctrl:1;         /* BRW_MASK_x           */
111    unsigned dep_ctrl:2;          /* BRW_DEPENDENCY_x     */
112    unsigned qtr_ctrl:2;          /* GEN6_COMPRESSION_x   */
113    unsigned thread_ctrl:2;       /* BRW_THREAD_x         */
114    unsigned pred_ctrl:4;         /* BRW_PREDICATE_x      */
115    unsigned pred_inv:1;          /* true or false        */
116    unsigned exec_size:3;         /* BRW_EXECUTE_x        */
117    unsigned cond_modifier:4;     /* BRW_CONDITIONAL_x    */
118    unsigned acc_wr_ctrl:1;       /* true or false        */
119    unsigned saturate:1;          /* true or false        */
120
121    /* true if the instruction should be ignored for instruction iteration */
122    unsigned marker:1;
123
124    unsigned pad:1;
125
126    struct toy_dst dst;
127    struct toy_src src[5];        /* match TGSI_FULL_MAX_SRC_REGISTERS */
128
129    struct {
130       int target;                /* TGSI_TEXTURE_x */
131       struct toy_src offsets[1]; /* need to be 4 when GATHER4 is supported */
132    } tex;
133
134    struct list_head list;
135 };
136
137 /**
138  * Toy compiler.
139  */
140 struct toy_compiler {
141    int gen;
142
143    struct toy_inst templ;
144    struct util_slab_mempool mempool;
145    struct list_head instructions;
146    struct list_head *iter, *iter_next;
147
148    /* this is not set until toy_compiler_legalize_for_asm() */
149    int num_instructions;
150
151    int rect_linear_width;
152    int next_vrf;
153
154    bool fail;
155    const char *reason;
156 };
157
158 /**
159  * Allocate the given number of VRF registers.
160  */
161 static inline int
162 tc_alloc_vrf(struct toy_compiler *tc, int count)
163 {
164    const int vrf = tc->next_vrf;
165
166    tc->next_vrf += count;
167
168    return vrf;
169 }
170
171 /**
172  * Allocate a temporary register.
173  */
174 static inline struct toy_dst
175 tc_alloc_tmp(struct toy_compiler *tc)
176 {
177    return tdst(TOY_FILE_VRF, tc_alloc_vrf(tc, 1), 0);
178 }
179
180 /**
181  * Allocate four temporary registers.
182  */
183 static inline void
184 tc_alloc_tmp4(struct toy_compiler *tc, struct toy_dst *tmp)
185 {
186    tmp[0] = tc_alloc_tmp(tc);
187    tmp[1] = tc_alloc_tmp(tc);
188    tmp[2] = tc_alloc_tmp(tc);
189    tmp[3] = tc_alloc_tmp(tc);
190 }
191
192 /**
193  * Duplicate an instruction at the current location.
194  */
195 static inline struct toy_inst *
196 tc_duplicate_inst(struct toy_compiler *tc, const struct toy_inst *inst)
197 {
198    struct toy_inst *new_inst;
199
200    new_inst = util_slab_alloc(&tc->mempool);
201    if (!new_inst)
202       return NULL;
203
204    *new_inst = *inst;
205    list_addtail(&new_inst->list, tc->iter_next);
206
207    return new_inst;
208 }
209
210 /**
211  * Move an instruction to the current location.
212  */
213 static inline void
214 tc_move_inst(struct toy_compiler *tc, struct toy_inst *inst)
215 {
216    list_del(&inst->list);
217    list_addtail(&inst->list, tc->iter_next);
218 }
219
220 /**
221  * Discard an instruction.
222  */
223 static inline void
224 tc_discard_inst(struct toy_compiler *tc, struct toy_inst *inst)
225 {
226    list_del(&inst->list);
227    util_slab_free(&tc->mempool, inst);
228 }
229
230 /**
231  * Add a new instruction at the current location, using tc->templ as the
232  * template.
233  */
234 static inline struct toy_inst *
235 tc_add(struct toy_compiler *tc)
236 {
237    return tc_duplicate_inst(tc, &tc->templ);
238 }
239
240 /**
241  * A convenient version of tc_add() for instructions with 3 source operands.
242  */
243 static inline struct toy_inst *
244 tc_add3(struct toy_compiler *tc, unsigned opcode,
245         struct toy_dst dst,
246         struct toy_src src0,
247         struct toy_src src1,
248         struct toy_src src2)
249 {
250    struct toy_inst *inst;
251
252    inst = tc_add(tc);
253    if (!inst)
254       return NULL;
255
256    inst->opcode = opcode;
257    inst->dst = dst;
258    inst->src[0] = src0;
259    inst->src[1] = src1;
260    inst->src[2] = src2;
261
262    return inst;
263 }
264
265 /**
266  * A convenient version of tc_add() for instructions with 2 source operands.
267  */
268 static inline struct toy_inst *
269 tc_add2(struct toy_compiler *tc, int opcode,
270             struct toy_dst dst,
271             struct toy_src src0,
272             struct toy_src src1)
273 {
274    return tc_add3(tc, opcode, dst, src0, src1, tsrc_null());
275 }
276
277 /**
278  * A convenient version of tc_add() for instructions with 1 source operand.
279  */
280 static inline struct toy_inst *
281 tc_add1(struct toy_compiler *tc, unsigned opcode,
282         struct toy_dst dst,
283         struct toy_src src0)
284 {
285    return tc_add2(tc, opcode, dst, src0, tsrc_null());
286 }
287
288 /**
289  * A convenient version of tc_add() for instructions without source or
290  * destination operands.
291  */
292 static inline struct toy_inst *
293 tc_add0(struct toy_compiler *tc, unsigned opcode)
294 {
295    return tc_add1(tc, opcode, tdst_null(), tsrc_null());
296 }
297
298 #define TC_ALU0(func, opcode)             \
299 static inline struct toy_inst *           \
300 func(struct toy_compiler *tc)             \
301 {                                         \
302    return tc_add0(tc, opcode);            \
303 }
304
305 #define TC_ALU1(func, opcode)             \
306 static inline struct toy_inst *           \
307 func(struct toy_compiler *tc,             \
308      struct toy_dst dst,                  \
309      struct toy_src src)                  \
310 {                                         \
311    return tc_add1(tc, opcode, dst, src);  \
312 }
313
314 #define TC_ALU2(func, opcode)             \
315 static inline struct toy_inst *           \
316 func(struct toy_compiler *tc,             \
317      struct toy_dst dst,                  \
318      struct toy_src src0,                 \
319      struct toy_src src1)                 \
320 {                                         \
321    return tc_add2(tc, opcode,             \
322          dst, src0, src1);                \
323 }
324
325 #define TC_ALU3(func, opcode)             \
326 static inline struct toy_inst *           \
327 func(struct toy_compiler *tc,             \
328      struct toy_dst dst,                  \
329      struct toy_src src0,                 \
330      struct toy_src src1,                 \
331      struct toy_src src2)                 \
332 {                                         \
333    return tc_add3(tc, opcode,             \
334          dst, src0, src1, src2);          \
335 }
336
337 #define TC_CND2(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      unsigned cond_modifier)              \
344 {                                         \
345    struct toy_inst *inst;                 \
346    inst = tc_add2(tc, opcode,             \
347          dst, src0, src1);                \
348    inst->cond_modifier = cond_modifier;   \
349    return inst;                           \
350 }
351
352 TC_ALU0(tc_NOP, BRW_OPCODE_NOP)
353 TC_ALU0(tc_ELSE, BRW_OPCODE_ELSE)
354 TC_ALU0(tc_ENDIF, BRW_OPCODE_ENDIF)
355 TC_ALU1(tc_MOV, BRW_OPCODE_MOV)
356 TC_ALU1(tc_RNDD, BRW_OPCODE_RNDD)
357 TC_ALU1(tc_INV, TOY_OPCODE_INV)
358 TC_ALU1(tc_FRC, BRW_OPCODE_FRC)
359 TC_ALU1(tc_EXP, TOY_OPCODE_EXP)
360 TC_ALU1(tc_LOG, TOY_OPCODE_LOG)
361 TC_ALU2(tc_ADD, BRW_OPCODE_ADD)
362 TC_ALU2(tc_MUL, BRW_OPCODE_MUL)
363 TC_ALU2(tc_AND, BRW_OPCODE_AND)
364 TC_ALU2(tc_OR, BRW_OPCODE_OR)
365 TC_ALU2(tc_DP2, BRW_OPCODE_DP2)
366 TC_ALU2(tc_DP3, BRW_OPCODE_DP3)
367 TC_ALU2(tc_DP4, BRW_OPCODE_DP4)
368 TC_ALU2(tc_SHL, BRW_OPCODE_SHL)
369 TC_ALU2(tc_SHR, BRW_OPCODE_SHR)
370 TC_ALU2(tc_POW, TOY_OPCODE_POW)
371 TC_ALU3(tc_MAC, BRW_OPCODE_MAC)
372 TC_CND2(tc_SEL, BRW_OPCODE_SEL)
373 TC_CND2(tc_CMP, BRW_OPCODE_CMP)
374 TC_CND2(tc_IF, BRW_OPCODE_IF)
375 TC_CND2(tc_SEND, BRW_OPCODE_SEND)
376
377 /**
378  * Upcast a list_head to an instruction.
379  */
380 static inline struct toy_inst *
381 tc_list_to_inst(struct toy_compiler *tc, struct list_head *item)
382 {
383    return container_of(item, (struct toy_inst *) NULL, list);
384 }
385
386 /**
387  * Return the instruction at the current location.
388  */
389 static inline struct toy_inst *
390 tc_current(struct toy_compiler *tc)
391 {
392    return (tc->iter != &tc->instructions) ?
393       tc_list_to_inst(tc, tc->iter) : NULL;
394 }
395
396 /**
397  * Set the current location to the head.
398  */
399 static inline void
400 tc_head(struct toy_compiler *tc)
401 {
402    tc->iter = &tc->instructions;
403    tc->iter_next = tc->iter->next;
404 }
405
406 /**
407  * Set the current location to the tail.
408  */
409 static inline void
410 tc_tail(struct toy_compiler *tc)
411 {
412    tc->iter = &tc->instructions;
413    tc->iter_next = tc->iter;
414 }
415
416 /**
417  * Advance the current location.
418  */
419 static inline struct toy_inst *
420 tc_next_no_skip(struct toy_compiler *tc)
421 {
422    /* stay at the tail so that new instructions are added there */
423    if (tc->iter_next == &tc->instructions) {
424       tc_tail(tc);
425       return NULL;
426    }
427
428    tc->iter = tc->iter_next;
429    tc->iter_next = tc->iter_next->next;
430
431    return tc_list_to_inst(tc, tc->iter);
432 }
433
434 /**
435  * Advance the current location, skipping markers.
436  */
437 static inline struct toy_inst *
438 tc_next(struct toy_compiler *tc)
439 {
440    struct toy_inst *inst;
441
442    do {
443       inst = tc_next_no_skip(tc);
444    } while (inst && inst->marker);
445
446    return inst;
447 }
448
449 static inline void
450 tc_fail(struct toy_compiler *tc, const char *reason)
451 {
452    if (!tc->fail) {
453       tc->fail = true;
454       tc->reason = reason;
455    }
456 }
457
458 void
459 toy_compiler_init(struct toy_compiler *tc, int gen);
460
461 void
462 toy_compiler_cleanup(struct toy_compiler *tc);
463
464 void
465 toy_compiler_dump(struct toy_compiler *tc);
466
467 void *
468 toy_compiler_assemble(struct toy_compiler *tc, int *size);
469
470 void
471 toy_compiler_disassemble(struct toy_compiler *tc, const void *kernel, int size);
472
473 #endif /* TOY_COMPILER_H */