3 # Copyright (C) 2014 Connor Abbott
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 # and/or sell copies of the Software, and to permit persons to whom the
10 # Software is furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 # Connor Abbott (cwabbott0@gmail.com)
28 # Class that represents all the information we have about the opcode
29 # NOTE: this must be kept in sync with nir_op_info
32 """Class that represents all the information we have about the opcode
33 NOTE: this must be kept in sync with nir_op_info
35 def __init__(self
, name
, output_size
, output_type
, input_sizes
,
36 input_types
, algebraic_properties
, const_expr
):
39 - name is the name of the opcode (prepend nir_op_ for the enum name)
40 - all types are strings that get nir_type_ prepended to them
41 - input_types is a list of types
42 - algebraic_properties is a space-seperated string, where nir_op_is_ is
43 prepended before each entry
44 - const_expr is an expression or series of statements that computes the
45 constant value of the opcode given the constant values of its inputs.
47 Constant expressions are formed from the variables src0, src1, ...,
48 src(N-1), where N is the number of arguments. The output of the
49 expression should be stored in the dst variable. Per-component input
50 and output variables will be scalars and non-per-component input and
51 output variables will be a struct with fields named x, y, z, and w
52 all of the correct type. Input and output variables can be assumed
53 to already be of the correct type and need no conversion. In
54 particular, the conversion from the C bool type to/from NIR_TRUE and
55 NIR_FALSE happens automatically.
57 For per-component instructions, the entire expression will be
58 executed once for each component. For non-per-component
59 instructions, the expression is expected to store the correct values
60 in dst.x, dst.y, etc. If "dst" does not exist anywhere in the
61 constant expression, an assignment to dst will happen automatically
62 and the result will be equivalent to "dst = <expression>" for
63 per-component instructions and "dst.x = dst.y = ... = <expression>"
64 for non-per-component instructions.
66 assert isinstance(name
, str)
67 assert isinstance(output_size
, int)
68 assert isinstance(output_type
, str)
69 assert isinstance(input_sizes
, list)
70 assert isinstance(input_sizes
[0], int)
71 assert isinstance(input_types
, list)
72 assert isinstance(input_types
[0], str)
73 assert isinstance(algebraic_properties
, str)
74 assert isinstance(const_expr
, str)
75 assert len(input_sizes
) == len(input_types
)
76 assert 0 <= output_size
<= 4
77 for size
in input_sizes
:
82 self
.num_inputs
= len(input_sizes
)
83 self
.output_size
= output_size
84 self
.output_type
= output_type
85 self
.input_sizes
= input_sizes
86 self
.input_types
= input_types
87 self
.algebraic_properties
= algebraic_properties
88 self
.const_expr
= const_expr
90 # helper variables for strings
100 commutative
= "commutative "
101 associative
= "associative "
103 # global dictionary of opcodes
106 def opcode(name
, output_size
, output_type
, input_sizes
, input_types
,
107 algebraic_properties
, const_expr
):
108 assert name
not in opcodes
109 opcodes
[name
] = Opcode(name
, output_size
, output_type
, input_sizes
,
110 input_types
, algebraic_properties
, const_expr
)
112 def unop_convert(name
, out_type
, in_type
, const_expr
):
113 opcode(name
, 0, out_type
, [0], [in_type
], "", const_expr
)
115 def unop(name
, ty
, const_expr
):
116 opcode(name
, 0, ty
, [0], [ty
], "", const_expr
)
118 def unop_horiz(name
, output_size
, output_type
, input_size
, input_type
,
120 opcode(name
, output_size
, output_type
, [input_size
], [input_type
], "",
123 def unop_reduce(name
, output_size
, output_type
, input_type
, prereduce_expr
,
124 reduce_expr
, final_expr
):
126 return "(" + prereduce_expr
.format(src
=src
) + ")"
128 return final_expr
.format(src
="(" + src
+ ")")
129 def reduce_(src0
, src1
):
130 return reduce_expr
.format(src0
=src0
, src1
=src1
)
131 src0
= prereduce("src0.x")
132 src1
= prereduce("src0.y")
133 src2
= prereduce("src0.z")
134 src3
= prereduce("src0.w")
135 unop_horiz(name
+ "2", output_size
, output_type
, 2, input_type
,
136 final(reduce_(src0
, src1
)))
137 unop_horiz(name
+ "3", output_size
, output_type
, 3, input_type
,
138 final(reduce_(reduce_(src0
, src1
), src2
)))
139 unop_horiz(name
+ "4", output_size
, output_type
, 4, input_type
,
140 final(reduce_(reduce_(src0
, src1
), reduce_(src2
, src3
))))
143 # These two move instructions differ in what modifiers they support and what
144 # the negate modifier means. Otherwise, they are identical.
145 unop("fmov", tfloat
, "src0")
146 unop("imov", tint
, "src0")
148 unop("ineg", tint
, "-src0")
149 unop("fneg", tfloat
, "-src0")
150 unop("inot", tint
, "~src0") # invert every bit of the integer
151 unop("fnot", tfloat
, "(src0 == 0.0f) ? 1.0f : 0.0f")
152 unop("fsign", tfloat
, "(src0 == 0.0f) ? 0.0f : ((src0 > 0.0f) ? 1.0f : -1.0f)")
153 unop("isign", tint
, "(src0 == 0) ? 0 : ((src0 > 0) ? 1 : -1)")
154 unop("iabs", tint
, "(src0 < 0) ? -src0 : src0")
155 unop("fabs", tfloat
, "fabsf(src0)")
156 unop("fsat", tfloat
, "(src0 > 1.0f) ? 1.0f : ((src0 <= 0.0f) ? 0.0f : src0)")
157 unop("frcp", tfloat
, "1.0f / src0")
158 unop("frsq", tfloat
, "1.0f / sqrtf(src0)")
159 unop("fsqrt", tfloat
, "sqrtf(src0)")
160 unop("fexp2", tfloat
, "exp2f(src0)")
161 unop("flog2", tfloat
, "log2f(src0)")
162 unop_convert("f2i", tint32
, tfloat32
, "src0") # Float-to-integer conversion.
163 unop_convert("f2u", tuint32
, tfloat32
, "src0") # Float-to-unsigned conversion
164 unop_convert("i2f", tfloat32
, tint32
, "src0") # Integer-to-float conversion.
165 # Float-to-boolean conversion
166 unop_convert("f2b", tbool
, tfloat32
, "src0 != 0.0f")
167 # Boolean-to-float conversion
168 unop_convert("b2f", tfloat32
, tbool
, "src0 ? 1.0f : 0.0f")
169 # Int-to-boolean conversion
170 unop_convert("i2b", tbool
, tint32
, "src0 != 0")
171 unop_convert("b2i", tint32
, tbool
, "src0 ? 1 : 0") # Boolean-to-int conversion
172 unop_convert("u2f", tfloat32
, tuint32
, "src0") # Unsigned-to-float conversion.
174 # Unary floating-point rounding operations.
177 unop("ftrunc", tfloat
, "bit_size == 64 ? trunc(src0) : truncf(src0)")
178 unop("fceil", tfloat
, "bit_size == 64 ? ceil(src0) : ceilf(src0)")
179 unop("ffloor", tfloat
, "bit_size == 64 ? floor(src0) : floorf(src0)")
180 unop("ffract", tfloat
, "src0 - (bit_size == 64 ? floor(src0) : floorf(src0))")
181 unop("fround_even", tfloat
, "bit_size == 64 ? _mesa_roundeven(src0) : _mesa_roundevenf(src0)")
183 unop("fquantize2f16", tfloat
, "(fabs(src0) < ldexpf(1.0, -14)) ? copysignf(0.0f, src0) : _mesa_half_to_float(_mesa_float_to_half(src0))")
185 # Trigonometric operations.
188 unop("fsin", tfloat
, "bit_size == 64 ? sin(src0) : sinf(src0)")
189 unop("fcos", tfloat
, "bit_size == 64 ? cos(src0) : cosf(src0)")
192 # Partial derivatives.
195 unop("fddx", tfloat
, "0.0") # the derivative of a constant is 0.
196 unop("fddy", tfloat
, "0.0")
197 unop("fddx_fine", tfloat
, "0.0")
198 unop("fddy_fine", tfloat
, "0.0")
199 unop("fddx_coarse", tfloat
, "0.0")
200 unop("fddy_coarse", tfloat
, "0.0")
203 # Floating point pack and unpack operations.
206 unop_horiz("pack_" + fmt
+ "_2x16", 1, tuint32
, 2, tfloat32
, """
207 dst.x = (uint32_t) pack_fmt_1x16(src0.x);
208 dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
209 """.replace("fmt", fmt
))
212 unop_horiz("pack_" + fmt
+ "_4x8", 1, tuint32
, 4, tfloat32
, """
213 dst.x = (uint32_t) pack_fmt_1x8(src0.x);
214 dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
215 dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
216 dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
217 """.replace("fmt", fmt
))
219 def unpack_2x16(fmt
):
220 unop_horiz("unpack_" + fmt
+ "_2x16", 2, tfloat32
, 1, tuint32
, """
221 dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
222 dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
223 """.replace("fmt", fmt
))
226 unop_horiz("unpack_" + fmt
+ "_4x8", 4, tfloat32
, 1, tuint32
, """
227 dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
228 dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
229 dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
230 dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
231 """.replace("fmt", fmt
))
245 unop_horiz("pack_uvec2_to_uint", 1, tuint32
, 2, tuint32
, """
246 dst.x = (src0.x & 0xffff) | (src0.y >> 16);
249 unop_horiz("pack_uvec4_to_uint", 1, tuint32
, 4, tuint32
, """
250 dst.x = (src0.x << 0) |
256 # Lowered floating point unpacking operations.
259 unop_horiz("unpack_half_2x16_split_x", 1, tfloat32
, 1, tuint32
,
260 "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
261 unop_horiz("unpack_half_2x16_split_y", 1, tfloat32
, 1, tuint32
,
262 "unpack_half_1x16((uint16_t)(src0.x >> 16))")
265 # Bit operations, part of ARB_gpu_shader5.
268 unop("bitfield_reverse", tuint32
, """
269 /* we're not winning any awards for speed here, but that's ok */
271 for (unsigned bit = 0; bit < 32; bit++)
272 dst |= ((src0 >> bit) & 1) << (31 - bit);
274 unop("bit_count", tuint32
, """
276 for (unsigned bit = 0; bit < 32; bit++) {
277 if ((src0 >> bit) & 1)
282 unop_convert("ufind_msb", tint32
, tuint32
, """
284 for (int bit = 31; bit > 0; bit--) {
285 if ((src0 >> bit) & 1) {
292 unop("ifind_msb", tint32
, """
294 for (int bit = 31; bit >= 0; bit--) {
295 /* If src0 < 0, we're looking for the first 0 bit.
296 * if src0 >= 0, we're looking for the first 1 bit.
298 if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
299 (!((src0 >> bit) & 1) && (src0 < 0))) {
306 unop("find_lsb", tint32
, """
308 for (unsigned bit = 0; bit < 32; bit++) {
309 if ((src0 >> bit) & 1) {
317 for i
in xrange(1, 5):
318 for j
in xrange(1, 5):
319 unop_horiz("fnoise{0}_{1}".format(i
, j
), i
, tfloat
, j
, tfloat
, "0.0f")
321 def binop_convert(name
, out_type
, in_type
, alg_props
, const_expr
):
322 opcode(name
, 0, out_type
, [0, 0], [in_type
, in_type
], alg_props
, const_expr
)
324 def binop(name
, ty
, alg_props
, const_expr
):
325 binop_convert(name
, ty
, ty
, alg_props
, const_expr
)
327 def binop_compare(name
, ty
, alg_props
, const_expr
):
328 binop_convert(name
, tbool
, ty
, alg_props
, const_expr
)
330 def binop_horiz(name
, out_size
, out_type
, src1_size
, src1_type
, src2_size
,
331 src2_type
, const_expr
):
332 opcode(name
, out_size
, out_type
, [src1_size
, src2_size
], [src1_type
, src2_type
],
335 def binop_reduce(name
, output_size
, output_type
, src_type
, prereduce_expr
,
336 reduce_expr
, final_expr
):
338 return final_expr
.format(src
= "(" + src
+ ")")
339 def reduce_(src0
, src1
):
340 return reduce_expr
.format(src0
=src0
, src1
=src1
)
341 def prereduce(src0
, src1
):
342 return "(" + prereduce_expr
.format(src0
=src0
, src1
=src1
) + ")"
343 src0
= prereduce("src0.x", "src1.x")
344 src1
= prereduce("src0.y", "src1.y")
345 src2
= prereduce("src0.z", "src1.z")
346 src3
= prereduce("src0.w", "src1.w")
347 opcode(name
+ "2", output_size
, output_type
,
348 [2, 2], [src_type
, src_type
], commutative
,
349 final(reduce_(src0
, src1
)))
350 opcode(name
+ "3", output_size
, output_type
,
351 [3, 3], [src_type
, src_type
], commutative
,
352 final(reduce_(reduce_(src0
, src1
), src2
)))
353 opcode(name
+ "4", output_size
, output_type
,
354 [4, 4], [src_type
, src_type
], commutative
,
355 final(reduce_(reduce_(src0
, src1
), reduce_(src2
, src3
))))
357 binop("fadd", tfloat
, commutative
+ associative
, "src0 + src1")
358 binop("iadd", tint
, commutative
+ associative
, "src0 + src1")
359 binop("fsub", tfloat
, "", "src0 - src1")
360 binop("isub", tint
, "", "src0 - src1")
362 binop("fmul", tfloat
, commutative
+ associative
, "src0 * src1")
363 # low 32-bits of signed/unsigned integer multiply
364 binop("imul", tint
, commutative
+ associative
, "src0 * src1")
365 # high 32-bits of signed integer multiply
366 binop("imul_high", tint32
, commutative
,
367 "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
368 # high 32-bits of unsigned integer multiply
369 binop("umul_high", tuint32
, commutative
,
370 "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
372 binop("fdiv", tfloat
, "", "src0 / src1")
373 binop("idiv", tint
, "", "src0 / src1")
374 binop("udiv", tuint
, "", "src0 / src1")
376 # returns a boolean representing the carry resulting from the addition of
377 # the two unsigned arguments.
379 binop_convert("uadd_carry", tuint
, tuint
, commutative
, "src0 + src1 < src0")
381 # returns a boolean representing the borrow resulting from the subtraction
382 # of the two unsigned arguments.
384 binop_convert("usub_borrow", tuint
, tuint
, "", "src0 < src1")
386 binop("fmod", tfloat
, "", "src0 - src1 * floorf(src0 / src1)")
387 binop("umod", tuint
, "", "src1 == 0 ? 0 : src0 % src1")
394 # these integer-aware comparisons return a boolean (0 or ~0)
396 binop_compare("flt", tfloat
, "", "src0 < src1")
397 binop_compare("fge", tfloat
, "", "src0 >= src1")
398 binop_compare("feq", tfloat
, commutative
, "src0 == src1")
399 binop_compare("fne", tfloat
, commutative
, "src0 != src1")
400 binop_compare("ilt", tint
, "", "src0 < src1")
401 binop_compare("ige", tint
, "", "src0 >= src1")
402 binop_compare("ieq", tint
, commutative
, "src0 == src1")
403 binop_compare("ine", tint
, commutative
, "src0 != src1")
404 binop_compare("ult", tuint
, "", "src0 < src1")
405 binop_compare("uge", tuint
, "", "src0 >= src1")
407 # integer-aware GLSL-style comparisons that compare floats and ints
409 binop_reduce("ball_fequal", 1, tbool
, tfloat
, "{src0} == {src1}",
410 "{src0} && {src1}", "{src}")
411 binop_reduce("bany_fnequal", 1, tbool
, tfloat
, "{src0} != {src1}",
412 "{src0} || {src1}", "{src}")
413 binop_reduce("ball_iequal", 1, tbool
, tint
, "{src0} == {src1}",
414 "{src0} && {src1}", "{src}")
415 binop_reduce("bany_inequal", 1, tbool
, tint
, "{src0} != {src1}",
416 "{src0} || {src1}", "{src}")
418 # non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
420 binop_reduce("fall_equal", 1, tfloat32
, tfloat32
, "{src0} == {src1}",
421 "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
422 binop_reduce("fany_nequal", 1, tfloat32
, tfloat32
, "{src0} != {src1}",
423 "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
425 # These comparisons for integer-less hardware return 1.0 and 0.0 for true
426 # and false respectively
428 binop("slt", tfloat32
, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
429 binop("sge", tfloat32
, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
430 binop("seq", tfloat32
, commutative
, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
431 binop("sne", tfloat32
, commutative
, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
434 binop("ishl", tint
, "", "src0 << src1")
435 binop("ishr", tint
, "", "src0 >> src1")
436 binop("ushr", tuint
, "", "src0 >> src1")
438 # bitwise logic operators
440 # These are also used as boolean and, or, xor for hardware supporting
444 binop("iand", tuint
, commutative
+ associative
, "src0 & src1")
445 binop("ior", tuint
, commutative
+ associative
, "src0 | src1")
446 binop("ixor", tuint
, commutative
+ associative
, "src0 ^ src1")
449 # floating point logic operators
451 # These use (src != 0.0) for testing the truth of the input, and output 1.0
452 # for true and 0.0 for false
454 binop("fand", tfloat32
, commutative
,
455 "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
456 binop("for", tfloat32
, commutative
,
457 "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
458 binop("fxor", tfloat32
, commutative
,
459 "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
461 binop_reduce("fdot", 1, tfloat
, tfloat
, "{src0} * {src1}", "{src0} + {src1}",
464 binop_reduce("fdot_replicated", 4, tfloat
, tfloat
,
465 "{src0} * {src1}", "{src0} + {src1}", "{src}")
467 opcode("fdph", 1, tfloat
, [3, 4], [tfloat
, tfloat
], "",
468 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
469 opcode("fdph_replicated", 4, tfloat
, [3, 4], [tfloat
, tfloat
], "",
470 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
472 binop("fmin", tfloat
, "", "fminf(src0, src1)")
473 binop("imin", tint
, commutative
+ associative
, "src1 > src0 ? src0 : src1")
474 binop("umin", tuint
, commutative
+ associative
, "src1 > src0 ? src0 : src1")
475 binop("fmax", tfloat
, "", "fmaxf(src0, src1)")
476 binop("imax", tint
, commutative
+ associative
, "src1 > src0 ? src1 : src0")
477 binop("umax", tuint
, commutative
+ associative
, "src1 > src0 ? src1 : src0")
479 # Saturated vector add for 4 8bit ints.
480 binop("usadd_4x8", tint32
, commutative
+ associative
, """
482 for (int i = 0; i < 32; i += 8) {
483 dst |= MIN2(((src0 >> i) & 0xff) + ((src1 >> i) & 0xff), 0xff) << i;
487 # Saturated vector subtract for 4 8bit ints.
488 binop("ussub_4x8", tint32
, "", """
490 for (int i = 0; i < 32; i += 8) {
491 int src0_chan = (src0 >> i) & 0xff;
492 int src1_chan = (src1 >> i) & 0xff;
493 if (src0_chan > src1_chan)
494 dst |= (src0_chan - src1_chan) << i;
498 # vector min for 4 8bit ints.
499 binop("umin_4x8", tint32
, commutative
+ associative
, """
501 for (int i = 0; i < 32; i += 8) {
502 dst |= MIN2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
506 # vector max for 4 8bit ints.
507 binop("umax_4x8", tint32
, commutative
+ associative
, """
509 for (int i = 0; i < 32; i += 8) {
510 dst |= MAX2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
514 # unorm multiply: (a * b) / 255.
515 binop("umul_unorm_4x8", tint32
, commutative
+ associative
, """
517 for (int i = 0; i < 32; i += 8) {
518 int src0_chan = (src0 >> i) & 0xff;
519 int src1_chan = (src1 >> i) & 0xff;
520 dst |= ((src0_chan * src1_chan) / 255) << i;
524 binop("fpow", tfloat
, "", "bit_size == 64 ? powf(src0, src1) : pow(src0, src1)")
526 binop_horiz("pack_half_2x16_split", 1, tuint32
, 1, tfloat32
, 1, tfloat32
,
527 "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
529 # bfm implements the behavior of the first operation of the SM5 "bfi" assembly
530 # and that of the "bfi1" i965 instruction. That is, it has undefined behavior
531 # if either of its arguments are 32.
532 binop_convert("bfm", tuint32
, tint32
, "", """
533 int bits = src0, offset = src1;
534 if (offset < 0 || bits < 0 || offset > 31 || bits > 31 || offset + bits > 32)
535 dst = 0; /* undefined */
537 dst = ((1u << bits) - 1) << offset;
540 opcode("ldexp", 0, tfloat
, [0, 0], [tfloat
, tint
], "", """
541 dst = (bit_size == 64) ? ldexp(src0, src1) : ldexpf(src0, src1);
542 /* flush denormals to zero. */
544 dst = copysignf(0.0f, src0);
547 # Combines the first component of each input to make a 2-component vector.
549 binop_horiz("vec2", 2, tuint
, 1, tuint
, 1, tuint
, """
555 binop("extract_u8", tuint
, "", "(uint8_t)(src0 >> (src1 * 8))")
556 binop("extract_i8", tint
, "", "(int8_t)(src0 >> (src1 * 8))")
559 binop("extract_u16", tuint
, "", "(uint16_t)(src0 >> (src1 * 16))")
560 binop("extract_i16", tint
, "", "(int16_t)(src0 >> (src1 * 16))")
563 def triop(name
, ty
, const_expr
):
564 opcode(name
, 0, ty
, [0, 0, 0], [ty
, ty
, ty
], "", const_expr
)
565 def triop_horiz(name
, output_size
, src1_size
, src2_size
, src3_size
, const_expr
):
566 opcode(name
, output_size
, tuint
,
567 [src1_size
, src2_size
, src3_size
],
568 [tuint
, tuint
, tuint
], "", const_expr
)
570 triop("ffma", tfloat
, "src0 * src1 + src2")
572 triop("flrp", tfloat
, "src0 * (1 - src2) + src1 * src2")
576 # A vector conditional select instruction (like ?:, but operating per-
577 # component on vectors). There are two versions, one for floating point
578 # bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
581 triop("fcsel", tfloat32
, "(src0 != 0.0f) ? src1 : src2")
582 opcode("bcsel", 0, tuint
, [0, 0, 0],
583 [tbool
, tuint
, tuint
], "", "src0 ? src1 : src2")
586 triop("bfi", tuint32
, """
587 unsigned mask = src0, insert = src1, base = src2;
596 dst = (base & ~mask) | (insert & mask);
600 # SM5 ubfe/ibfe assembly
601 opcode("ubfe", 0, tuint32
,
602 [0, 0, 0], [tuint32
, tint32
, tint32
], "", """
603 unsigned base = src0;
604 int offset = src1, bits = src2;
607 } else if (bits < 0 || offset < 0) {
608 dst = 0; /* undefined */
609 } else if (offset + bits < 32) {
610 dst = (base << (32 - bits - offset)) >> (32 - bits);
612 dst = base >> offset;
615 opcode("ibfe", 0, tint32
,
616 [0, 0, 0], [tint32
, tint32
, tint32
], "", """
618 int offset = src1, bits = src2;
621 } else if (bits < 0 || offset < 0) {
622 dst = 0; /* undefined */
623 } else if (offset + bits < 32) {
624 dst = (base << (32 - bits - offset)) >> (32 - bits);
626 dst = base >> offset;
630 # GLSL bitfieldExtract()
631 opcode("ubitfield_extract", 0, tuint32
,
632 [0, 0, 0], [tuint32
, tint32
, tint32
], "", """
633 unsigned base = src0;
634 int offset = src1, bits = src2;
637 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
638 dst = 0; /* undefined per the spec */
640 dst = (base >> offset) & ((1ull << bits) - 1);
643 opcode("ibitfield_extract", 0, tint32
,
644 [0, 0, 0], [tint32
, tint32
, tint32
], "", """
646 int offset = src1, bits = src2;
649 } else if (offset < 0 || bits < 0 || offset + bits > 32) {
652 dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
656 # Combines the first component of each input to make a 3-component vector.
658 triop_horiz("vec3", 3, 1, 1, 1, """
664 def quadop_horiz(name
, output_size
, src1_size
, src2_size
, src3_size
,
665 src4_size
, const_expr
):
666 opcode(name
, output_size
, tuint
,
667 [src1_size
, src2_size
, src3_size
, src4_size
],
668 [tuint
, tuint
, tuint
, tuint
],
671 opcode("bitfield_insert", 0, tuint32
, [0, 0, 0, 0],
672 [tuint32
, tuint32
, tint32
, tint32
], "", """
673 unsigned base = src0, insert = src1;
674 int offset = src2, bits = src3;
677 } else if (offset < 0 || bits < 0 || bits + offset > 32) {
680 unsigned mask = ((1ull << bits) - 1) << offset;
681 dst = (base & ~mask) | ((insert << bits) & mask);
685 quadop_horiz("vec4", 4, 1, 1, 1, 1, """