summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/ilo/shader/toy_compiler.h
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2012-12-13 05:48:28 +0800
committerChia-I Wu <[email protected]>2013-04-26 16:20:52 +0800
commit7118ff8bb02046bb2f440e2a5c48d9a41bb057b1 (patch)
treefacfe5b880db82818b95521da5edc5803de749be /src/gallium/drivers/ilo/shader/toy_compiler.h
parent0fa2d0e98aec1e864f7edc225eb9cda449051733 (diff)
ilo: add a toy shader compiler
This is a simple shader compiler that performs almost zero optimizations. The generated code is usually much larger comparing to that generated by i965. The generated code also requires many more registers. Function-wise, it lacks register spilling and does not support most TGSI indirections. Other than those, it works alright.
Diffstat (limited to 'src/gallium/drivers/ilo/shader/toy_compiler.h')
-rw-r--r--src/gallium/drivers/ilo/shader/toy_compiler.h473
1 files changed, 473 insertions, 0 deletions
diff --git a/src/gallium/drivers/ilo/shader/toy_compiler.h b/src/gallium/drivers/ilo/shader/toy_compiler.h
new file mode 100644
index 00000000000..a6413ead066
--- /dev/null
+++ b/src/gallium/drivers/ilo/shader/toy_compiler.h
@@ -0,0 +1,473 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2012-2013 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chia-I Wu <[email protected]>
+ */
+
+#ifndef TOY_COMPILER_H
+#define TOY_COMPILER_H
+
+#include "brw_defines.h"
+
+#include "util/u_slab.h"
+#include "ilo_common.h"
+#include "toy_compiler_reg.h"
+
+/**
+ * Toy opcodes.
+ */
+enum toy_opcode {
+ /* 0..127 are reserved for BRW_OPCODE_x */
+ TOY_OPCODE_LAST_HW = 127,
+
+ /* TGSI register functions */
+ TOY_OPCODE_TGSI_IN,
+ TOY_OPCODE_TGSI_CONST,
+ TOY_OPCODE_TGSI_SV,
+ TOY_OPCODE_TGSI_IMM,
+ TOY_OPCODE_TGSI_INDIRECT_FETCH,
+ TOY_OPCODE_TGSI_INDIRECT_STORE,
+
+ /* TGSI sampling functions */
+ TOY_OPCODE_TGSI_TEX,
+ TOY_OPCODE_TGSI_TXB,
+ TOY_OPCODE_TGSI_TXD,
+ TOY_OPCODE_TGSI_TXL,
+ TOY_OPCODE_TGSI_TXP,
+ TOY_OPCODE_TGSI_TXF,
+ TOY_OPCODE_TGSI_TXQ,
+ TOY_OPCODE_TGSI_TXQ_LZ,
+ TOY_OPCODE_TGSI_TEX2,
+ TOY_OPCODE_TGSI_TXB2,
+ TOY_OPCODE_TGSI_TXL2,
+ TOY_OPCODE_TGSI_SAMPLE,
+ TOY_OPCODE_TGSI_SAMPLE_I,
+ TOY_OPCODE_TGSI_SAMPLE_I_MS,
+ TOY_OPCODE_TGSI_SAMPLE_B,
+ TOY_OPCODE_TGSI_SAMPLE_C,
+ TOY_OPCODE_TGSI_SAMPLE_C_LZ,
+ TOY_OPCODE_TGSI_SAMPLE_D,
+ TOY_OPCODE_TGSI_SAMPLE_L,
+ TOY_OPCODE_TGSI_GATHER4,
+ TOY_OPCODE_TGSI_SVIEWINFO,
+ TOY_OPCODE_TGSI_SAMPLE_POS,
+ TOY_OPCODE_TGSI_SAMPLE_INFO,
+
+ /* math functions */
+ TOY_OPCODE_INV,
+ TOY_OPCODE_LOG,
+ TOY_OPCODE_EXP,
+ TOY_OPCODE_SQRT,
+ TOY_OPCODE_RSQ,
+ TOY_OPCODE_SIN,
+ TOY_OPCODE_COS,
+ TOY_OPCODE_FDIV,
+ TOY_OPCODE_POW,
+ TOY_OPCODE_INT_DIV_QUOTIENT,
+ TOY_OPCODE_INT_DIV_REMAINDER,
+
+ /* URB functions */
+ TOY_OPCODE_URB_WRITE,
+
+ /* GS-specific functions */
+ TOY_OPCODE_EMIT,
+ TOY_OPCODE_ENDPRIM,
+
+ /* FS-specific functions */
+ TOY_OPCODE_DDX,
+ TOY_OPCODE_DDY,
+ TOY_OPCODE_FB_WRITE,
+ TOY_OPCODE_KIL,
+};
+
+/**
+ * Toy instruction.
+ */
+struct toy_inst {
+ unsigned opcode:8; /* enum toy_opcode */
+ unsigned access_mode:1; /* BRW_ALIGN_x */
+ unsigned mask_ctrl:1; /* BRW_MASK_x */
+ unsigned dep_ctrl:2; /* BRW_DEPENDENCY_x */
+ unsigned qtr_ctrl:2; /* GEN6_COMPRESSION_x */
+ unsigned thread_ctrl:2; /* BRW_THREAD_x */
+ unsigned pred_ctrl:4; /* BRW_PREDICATE_x */
+ unsigned pred_inv:1; /* true or false */
+ unsigned exec_size:3; /* BRW_EXECUTE_x */
+ unsigned cond_modifier:4; /* BRW_CONDITIONAL_x */
+ unsigned acc_wr_ctrl:1; /* true or false */
+ unsigned saturate:1; /* true or false */
+
+ /* true if the instruction should be ignored for instruction iteration */
+ unsigned marker:1;
+
+ unsigned pad:1;
+
+ struct toy_dst dst;
+ struct toy_src src[5]; /* match TGSI_FULL_MAX_SRC_REGISTERS */
+
+ struct {
+ int target; /* TGSI_TEXTURE_x */
+ struct toy_src offsets[1]; /* need to be 4 when GATHER4 is supported */
+ } tex;
+
+ struct list_head list;
+};
+
+/**
+ * Toy compiler.
+ */
+struct toy_compiler {
+ int gen;
+
+ struct toy_inst templ;
+ struct util_slab_mempool mempool;
+ struct list_head instructions;
+ struct list_head *iter, *iter_next;
+
+ /* this is not set until toy_compiler_legalize_for_asm() */
+ int num_instructions;
+
+ int rect_linear_width;
+ int next_vrf;
+
+ bool fail;
+ const char *reason;
+};
+
+/**
+ * Allocate the given number of VRF registers.
+ */
+static inline int
+tc_alloc_vrf(struct toy_compiler *tc, int count)
+{
+ const int vrf = tc->next_vrf;
+
+ tc->next_vrf += count;
+
+ return vrf;
+}
+
+/**
+ * Allocate a temporary register.
+ */
+static inline struct toy_dst
+tc_alloc_tmp(struct toy_compiler *tc)
+{
+ return tdst(TOY_FILE_VRF, tc_alloc_vrf(tc, 1), 0);
+}
+
+/**
+ * Allocate four temporary registers.
+ */
+static inline void
+tc_alloc_tmp4(struct toy_compiler *tc, struct toy_dst *tmp)
+{
+ tmp[0] = tc_alloc_tmp(tc);
+ tmp[1] = tc_alloc_tmp(tc);
+ tmp[2] = tc_alloc_tmp(tc);
+ tmp[3] = tc_alloc_tmp(tc);
+}
+
+/**
+ * Duplicate an instruction at the current location.
+ */
+static inline struct toy_inst *
+tc_duplicate_inst(struct toy_compiler *tc, const struct toy_inst *inst)
+{
+ struct toy_inst *new_inst;
+
+ new_inst = util_slab_alloc(&tc->mempool);
+ if (!new_inst)
+ return NULL;
+
+ *new_inst = *inst;
+ list_addtail(&new_inst->list, tc->iter_next);
+
+ return new_inst;
+}
+
+/**
+ * Move an instruction to the current location.
+ */
+static inline void
+tc_move_inst(struct toy_compiler *tc, struct toy_inst *inst)
+{
+ list_del(&inst->list);
+ list_addtail(&inst->list, tc->iter_next);
+}
+
+/**
+ * Discard an instruction.
+ */
+static inline void
+tc_discard_inst(struct toy_compiler *tc, struct toy_inst *inst)
+{
+ list_del(&inst->list);
+ util_slab_free(&tc->mempool, inst);
+}
+
+/**
+ * Add a new instruction at the current location, using tc->templ as the
+ * template.
+ */
+static inline struct toy_inst *
+tc_add(struct toy_compiler *tc)
+{
+ return tc_duplicate_inst(tc, &tc->templ);
+}
+
+/**
+ * A convenient version of tc_add() for instructions with 3 source operands.
+ */
+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)
+{
+ struct toy_inst *inst;
+
+ inst = tc_add(tc);
+ if (!inst)
+ return NULL;
+
+ inst->opcode = opcode;
+ inst->dst = dst;
+ inst->src[0] = src0;
+ inst->src[1] = src1;
+ inst->src[2] = src2;
+
+ return inst;
+}
+
+/**
+ * A convenient version of tc_add() for instructions with 2 source operands.
+ */
+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)
+{
+ return tc_add3(tc, opcode, dst, src0, src1, tsrc_null());
+}
+
+/**
+ * A convenient version of tc_add() for instructions with 1 source operand.
+ */
+static inline struct toy_inst *
+tc_add1(struct toy_compiler *tc, unsigned opcode,
+ struct toy_dst dst,
+ struct toy_src src0)
+{
+ return tc_add2(tc, opcode, dst, src0, tsrc_null());
+}
+
+/**
+ * A convenient version of tc_add() for instructions without source or
+ * destination operands.
+ */
+static inline struct toy_inst *
+tc_add0(struct toy_compiler *tc, unsigned opcode)
+{
+ return tc_add1(tc, opcode, tdst_null(), tsrc_null());
+}
+
+#define TC_ALU0(func, opcode) \
+static inline struct toy_inst * \
+func(struct toy_compiler *tc) \
+{ \
+ return tc_add0(tc, opcode); \
+}
+
+#define TC_ALU1(func, opcode) \
+static inline struct toy_inst * \
+func(struct toy_compiler *tc, \
+ struct toy_dst dst, \
+ struct toy_src src) \
+{ \
+ return tc_add1(tc, opcode, dst, src); \
+}
+
+#define TC_ALU2(func, opcode) \
+static inline struct toy_inst * \
+func(struct toy_compiler *tc, \
+ struct toy_dst dst, \
+ struct toy_src src0, \
+ struct toy_src src1) \
+{ \
+ return tc_add2(tc, opcode, \
+ dst, src0, src1); \
+}
+
+#define TC_ALU3(func, opcode) \
+static inline struct toy_inst * \
+func(struct toy_compiler *tc, \
+ struct toy_dst dst, \
+ struct toy_src src0, \
+ struct toy_src src1, \
+ struct toy_src src2) \
+{ \
+ return tc_add3(tc, opcode, \
+ dst, src0, src1, src2); \
+}
+
+#define TC_CND2(func, opcode) \
+static inline struct toy_inst * \
+func(struct toy_compiler *tc, \
+ struct toy_dst dst, \
+ struct toy_src src0, \
+ struct toy_src src1, \
+ unsigned cond_modifier) \
+{ \
+ struct toy_inst *inst; \
+ inst = tc_add2(tc, opcode, \
+ dst, src0, src1); \
+ inst->cond_modifier = cond_modifier; \
+ return inst; \
+}
+
+TC_ALU0(tc_NOP, BRW_OPCODE_NOP)
+TC_ALU0(tc_ELSE, BRW_OPCODE_ELSE)
+TC_ALU0(tc_ENDIF, BRW_OPCODE_ENDIF)
+TC_ALU1(tc_MOV, BRW_OPCODE_MOV)
+TC_ALU1(tc_RNDD, BRW_OPCODE_RNDD)
+TC_ALU1(tc_INV, TOY_OPCODE_INV)
+TC_ALU1(tc_FRC, BRW_OPCODE_FRC)
+TC_ALU1(tc_EXP, TOY_OPCODE_EXP)
+TC_ALU1(tc_LOG, TOY_OPCODE_LOG)
+TC_ALU2(tc_ADD, BRW_OPCODE_ADD)
+TC_ALU2(tc_MUL, BRW_OPCODE_MUL)
+TC_ALU2(tc_AND, BRW_OPCODE_AND)
+TC_ALU2(tc_OR, BRW_OPCODE_OR)
+TC_ALU2(tc_DP2, BRW_OPCODE_DP2)
+TC_ALU2(tc_DP3, BRW_OPCODE_DP3)
+TC_ALU2(tc_DP4, BRW_OPCODE_DP4)
+TC_ALU2(tc_SHL, BRW_OPCODE_SHL)
+TC_ALU2(tc_SHR, BRW_OPCODE_SHR)
+TC_ALU2(tc_POW, TOY_OPCODE_POW)
+TC_ALU3(tc_MAC, BRW_OPCODE_MAC)
+TC_CND2(tc_SEL, BRW_OPCODE_SEL)
+TC_CND2(tc_CMP, BRW_OPCODE_CMP)
+TC_CND2(tc_IF, BRW_OPCODE_IF)
+TC_CND2(tc_SEND, BRW_OPCODE_SEND)
+
+/**
+ * Upcast a list_head to an instruction.
+ */
+static inline struct toy_inst *
+tc_list_to_inst(struct toy_compiler *tc, struct list_head *item)
+{
+ return container_of(item, (struct toy_inst *) NULL, list);
+}
+
+/**
+ * Return the instruction at the current location.
+ */
+static inline struct toy_inst *
+tc_current(struct toy_compiler *tc)
+{
+ return (tc->iter != &tc->instructions) ?
+ tc_list_to_inst(tc, tc->iter) : NULL;
+}
+
+/**
+ * Set the current location to the head.
+ */
+static inline void
+tc_head(struct toy_compiler *tc)
+{
+ tc->iter = &tc->instructions;
+ tc->iter_next = tc->iter->next;
+}
+
+/**
+ * Set the current location to the tail.
+ */
+static inline void
+tc_tail(struct toy_compiler *tc)
+{
+ tc->iter = &tc->instructions;
+ tc->iter_next = tc->iter;
+}
+
+/**
+ * Advance the current location.
+ */
+static inline struct toy_inst *
+tc_next_no_skip(struct toy_compiler *tc)
+{
+ /* stay at the tail so that new instructions are added there */
+ if (tc->iter_next == &tc->instructions) {
+ tc_tail(tc);
+ return NULL;
+ }
+
+ tc->iter = tc->iter_next;
+ tc->iter_next = tc->iter_next->next;
+
+ return tc_list_to_inst(tc, tc->iter);
+}
+
+/**
+ * Advance the current location, skipping markers.
+ */
+static inline struct toy_inst *
+tc_next(struct toy_compiler *tc)
+{
+ struct toy_inst *inst;
+
+ do {
+ inst = tc_next_no_skip(tc);
+ } while (inst && inst->marker);
+
+ return inst;
+}
+
+static inline void
+tc_fail(struct toy_compiler *tc, const char *reason)
+{
+ if (!tc->fail) {
+ tc->fail = true;
+ tc->reason = reason;
+ }
+}
+
+void
+toy_compiler_init(struct toy_compiler *tc, int gen);
+
+void
+toy_compiler_cleanup(struct toy_compiler *tc);
+
+void
+toy_compiler_dump(struct toy_compiler *tc);
+
+void *
+toy_compiler_assemble(struct toy_compiler *tc, int *size);
+
+void
+toy_compiler_disassemble(struct toy_compiler *tc, const void *kernel, int size);
+
+#endif /* TOY_COMPILER_H */