Revert "nir/opcodes: Use fpclassify() instead of isnormal() for ldexp"
[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 tunsigned = "unsigned"
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, in_type, out_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("fexp", tfloat, "expf(src0)") # < e^x
157 unop("flog", tfloat, "logf(src0)") # log base e
158 unop("fexp2", tfloat, "exp2f(src0)")
159 unop("flog2", tfloat, "log2f(src0)")
160 unop_convert("f2i", tfloat, tint, "src0") # Float-to-integer conversion.
161 unop_convert("f2u", tfloat, tunsigned, "src0") # Float-to-unsigned conversion
162 unop_convert("i2f", tint, tfloat, "src0") # Integer-to-float conversion.
163 # Float-to-boolean conversion
164 unop_convert("f2b", tfloat, tbool, "src0 == 0.0f")
165 # Boolean-to-float conversion
166 unop_convert("b2f", tbool, tfloat, "src0 ? 1.0f : 0.0f")
167 # Int-to-boolean conversion
168 unop_convert("i2b", tint, tbool, "src0 == 0")
169 unop_convert("b2i", tbool, tint, "src0 ? 0 : -1") # Boolean-to-int conversion
170 unop_convert("u2f", tunsigned, tfloat, "src0") #Unsigned-to-float conversion.
171
172 unop_reduce("bany", 1, tbool, tbool, "{src}", "{src0} || {src1}", "{src}")
173 unop_reduce("ball", 1, tbool, tbool, "{src}", "{src0} && {src1}", "{src}")
174 unop_reduce("fany", 1, tfloat, tfloat, "{src} != 0.0f", "{src0} || {src1}",
175 "{src} ? 1.0f : 0.0f")
176 unop_reduce("fall", 1, tfloat, tfloat, "{src} != 0.0f", "{src0} && {src1}",
177 "{src} ? 1.0f : 0.0f")
178
179 # Unary floating-point rounding operations.
180
181
182 unop("ftrunc", tfloat, "truncf(src0)")
183 unop("fceil", tfloat, "ceilf(src0)")
184 unop("ffloor", tfloat, "floorf(src0)")
185 unop("ffract", tfloat, "src0 - floorf(src0)")
186 unop("fround_even", tfloat, "_mesa_round_to_even(src0)")
187
188
189 # Trigonometric operations.
190
191
192 unop("fsin", tfloat, "sinf(src0)")
193 unop("fcos", tfloat, "cosf(src0)")
194 unop("fsin_reduced", tfloat, "sinf(src0)")
195 unop("fcos_reduced", tfloat, "cosf(src0)")
196
197
198 # Partial derivatives.
199
200
201 unop("fddx", tfloat, "0.0f") # the derivative of a constant is 0.
202 unop("fddy", tfloat, "0.0f")
203 unop("fddx_fine", tfloat, "0.0f")
204 unop("fddy_fine", tfloat, "0.0f")
205 unop("fddx_coarse", tfloat, "0.0f")
206 unop("fddy_coarse", tfloat, "0.0f")
207
208
209 # Floating point pack and unpack operations.
210
211 def pack_2x16(fmt):
212 unop_horiz("pack_" + fmt + "_2x16", 1, tunsigned, 2, tfloat, """
213 dst.x = (uint32_t) pack_fmt_1x16(src0.x);
214 dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
215 """.replace("fmt", fmt))
216
217 def pack_4x8(fmt):
218 unop_horiz("pack_" + fmt + "_4x8", 1, tunsigned, 4, tfloat, """
219 dst.x = (uint32_t) pack_fmt_1x8(src0.x);
220 dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
221 dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
222 dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
223 """.replace("fmt", fmt))
224
225 def unpack_2x16(fmt):
226 unop_horiz("unpack_" + fmt + "_2x16", 2, tfloat, 1, tunsigned, """
227 dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
228 dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
229 """.replace("fmt", fmt))
230
231 def unpack_4x8(fmt):
232 unop_horiz("unpack_" + fmt + "_4x8", 4, tfloat, 1, tunsigned, """
233 dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
234 dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
235 dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
236 dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
237 """.replace("fmt", fmt))
238
239
240 pack_2x16("snorm")
241 pack_4x8("snorm")
242 pack_2x16("unorm")
243 pack_4x8("unorm")
244 pack_2x16("half")
245 unpack_2x16("snorm")
246 unpack_4x8("snorm")
247 unpack_2x16("unorm")
248 unpack_4x8("unorm")
249 unpack_2x16("half")
250
251
252 # Lowered floating point unpacking operations.
253
254
255 unop_horiz("unpack_half_2x16_split_x", 1, tfloat, 1, tunsigned,
256 "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
257 unop_horiz("unpack_half_2x16_split_y", 1, tfloat, 1, tunsigned,
258 "unpack_half_1x16((uint16_t)(src0.x >> 16))")
259
260
261 # Bit operations, part of ARB_gpu_shader5.
262
263
264 unop("bitfield_reverse", tunsigned, """
265 /* we're not winning any awards for speed here, but that's ok */
266 dst = 0;
267 for (unsigned bit = 0; bit < 32; bit++)
268 dst |= ((src0 >> bit) & 1) << (31 - bit);
269 """)
270 unop("bit_count", tunsigned, """
271 dst = 0;
272 for (unsigned bit = 0; bit < 32; bit++) {
273 if ((src0 >> bit) & 1)
274 dst++;
275 }
276 """)
277
278 unop_convert("ufind_msb", tunsigned, tint, """
279 dst = -1;
280 for (int bit = 31; bit > 0; bit--) {
281 if ((src0 >> bit) & 1) {
282 dst = bit;
283 break;
284 }
285 }
286 """)
287
288 unop("ifind_msb", tint, """
289 dst = -1;
290 for (int bit = 31; bit >= 0; bit--) {
291 /* If src0 < 0, we're looking for the first 0 bit.
292 * if src0 >= 0, we're looking for the first 1 bit.
293 */
294 if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
295 (!((src0 >> bit) & 1) && (src0 < 0))) {
296 dst = bit;
297 break;
298 }
299 }
300 """)
301
302 unop("find_lsb", tint, """
303 dst = -1;
304 for (unsigned bit = 0; bit < 32; bit++) {
305 if ((src0 >> bit) & 1) {
306 dst = bit;
307 break;
308 }
309 }
310 """)
311
312
313 for i in xrange(1, 5):
314 for j in xrange(1, 5):
315 unop_horiz("fnoise{0}_{1}".format(i, j), i, tfloat, j, tfloat, "0.0f")
316
317 def binop_convert(name, out_type, in_type, alg_props, const_expr):
318 opcode(name, 0, out_type, [0, 0], [in_type, in_type], alg_props, const_expr)
319
320 def binop(name, ty, alg_props, const_expr):
321 binop_convert(name, ty, ty, alg_props, const_expr)
322
323 def binop_compare(name, ty, alg_props, const_expr):
324 binop_convert(name, tbool, ty, alg_props, const_expr)
325
326 def binop_horiz(name, out_size, out_type, src1_size, src1_type, src2_size,
327 src2_type, const_expr):
328 opcode(name, out_size, out_type, [src1_size, src2_size], [src1_type, src2_type],
329 "", const_expr)
330
331 def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
332 reduce_expr, final_expr):
333 def final(src):
334 return final_expr.format(src= "(" + src + ")")
335 def reduce_(src0, src1):
336 return reduce_expr.format(src0=src0, src1=src1)
337 def prereduce(src0, src1):
338 return "(" + prereduce_expr.format(src0=src0, src1=src1) + ")"
339 src0 = prereduce("src0.x", "src1.x")
340 src1 = prereduce("src0.y", "src1.y")
341 src2 = prereduce("src0.z", "src1.z")
342 src3 = prereduce("src0.w", "src1.w")
343 opcode(name + "2", output_size, output_type,
344 [2, 2], [src_type, src_type], commutative,
345 final(reduce_(src0, src1)))
346 opcode(name + "3", output_size, output_type,
347 [3, 3], [src_type, src_type], commutative,
348 final(reduce_(reduce_(src0, src1), src2)))
349 opcode(name + "4", output_size, output_type,
350 [4, 4], [src_type, src_type], commutative,
351 final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
352
353 binop("fadd", tfloat, commutative + associative, "src0 + src1")
354 binop("iadd", tint, commutative + associative, "src0 + src1")
355 binop("fsub", tfloat, "", "src0 - src1")
356 binop("isub", tint, "", "src0 - src1")
357
358 binop("fmul", tfloat, commutative + associative, "src0 * src1")
359 # low 32-bits of signed/unsigned integer multiply
360 binop("imul", tint, commutative + associative, "src0 * src1")
361 # high 32-bits of signed integer multiply
362 binop("imul_high", tint, commutative,
363 "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
364 # high 32-bits of unsigned integer multiply
365 binop("umul_high", tunsigned, commutative,
366 "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
367
368 binop("fdiv", tfloat, "", "src0 / src1")
369 binop("idiv", tint, "", "src0 / src1")
370 binop("udiv", tunsigned, "", "src0 / src1")
371
372 # returns a boolean representing the carry resulting from the addition of
373 # the two unsigned arguments.
374
375 binop_convert("uadd_carry", tbool, tunsigned, commutative, "src0 + src1 < src0")
376
377 # returns a boolean representing the borrow resulting from the subtraction
378 # of the two unsigned arguments.
379
380 binop_convert("usub_borrow", tbool, tunsigned, "", "src1 < src0")
381
382 binop("fmod", tfloat, "", "src0 - src1 * floorf(src0 / src1)")
383 binop("umod", tunsigned, "", "src1 == 0 ? 0 : src0 % src1")
384
385 #
386 # Comparisons
387 #
388
389
390 # these integer-aware comparisons return a boolean (0 or ~0)
391
392 binop_compare("flt", tfloat, "", "src0 < src1")
393 binop_compare("fge", tfloat, "", "src0 >= src1")
394 binop_compare("feq", tfloat, commutative, "src0 == src1")
395 binop_compare("fne", tfloat, commutative, "src0 != src1")
396 binop_compare("ilt", tint, "", "src0 < src1")
397 binop_compare("ige", tint, "", "src0 >= src1")
398 binop_compare("ieq", tint, commutative, "src0 == src1")
399 binop_compare("ine", tint, commutative, "src0 != src1")
400 binop_compare("ult", tunsigned, "", "src0 < src1")
401 binop_compare("uge", tunsigned, "", "src0 >= src1")
402
403 # integer-aware GLSL-style comparisons that compare floats and ints
404
405 binop_reduce("ball_fequal", 1, tbool, tfloat, "{src0} == {src1}",
406 "{src0} && {src1}", "{src}")
407 binop_reduce("bany_fnequal", 1, tbool, tfloat, "{src0} != {src1}",
408 "{src0} || {src1}", "{src}")
409 binop_reduce("ball_iequal", 1, tbool, tint, "{src0} == {src1}",
410 "{src0} && {src1}", "{src}")
411 binop_reduce("bany_inequal", 1, tbool, tint, "{src0} != {src1}",
412 "{src0} || {src1}", "{src}")
413
414 # non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
415
416 binop_reduce("fall_equal", 1, tfloat, tfloat, "{src0} == {src1}",
417 "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
418 binop_reduce("fany_nequal", 1, tfloat, tfloat, "{src0} != {src1}",
419 "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
420
421 # These comparisons for integer-less hardware return 1.0 and 0.0 for true
422 # and false respectively
423
424 binop("slt", tfloat, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
425 binop("sge", tfloat, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
426 binop("seq", tfloat, commutative, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
427 binop("sne", tfloat, commutative, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
428
429
430 binop("ishl", tint, "", "src0 << src1")
431 binop("ishr", tint, "", "src0 >> src1")
432 binop("ushr", tunsigned, "", "src0 >> src1")
433
434 # bitwise logic operators
435 #
436 # These are also used as boolean and, or, xor for hardware supporting
437 # integers.
438
439
440 binop("iand", tunsigned, commutative + associative, "src0 & src1")
441 binop("ior", tunsigned, commutative + associative, "src0 | src1")
442 binop("ixor", tunsigned, commutative + associative, "src0 ^ src1")
443
444
445 # floating point logic operators
446 #
447 # These use (src != 0.0) for testing the truth of the input, and output 1.0
448 # for true and 0.0 for false
449
450 binop("fand", tfloat, commutative,
451 "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
452 binop("for", tfloat, commutative,
453 "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
454 binop("fxor", tfloat, commutative,
455 "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
456
457 binop_reduce("fdot", 1, tfloat, tfloat, "{src0} * {src1}", "{src0} + {src1}",
458 "{src}")
459
460 binop("fmin", tfloat, "", "fminf(src0, src1)")
461 binop("imin", tint, commutative + associative, "src1 > src0 ? src0 : src1")
462 binop("umin", tunsigned, commutative + associative, "src1 > src0 ? src0 : src1")
463 binop("fmax", tfloat, "", "fmaxf(src0, src1)")
464 binop("imax", tint, commutative + associative, "src1 > src0 ? src1 : src0")
465 binop("umax", tunsigned, commutative + associative, "src1 > src0 ? src1 : src0")
466
467 binop("fpow", tfloat, "", "powf(src0, src1)")
468
469 binop_horiz("pack_half_2x16_split", 1, tunsigned, 1, tfloat, 1, tfloat,
470 "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
471
472 binop_convert("bfm", tunsigned, tint, "", """
473 int offset = src0, bits = src1;
474 if (offset < 0 || bits < 0 || offset + bits > 32)
475 dst = 0; /* undefined per the spec */
476 else
477 dst = ((1 << bits)- 1) << offset;
478 """)
479
480 opcode("ldexp", 0, tunsigned, [0, 0], [tfloat, tint], "", """
481 dst = ldexp(src0, src1);
482 /* flush denormals to zero. */
483 if (!isnormal(dst))
484 dst = copysign(0.0f, src0);
485 """)
486
487 # Combines the first component of each input to make a 2-component vector.
488
489 binop_horiz("vec2", 2, tunsigned, 1, tunsigned, 1, tunsigned, """
490 dst.x = src0.x;
491 dst.y = src1.x;
492 """)
493
494 def triop(name, ty, const_expr):
495 opcode(name, 0, ty, [0, 0, 0], [ty, ty, ty], "", const_expr)
496 def triop_horiz(name, output_size, src1_size, src2_size, src3_size, const_expr):
497 opcode(name, output_size, tunsigned,
498 [src1_size, src2_size, src3_size],
499 [tunsigned, tunsigned, tunsigned], "", const_expr)
500
501 triop("ffma", tfloat, "src0 * src1 + src2")
502
503 triop("flrp", tfloat, "src0 * (1 - src2) + src1 * src2")
504
505 # Conditional Select
506 #
507 # A vector conditional select instruction (like ?:, but operating per-
508 # component on vectors). There are two versions, one for floating point
509 # bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
510
511
512 triop("fcsel", tfloat, "(src0 != 0.0f) ? src1 : src2")
513 opcode("bcsel", 0, tunsigned, [0, 0, 0],
514 [tbool, tunsigned, tunsigned], "", "src0 ? src1 : src2")
515
516 triop("bfi", tunsigned, """
517 unsigned mask = src0, insert = src1 & mask, base = src2;
518 if (mask == 0) {
519 dst = base;
520 } else {
521 unsigned tmp = mask;
522 while (!(tmp & 1)) {
523 tmp >>= 1;
524 insert <<= 1;
525 }
526 dst = (base & ~mask) | insert;
527 }
528 """)
529
530 opcode("ubitfield_extract", 0, tunsigned,
531 [0, 1, 1], [tunsigned, tint, tint], "", """
532 unsigned base = src0;
533 int offset = src1.x, bits = src2.x;
534 if (bits == 0) {
535 dst = 0;
536 } else if (bits < 0 || offset < 0 || offset + bits > 32) {
537 dst = 0; /* undefined per the spec */
538 } else {
539 dst = (base >> offset) & ((1 << bits) - 1);
540 }
541 """)
542 opcode("ibitfield_extract", 0, tint,
543 [0, 1, 1], [tint, tint, tint], "", """
544 int base = src0;
545 int offset = src1.x, bits = src2.x;
546 if (bits == 0) {
547 dst = 0;
548 } else if (offset < 0 || bits < 0 || offset + bits > 32) {
549 dst = 0;
550 } else {
551 dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
552 }
553 """)
554
555 # Combines the first component of each input to make a 3-component vector.
556
557 triop_horiz("vec3", 3, 1, 1, 1, """
558 dst.x = src0.x;
559 dst.y = src1.x;
560 dst.z = src2.x;
561 """)
562
563 def quadop_horiz(name, output_size, src1_size, src2_size, src3_size,
564 src4_size, const_expr):
565 opcode(name, output_size, tunsigned,
566 [src1_size, src2_size, src3_size, src4_size],
567 [tunsigned, tunsigned, tunsigned, tunsigned],
568 "", const_expr)
569
570 opcode("bitfield_insert", 0, tunsigned, [0, 0, 1, 1],
571 [tunsigned, tunsigned, tint, tint], "", """
572 unsigned base = src0, insert = src1;
573 int offset = src2.x, bits = src3.x;
574 if (bits == 0) {
575 dst = 0;
576 } else if (offset < 0 || bits < 0 || bits + offset > 32) {
577 dst = 0;
578 } else {
579 unsigned mask = ((1 << bits) - 1) << offset;
580 dst = (base & ~mask) | ((insert << bits) & mask);
581 }
582 """)
583
584 quadop_horiz("vec4", 4, 1, 1, 1, 1, """
585 dst.x = src0.x;
586 dst.y = src1.x;
587 dst.z = src2.x;
588 dst.w = src3.x;
589 """)
590
591