2 * Copyright (c) 2019 Zodiac Inflight Innovations
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:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
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.
24 * Jonathan Marek <jonathan@marek.ca>
27 #include "etnaviv_compiler_nir.h"
29 /* to map nir srcs should to etna_inst srcs */
31 SRC_0_1_2
= (0 << 0) | (1 << 2) | (2 << 4),
32 SRC_0_1_X
= (0 << 0) | (1 << 2) | (3 << 4),
33 SRC_0_X_X
= (0 << 0) | (3 << 2) | (3 << 4),
34 SRC_0_X_1
= (0 << 0) | (3 << 2) | (1 << 4),
35 SRC_0_1_0
= (0 << 0) | (1 << 2) | (0 << 4),
36 SRC_X_X_0
= (3 << 0) | (3 << 2) | (0 << 4),
37 SRC_0_X_0
= (0 << 0) | (3 << 2) | (0 << 4),
40 /* info to translate a nir op to etna_inst */
42 uint8_t opcode
; /* INST_OPCODE_ */
43 uint8_t src
; /* SRC_ enum */
44 uint8_t cond
; /* INST_CONDITION_ */
45 uint8_t type
; /* INST_TYPE_ */
48 static const struct etna_op_info etna_ops
[] = {
49 [0 ... nir_num_opcodes
- 1] = {0xff},
52 #define OPCT(nir, op, src, cond, type) [nir_op_##nir] = { \
55 INST_CONDITION_##cond, \
58 #define OPC(nir, op, src, cond) OPCT(nir, op, src, cond, F32)
59 #define IOPC(nir, op, src, cond) OPCT(nir, op, src, cond, S32)
60 #define UOPC(nir, op, src, cond) OPCT(nir, op, src, cond, U32)
61 #define OP(nir, op, src) OPC(nir, op, src, TRUE)
62 #define IOP(nir, op, src) IOPC(nir, op, src, TRUE)
63 #define UOP(nir, op, src) UOPC(nir, op, src, TRUE)
64 OP(mov
, MOV
, X_X_0
), OP(fneg
, MOV
, X_X_0
), OP(fabs
, MOV
, X_X_0
), OP(fsat
, MOV
, X_X_0
),
65 OP(fmul
, MUL
, 0_1_X
), OP(fadd
, ADD
, 0_X_1
), OP(ffma
, MAD
, 0_1_2
),
66 OP(fdot2
, DP2
, 0_1_X
), OP(fdot3
, DP3
, 0_1_X
), OP(fdot4
, DP4
, 0_1_X
),
67 OPC(fmin
, SELECT
, 0_1_0
, GT
), OPC(fmax
, SELECT
, 0_1_0
, LT
),
68 OP(ffract
, FRC
, X_X_0
), OP(frcp
, RCP
, X_X_0
), OP(frsq
, RSQ
, X_X_0
),
69 OP(fsqrt
, SQRT
, X_X_0
), OP(fsin
, SIN
, X_X_0
), OP(fcos
, COS
, X_X_0
),
70 OP(fsign
, SIGN
, X_X_0
), OP(ffloor
, FLOOR
, X_X_0
), OP(fceil
, CEIL
, X_X_0
),
71 OP(flog2
, LOG
, X_X_0
), OP(fexp2
, EXP
, X_X_0
),
72 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
),
73 OPC(fcsel
, SELECT
, 0_1_2
, NZ
),
75 OP(fddx
, DSX
, 0_X_0
), OP(fddy
, DSY
, 0_X_0
),
78 IOP(i2f32
, I2F
, 0_X_X
),
79 UOP(u2f32
, I2F
, 0_X_X
),
80 IOP(f2i32
, F2I
, 0_X_X
),
81 UOP(f2u32
, F2I
, 0_X_X
),
82 UOP(b2f32
, AND
, 0_X_X
), /* AND with fui(1.0f) */
83 UOP(b2i32
, AND
, 0_X_X
), /* AND with 1 */
84 OPC(f2b32
, CMP
, 0_X_X
, NE
), /* != 0.0 */
85 UOPC(i2b32
, CMP
, 0_X_X
, NE
), /* != 0 */
88 IOP(iadd
, ADD
, 0_X_1
),
89 IOP(imul
, IMULLO0
, 0_1_X
),
90 /* IOP(imad, IMADLO0, 0_1_2), */
91 IOP(ineg
, ADD
, X_X_0
), /* ADD 0, -x */
92 IOP(iabs
, IABS
, X_X_0
),
93 IOP(isign
, SIGN
, X_X_0
),
94 IOPC(imin
, SELECT
, 0_1_0
, GT
),
95 IOPC(imax
, SELECT
, 0_1_0
, LT
),
96 UOPC(umin
, SELECT
, 0_1_0
, GT
),
97 UOPC(umax
, SELECT
, 0_1_0
, LT
),
100 UOPC(b32csel
, SELECT
, 0_1_2
, NZ
),
102 /* compare with int result */
103 OPC(feq32
, CMP
, 0_1_X
, EQ
),
104 OPC(fneu32
, CMP
, 0_1_X
, NE
),
105 OPC(fge32
, CMP
, 0_1_X
, GE
),
106 OPC(flt32
, CMP
, 0_1_X
, LT
),
107 IOPC(ieq32
, CMP
, 0_1_X
, EQ
),
108 IOPC(ine32
, CMP
, 0_1_X
, NE
),
109 IOPC(ige32
, CMP
, 0_1_X
, GE
),
110 IOPC(ilt32
, CMP
, 0_1_X
, LT
),
111 UOPC(uge32
, CMP
, 0_1_X
, GE
),
112 UOPC(ult32
, CMP
, 0_1_X
, LT
),
116 IOP(iand
, AND
, 0_X_1
),
117 IOP(ixor
, XOR
, 0_X_1
),
118 IOP(inot
, NOT
, X_X_0
),
119 IOP(ishl
, LSHIFT
, 0_X_1
),
120 IOP(ishr
, RSHIFT
, 0_X_1
),
121 UOP(ushr
, RSHIFT
, 0_X_1
),
125 etna_emit_alu(struct etna_compile
*c
, nir_op op
, struct etna_inst_dst dst
,
126 struct etna_inst_src src
[3], bool saturate
)
128 struct etna_op_info ei
= etna_ops
[op
];
129 unsigned swiz_scalar
= INST_SWIZ_BROADCAST(ffs(dst
.write_mask
) - 1);
131 if (ei
.opcode
== 0xff)
132 compile_error(c
, "Unhandled ALU op: %s\n", nir_op_infos
[op
].name
);
134 struct etna_inst inst
= {
147 if (c
->specs
->has_new_transcendentals
)
155 /* scalar instructions we want src to be in x component */
156 src
[0].swiz
= inst_swiz_compose(src
[0].swiz
, swiz_scalar
);
157 src
[1].swiz
= inst_swiz_compose(src
[1].swiz
, swiz_scalar
);
159 /* deal with instructions which don't have 1:1 mapping */
161 inst
.src
[2] = etna_immediate_float(1.0f
);
164 inst
.src
[2] = etna_immediate_int(1);
167 inst
.src
[1] = etna_immediate_float(0.0f
);
170 inst
.src
[1] = etna_immediate_int(0);
173 inst
.src
[0] = etna_immediate_int(0);
180 /* set the "true" value for CMP instructions */
181 if (inst
.opcode
== INST_OPCODE_CMP
)
182 inst
.src
[2] = etna_immediate_int(-1);
184 for (unsigned j
= 0; j
< 3; j
++) {
185 unsigned i
= ((ei
.src
>> j
*2) & 3);
187 inst
.src
[j
] = src
[i
];
194 etna_emit_tex(struct etna_compile
*c
, nir_texop op
, unsigned texid
, unsigned dst_swiz
,
195 struct etna_inst_dst dst
, struct etna_inst_src coord
,
196 struct etna_inst_src lod_bias
, struct etna_inst_src compare
)
198 struct etna_inst inst
= {
200 .tex
.id
= texid
+ (is_fs(c
) ? 0 : c
->specs
->vertex_sampler_offset
),
201 .tex
.swiz
= dst_swiz
,
206 inst
.src
[1] = lod_bias
;
209 inst
.src
[2] = compare
;
212 case nir_texop_tex
: inst
.opcode
= INST_OPCODE_TEXLD
; break;
213 case nir_texop_txb
: inst
.opcode
= INST_OPCODE_TEXLDB
; break;
214 case nir_texop_txl
: inst
.opcode
= INST_OPCODE_TEXLDL
; break;
216 compile_error(c
, "Unhandled NIR tex type: %d\n", op
);
223 etna_emit_jump(struct etna_compile
*c
, unsigned block
, struct etna_inst_src condition
)
225 if (!condition
.use
) {
226 emit_inst(c
, &(struct etna_inst
) {.opcode
= INST_OPCODE_BRANCH
, .imm
= block
});
230 struct etna_inst inst
= {
231 .opcode
= INST_OPCODE_BRANCH
,
232 .cond
= INST_CONDITION_NOT
,
233 .type
= INST_TYPE_U32
,
237 inst
.src
[0].swiz
= INST_SWIZ_BROADCAST(inst
.src
[0].swiz
& 3);
242 etna_emit_discard(struct etna_compile
*c
, struct etna_inst_src condition
)
244 if (!condition
.use
) {
245 emit_inst(c
, &(struct etna_inst
) { .opcode
= INST_OPCODE_TEXKILL
});
249 struct etna_inst inst
= {
250 .opcode
= INST_OPCODE_TEXKILL
,
251 .cond
= INST_CONDITION_NZ
,
252 .type
= (c
->specs
->halti
< 2) ? INST_TYPE_F32
: INST_TYPE_U32
,
255 inst
.src
[0].swiz
= INST_SWIZ_BROADCAST(inst
.src
[0].swiz
& 3);