8cad74832a6d29a5886588063b3121e92696bc27
2 # Copyright (C) 2014 Connor Abbott
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, sublicense,
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 next
12 # paragraph) shall be included in all copies or substantial portions of the
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 NONINFRINGEMENT. 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 DEALINGS
24 # Connor Abbott (cwabbott0@gmail.com)
27 # Class that represents all the information we have about the opcode
28 # NOTE: this must be kept in sync with nir_op_info
31 """Class that represents all the information we have about the opcode
32 NOTE: this must be kept in sync with nir_op_info
34 def __init__(self
, name
, output_size
, output_type
, input_sizes
,
35 input_types
, algebraic_properties
, const_expr
):
38 - name is the name of the opcode (prepend nir_op_ for the enum name)
39 - all types are strings that get nir_type_ prepended to them
40 - input_types is a list of types
41 - algebraic_properties is a space-seperated string, where nir_op_is_ is
42 prepended before each entry
43 - const_expr is an expression or series of statements that computes the
44 constant value of the opcode given the constant values of its inputs.
46 Constant expressions are formed from the variables src0, src1, ...,
47 src(N-1), where N is the number of arguments. The output of the
48 expression should be stored in the dst variable. Per-component input
49 and output variables will be scalars and non-per-component input and
50 output variables will be a struct with fields named x, y, z, and w
51 all of the correct type. Input and output variables can be assumed
52 to already be of the correct type and need no conversion. In
53 particular, the conversion from the C bool type to/from NIR_TRUE and
54 NIR_FALSE happens automatically.
56 For per-component instructions, the entire expression will be
57 executed once for each component. For non-per-component
58 instructions, the expression is expected to store the correct values
59 in dst.x, dst.y, etc. If "dst" does not exist anywhere in the
60 constant expression, an assignment to dst will happen automatically
61 and the result will be equivalent to "dst = <expression>" for
62 per-component instructions and "dst.x = dst.y = ... = <expression>"
63 for non-per-component instructions.
65 assert isinstance(name
, str)
66 assert isinstance(output_size
, int)
67 assert isinstance(output_type
, str)
68 assert isinstance(input_sizes
, list)
69 assert isinstance(input_sizes
[0], int)
70 assert isinstance(input_types
, list)
71 assert isinstance(input_types
[0], str)
72 assert isinstance(algebraic_properties
, str)
73 assert isinstance(const_expr
, str)
74 assert len(input_sizes
) == len(input_types
)
75 assert 0 <= output_size
<= 4
76 for size
in input_sizes
:
81 self
.num_inputs
= len(input_sizes
)
82 self
.output_size
= output_size
83 self
.output_type
= output_type
84 self
.input_sizes
= input_sizes
85 self
.input_types
= input_types
86 self
.algebraic_properties
= algebraic_properties
87 self
.const_expr
= const_expr
89 # helper variables for strings
101 commutative
= "commutative "
102 associative
= "associative "
104 # global dictionary of opcodes
107 def opcode(name
, output_size
, output_type
, input_sizes
, input_types
,
108 algebraic_properties
, const_expr
):
109 assert name
not in opcodes
110 opcodes
[name
] = Opcode(name
, output_size
, output_type
, input_sizes
,
111 input_types
, algebraic_properties
, const_expr
)
113 def unop_convert(name
, out_type
, in_type
, const_expr
):
114 opcode(name
, 0, out_type
, [0], [in_type
], "", const_expr
)
116 def unop(name
, ty
, const_expr
):
117 opcode(name
, 0, ty
, [0], [ty
], "", const_expr
)
119 def unop_horiz(name
, output_size
, output_type
, input_size
, input_type
,
121 opcode(name
, output_size
, output_type
, [input_size
], [input_type
], "",
124 def unop_reduce(name
, output_size
, output_type
, input_type
, prereduce_expr
,
125 reduce_expr
, final_expr
):
127 return "(" + prereduce_expr
.format(src
=src
) + ")"
129 return final_expr
.format(src
="(" + src
+ ")")
130 def reduce_(src0
, src1
):
131 return reduce_expr
.format(src0
=src0
, src1
=src1
)
132 src0
= prereduce("src0.x")
133 src1
= prereduce("src0.y")
134 src2
= prereduce("src0.z")
135 src3
= prereduce("src0.w")
136 unop_horiz(name
+ "2", output_size
, output_type
, 2, input_type
,
137 final(reduce_(src0
, src1
)))
138 unop_horiz(name
+ "3", output_size
, output_type
, 3, input_type
,
139 final(reduce_(reduce_(src0
, src1
), src2
)))
140 unop_horiz(name
+ "4", output_size
, output_type
, 4, input_type
,
141 final(reduce_(reduce_(src0
, src1
), reduce_(src2
, src3
))))
144 # These two move instructions differ in what modifiers they support and what
145 # the negate modifier means. Otherwise, they are identical.
146 unop("fmov", tfloat
, "src0")
147 unop("imov", tint
, "src0")
149 unop("ineg", tint
, "-src0")
150 unop("fneg", tfloat
, "-src0")
151 unop("inot", tint
, "~src0") # invert every bit of the integer
152 unop("fnot", tfloat
, ("bit_size == 64 ? ((src0 == 0.0) ? 1.0 : 0.0f) : " +
153 "((src0 == 0.0f) ? 1.0f : 0.0f)"))
154 unop("fsign", tfloat
, ("bit_size == 64 ? " +
155 "((src0 == 0.0) ? 0.0 : ((src0 > 0.0) ? 1.0 : -1.0)) : " +
156 "((src0 == 0.0f) ? 0.0f : ((src0 > 0.0f) ? 1.0f : -1.0f))"))
157 unop("isign", tint
, "(src0 == 0) ? 0 : ((src0 > 0) ? 1 : -1)")
158 unop("iabs", tint
, "(src0 < 0) ? -src0 : src0")
159 unop("fabs", tfloat
, "bit_size == 64 ? fabs(src0) : fabsf(src0)")
160 unop("fsat", tfloat
, ("bit_size == 64 ? " +
161 "((src0 > 1.0) ? 1.0 : ((src0 <= 0.0) ? 0.0 : src0)) : " +
162 "((src0 > 1.0f) ? 1.0f : ((src0 <= 0.0f) ? 0.0f : src0))"))
163 unop("frcp", tfloat
, "bit_size == 64 ? 1.0 / src0 : 1.0f / src0")
164 unop("frsq", tfloat
, "bit_size == 64 ? 1.0 / sqrt(src0) : 1.0f / sqrtf(src0)")
165 unop("fsqrt", tfloat
, "bit_size == 64 ? sqrt(src0) : sqrtf(src0)")
166 unop("fexp2", tfloat
, "exp2f(src0)")
167 unop("flog2", tfloat
, "log2f(src0)")
168 unop_convert("f2i", tint32
, tfloat32
, "src0") # Float-to-integer conversion.
169 unop_convert("f2u", tuint32
, tfloat32
, "src0") # Float-to-unsigned conversion
170 unop_convert("d2i", tint32
, tfloat64
, "src0") # Double-to-integer conversion.
171 unop_convert("d2u", tuint32
, tfloat64
, "src0") # Double-to-unsigned conversion.
172 unop_convert("i2f", tfloat32
, tint32
, "src0") # Integer-to-float conversion.
173 unop_convert("i2d", tfloat64
, tint32
, "src0") # Integer-to-double conversion.
174 unop_convert("i2i32", tint32
, tint
, "src0") # General int (int8_t, int64_t, etc.) to int32_t conversion
175 unop_convert("u2i32", tint32
, tuint
, "src0") # General uint (uint8_t, uint64_t, etc.) to int32_t conversion
176 unop_convert("i2u32", tuint32
, tint
, "src0") # General int (int8_t, int64_t, etc.) to uint32_t conversion
177 unop_convert("u2u32", tuint32
, tuint
, "src0") # General uint (uint8_t, uint64_t, etc.) to uint32_t conversion
178 unop_convert("i2i64", tint64
, tint
, "src0") # General int (int8_t, int32_t, etc.) to int64_t conversion
179 unop_convert("u2i64", tint64
, tuint
, "src0") # General uint (uint8_t, uint64_t, etc.) to int64_t conversion
180 unop_convert("f2i64", tint64
, tfloat
, "src0") # General float (float or double) to int64_t conversion
181 unop_convert("i2u64", tuint64
, tint
, "src0") # General int (int8_t, int64_t, etc.) to uint64_t conversion
182 unop_convert("u2u64", tuint64
, tuint
, "src0") # General uint (uint8_t, uint32_t, etc.) to uint64_t conversion
183 unop_convert("f2u64", tuint64
, tfloat
, "src0") # General float (float or double) to uint64_t conversion
184 unop_convert("i642f", tfloat32
, tint64
, "src0") # int64_t-to-float conversion.
185 unop_convert("i642b", tbool
, tint64
, "src0") # int64_t-to-bool conversion.
186 unop_convert("i642d", tfloat64
, tint64
, "src0") # int64_t-to-double conversion.
187 unop_convert("u642f", tfloat32
, tuint64
, "src0") # uint64_t-to-float conversion.
188 unop_convert("u642d", tfloat64
, tuint64
, "src0") # uint64_t-to-double conversion.
190 # Float-to-boolean conversion
191 unop_convert("f2b", tbool
, tfloat32
, "src0 != 0.0f")
192 unop_convert("d2b", tbool
, tfloat64
, "src0 != 0.0")
193 # Boolean-to-float conversion
194 unop_convert("b2f", tfloat32
, tbool
, "src0 ? 1.0f : 0.0f")
195 # Int-to-boolean conversion
196 unop_convert("i2b", tbool
, tint
, "src0 != 0")
197 unop_convert("b2i", tint32
, tbool
, "src0 ? 1 : 0") # Boolean-to-int conversion
198 unop_convert("b2i64", tint64
, tbool
, "src0 ? 1 : 0") # Boolean-to-int64_t conversion.
199 unop_convert("u2f", tfloat32
, tuint32
, "src0") # Unsigned-to-float conversion.
200 unop_convert("u2d", tfloat64
, tuint32
, "src0") # Unsigned-to-double conversion.
201 # double-to-float conversion
202 unop_convert("d2f", tfloat32
, tfloat64
, "src0") # Double to single precision
203 unop_convert("f2d", tfloat64
, tfloat32
, "src0") # Single to double precision
205 # Unary floating-point rounding operations.
208 unop("ftrunc", tfloat
, "bit_size == 64 ? trunc(src0) : truncf(src0)")
209 unop("fceil", tfloat
, "bit_size == 64 ? ceil(src0) : ceilf(src0)")
210 unop("ffloor", tfloat
, "bit_size == 64 ? floor(src0) : floorf(src0)")
211 unop("ffract", tfloat
, "src0 - (bit_size == 64 ? floor(src0) : floorf(src0))")
212 unop("fround_even", tfloat
, "bit_size == 64 ? _mesa_roundeven(src0) : _mesa_roundevenf(src0)")
214 unop("fquantize2f16", tfloat
, "(fabs(src0) < ldexpf(1.0, -14)) ? copysignf(0.0f, src0) : _mesa_half_to_float(_mesa_float_to_half(src0))")
216 # Trigonometric operations.
219 unop("fsin", tfloat
, "bit_size == 64 ? sin(src0) : sinf(src0)")
220 unop("fcos", tfloat
, "bit_size == 64 ? cos(src0) : cosf(src0)")
223 # Partial derivatives.
226 unop("fddx", tfloat
, "0.0") # the derivative of a constant is 0.
227 unop("fddy", tfloat
, "0.0")
228 unop("fddx_fine", tfloat
, "0.0")
229 unop("fddy_fine", tfloat
, "0.0")
230 unop("fddx_coarse", tfloat
, "0.0")
231 unop("fddy_coarse", tfloat
, "0.0")
234 # Floating point pack and unpack operations.
237 unop_horiz("pack_" + fmt
+ "_2x16", 1, tuint32
, 2, tfloat32
, """
238 dst.x = (uint32_t) pack_fmt_1x16(src0.x);
239 dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
240 """.replace("fmt", fmt
))
243 unop_horiz("pack_" + fmt
+ "_4x8", 1, tuint32
, 4, tfloat32
, """
244 dst.x = (uint32_t) pack_fmt_1x8(src0.x);
245 dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
246 dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
247 dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
248 """.replace("fmt", fmt
))
250 def unpack_2x16(fmt
):
251 unop_horiz("unpack_" + fmt
+ "_2x16", 2, tfloat32
, 1, tuint32
, """
252 dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
253 dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
254 """.replace("fmt", fmt
))
257 unop_horiz("unpack_" + fmt
+ "_4x8", 4, tfloat32
, 1, tuint32
, """
258 dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
259 dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
260 dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
261 dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
262 """.replace("fmt", fmt
))
276 unop_horiz("pack_uvec2_to_uint", 1, tuint32
, 2, tuint32
, """
277 dst.x = (src0.x & 0xffff) | (src0.y << 16);
280 unop_horiz("pack_uvec4_to_uint", 1, tuint32
, 4, tuint32
, """
281 dst.x = (src0.x << 0) |
287 unop_horiz("pack_64_2x32", 1, tuint64
, 2, tuint32
,
288 "dst.x = src0.x | ((uint64_t)src0.y << 32);")
290 unop_horiz("unpack_64_2x32", 2, tuint32
, 1, tuint64
,
291 "dst.x = src0.x; dst.y = src0.x >> 32;")
293 # Lowered floating point unpacking operations.
296 unop_horiz("unpack_half_2x16_split_x", 1, tfloat32
, 1, tuint32
,
297 "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
298 unop_horiz("unpack_half_2x16_split_y", 1, tfloat32
, 1, tuint32
,
299 "unpack_half_1x16((uint16_t)(src0.x >> 16))")
301 unop_convert("unpack_64_2x32_split_x", tuint32
, tuint64
, "src0")
302 unop_convert("unpack_64_2x32_split_y", tuint32
, tuint64
, "src0 >> 32")
304 # Bit operations, part of ARB_gpu_shader5.
307 unop("bitfield_reverse", tuint32
, """
308 /* we're not winning any awards for speed here, but that's ok */
310 for (unsigned bit = 0; bit < 32; bit++)
311 dst |= ((src0 >> bit) & 1) << (31 - bit);
313 unop("bit_count", tuint32
, """
315 for (unsigned bit = 0; bit < 32; bit++) {
316 if ((src0 >> bit) & 1)
321 unop_convert("ufind_msb", tint32
, tuint32
, """
323 for (int bit = 31; bit > 0; bit--) {
324 if ((src0 >> bit) & 1) {
331 unop("ifind_msb", tint32
, """
333 for (int bit = 31; bit >= 0; bit--) {
334 /* If src0 < 0, we're looking for the first 0 bit.
335 * if src0 >= 0, we're looking for the first 1 bit.
337 if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
338 (!((src0 >> bit) & 1) && (src0 < 0))) {
345 unop("find_lsb", tint32
, """
347 for (unsigned bit = 0; bit < 32; bit++) {
348 if ((src0 >> bit) & 1) {
356 for i
in xrange(1, 5):
357 for j
in xrange(1, 5):
358 unop_horiz("fnoise{0}_{1}".format(i
, j
), i
, tfloat
, j
, tfloat
, "0.0f")
360 def binop_convert(name
, out_type
, in_type
, alg_props
, const_expr
):
361 opcode(name
, 0, out_type
, [0, 0], [in_type
, in_type
], alg_props
, const_expr
)
363 def binop(name
, ty
, alg_props
, const_expr
):
364 binop_convert(name
, ty
, ty
, alg_props
, const_expr
)
366 def binop_compare(name
, ty
, alg_props
, const_expr
):
367 binop_convert(name
, tbool
, ty
, alg_props
, const_expr
)
369 def binop_horiz(name
, out_size
, out_type
, src1_size
, src1_type
, src2_size
,
370 src2_type
, const_expr
):
371 opcode(name
, out_size
, out_type
, [src1_size
, src2_size
], [src1_type
, src2_type
],
374 def binop_reduce(name
, output_size
, output_type
, src_type
, prereduce_expr
,
375 reduce_expr
, final_expr
):
377 return final_expr
.format(src
= "(" + src
+ ")")
378 def reduce_(src0
, src1
):
379 return reduce_expr
.format(src0
=src0
, src1
=src1
)
380 def prereduce(src0
, src1
):
381 return "(" + prereduce_expr
.format(src0
=src0
, src1
=src1
) + ")"
382 src0
= prereduce("src0.x", "src1.x")
383 src1
= prereduce("src0.y", "src1.y")
384 src2
= prereduce("src0.z", "src1.z")
385 src3
= prereduce("src0.w", "src1.w")
386 opcode(name
+ "2", output_size
, output_type
,
387 [2, 2], [src_type
, src_type
], commutative
,
388 final(reduce_(src0
, src1
)))
389 opcode(name
+ "3", output_size
, output_type
,
390 [3, 3], [src_type
, src_type
], commutative
,
391 final(reduce_(reduce_(src0
, src1
), src2
)))
392 opcode(name
+ "4", output_size
, output_type
,
393 [4, 4], [src_type
, src_type
], commutative
,
394 final(reduce_(reduce_(src0
, src1
), reduce_(src2
, src3
))))
396 binop("fadd", tfloat
, commutative
+ associative
, "src0 + src1")
397 binop("iadd", tint
, commutative
+ associative
, "src0 + src1")
398 binop("fsub", tfloat
, "", "src0 - src1")
399 binop("isub", tint
, "", "src0 - src1")
401 binop("fmul", tfloat
, commutative
+ associative
, "src0 * src1")
402 # low 32-bits of signed/unsigned integer multiply
403 binop("imul", tint
, commutative
+ associative
, "src0 * src1")
404 # high 32-bits of signed integer multiply
405 binop("imul_high", tint32
, commutative
,
406 "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
407 # high 32-bits of unsigned integer multiply
408 binop("umul_high", tuint32
, commutative
,
409 "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
411 binop("fdiv", tfloat
, "", "src0 / src1")
412 binop("idiv", tint
, "", "src0 / src1")
413 binop("udiv", tuint
, "", "src0 / src1")
415 # returns a boolean representing the carry resulting from the addition of
416 # the two unsigned arguments.
418 binop_convert("uadd_carry", tuint
, tuint
, commutative
, "src0 + src1 < src0")
420 # returns a boolean representing the borrow resulting from the subtraction
421 # of the two unsigned arguments.
423 binop_convert("usub_borrow", tuint
, tuint
, "", "src0 < src1")
425 binop("umod", tuint
, "", "src1 == 0 ? 0 : src0 % src1")
427 # For signed integers, there are several different possible definitions of
428 # "modulus" or "remainder". We follow the conventions used by LLVM and
429 # SPIR-V. The irem opcode implements the standard C/C++ signed "%"
430 # operation while the imod opcode implements the more mathematical
431 # "modulus" operation. For details on the difference, see
433 # http://mathforum.org/library/drmath/view/52343.html
435 binop("irem", tint
, "", "src1 == 0 ? 0 : src0 % src1")
436 binop("imod", tint
, "",
437 "src1 == 0 ? 0 : ((src0 % src1 == 0 || (src0 >= 0) == (src1 >= 0)) ?"
438 " src0 % src1 : src0 % src1 + src1)")
439 binop("fmod", tfloat
, "", "src0 - src1 * floorf(src0 / src1)")
440 binop("frem", tfloat
, "", "src0 - src1 * truncf(src0 / src1)")
447 # these integer-aware comparisons return a boolean (0 or ~0)
449 binop_compare("flt", tfloat
, "", "src0 < src1")
450 binop_compare("fge", tfloat
, "", "src0 >= src1")
451 binop_compare("feq", tfloat
, commutative
, "src0 == src1")
452 binop_compare("fne", tfloat
, commutative
, "src0 != src1")
453 binop_compare("ilt", tint
, "", "src0 < src1")
454 binop_compare("ige", tint
, "", "src0 >= src1")
455 binop_compare("ieq", tint
, commutative
, "src0 == src1")
456 binop_compare("ine", tint
, commutative
, "src0 != src1")
457 binop_compare("ult", tuint
, "", "src0 < src1")
458 binop_compare("uge", tuint
, "", "src0 >= src1")
460 # integer-aware GLSL-style comparisons that compare floats and ints
462 binop_reduce("ball_fequal", 1, tbool
, tfloat
, "{src0} == {src1}",
463 "{src0} && {src1}", "{src}")
464 binop_reduce("bany_fnequal", 1, tbool
, tfloat
, "{src0} != {src1}",
465 "{src0} || {src1}", "{src}")
466 binop_reduce("ball_iequal", 1, tbool
, tint
, "{src0} == {src1}",
467 "{src0} && {src1}", "{src}")
468 binop_reduce("bany_inequal", 1, tbool
, tint
, "{src0} != {src1}",
469 "{src0} || {src1}", "{src}")
471 # non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
473 binop_reduce("fall_equal", 1, tfloat32
, tfloat32
, "{src0} == {src1}",
474 "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
475 binop_reduce("fany_nequal", 1, tfloat32
, tfloat32
, "{src0} != {src1}",
476 "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
478 # These comparisons for integer-less hardware return 1.0 and 0.0 for true
479 # and false respectively
481 binop("slt", tfloat32
, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
482 binop("sge", tfloat32
, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
483 binop("seq", tfloat32
, commutative
, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
484 binop("sne", tfloat32
, commutative
, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
487 opcode("ishl", 0, tint
, [0, 0], [tint
, tuint32
], "", "src0 << src1")
488 opcode("ishr", 0, tint
, [0, 0], [tint
, tuint32
], "", "src0 >> src1")
489 opcode("ushr", 0, tuint
, [0, 0], [tuint
, tuint32
], "", "src0 >> src1")
491 # bitwise logic operators
493 # These are also used as boolean and, or, xor for hardware supporting
497 binop("iand", tuint
, commutative
+ associative
, "src0 & src1")
498 binop("ior", tuint
, commutative
+ associative
, "src0 | src1")
499 binop("ixor", tuint
, commutative
+ associative
, "src0 ^ src1")
502 # floating point logic operators
504 # These use (src != 0.0) for testing the truth of the input, and output 1.0
505 # for true and 0.0 for false
507 binop("fand", tfloat32
, commutative
,
508 "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
509 binop("for", tfloat32
, commutative
,
510 "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
511 binop("fxor", tfloat32
, commutative
,
512 "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
514 binop_reduce("fdot", 1, tfloat
, tfloat
, "{src0} * {src1}", "{src0} + {src1}",
517 binop_reduce("fdot_replicated", 4, tfloat
, tfloat
,
518 "{src0} * {src1}", "{src0} + {src1}", "{src}")
520 opcode("fdph", 1, tfloat
, [3, 4], [tfloat
, tfloat
], "",
521 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
522 opcode("fdph_replicated", 4, tfloat
, [3, 4], [tfloat
, tfloat
], "",
523 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
525 binop("fmin", tfloat
, "", "fminf(src0, src1)")
526 binop("imin", tint
, commutative
+ associative
, "src1 > src0 ? src0 : src1")
527 binop("umin", tuint
, commutative
+ associative
, "src1 > src0 ? src0 : src1")
528 binop("fmax", tfloat
, "", "fmaxf(src0, src1)")
529 binop("imax", tint
, commutative
+ associative
, "src1 > src0 ? src1 : src0")
530 binop("umax", tuint
, commutative
+ associative
, "src1 > src0 ? src1 : src0")
532 # Saturated vector add for 4 8bit ints.
533 binop("usadd_4x8", tint32
, commutative
+ associative
, """
535 for (int i = 0; i < 32; i += 8) {
536 dst |= MIN2(((src0 >> i) & 0xff) + ((src1 >> i) & 0xff), 0xff) << i;
540 # Saturated vector subtract for 4 8bit ints.
541 binop("ussub_4x8", tint32
, "", """
543 for (int i = 0; i < 32; i += 8) {
544 int src0_chan = (src0 >> i) & 0xff;
545 int src1_chan = (src1 >> i) & 0xff;
546 if (src0_chan > src1_chan)
547 dst |= (src0_chan - src1_chan) << i;
551 # vector min for 4 8bit ints.
552 binop("umin_4x8", tint32
, commutative
+ associative
, """
554 for (int i = 0; i < 32; i += 8) {
555 dst |= MIN2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
559 # vector max for 4 8bit ints.
560 binop("umax_4x8", tint32
, commutative
+ associative
, """
562 for (int i = 0; i < 32; i += 8) {
563 dst |= MAX2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
567 # unorm multiply: (a * b) / 255.
568 binop("umul_unorm_4x8", tint32
, commutative
+ associative
, """
570 for (int i = 0; i < 32; i += 8) {
571 int src0_chan = (src0 >> i) & 0xff;
572 int src1_chan = (src1 >> i) & 0xff;
573 dst |= ((src0_chan * src1_chan) / 255) << i;
577 binop("fpow", tfloat
, "", "bit_size == 64 ? powf(src0, src1) : pow(src0, src1)")
579 binop_horiz("pack_half_2x16_split", 1, tuint32
, 1, tfloat32
, 1, tfloat32
,
580 "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
582 binop_convert("pack_64_2x32_split", tuint64
, tuint32
, "",
583 "src0 | ((uint64_t)src1 << 32)")
585 # bfm implements the behavior of the first operation of the SM5 "bfi" assembly
586 # and that of the "bfi1" i965 instruction. That is, it has undefined behavior
587 # if either of its arguments are 32.
588 binop_convert("bfm", tuint32
, tint32
, "", """
589 int bits = src0, offset = src1;
590 if (offset < 0 || bits < 0 || offset > 31 || bits > 31 || offset + bits > 32)
591 dst = 0; /* undefined */
593 dst = ((1u << bits) - 1) << offset;
596 opcode("ldexp", 0, tfloat
, [0, 0], [tfloat
, tint32
], "", """
597 dst = (bit_size == 64) ? ldexp(src0, src1) : ldexpf(src0, src1);
598 /* flush denormals to zero. */
600 dst = copysignf(0.0f, src0);
603 # Combines the first component of each input to make a 2-component vector.
605 binop_horiz("vec2", 2, tuint
, 1, tuint
, 1, tuint
, """
611 binop("extract_u8", tuint
, "", "(uint8_t)(src0 >> (src1 * 8))")
612 binop("extract_i8", tint
, "", "(int8_t)(src0 >> (src1 * 8))")
615 binop("extract_u16", tuint
, "", "(uint16_t)(src0 >> (src1 * 16))")
616 binop("extract_i16", tint
, "", "(int16_t)(src0 >> (src1 * 16))")
619 def triop(name
, ty
, const_expr
):
620 opcode(name
, 0, ty
, [0, 0, 0], [ty
, ty
, ty
], "", const_expr
)
621 def triop_horiz(name
, output_size
, src1_size
, src2_size
, src3_size
, const_expr
):
622 opcode(name
, output_size
, tuint
,
623 [src1_size
, src2_size
, src3_size
],
624 [tuint
, tuint
, tuint
], "", const_expr
)
626 triop("ffma", tfloat
, "src0 * src1 + src2")
628 triop("flrp", tfloat
, "src0 * (1 - src2) + src1 * src2")
632 # A vector conditional select instruction (like ?:, but operating per-
633 # component on vectors). There are two versions, one for floating point
634 # bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
637 triop("fcsel", tfloat32
, "(src0 != 0.0f) ? src1 : src2")
638 opcode("bcsel", 0, tuint
, [0, 0, 0],
639 [tbool
, tuint
, tuint
], "", "src0 ? src1 : src2")
642 triop("bfi", tuint32
, """
643 unsigned mask = src0, insert = src1, base = src2;
652 dst = (base & ~mask) | (insert & mask);
656 # SM5 ubfe/ibfe assembly
657 opcode("ubfe", 0, tuint32
,
658 [0, 0, 0], [tuint32
, tint32
, tint32
], "", """
659 unsigned base = src0;
660 int offset = src1, bits = src2;
663 } else if (bits < 0 || offset < 0) {
664 dst = 0; /* undefined */
665 } else if (offset + bits < 32) {
666 dst = (base << (32 - bits - offset)) >> (32 - bits);
668 dst = base >> offset;
671 opcode("ibfe", 0, tint32
,
672 [0, 0, 0], [tint32
, tint32
, tint32
], "", """
674 int offset = src1, bits = src2;
677 } else if (bits < 0 || offset < 0) {
678 dst = 0; /* undefined */
679 } else if (offset + bits < 32) {
680 dst = (base << (32 - bits - offset)) >> (32 - bits);
682 dst = base >> offset;
686 # GLSL bitfieldExtract()
687 opcode("ubitfield_extract", 0, tuint32
,
688 [0, 0, 0], [tuint32
, tint32
, tint32
], "", """
689 unsigned base = src0;
690 int offset = src1, bits = src2;
693 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
694 dst = 0; /* undefined per the spec */
696 dst = (base >> offset) & ((1ull << bits) - 1);
699 opcode("ibitfield_extract", 0, tint32
,
700 [0, 0, 0], [tint32
, tint32
, tint32
], "", """
702 int offset = src1, bits = src2;
705 } else if (offset < 0 || bits < 0 || offset + bits > 32) {
708 dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
712 # Combines the first component of each input to make a 3-component vector.
714 triop_horiz("vec3", 3, 1, 1, 1, """
720 def quadop_horiz(name
, output_size
, src1_size
, src2_size
, src3_size
,
721 src4_size
, const_expr
):
722 opcode(name
, output_size
, tuint
,
723 [src1_size
, src2_size
, src3_size
, src4_size
],
724 [tuint
, tuint
, tuint
, tuint
],
727 opcode("bitfield_insert", 0, tuint32
, [0, 0, 0, 0],
728 [tuint32
, tuint32
, tint32
, tint32
], "", """
729 unsigned base = src0, insert = src1;
730 int offset = src2, bits = src3;
733 } else if (offset < 0 || bits < 0 || bits + offset > 32) {
736 unsigned mask = ((1ull << bits) - 1) << offset;
737 dst = (base & ~mask) | ((insert << bits) & mask);
741 quadop_horiz("vec4", 4, 1, 1, 1, 1, """