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