nir: add support for d2f and f2d
[mesa.git] / src / compiler / nir / nir_opcodes.py
1 #! /usr/bin/env python
2 #
3 # Copyright (C) 2014 Connor Abbott
4 #
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:
11 #
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
14 # Software.
15 #
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
22 # IN THE SOFTWARE.
23 #
24 # Authors:
25 # Connor Abbott (cwabbott0@gmail.com)
26
27
28 # Class that represents all the information we have about the opcode
29 # NOTE: this must be kept in sync with nir_op_info
30
31 class Opcode(object):
32 """Class that represents all the information we have about the opcode
33 NOTE: this must be kept in sync with nir_op_info
34 """
35 def __init__(self, name, output_size, output_type, input_sizes,
36 input_types, algebraic_properties, const_expr):
37 """Parameters:
38
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.
46
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.
56
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.
65 """
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:
78 assert 0 <= size <= 4
79 if output_size != 0:
80 assert size != 0
81 self.name = name
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
89
90 # helper variables for strings
91 tfloat = "float"
92 tint = "int"
93 tbool = "bool32"
94 tuint = "uint"
95 tfloat32 = "float32"
96 tint32 = "int32"
97 tuint32 = "uint32"
98 tfloat64 = "float64"
99
100 commutative = "commutative "
101 associative = "associative "
102
103 # global dictionary of opcodes
104 opcodes = {}
105
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)
111
112 def unop_convert(name, out_type, in_type, const_expr):
113 opcode(name, 0, out_type, [0], [in_type], "", const_expr)
114
115 def unop(name, ty, const_expr):
116 opcode(name, 0, ty, [0], [ty], "", const_expr)
117
118 def unop_horiz(name, output_size, output_type, input_size, input_type,
119 const_expr):
120 opcode(name, output_size, output_type, [input_size], [input_type], "",
121 const_expr)
122
123 def unop_reduce(name, output_size, output_type, input_type, prereduce_expr,
124 reduce_expr, final_expr):
125 def prereduce(src):
126 return "(" + prereduce_expr.format(src=src) + ")"
127 def final(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))))
141
142
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")
147
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.
173 # double-to-float conversion
174 unop_convert("d2f", tfloat32, tfloat64, "src0") # Single to double precision
175 unop_convert("f2d", tfloat64, tfloat32, "src0") # Double to single precision
176
177 # Unary floating-point rounding operations.
178
179
180 unop("ftrunc", tfloat, "bit_size == 64 ? trunc(src0) : truncf(src0)")
181 unop("fceil", tfloat, "bit_size == 64 ? ceil(src0) : ceilf(src0)")
182 unop("ffloor", tfloat, "bit_size == 64 ? floor(src0) : floorf(src0)")
183 unop("ffract", tfloat, "src0 - (bit_size == 64 ? floor(src0) : floorf(src0))")
184 unop("fround_even", tfloat, "bit_size == 64 ? _mesa_roundeven(src0) : _mesa_roundevenf(src0)")
185
186 unop("fquantize2f16", tfloat, "(fabs(src0) < ldexpf(1.0, -14)) ? copysignf(0.0f, src0) : _mesa_half_to_float(_mesa_float_to_half(src0))")
187
188 # Trigonometric operations.
189
190
191 unop("fsin", tfloat, "bit_size == 64 ? sin(src0) : sinf(src0)")
192 unop("fcos", tfloat, "bit_size == 64 ? cos(src0) : cosf(src0)")
193
194
195 # Partial derivatives.
196
197
198 unop("fddx", tfloat, "0.0") # the derivative of a constant is 0.
199 unop("fddy", tfloat, "0.0")
200 unop("fddx_fine", tfloat, "0.0")
201 unop("fddy_fine", tfloat, "0.0")
202 unop("fddx_coarse", tfloat, "0.0")
203 unop("fddy_coarse", tfloat, "0.0")
204
205
206 # Floating point pack and unpack operations.
207
208 def pack_2x16(fmt):
209 unop_horiz("pack_" + fmt + "_2x16", 1, tuint32, 2, tfloat32, """
210 dst.x = (uint32_t) pack_fmt_1x16(src0.x);
211 dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
212 """.replace("fmt", fmt))
213
214 def pack_4x8(fmt):
215 unop_horiz("pack_" + fmt + "_4x8", 1, tuint32, 4, tfloat32, """
216 dst.x = (uint32_t) pack_fmt_1x8(src0.x);
217 dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
218 dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
219 dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
220 """.replace("fmt", fmt))
221
222 def unpack_2x16(fmt):
223 unop_horiz("unpack_" + fmt + "_2x16", 2, tfloat32, 1, tuint32, """
224 dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
225 dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
226 """.replace("fmt", fmt))
227
228 def unpack_4x8(fmt):
229 unop_horiz("unpack_" + fmt + "_4x8", 4, tfloat32, 1, tuint32, """
230 dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
231 dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
232 dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
233 dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
234 """.replace("fmt", fmt))
235
236
237 pack_2x16("snorm")
238 pack_4x8("snorm")
239 pack_2x16("unorm")
240 pack_4x8("unorm")
241 pack_2x16("half")
242 unpack_2x16("snorm")
243 unpack_4x8("snorm")
244 unpack_2x16("unorm")
245 unpack_4x8("unorm")
246 unpack_2x16("half")
247
248 unop_horiz("pack_uvec2_to_uint", 1, tuint32, 2, tuint32, """
249 dst.x = (src0.x & 0xffff) | (src0.y >> 16);
250 """)
251
252 unop_horiz("pack_uvec4_to_uint", 1, tuint32, 4, tuint32, """
253 dst.x = (src0.x << 0) |
254 (src0.y << 8) |
255 (src0.z << 16) |
256 (src0.w << 24);
257 """)
258
259 # Lowered floating point unpacking operations.
260
261
262 unop_horiz("unpack_half_2x16_split_x", 1, tfloat32, 1, tuint32,
263 "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
264 unop_horiz("unpack_half_2x16_split_y", 1, tfloat32, 1, tuint32,
265 "unpack_half_1x16((uint16_t)(src0.x >> 16))")
266
267
268 # Bit operations, part of ARB_gpu_shader5.
269
270
271 unop("bitfield_reverse", tuint32, """
272 /* we're not winning any awards for speed here, but that's ok */
273 dst = 0;
274 for (unsigned bit = 0; bit < 32; bit++)
275 dst |= ((src0 >> bit) & 1) << (31 - bit);
276 """)
277 unop("bit_count", tuint32, """
278 dst = 0;
279 for (unsigned bit = 0; bit < 32; bit++) {
280 if ((src0 >> bit) & 1)
281 dst++;
282 }
283 """)
284
285 unop_convert("ufind_msb", tint32, tuint32, """
286 dst = -1;
287 for (int bit = 31; bit > 0; bit--) {
288 if ((src0 >> bit) & 1) {
289 dst = bit;
290 break;
291 }
292 }
293 """)
294
295 unop("ifind_msb", tint32, """
296 dst = -1;
297 for (int bit = 31; bit >= 0; bit--) {
298 /* If src0 < 0, we're looking for the first 0 bit.
299 * if src0 >= 0, we're looking for the first 1 bit.
300 */
301 if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
302 (!((src0 >> bit) & 1) && (src0 < 0))) {
303 dst = bit;
304 break;
305 }
306 }
307 """)
308
309 unop("find_lsb", tint32, """
310 dst = -1;
311 for (unsigned bit = 0; bit < 32; bit++) {
312 if ((src0 >> bit) & 1) {
313 dst = bit;
314 break;
315 }
316 }
317 """)
318
319
320 for i in xrange(1, 5):
321 for j in xrange(1, 5):
322 unop_horiz("fnoise{0}_{1}".format(i, j), i, tfloat, j, tfloat, "0.0f")
323
324 def binop_convert(name, out_type, in_type, alg_props, const_expr):
325 opcode(name, 0, out_type, [0, 0], [in_type, in_type], alg_props, const_expr)
326
327 def binop(name, ty, alg_props, const_expr):
328 binop_convert(name, ty, ty, alg_props, const_expr)
329
330 def binop_compare(name, ty, alg_props, const_expr):
331 binop_convert(name, tbool, ty, alg_props, const_expr)
332
333 def binop_horiz(name, out_size, out_type, src1_size, src1_type, src2_size,
334 src2_type, const_expr):
335 opcode(name, out_size, out_type, [src1_size, src2_size], [src1_type, src2_type],
336 "", const_expr)
337
338 def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
339 reduce_expr, final_expr):
340 def final(src):
341 return final_expr.format(src= "(" + src + ")")
342 def reduce_(src0, src1):
343 return reduce_expr.format(src0=src0, src1=src1)
344 def prereduce(src0, src1):
345 return "(" + prereduce_expr.format(src0=src0, src1=src1) + ")"
346 src0 = prereduce("src0.x", "src1.x")
347 src1 = prereduce("src0.y", "src1.y")
348 src2 = prereduce("src0.z", "src1.z")
349 src3 = prereduce("src0.w", "src1.w")
350 opcode(name + "2", output_size, output_type,
351 [2, 2], [src_type, src_type], commutative,
352 final(reduce_(src0, src1)))
353 opcode(name + "3", output_size, output_type,
354 [3, 3], [src_type, src_type], commutative,
355 final(reduce_(reduce_(src0, src1), src2)))
356 opcode(name + "4", output_size, output_type,
357 [4, 4], [src_type, src_type], commutative,
358 final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
359
360 binop("fadd", tfloat, commutative + associative, "src0 + src1")
361 binop("iadd", tint, commutative + associative, "src0 + src1")
362 binop("fsub", tfloat, "", "src0 - src1")
363 binop("isub", tint, "", "src0 - src1")
364
365 binop("fmul", tfloat, commutative + associative, "src0 * src1")
366 # low 32-bits of signed/unsigned integer multiply
367 binop("imul", tint, commutative + associative, "src0 * src1")
368 # high 32-bits of signed integer multiply
369 binop("imul_high", tint32, commutative,
370 "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
371 # high 32-bits of unsigned integer multiply
372 binop("umul_high", tuint32, commutative,
373 "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
374
375 binop("fdiv", tfloat, "", "src0 / src1")
376 binop("idiv", tint, "", "src0 / src1")
377 binop("udiv", tuint, "", "src0 / src1")
378
379 # returns a boolean representing the carry resulting from the addition of
380 # the two unsigned arguments.
381
382 binop_convert("uadd_carry", tuint, tuint, commutative, "src0 + src1 < src0")
383
384 # returns a boolean representing the borrow resulting from the subtraction
385 # of the two unsigned arguments.
386
387 binop_convert("usub_borrow", tuint, tuint, "", "src0 < src1")
388
389 binop("fmod", tfloat, "", "src0 - src1 * floorf(src0 / src1)")
390 binop("umod", tuint, "", "src1 == 0 ? 0 : src0 % src1")
391
392 #
393 # Comparisons
394 #
395
396
397 # these integer-aware comparisons return a boolean (0 or ~0)
398
399 binop_compare("flt", tfloat, "", "src0 < src1")
400 binop_compare("fge", tfloat, "", "src0 >= src1")
401 binop_compare("feq", tfloat, commutative, "src0 == src1")
402 binop_compare("fne", tfloat, commutative, "src0 != src1")
403 binop_compare("ilt", tint, "", "src0 < src1")
404 binop_compare("ige", tint, "", "src0 >= src1")
405 binop_compare("ieq", tint, commutative, "src0 == src1")
406 binop_compare("ine", tint, commutative, "src0 != src1")
407 binop_compare("ult", tuint, "", "src0 < src1")
408 binop_compare("uge", tuint, "", "src0 >= src1")
409
410 # integer-aware GLSL-style comparisons that compare floats and ints
411
412 binop_reduce("ball_fequal", 1, tbool, tfloat, "{src0} == {src1}",
413 "{src0} && {src1}", "{src}")
414 binop_reduce("bany_fnequal", 1, tbool, tfloat, "{src0} != {src1}",
415 "{src0} || {src1}", "{src}")
416 binop_reduce("ball_iequal", 1, tbool, tint, "{src0} == {src1}",
417 "{src0} && {src1}", "{src}")
418 binop_reduce("bany_inequal", 1, tbool, tint, "{src0} != {src1}",
419 "{src0} || {src1}", "{src}")
420
421 # non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
422
423 binop_reduce("fall_equal", 1, tfloat32, tfloat32, "{src0} == {src1}",
424 "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
425 binop_reduce("fany_nequal", 1, tfloat32, tfloat32, "{src0} != {src1}",
426 "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
427
428 # These comparisons for integer-less hardware return 1.0 and 0.0 for true
429 # and false respectively
430
431 binop("slt", tfloat32, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
432 binop("sge", tfloat32, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
433 binop("seq", tfloat32, commutative, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
434 binop("sne", tfloat32, commutative, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
435
436
437 binop("ishl", tint, "", "src0 << src1")
438 binop("ishr", tint, "", "src0 >> src1")
439 binop("ushr", tuint, "", "src0 >> src1")
440
441 # bitwise logic operators
442 #
443 # These are also used as boolean and, or, xor for hardware supporting
444 # integers.
445
446
447 binop("iand", tuint, commutative + associative, "src0 & src1")
448 binop("ior", tuint, commutative + associative, "src0 | src1")
449 binop("ixor", tuint, commutative + associative, "src0 ^ src1")
450
451
452 # floating point logic operators
453 #
454 # These use (src != 0.0) for testing the truth of the input, and output 1.0
455 # for true and 0.0 for false
456
457 binop("fand", tfloat32, commutative,
458 "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
459 binop("for", tfloat32, commutative,
460 "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
461 binop("fxor", tfloat32, commutative,
462 "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
463
464 binop_reduce("fdot", 1, tfloat, tfloat, "{src0} * {src1}", "{src0} + {src1}",
465 "{src}")
466
467 binop_reduce("fdot_replicated", 4, tfloat, tfloat,
468 "{src0} * {src1}", "{src0} + {src1}", "{src}")
469
470 opcode("fdph", 1, tfloat, [3, 4], [tfloat, tfloat], "",
471 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
472 opcode("fdph_replicated", 4, tfloat, [3, 4], [tfloat, tfloat], "",
473 "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
474
475 binop("fmin", tfloat, "", "fminf(src0, src1)")
476 binop("imin", tint, commutative + associative, "src1 > src0 ? src0 : src1")
477 binop("umin", tuint, commutative + associative, "src1 > src0 ? src0 : src1")
478 binop("fmax", tfloat, "", "fmaxf(src0, src1)")
479 binop("imax", tint, commutative + associative, "src1 > src0 ? src1 : src0")
480 binop("umax", tuint, commutative + associative, "src1 > src0 ? src1 : src0")
481
482 # Saturated vector add for 4 8bit ints.
483 binop("usadd_4x8", tint32, commutative + associative, """
484 dst = 0;
485 for (int i = 0; i < 32; i += 8) {
486 dst |= MIN2(((src0 >> i) & 0xff) + ((src1 >> i) & 0xff), 0xff) << i;
487 }
488 """)
489
490 # Saturated vector subtract for 4 8bit ints.
491 binop("ussub_4x8", tint32, "", """
492 dst = 0;
493 for (int i = 0; i < 32; i += 8) {
494 int src0_chan = (src0 >> i) & 0xff;
495 int src1_chan = (src1 >> i) & 0xff;
496 if (src0_chan > src1_chan)
497 dst |= (src0_chan - src1_chan) << i;
498 }
499 """)
500
501 # vector min for 4 8bit ints.
502 binop("umin_4x8", tint32, commutative + associative, """
503 dst = 0;
504 for (int i = 0; i < 32; i += 8) {
505 dst |= MIN2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
506 }
507 """)
508
509 # vector max for 4 8bit ints.
510 binop("umax_4x8", tint32, commutative + associative, """
511 dst = 0;
512 for (int i = 0; i < 32; i += 8) {
513 dst |= MAX2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
514 }
515 """)
516
517 # unorm multiply: (a * b) / 255.
518 binop("umul_unorm_4x8", tint32, commutative + associative, """
519 dst = 0;
520 for (int i = 0; i < 32; i += 8) {
521 int src0_chan = (src0 >> i) & 0xff;
522 int src1_chan = (src1 >> i) & 0xff;
523 dst |= ((src0_chan * src1_chan) / 255) << i;
524 }
525 """)
526
527 binop("fpow", tfloat, "", "bit_size == 64 ? powf(src0, src1) : pow(src0, src1)")
528
529 binop_horiz("pack_half_2x16_split", 1, tuint32, 1, tfloat32, 1, tfloat32,
530 "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
531
532 # bfm implements the behavior of the first operation of the SM5 "bfi" assembly
533 # and that of the "bfi1" i965 instruction. That is, it has undefined behavior
534 # if either of its arguments are 32.
535 binop_convert("bfm", tuint32, tint32, "", """
536 int bits = src0, offset = src1;
537 if (offset < 0 || bits < 0 || offset > 31 || bits > 31 || offset + bits > 32)
538 dst = 0; /* undefined */
539 else
540 dst = ((1u << bits) - 1) << offset;
541 """)
542
543 opcode("ldexp", 0, tfloat, [0, 0], [tfloat, tint], "", """
544 dst = (bit_size == 64) ? ldexp(src0, src1) : ldexpf(src0, src1);
545 /* flush denormals to zero. */
546 if (!isnormal(dst))
547 dst = copysignf(0.0f, src0);
548 """)
549
550 # Combines the first component of each input to make a 2-component vector.
551
552 binop_horiz("vec2", 2, tuint, 1, tuint, 1, tuint, """
553 dst.x = src0.x;
554 dst.y = src1.x;
555 """)
556
557 # Byte extraction
558 binop("extract_u8", tuint, "", "(uint8_t)(src0 >> (src1 * 8))")
559 binop("extract_i8", tint, "", "(int8_t)(src0 >> (src1 * 8))")
560
561 # Word extraction
562 binop("extract_u16", tuint, "", "(uint16_t)(src0 >> (src1 * 16))")
563 binop("extract_i16", tint, "", "(int16_t)(src0 >> (src1 * 16))")
564
565
566 def triop(name, ty, const_expr):
567 opcode(name, 0, ty, [0, 0, 0], [ty, ty, ty], "", const_expr)
568 def triop_horiz(name, output_size, src1_size, src2_size, src3_size, const_expr):
569 opcode(name, output_size, tuint,
570 [src1_size, src2_size, src3_size],
571 [tuint, tuint, tuint], "", const_expr)
572
573 triop("ffma", tfloat, "src0 * src1 + src2")
574
575 triop("flrp", tfloat, "src0 * (1 - src2) + src1 * src2")
576
577 # Conditional Select
578 #
579 # A vector conditional select instruction (like ?:, but operating per-
580 # component on vectors). There are two versions, one for floating point
581 # bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
582
583
584 triop("fcsel", tfloat32, "(src0 != 0.0f) ? src1 : src2")
585 opcode("bcsel", 0, tuint, [0, 0, 0],
586 [tbool, tuint, tuint], "", "src0 ? src1 : src2")
587
588 # SM5 bfi assembly
589 triop("bfi", tuint32, """
590 unsigned mask = src0, insert = src1, base = src2;
591 if (mask == 0) {
592 dst = base;
593 } else {
594 unsigned tmp = mask;
595 while (!(tmp & 1)) {
596 tmp >>= 1;
597 insert <<= 1;
598 }
599 dst = (base & ~mask) | (insert & mask);
600 }
601 """)
602
603 # SM5 ubfe/ibfe assembly
604 opcode("ubfe", 0, tuint32,
605 [0, 0, 0], [tuint32, tint32, tint32], "", """
606 unsigned base = src0;
607 int offset = src1, bits = src2;
608 if (bits == 0) {
609 dst = 0;
610 } else if (bits < 0 || offset < 0) {
611 dst = 0; /* undefined */
612 } else if (offset + bits < 32) {
613 dst = (base << (32 - bits - offset)) >> (32 - bits);
614 } else {
615 dst = base >> offset;
616 }
617 """)
618 opcode("ibfe", 0, tint32,
619 [0, 0, 0], [tint32, tint32, tint32], "", """
620 int base = src0;
621 int offset = src1, bits = src2;
622 if (bits == 0) {
623 dst = 0;
624 } else if (bits < 0 || offset < 0) {
625 dst = 0; /* undefined */
626 } else if (offset + bits < 32) {
627 dst = (base << (32 - bits - offset)) >> (32 - bits);
628 } else {
629 dst = base >> offset;
630 }
631 """)
632
633 # GLSL bitfieldExtract()
634 opcode("ubitfield_extract", 0, tuint32,
635 [0, 0, 0], [tuint32, tint32, tint32], "", """
636 unsigned base = src0;
637 int offset = src1, bits = src2;
638 if (bits == 0) {
639 dst = 0;
640 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
641 dst = 0; /* undefined per the spec */
642 } else {
643 dst = (base >> offset) & ((1ull << bits) - 1);
644 }
645 """)
646 opcode("ibitfield_extract", 0, tint32,
647 [0, 0, 0], [tint32, tint32, tint32], "", """
648 int base = src0;
649 int offset = src1, bits = src2;
650 if (bits == 0) {
651 dst = 0;
652 } else if (offset < 0 || bits < 0 || offset + bits > 32) {
653 dst = 0;
654 } else {
655 dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
656 }
657 """)
658
659 # Combines the first component of each input to make a 3-component vector.
660
661 triop_horiz("vec3", 3, 1, 1, 1, """
662 dst.x = src0.x;
663 dst.y = src1.x;
664 dst.z = src2.x;
665 """)
666
667 def quadop_horiz(name, output_size, src1_size, src2_size, src3_size,
668 src4_size, const_expr):
669 opcode(name, output_size, tuint,
670 [src1_size, src2_size, src3_size, src4_size],
671 [tuint, tuint, tuint, tuint],
672 "", const_expr)
673
674 opcode("bitfield_insert", 0, tuint32, [0, 0, 0, 0],
675 [tuint32, tuint32, tint32, tint32], "", """
676 unsigned base = src0, insert = src1;
677 int offset = src2, bits = src3;
678 if (bits == 0) {
679 dst = 0;
680 } else if (offset < 0 || bits < 0 || bits + offset > 32) {
681 dst = 0;
682 } else {
683 unsigned mask = ((1ull << bits) - 1) << offset;
684 dst = (base & ~mask) | ((insert << bits) & mask);
685 }
686 """)
687
688 quadop_horiz("vec4", 4, 1, 1, 1, 1, """
689 dst.x = src0.x;
690 dst.y = src1.x;
691 dst.z = src2.x;
692 dst.w = src3.x;
693 """)
694
695