• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019 Zodiac Inflight Innovations
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, sub license,
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 (including the
12  * next paragraph) shall be included in all copies or substantial portions
13  * of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Jonathan Marek <jonathan@marek.ca>
25  */
26 
27 #include "etnaviv_compiler_nir.h"
28 #include "util/compiler.h"
29 
30 /* to map nir srcs should to etna_inst srcs */
31 enum {
32    SRC_0_1_2 = (0 << 0) | (1 << 2) | (2 << 4),
33    SRC_0_1_X = (0 << 0) | (1 << 2) | (3 << 4),
34    SRC_0_X_X = (0 << 0) | (3 << 2) | (3 << 4),
35    SRC_0_X_1 = (0 << 0) | (3 << 2) | (1 << 4),
36    SRC_0_1_0 = (0 << 0) | (1 << 2) | (0 << 4),
37    SRC_X_X_0 = (3 << 0) | (3 << 2) | (0 << 4),
38    SRC_0_X_0 = (0 << 0) | (3 << 2) | (0 << 4),
39 };
40 
41 /* info to translate a nir op to etna_inst */
42 struct etna_op_info {
43    uint8_t opcode; /* INST_OPCODE_ */
44    uint8_t src; /* SRC_ enum  */
45    uint8_t cond; /* INST_CONDITION_ */
46    uint8_t type; /* INST_TYPE_ */
47 };
48 
49 static const struct etna_op_info etna_ops[] = {
50    [0 ... nir_num_opcodes - 1] = {0xff},
51 #undef TRUE
52 #undef FALSE
53 #define OPCT(nir, op, src, cond, type) [nir_op_##nir] = { \
54    INST_OPCODE_##op, \
55    SRC_##src, \
56    INST_CONDITION_##cond, \
57    INST_TYPE_##type \
58 }
59 #define OPC(nir, op, src, cond) OPCT(nir, op, src, cond, F32)
60 #define IOPC(nir, op, src, cond) OPCT(nir, op, src, cond, S32)
61 #define UOPC(nir, op, src, cond) OPCT(nir, op, src, cond, U32)
62 #define OP(nir, op, src) OPC(nir, op, src, TRUE)
63 #define IOP(nir, op, src) IOPC(nir, op, src, TRUE)
64 #define UOP(nir, op, src) UOPC(nir, op, src, TRUE)
65    OP(mov, MOV, X_X_0), OP(fneg, MOV, X_X_0), OP(fabs, MOV, X_X_0), OP(fsat, MOV, X_X_0),
66    OP(fmul, MUL, 0_1_X), OP(fadd, ADD, 0_X_1), OP(ffma, MAD, 0_1_2),
67    OP(fdot2, DP2, 0_1_X), OP(fdot3, DP3, 0_1_X), OP(fdot4, DP4, 0_1_X),
68    OPC(fmin, SELECT, 0_1_0, GT), OPC(fmax, SELECT, 0_1_0, LT),
69    OP(ffract, FRC, X_X_0), OP(frcp, RCP, X_X_0), OP(frsq, RSQ, X_X_0),
70    OP(fsqrt, SQRT, X_X_0), OP(fsin, SIN, X_X_0), OP(fcos, COS, X_X_0),
71    OP(fsign, SIGN, X_X_0), OP(ffloor, FLOOR, X_X_0), OP(fceil, CEIL, X_X_0),
72    OP(flog2, LOG, X_X_0), OP(fexp2, EXP, X_X_0),
73    OPC(seq, SET, 0_1_X, EQ), OPC(sne, SET, 0_1_X, NE), OPC(sge, SET, 0_1_X, GE), OPC(slt, SET, 0_1_X, LT),
74    OPC(fcsel, SELECT, 0_1_2, NZ),
75    OP(fdiv, DIV, 0_1_X),
76    OP(fddx, DSX, 0_X_0), OP(fddy, DSY, 0_X_0),
77 
78    /* type convert */
79    IOP(i2f32, I2F, 0_X_X),
80    IOP(i2i32, I2I, 0_X_X),
81    OPCT(i2i16, I2I, 0_X_X, TRUE, S16),
82    OPCT(i2i8,  I2I, 0_X_X, TRUE, S8),
83    UOP(u2f32, I2F, 0_X_X),
84    UOP(u2u32, I2I, 0_X_X),
85    OPCT(u2u16, I2I, 0_X_X, TRUE, U16),
86    OPCT(u2u8,  I2I, 0_X_X, TRUE, U8),
87    IOP(f2i32, F2I, 0_X_X),
88    OPCT(f2i16, F2I, 0_X_X, TRUE, S16),
89    OPCT(f2i8,  F2I, 0_X_X, TRUE, S8),
90    UOP(f2u32, F2I, 0_X_X),
91    OPCT(f2u16, F2I, 0_X_X, TRUE, U16),
92    OPCT(f2u8,  F2I, 0_X_X, TRUE, U8),
93    UOP(b2f32, AND, 0_X_X), /* AND with fui(1.0f) */
94    UOP(b2i32, AND, 0_X_X), /* AND with 1 */
95 
96    /* arithmetic */
97    IOP(iadd, ADD, 0_X_1),
98    IOP(imul, IMULLO0, 0_1_X),
99    /* IOP(imad, IMADLO0, 0_1_2), */
100    IOP(ineg, ADD, X_X_0), /* ADD 0, -x */
101    IOP(iabs, IABS, X_X_0),
102    IOP(isign, SIGN, X_X_0),
103    IOPC(imin, SELECT, 0_1_0, GT),
104    IOPC(imax, SELECT, 0_1_0, LT),
105    UOPC(umin, SELECT, 0_1_0, GT),
106    UOPC(umax, SELECT, 0_1_0, LT),
107 
108    /* select */
109    UOPC(b32csel, SELECT, 0_1_2, NZ),
110 
111    /* compare with int result */
112     OPC(feq32, CMP, 0_1_X, EQ),
113     OPC(fneu32, CMP, 0_1_X, NE),
114     OPC(fge32, CMP, 0_1_X, GE),
115     OPC(flt32, CMP, 0_1_X, LT),
116    IOPC(ieq32, CMP, 0_1_X, EQ),
117    IOPC(ine32, CMP, 0_1_X, NE),
118    IOPC(ige32, CMP, 0_1_X, GE),
119    IOPC(ilt32, CMP, 0_1_X, LT),
120    UOPC(uge32, CMP, 0_1_X, GE),
121    UOPC(ult32, CMP, 0_1_X, LT),
122 
123    /* bit ops */
124    IOP(ior,  OR,  0_X_1),
125    IOP(iand, AND, 0_X_1),
126    IOP(ixor, XOR, 0_X_1),
127    IOP(inot, NOT, X_X_0),
128    IOP(ishl, LSHIFT, 0_X_1),
129    IOP(ishr, RSHIFT, 0_X_1),
130    UOP(ushr, RSHIFT, 0_X_1),
131    UOP(uclz, LEADZERO, 0_X_X),
132 };
133 
134 void
etna_emit_alu(struct etna_compile * c,nir_op op,struct etna_inst_dst dst,struct etna_inst_src src[3],bool saturate)135 etna_emit_alu(struct etna_compile *c, nir_op op, struct etna_inst_dst dst,
136               struct etna_inst_src src[3], bool saturate)
137 {
138    struct etna_op_info ei = etna_ops[op];
139    unsigned swiz_scalar = INST_SWIZ_BROADCAST(ffs(dst.write_mask) - 1);
140 
141    if (ei.opcode == 0xff)
142       compile_error(c, "Unhandled ALU op: %s\n", nir_op_infos[op].name);
143 
144    struct etna_inst inst = {
145       .opcode = ei.opcode,
146       .type = ei.type,
147       .cond = ei.cond,
148       .dst = dst,
149       .sat = saturate,
150    };
151 
152    switch (op) {
153    case nir_op_fdiv:
154    case nir_op_flog2:
155    case nir_op_fsin:
156    case nir_op_fcos:
157       if (c->specs->has_new_transcendentals)
158          inst.tex.amode = 1;
159       FALLTHROUGH;
160    case nir_op_frsq:
161    case nir_op_frcp:
162    case nir_op_fexp2:
163    case nir_op_fsqrt:
164    case nir_op_imul:
165       /* scalar instructions we want src to be in x component */
166       src[0].swiz = inst_swiz_compose(src[0].swiz, swiz_scalar);
167       src[1].swiz = inst_swiz_compose(src[1].swiz, swiz_scalar);
168       break;
169    /* deal with instructions which don't have 1:1 mapping */
170    case nir_op_b2f32:
171       inst.src[2] = etna_immediate_float(1.0f);
172       break;
173    case nir_op_b2i32:
174       inst.src[2] = etna_immediate_int(1);
175       break;
176    case nir_op_ineg:
177       inst.src[0] = etna_immediate_int(0);
178       src[0].neg = 1;
179       break;
180    default:
181       break;
182    }
183 
184    /* set the "true" value for CMP instructions */
185    if (inst.opcode == INST_OPCODE_CMP)
186       inst.src[2] = etna_immediate_int(-1);
187 
188    for (unsigned j = 0; j < 3; j++) {
189       unsigned i = ((ei.src >> j*2) & 3);
190       if (i < 3)
191          inst.src[j] = src[i];
192    }
193 
194    emit_inst(c, &inst);
195 }
196 
197 void
etna_emit_tex(struct etna_compile * c,nir_texop op,unsigned texid,unsigned dst_swiz,struct etna_inst_dst dst,struct etna_inst_src coord,struct etna_inst_src src1,struct etna_inst_src src2)198 etna_emit_tex(struct etna_compile *c, nir_texop op, unsigned texid, unsigned dst_swiz,
199               struct etna_inst_dst dst, struct etna_inst_src coord,
200               struct etna_inst_src src1, struct etna_inst_src src2)
201 {
202    struct etna_inst inst = {
203       .dst = dst,
204       .tex.id = texid + (is_fs(c) ? 0 : c->specs->vertex_sampler_offset),
205       .tex.swiz = dst_swiz,
206       .src[0] = coord,
207    };
208 
209    if (src1.use)
210       inst.src[1] = src1;
211 
212    if (src2.use)
213       inst.src[2] = src2;
214 
215    switch (op) {
216    case nir_texop_tex: inst.opcode = INST_OPCODE_TEXLD; break;
217    case nir_texop_txb: inst.opcode = INST_OPCODE_TEXLDB; break;
218    case nir_texop_txd: inst.opcode = INST_OPCODE_TEXLDD; break;
219    case nir_texop_txl: inst.opcode = INST_OPCODE_TEXLDL; break;
220    default:
221       compile_error(c, "Unhandled NIR tex type: %d\n", op);
222    }
223 
224    emit_inst(c, &inst);
225 }
226 
227 void
etna_emit_jump(struct etna_compile * c,unsigned block,struct etna_inst_src condition)228 etna_emit_jump(struct etna_compile *c, unsigned block, struct etna_inst_src condition)
229 {
230    if (!condition.use) {
231       emit_inst(c, &(struct etna_inst) {.opcode = INST_OPCODE_BRANCH, .imm = block });
232       return;
233    }
234 
235    struct etna_inst inst = {
236       .opcode = INST_OPCODE_BRANCH,
237       .cond = INST_CONDITION_NOT,
238       .type = INST_TYPE_U32,
239       .src[0] = condition,
240       .imm = block,
241    };
242    inst.src[0].swiz = INST_SWIZ_BROADCAST(inst.src[0].swiz & 3);
243    emit_inst(c, &inst);
244 }
245 
246 void
etna_emit_discard(struct etna_compile * c,struct etna_inst_src condition)247 etna_emit_discard(struct etna_compile *c, struct etna_inst_src condition)
248 {
249    if (!condition.use) {
250       emit_inst(c, &(struct etna_inst) { .opcode = INST_OPCODE_TEXKILL });
251       return;
252    }
253 
254    struct etna_inst inst = {
255       .opcode = INST_OPCODE_TEXKILL,
256       .cond = INST_CONDITION_NZ,
257       .type = (c->specs->halti < 2) ? INST_TYPE_F32 : INST_TYPE_U32,
258       .src[0] = condition,
259    };
260    inst.src[0].swiz = INST_SWIZ_BROADCAST(inst.src[0].swiz & 3);
261    emit_inst(c, &inst);
262 }
263