0eff89783dd13e8bb8aca99753bad088e3815104
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
96 commutative
= "commutative "
97 associative
= "associative "
99 # global dictionary of opcodes
102 def opcode(name
, output_size
, output_type
, input_sizes
, input_types
,
103 algebraic_properties
, const_expr
):
104 assert name
not in opcodes
105 opcodes
[name
] = Opcode(name
, output_size
, output_type
, input_sizes
,
106 input_types
, algebraic_properties
, const_expr
)
108 def unop_convert(name
, out_type
, in_type
, const_expr
):
109 opcode(name
, 0, out_type
, [0], [in_type
], "", const_expr
)
111 def unop(name
, ty
, const_expr
):
112 opcode(name
, 0, ty
, [0], [ty
], "", const_expr
)
114 def unop_horiz(name
, output_size
, output_type
, input_size
, input_type
,
116 opcode(name
, output_size
, output_type
, [input_size
], [input_type
], "",
119 def unop_reduce(name
, output_size
, output_type
, input_type
, prereduce_expr
,
120 reduce_expr
, final_expr
):
122 return "(" + prereduce_expr
.format(src
=src
) + ")"
124 return final_expr
.format(src
="(" + src
+ ")")
125 def reduce_(src0
, src1
):
126 return reduce_expr
.format(src0
=src0
, src1
=src1
)
127 src0
= prereduce("src0.x")
128 src1
= prereduce("src0.y")
129 src2
= prereduce("src0.z")
130 src3
= prereduce("src0.w")
131 unop_horiz(name
+ "2", output_size
, output_type
, 2, input_type
,
132 final(reduce_(src0
, src1
)))
133 unop_horiz(name
+ "3", output_size
, output_type
, 3, input_type
,
134 final(reduce_(reduce_(src0
, src1
), src2
)))
135 unop_horiz(name
+ "4", output_size
, output_type
, 4, input_type
,
136 final(reduce_(reduce_(src0
, src1
), reduce_(src2
, src3
))))
139 # These two move instructions differ in what modifiers they support and what
140 # the negate modifier means. Otherwise, they are identical.
141 unop("fmov", tfloat
, "src0")
142 unop("imov", tint
, "src0")
144 unop("ineg", tint
, "-src0")
145 unop("fneg", tfloat
, "-src0")
146 unop("inot", tint
, "~src0") # invert every bit of the integer
147 unop("fnot", tfloat
, "(src0 == 0.0f) ? 1.0f : 0.0f")
148 unop("fsign", tfloat
, "(src0 == 0.0f) ? 0.0f : ((src0 > 0.0f) ? 1.0f : -1.0f)")
149 unop("isign", tint
, "(src0 == 0) ? 0 : ((src0 > 0) ? 1 : -1)")
150 unop("iabs", tint
, "(src0 < 0) ? -src0 : src0")
151 unop("fabs", tfloat
, "fabsf(src0)")
152 unop("fsat", tfloat
, "(src0 > 1.0f) ? 1.0f : ((src0 <= 0.0f) ? 0.0f : src0)")
153 unop("frcp", tfloat
, "1.0f / src0")
154 unop("frsq", tfloat
, "1.0f / sqrtf(src0)")
155 unop("fsqrt", tfloat
, "sqrtf(src0)")
156 unop("fexp2", tfloat
, "exp2f(src0)")
157 unop("flog2", tfloat
, "log2f(src0)")
158 unop_convert("f2i", tint
, tfloat
, "src0") # Float-to-integer conversion.
159 unop_convert("f2u", tuint
, tfloat
, "src0") # Float-to-unsigned conversion
160 unop_convert("i2f", tfloat
, tint
, "src0") # Integer-to-float conversion.
161 # Float-to-boolean conversion
162 unop_convert("f2b", tbool
, tfloat
, "src0 != 0.0f")
163 # Boolean-to-float conversion
164 unop_convert("b2f", tfloat
, tbool
, "src0 ? 1.0f : 0.0f")
165 # Int-to-boolean conversion
166 unop_convert("i2b", tbool
, tint
, "src0 != 0")
167 unop_convert("b2i", tint
, tbool
, "src0 ? 1 : 0") # Boolean-to-int conversion
168 unop_convert("u2f", tfloat
, tuint
, "src0") # Unsigned-to-float conversion.
170 # Unary floating-point rounding operations.
173 unop("ftrunc", tfloat
, "truncf(src0)")
174 unop("fceil", tfloat
, "ceilf(src0)")
175 unop("ffloor", tfloat
, "floorf(src0)")
176 unop("ffract", tfloat
, "src0 - floorf(src0)")
177 unop("fround_even", tfloat
, "_mesa_roundevenf(src0)")
179 unop("fquantize2f16", tfloat
, "(fabs(src0) < ldexpf(1.0, -14)) ? copysignf(0.0f, src0) : _mesa_half_to_float(_mesa_float_to_half(src0))")
181 # Trigonometric operations.
184 unop("fsin", tfloat
, "sinf(src0)")
185 unop("fcos", tfloat
, "cosf(src0)")
188 # Partial derivatives.
191 unop("fddx", tfloat
, "0.0f") # the derivative of a constant is 0.
192 unop("fddy", tfloat
, "0.0f")
193 unop("fddx_fine", tfloat
, "0.0f")
194 unop("fddy_fine", tfloat
, "0.0f")
195 unop("fddx_coarse", tfloat
, "0.0f")
196 unop("fddy_coarse", tfloat
, "0.0f")
199 # Floating point pack and unpack operations.
202 unop_horiz("pack_" + fmt
+ "_2x16", 1, tuint
, 2, tfloat
, """
203 dst.x = (uint32_t) pack_fmt_1x16(src0.x);
204 dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
205 """.replace("fmt", fmt
))
208 unop_horiz("pack_" + fmt
+ "_4x8", 1, tuint
, 4, tfloat
, """
209 dst.x = (uint32_t) pack_fmt_1x8(src0.x);
210 dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
211 dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
212 dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
213 """.replace("fmt", fmt
))
215 def unpack_2x16(fmt
):
216 unop_horiz("unpack_" + fmt
+ "_2x16", 2, tfloat
, 1, tuint
, """
217 dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
218 dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
219 """.replace("fmt", fmt
))
222 unop_horiz("unpack_" + fmt
+ "_4x8", 4, tfloat
, 1, tuint
, """
223 dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
224 dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
225 dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
226 dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
227 """.replace("fmt", fmt
))
241 unop_horiz("pack_uvec2_to_uint", 0, tuint
, 2, tuint
, """
242 dst = (src0.x & 0xffff) | (src0.y >> 16);
245 unop_horiz("pack_uvec4_to_uint", 0, tuint
, 4, tuint
, """
246 dst = (src0.x << 0) |
252 # Lowered floating point unpacking operations.
255 unop_horiz("unpack_half_2x16_split_x", 1, tfloat
, 1, tuint
,
256 "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
257 unop_horiz("unpack_half_2x16_split_y", 1, tfloat
, 1, tuint
,
258 "unpack_half_1x16((uint16_t)(src0.x >> 16))")
261 # Bit operations, part of ARB_gpu_shader5.
264 unop("bitfield_reverse", tuint
, """
265 /* we're not winning any awards for speed here, but that's ok */
267 for (unsigned bit = 0; bit < 32; bit++)
268 dst |= ((src0 >> bit) & 1) << (31 - bit);
270 unop("bit_count", tuint
, """
272 for (unsigned bit = 0; bit < 32; bit++) {
273 if ((src0 >> bit) & 1)
278 unop_convert("ufind_msb", tint
, tuint
, """
280 for (int bit = 31; bit > 0; bit--) {
281 if ((src0 >> bit) & 1) {
288 unop("ifind_msb", tint
, """
290 for (int bit = 31; bit >= 0; bit--) {
291 /* If src0 < 0, we're looking for the first 0 bit.
292 * if src0 >= 0, we're looking for the first 1 bit.
294 if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
295 (!((src0 >> bit) & 1) && (src0 < 0))) {
302 unop("find_lsb", tint
, """
304 for (unsigned bit = 0; bit < 32; bit++) {
305 if ((src0 >> bit) & 1) {
313 for i
in xrange(1, 5):
314 for j
in xrange(1, 5):
315 unop_horiz("fnoise{0}_{1}".format(i
, j
), i
, tfloat
, j
, tfloat
, "0.0f")
317 def binop_convert(name
, out_type
, in_type
, alg_props
, const_expr
):
318 opcode(name
, 0, out_type
, [0, 0], [in_type
, in_type
], alg_props
, const_expr
)
320 def binop(name
, ty
, alg_props
, const_expr
):
321 binop_convert(name
, ty
, ty
, alg_props
, const_expr
)
323 def binop_compare(name
, ty
, alg_props
, const_expr
):
324 binop_convert(name
, tbool
, ty
, alg_props
, const_expr
)
326 def binop_horiz(name
, out_size
, out_type
, src1_size
, src1_type
, src2_size
,
327 src2_type
, const_expr
):
328 opcode(name
, out_size
, out_type
, [src1_size
, src2_size
], [src1_type
, src2_type
],
331 def binop_reduce(name
, output_size
, output_type
, src_type
, prereduce_expr
,
332 reduce_expr
, final_expr
):
334 return final_expr
.format(src
= "(" + src
+ ")")
335 def reduce_(src0
, src1
):
336 return reduce_expr
.format(src0
=src0
, src1
=src1
)
337 def prereduce(src0
, src1
):
338 return "(" + prereduce_expr
.format(src0
=src0
, src1
=src1
) + ")"
339 src0
= prereduce("src0.x", "src1.x")
340 src1
= prereduce("src0.y", "src1.y")
341 src2
= prereduce("src0.z", "src1.z")
342 src3
= prereduce("src0.w", "src1.w")
343 opcode(name
+ "2", output_size
, output_type
,
344 [2, 2], [src_type
, src_type
], commutative
,
345 final(reduce_(src0
, src1
)))
346 opcode(name
+ "3", output_size
, output_type
,
347 [3, 3], [src_type
, src_type
], commutative
,
348 final(reduce_(reduce_(src0
, src1
), src2
)))
349 opcode(name
+ "4", output_size
, output_type
,
350 [4, 4], [src_type
, src_type
], commutative
,
351 final(reduce_(reduce_(src0
, src1
), reduce_(src2
, src3
))))
353 binop("fadd", tfloat
, commutative
+ associative
, "src0 + src1")
354 binop("iadd", tint
, commutative
+ associative
, "src0 + src1")
355 binop("fsub", tfloat
, "", "src0 - src1")
356 binop("isub", tint
, "", "src0 - src1")
358 binop("fmul", tfloat
, commutative
+ associative
, "src0 * src1")
359 # low 32-bits of signed/unsigned integer multiply
360 binop("imul", tint
, commutative
+ associative
, "src0 * src1")
361 # high 32-bits of signed integer multiply
362 binop("imul_high", tint
, commutative
,
363 "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
364 # high 32-bits of unsigned integer multiply
365 binop("umul_high", tuint
, commutative
,
366 "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
368 binop("fdiv", tfloat
, "", "src0 / src1")
369 binop("idiv", tint
, "", "src0 / src1")
370 binop("udiv", tuint
, "", "src0 / src1")
372 # returns a boolean representing the carry resulting from the addition of
373 # the two unsigned arguments.
375 binop_convert("uadd_carry", tuint
, tuint
, commutative
, "src0 + src1 < src0")
377 # returns a boolean representing the borrow resulting from the subtraction
378 # of the two unsigned arguments.
380 binop_convert("usub_borrow", tuint
, tuint
, "", "src0 < src1")
382 binop("umod", tuint
, "", "src1 == 0 ? 0 : src0 % src1")
384 # For signed integers, there are several different possible definitions of
385 # "modulus" or "remainder". We follow the conventions used by LLVM and
386 # SPIR-V. The irem opcode implements the standard C/C++ signed "%"
387 # operation while the imod opcode implements the more mathematical
388 # "modulus" operation. For details on the difference, see
390 # http://mathforum.org/library/drmath/view/52343.html
392 binop("irem", tint
, "", "src1 == 0 ? 0 : src0 % src1")
393 binop("imod", tint
, "",
394 "src1 == 0 ? 0 : ((src0 % src1 == 0 || (src0 >= 0) == (src1 >= 0)) ?"
395 " src0 % src1 : src0 % src1 + src1)")
396 binop("fmod", tfloat
, "", "src0 - src1 * floorf(src0 / src1)")
397 binop("frem", tfloat
, "", "src0 - src1 * truncf(src0 / src1)")
404 # these integer-aware comparisons return a boolean (0 or ~0)
406 binop_compare("flt", tfloat
, "", "src0 < src1")
407 binop_compare("fge", tfloat
, "", "src0 >= src1")
408 binop_compare("feq", tfloat
, commutative
, "src0 == src1")
409 binop_compare("fne", tfloat
, commutative
, "src0 != src1")
410 binop_compare("ilt", tint
, "", "src0 < src1")
411 binop_compare("ige", tint
, "", "src0 >= src1")
412 binop_compare("ieq", tint
, commutative
, "src0 == src1")
413 binop_compare("ine", tint
, commutative
, "src0 != src1")
414 binop_compare("ult", tuint
, "", "src0 < src1")
415 binop_compare("uge", tuint
, "", "src0 >= src1")
417 # integer-aware GLSL-style comparisons that compare floats and ints
419 binop_reduce("ball_fequal", 1, tbool
, tfloat
, "{src0} == {src1}",
420 "{src0} && {src1}", "{src}")
421 binop_reduce("bany_fnequal", 1, tbool
, tfloat
, "{src0} != {src1}",
422 "{src0} || {src1}", "{src}")
423 binop_reduce("ball_iequal", 1, tbool
, tint
, "{src0} == {src1}",
424 "{src0} && {src1}", "{src}")
425 binop_reduce("bany_inequal", 1, tbool
, tint
, "{src0} != {src1}",
426 "{src0} || {src1}", "{src}")
428 # non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
430 binop_reduce("fall_equal", 1, tfloat
, tfloat
, "{src0} == {src1}",
431 "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
432 binop_reduce("fany_nequal", 1, tfloat
, tfloat
, "{src0} != {src1}",
433 "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
435 # These comparisons for integer-less hardware return 1.0 and 0.0 for true
436 # and false respectively
438 binop("slt", tfloat
, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
439 binop("sge", tfloat
, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
440 binop("seq", tfloat
, commutative
, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
441 binop("sne", tfloat
, commutative
, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
444 binop("ishl", tint
, "", "src0 << src1")
445 binop("ishr", tint
, "", "src0 >> src1")
446 binop("ushr", tuint
, "", "src0 >> src1")
448 # bitwise logic operators
450 # These are also used as boolean and, or, xor for hardware supporting
454 binop("iand", tuint
, commutative
+ associative
, "src0 & src1")
455 binop("ior", tuint
, commutative
+ associative
, "src0 | src1")
456 binop("ixor", tuint
, commutative
+ associative
, "src0 ^ src1")
459 # floating point logic operators
461 # These use (src != 0.0) for testing the truth of the input, and output 1.0
462 # for true and 0.0 for false
464 binop("fand", tfloat
, commutative
,
465 "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
466 binop("for", tfloat
, commutative
,
467 "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
468 binop("fxor", tfloat
, commutative
,
469 "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
471 binop_reduce("fdot", 1, tfloat
, tfloat
, "{src0} * {src1}", "{src0} + {src1}",
474 binop_reduce("fdot_replicated", 4, tfloat
, tfloat
,
475 "{src0} * {src1}", "{src0} + {src1}", "{src}")
477 opcode("fdph", 1, tfloat
, [3, 4], [tfloat
, tfloat
], "",
478 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
479 opcode("fdph_replicated", 4, tfloat
, [3, 4], [tfloat
, tfloat
], "",
480 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
482 binop("fmin", tfloat
, "", "fminf(src0, src1)")
483 binop("imin", tint
, commutative
+ associative
, "src1 > src0 ? src0 : src1")
484 binop("umin", tuint
, commutative
+ associative
, "src1 > src0 ? src0 : src1")
485 binop("fmax", tfloat
, "", "fmaxf(src0, src1)")
486 binop("imax", tint
, commutative
+ associative
, "src1 > src0 ? src1 : src0")
487 binop("umax", tuint
, commutative
+ associative
, "src1 > src0 ? src1 : src0")
489 # Saturated vector add for 4 8bit ints.
490 binop("usadd_4x8", tint
, commutative
+ associative
, """
492 for (int i = 0; i < 32; i += 8) {
493 dst |= MIN2(((src0 >> i) & 0xff) + ((src1 >> i) & 0xff), 0xff) << i;
497 # Saturated vector subtract for 4 8bit ints.
498 binop("ussub_4x8", tint
, "", """
500 for (int i = 0; i < 32; i += 8) {
501 int src0_chan = (src0 >> i) & 0xff;
502 int src1_chan = (src1 >> i) & 0xff;
503 if (src0_chan > src1_chan)
504 dst |= (src0_chan - src1_chan) << i;
508 # vector min for 4 8bit ints.
509 binop("umin_4x8", tint
, commutative
+ associative
, """
511 for (int i = 0; i < 32; i += 8) {
512 dst |= MIN2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
516 # vector max for 4 8bit ints.
517 binop("umax_4x8", tint
, commutative
+ associative
, """
519 for (int i = 0; i < 32; i += 8) {
520 dst |= MAX2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
524 # unorm multiply: (a * b) / 255.
525 binop("umul_unorm_4x8", tint
, commutative
+ associative
, """
527 for (int i = 0; i < 32; i += 8) {
528 int src0_chan = (src0 >> i) & 0xff;
529 int src1_chan = (src1 >> i) & 0xff;
530 dst |= ((src0_chan * src1_chan) / 255) << i;
534 binop("fpow", tfloat
, "", "powf(src0, src1)")
536 binop_horiz("pack_half_2x16_split", 1, tuint
, 1, tfloat
, 1, tfloat
,
537 "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
539 # bfm implements the behavior of the first operation of the SM5 "bfi" assembly
540 # and that of the "bfi1" i965 instruction. That is, it has undefined behavior
541 # if either of its arguments are 32.
542 binop_convert("bfm", tuint
, tint
, "", """
543 int bits = src0, offset = src1;
544 if (offset < 0 || bits < 0 || offset > 31 || bits > 31 || offset + bits > 32)
545 dst = 0; /* undefined */
547 dst = ((1u << bits) - 1) << offset;
550 opcode("ldexp", 0, tfloat
, [0, 0], [tfloat
, tint
], "", """
551 dst = ldexpf(src0, src1);
552 /* flush denormals to zero. */
554 dst = copysignf(0.0f, src0);
557 # Combines the first component of each input to make a 2-component vector.
559 binop_horiz("vec2", 2, tuint
, 1, tuint
, 1, tuint
, """
565 binop("extract_ubyte", tuint
, "", "(uint8_t)(src0 >> (src1 * 8))")
566 binop("extract_ibyte", tint
, "", "(int8_t)(src0 >> (src1 * 8))")
569 binop("extract_uword", tuint
, "", "(uint16_t)(src0 >> (src1 * 16))")
570 binop("extract_iword", tint
, "", "(int16_t)(src0 >> (src1 * 16))")
573 def triop(name
, ty
, const_expr
):
574 opcode(name
, 0, ty
, [0, 0, 0], [ty
, ty
, ty
], "", const_expr
)
575 def triop_horiz(name
, output_size
, src1_size
, src2_size
, src3_size
, const_expr
):
576 opcode(name
, output_size
, tuint
,
577 [src1_size
, src2_size
, src3_size
],
578 [tuint
, tuint
, tuint
], "", const_expr
)
580 triop("ffma", tfloat
, "src0 * src1 + src2")
582 triop("flrp", tfloat
, "src0 * (1 - src2) + src1 * src2")
586 # A vector conditional select instruction (like ?:, but operating per-
587 # component on vectors). There are two versions, one for floating point
588 # bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
591 triop("fcsel", tfloat
, "(src0 != 0.0f) ? src1 : src2")
592 opcode("bcsel", 0, tuint
, [0, 0, 0],
593 [tbool
, tuint
, tuint
], "", "src0 ? src1 : src2")
596 triop("bfi", tuint
, """
597 unsigned mask = src0, insert = src1, base = src2;
606 dst = (base & ~mask) | (insert & mask);
610 # SM5 ubfe/ibfe assembly
611 opcode("ubfe", 0, tuint
,
612 [0, 0, 0], [tuint
, tint
, tint
], "", """
613 unsigned base = src0;
614 int offset = src1, bits = src2;
617 } else if (bits < 0 || offset < 0) {
618 dst = 0; /* undefined */
619 } else if (offset + bits < 32) {
620 dst = (base << (32 - bits - offset)) >> (32 - bits);
622 dst = base >> offset;
625 opcode("ibfe", 0, tint
,
626 [0, 0, 0], [tint
, tint
, tint
], "", """
628 int offset = src1, bits = src2;
631 } else if (bits < 0 || offset < 0) {
632 dst = 0; /* undefined */
633 } else if (offset + bits < 32) {
634 dst = (base << (32 - bits - offset)) >> (32 - bits);
636 dst = base >> offset;
640 # GLSL bitfieldExtract()
641 opcode("ubitfield_extract", 0, tuint
,
642 [0, 0, 0], [tuint
, tint
, tint
], "", """
643 unsigned base = src0;
644 int offset = src1, bits = src2;
647 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
648 dst = 0; /* undefined per the spec */
650 dst = (base >> offset) & ((1ull << bits) - 1);
653 opcode("ibitfield_extract", 0, tint
,
654 [0, 0, 0], [tint
, tint
, tint
], "", """
656 int offset = src1, bits = src2;
659 } else if (offset < 0 || bits < 0 || offset + bits > 32) {
662 dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
666 # Combines the first component of each input to make a 3-component vector.
668 triop_horiz("vec3", 3, 1, 1, 1, """
674 def quadop_horiz(name
, output_size
, src1_size
, src2_size
, src3_size
,
675 src4_size
, const_expr
):
676 opcode(name
, output_size
, tuint
,
677 [src1_size
, src2_size
, src3_size
, src4_size
],
678 [tuint
, tuint
, tuint
, tuint
],
681 opcode("bitfield_insert", 0, tuint
, [0, 0, 0, 0],
682 [tuint
, tuint
, tint
, tint
], "", """
683 unsigned base = src0, insert = src1;
684 int offset = src2, bits = src3;
687 } else if (offset < 0 || bits < 0 || bits + offset > 32) {
690 unsigned mask = ((1ull << bits) - 1) << offset;
691 dst = (base & ~mask) | ((insert << bits) & mask);
695 quadop_horiz("vec4", 4, 1, 1, 1, 1, """