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