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 /* info to translate a nir op to etna_inst */
31 struct etna_op_info {
32 enum isa_opc opcode;
33 enum isa_cond cond;
34 enum isa_type type;
35 };
36
37 static const struct etna_op_info etna_ops[] = {
38 [0 ... nir_num_opcodes - 1] = {0xff},
39 #undef TRUE
40 #undef FALSE
41 #define OPCT(nir, op, cond, type) [nir_op_##nir] = { \
42 ISA_OPC_##op, \
43 ISA_COND_##cond, \
44 ISA_TYPE_##type \
45 }
46 #define OPC(nir, op, cond) OPCT(nir, op, cond, F32)
47 #define IOPC(nir, op, cond) OPCT(nir, op, cond, S32)
48 #define UOPC(nir, op, cond) OPCT(nir, op, cond, U32)
49 #define OP(nir, op) OPC(nir, op, TRUE)
50 #define IOP(nir, op) IOPC(nir, op, TRUE)
51 #define UOP(nir, op) UOPC(nir, op, TRUE)
52 OP(mov, MOV), OP(fneg, MOV), OP(fabs, MOV), OP(fsat, MOV),
53 OP(fmul, MUL), OP(fadd, ADD), OP(ffma, MAD),
54 OP(fdot2, DP2), OP(fdot3, DP3), OP(fdot4, DP4),
55 OPC(fmin, SELECT, GT), OPC(fmax, SELECT, LT),
56 OP(ffract, FRC), OP(frcp, RCP), OP(frsq, RSQ),
57 OP(fsqrt, SQRT), OP(fsin, SIN), OP(fcos, COS),
58 OP(fsign, SIGN), OP(ffloor, FLOOR), OP(fceil, CEIL),
59 OP(flog2, LOG), OP(fexp2, EXP),
60 OPC(seq, SET, EQ), OPC(sne, SET, NE), OPC(sge, SET, GE), OPC(slt, SET, LT),
61 OPC(fcsel, SELECT, NZ),
62 OP(fdiv, DIV),
63
64 /* type convert */
65 IOP(i2f32, I2F),
66 IOP(i2i32, I2I),
67 OPCT(i2i16, I2I, TRUE, S16),
68 OPCT(i2i8, I2I, TRUE, S8),
69 UOP(u2f32, I2F),
70 UOP(u2u32, I2I),
71 OPCT(u2u16, I2I, TRUE, U16),
72 OPCT(u2u8, I2I, TRUE, U8),
73 IOP(f2i32, F2I),
74 OPCT(f2i16, F2I, TRUE, S16),
75 OPCT(f2i8, F2I, TRUE, S8),
76 UOP(f2u32, F2I),
77 OPCT(f2u16, F2I, TRUE, U16),
78 OPCT(f2u8, F2I, TRUE, U8),
79 UOP(b2f32, AND), /* AND with fui(1.0f) */
80 UOP(b2i32, AND), /* AND with 1 */
81 UOP(b2i8, AND), /* AND with 1 */
82
83 /* arithmetic */
84 IOP(iadd, ADD),
85 IOP(imul, IMULLO0),
86 /* IOP(imad, IMADLO0), */
87 IOP(ineg, ADD), /* ADD 0, -x */
88 IOP(iabs, IABS),
89 IOP(isign, SIGN),
90 IOPC(imin, SELECT, GT),
91 IOPC(imax, SELECT, LT),
92 UOPC(umin, SELECT, GT),
93 UOPC(umax, SELECT, LT),
94
95 /* select */
96 UOPC(b32csel, SELECT, NZ),
97
98 /* compare with int result */
99 OPC(feq32, CMP, EQ),
100 OPC(fneu32, CMP, NE),
101 OPC(fge32, CMP, GE),
102 OPC(flt32, CMP, LT),
103 IOPC(ieq32, CMP, EQ),
104 IOPC(ine32, CMP, NE),
105 IOPC(ige32, CMP, GE),
106 IOPC(ilt32, CMP, LT),
107 UOPC(uge32, CMP, GE),
108 UOPC(ult32, CMP, LT),
109
110 /* bit ops */
111 IOP(ior, OR),
112 IOP(iand, AND),
113 IOP(ixor, XOR),
114 IOP(inot, NOT),
115 IOP(ishl, LSHIFT),
116 IOP(ishr, RSHIFT),
117 UOP(ushr, RSHIFT),
118 UOP(uclz, LEADZERO),
119 };
120
121 void
etna_emit_alu(struct etna_compile * c,nir_op op,struct etna_inst_dst dst,struct etna_inst_src src[3],bool saturate)122 etna_emit_alu(struct etna_compile *c, nir_op op, struct etna_inst_dst dst,
123 struct etna_inst_src src[3], bool saturate)
124 {
125 struct etna_op_info ei = etna_ops[op];
126 unsigned swiz_scalar = INST_SWIZ_BROADCAST(ffs(dst.write_mask) - 1);
127
128 if (ei.opcode == 0xff)
129 compile_error(c, "Unhandled ALU op: %s\n", nir_op_infos[op].name);
130
131 struct etna_inst inst = {
132 .opcode = ei.opcode,
133 .type = ei.type,
134 .cond = ei.cond,
135 .dst = dst,
136 .sat = saturate,
137 .src[0] = src[0],
138 .src[1] = src[1],
139 .src[2] = src[2],
140
141 };
142
143 switch (op) {
144 case nir_op_fdiv:
145 case nir_op_flog2:
146 case nir_op_fsin:
147 case nir_op_fcos:
148 if (c->specs->has_new_transcendentals)
149 inst.rounding = ISA_ROUNDING_RTZ;
150 FALLTHROUGH;
151 case nir_op_frsq:
152 case nir_op_frcp:
153 case nir_op_fexp2:
154 case nir_op_fsqrt:
155 case nir_op_imul:
156 /* scalar instructions we want src to be in x component */
157 inst.src[0].swiz = inst_swiz_compose(src[0].swiz, swiz_scalar);
158 inst.src[1].swiz = inst_swiz_compose(src[1].swiz, swiz_scalar);
159 break;
160 /* deal with instructions which don't have 1:1 mapping */
161 case nir_op_fmin:
162 case nir_op_fmax:
163 case nir_op_imin:
164 case nir_op_imax:
165 case nir_op_umin:
166 case nir_op_umax:
167 inst.src[2] = src[0];
168 break;
169 case nir_op_b2f32:
170 inst.src[1] = etna_immediate_float(1.0f);
171 break;
172 case nir_op_b2i32:
173 inst.src[1] = etna_immediate_int(1);
174 break;
175 case nir_op_ineg:
176 /* ADD 0, -x */
177 inst.src[0] = etna_immediate_int(0);
178 inst.src[1] = src[0];
179 inst.src[1].neg = 1;
180 break;
181 default:
182 break;
183 }
184
185 /* set the "true" value for CMP instructions */
186 if (inst.opcode == ISA_OPC_CMP)
187 inst.src[2] = etna_immediate_int(-1);
188
189 emit_inst(c, &inst);
190 }
191
192 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)193 etna_emit_tex(struct etna_compile *c, nir_texop op, unsigned texid, unsigned dst_swiz,
194 struct etna_inst_dst dst, struct etna_inst_src coord,
195 struct etna_inst_src src1, struct etna_inst_src src2)
196 {
197 struct etna_inst inst = {
198 .dst = dst,
199 .tex.id = texid + (is_fs(c) ? 0 : c->specs->vertex_sampler_offset),
200 .tex.swiz = dst_swiz,
201 .src[0] = coord,
202 };
203
204 if (src1.use)
205 inst.src[1] = src1;
206
207 if (src2.use)
208 inst.src[2] = src2;
209
210 switch (op) {
211 case nir_texop_tex: inst.opcode = ISA_OPC_TEXLD; break;
212 case nir_texop_txb: inst.opcode = ISA_OPC_TEXLDB; break;
213 case nir_texop_txd: inst.opcode = ISA_OPC_TEXLDD; break;
214 case nir_texop_txl: inst.opcode = ISA_OPC_TEXLDL; break;
215 default:
216 compile_error(c, "Unhandled NIR tex type: %d\n", op);
217 }
218
219 emit_inst(c, &inst);
220 }
221
222 void
etna_emit_jump(struct etna_compile * c,unsigned block,struct etna_inst_src condition)223 etna_emit_jump(struct etna_compile *c, unsigned block, struct etna_inst_src condition)
224 {
225 if (!condition.use) {
226 emit_inst(c, &(struct etna_inst) {.opcode = ISA_OPC_BRANCH, .imm = block });
227 return;
228 }
229
230 struct etna_inst inst = {
231 .opcode = ISA_OPC_BRANCH_UNARY,
232 .cond = ISA_COND_NOT,
233 .type = ISA_TYPE_U32,
234 .src[0] = condition,
235 .imm = block,
236 };
237 inst.src[0].swiz = INST_SWIZ_BROADCAST(inst.src[0].swiz & 3);
238 emit_inst(c, &inst);
239 }
240
241 void
etna_emit_discard(struct etna_compile * c,struct etna_inst_src condition)242 etna_emit_discard(struct etna_compile *c, struct etna_inst_src condition)
243 {
244 if (!condition.use) {
245 emit_inst(c, &(struct etna_inst) { .opcode = ISA_OPC_TEXKILL });
246 return;
247 }
248
249 struct etna_inst inst = {
250 .opcode = ISA_OPC_TEXKILL,
251 .cond = ISA_COND_NZ,
252 .type = (c->info->halti < 2) ? ISA_TYPE_F32 : ISA_TYPE_U32,
253 .src[0] = condition,
254 };
255 inst.src[0].swiz = INST_SWIZ_BROADCAST(inst.src[0].swiz & 3);
256 emit_inst(c, &inst);
257 }
258