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"
28
#include "util/compiler.h"
30
/* to map nir srcs should to etna_inst srcs */
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),
41
/* info to translate a nir op to etna_inst */
43
uint8_t opcode; /* INST_OPCODE_ */
44
uint8_t src; /* SRC_ enum */
45
uint8_t cond; /* INST_CONDITION_ */
46
uint8_t type; /* INST_TYPE_ */
49
static const struct etna_op_info etna_ops[] = {
50
[0 ... nir_num_opcodes - 1] = {0xff},
53
#define OPCT(nir, op, src, cond, type) [nir_op_##nir] = { \
56
INST_CONDITION_##cond, \
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),
76
OP(fddx, DSX, 0_X_0), OP(fddy, DSY, 0_X_0),
79
IOP(i2f32, I2F, 0_X_X),
80
UOP(u2f32, I2F, 0_X_X),
81
IOP(f2i32, F2I, 0_X_X),
82
UOP(f2u32, F2I, 0_X_X),
83
UOP(b2f32, AND, 0_X_X), /* AND with fui(1.0f) */
84
UOP(b2i32, AND, 0_X_X), /* AND with 1 */
85
OPC(f2b32, CMP, 0_X_X, NE), /* != 0.0 */
86
UOPC(i2b32, CMP, 0_X_X, NE), /* != 0 */
89
IOP(iadd, ADD, 0_X_1),
90
IOP(imul, IMULLO0, 0_1_X),
91
/* IOP(imad, IMADLO0, 0_1_2), */
92
IOP(ineg, ADD, X_X_0), /* ADD 0, -x */
93
IOP(iabs, IABS, X_X_0),
94
IOP(isign, SIGN, X_X_0),
95
IOPC(imin, SELECT, 0_1_0, GT),
96
IOPC(imax, SELECT, 0_1_0, LT),
97
UOPC(umin, SELECT, 0_1_0, GT),
98
UOPC(umax, SELECT, 0_1_0, LT),
101
UOPC(b32csel, SELECT, 0_1_2, NZ),
103
/* compare with int result */
104
OPC(feq32, CMP, 0_1_X, EQ),
105
OPC(fneu32, CMP, 0_1_X, NE),
106
OPC(fge32, CMP, 0_1_X, GE),
107
OPC(flt32, CMP, 0_1_X, LT),
108
IOPC(ieq32, CMP, 0_1_X, EQ),
109
IOPC(ine32, CMP, 0_1_X, NE),
110
IOPC(ige32, CMP, 0_1_X, GE),
111
IOPC(ilt32, CMP, 0_1_X, LT),
112
UOPC(uge32, CMP, 0_1_X, GE),
113
UOPC(ult32, CMP, 0_1_X, LT),
117
IOP(iand, AND, 0_X_1),
118
IOP(ixor, XOR, 0_X_1),
119
IOP(inot, NOT, X_X_0),
120
IOP(ishl, LSHIFT, 0_X_1),
121
IOP(ishr, RSHIFT, 0_X_1),
122
UOP(ushr, RSHIFT, 0_X_1),
126
etna_emit_alu(struct etna_compile *c, nir_op op, struct etna_inst_dst dst,
127
struct etna_inst_src src[3], bool saturate)
129
struct etna_op_info ei = etna_ops[op];
130
unsigned swiz_scalar = INST_SWIZ_BROADCAST(ffs(dst.write_mask) - 1);
132
if (ei.opcode == 0xff)
133
compile_error(c, "Unhandled ALU op: %s\n", nir_op_infos[op].name);
135
struct etna_inst inst = {
148
if (c->specs->has_new_transcendentals)
156
/* scalar instructions we want src to be in x component */
157
src[0].swiz = inst_swiz_compose(src[0].swiz, swiz_scalar);
158
src[1].swiz = inst_swiz_compose(src[1].swiz, swiz_scalar);
160
/* deal with instructions which don't have 1:1 mapping */
162
inst.src[2] = etna_immediate_float(1.0f);
165
inst.src[2] = etna_immediate_int(1);
168
inst.src[1] = etna_immediate_float(0.0f);
171
inst.src[1] = etna_immediate_int(0);
174
inst.src[0] = etna_immediate_int(0);
181
/* set the "true" value for CMP instructions */
182
if (inst.opcode == INST_OPCODE_CMP)
183
inst.src[2] = etna_immediate_int(-1);
185
for (unsigned j = 0; j < 3; j++) {
186
unsigned i = ((ei.src >> j*2) & 3);
188
inst.src[j] = src[i];
195
etna_emit_tex(struct etna_compile *c, nir_texop op, unsigned texid, unsigned dst_swiz,
196
struct etna_inst_dst dst, struct etna_inst_src coord,
197
struct etna_inst_src lod_bias, struct etna_inst_src compare)
199
struct etna_inst inst = {
201
.tex.id = texid + (is_fs(c) ? 0 : c->specs->vertex_sampler_offset),
202
.tex.swiz = dst_swiz,
207
inst.src[1] = lod_bias;
210
inst.src[2] = compare;
213
case nir_texop_tex: inst.opcode = INST_OPCODE_TEXLD; break;
214
case nir_texop_txb: inst.opcode = INST_OPCODE_TEXLDB; break;
215
case nir_texop_txl: inst.opcode = INST_OPCODE_TEXLDL; break;
217
compile_error(c, "Unhandled NIR tex type: %d\n", op);
224
etna_emit_jump(struct etna_compile *c, unsigned block, struct etna_inst_src condition)
226
if (!condition.use) {
227
emit_inst(c, &(struct etna_inst) {.opcode = INST_OPCODE_BRANCH, .imm = block });
231
struct etna_inst inst = {
232
.opcode = INST_OPCODE_BRANCH,
233
.cond = INST_CONDITION_NOT,
234
.type = INST_TYPE_U32,
238
inst.src[0].swiz = INST_SWIZ_BROADCAST(inst.src[0].swiz & 3);
243
etna_emit_discard(struct etna_compile *c, struct etna_inst_src condition)
245
if (!condition.use) {
246
emit_inst(c, &(struct etna_inst) { .opcode = INST_OPCODE_TEXKILL });
250
struct etna_inst inst = {
251
.opcode = INST_OPCODE_TEXKILL,
252
.cond = INST_CONDITION_NZ,
253
.type = (c->specs->halti < 2) ? INST_TYPE_F32 : INST_TYPE_U32,
256
inst.src[0].swiz = INST_SWIZ_BROADCAST(inst.src[0].swiz & 3);