• 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 /* 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