[Mesa-dev] [RFC 10/11] glsl: Add "built-in" functions to do fp64_to_fp32(fp64)

Elie Tournier tournier.elie at gmail.com
Fri Mar 3 16:23:06 UTC 2017


Signed-off-by: Elie Tournier <elie.tournier at collabora.com>
---
 src/compiler/glsl/builtin_float64.h     | 589 ++++++++++++++++++++++++++++++++
 src/compiler/glsl/builtin_functions.cpp |   4 +
 src/compiler/glsl/builtin_functions.h   |   3 +
 src/compiler/glsl/float64.glsl          | 133 ++++++++
 4 files changed, 729 insertions(+)

diff --git a/src/compiler/glsl/builtin_float64.h b/src/compiler/glsl/builtin_float64.h
index b50ebc2dc2..dad5811289 100644
--- a/src/compiler/glsl/builtin_float64.h
+++ b/src/compiler/glsl/builtin_float64.h
@@ -23652,3 +23652,592 @@ fp32_to_fp64(void *mem_ctx, builtin_available_predicate avail)
    sig->replace_parameters(&sig_parameters);
    return sig;
 }
+ir_function_signature *
+packFloat32(void *mem_ctx, builtin_available_predicate avail)
+{
+   ir_function_signature *const sig =
+      new(mem_ctx) ir_function_signature(glsl_type::uint_type, avail);
+   ir_factory body(&sig->body, mem_ctx);
+   sig->is_defined = true;
+
+   exec_list sig_parameters;
+
+   ir_variable *const r13A7 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zSign", ir_var_function_in);
+   sig_parameters.push_tail(r13A7);
+   ir_variable *const r13A8 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zExp", ir_var_function_in);
+   sig_parameters.push_tail(r13A8);
+   ir_variable *const r13A9 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zFrac", ir_var_function_in);
+   sig_parameters.push_tail(r13A9);
+   ir_expression *const r13AA = lshift(r13A7, body.constant(int(31)));
+   ir_expression *const r13AB = lshift(r13A8, body.constant(int(23)));
+   ir_expression *const r13AC = add(r13AA, r13AB);
+   ir_expression *const r13AD = add(r13AC, r13A9);
+   body.emit(ret(r13AD));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+shift32RightJamming(void *mem_ctx, builtin_available_predicate avail)
+{
+   ir_function_signature *const sig =
+      new(mem_ctx) ir_function_signature(glsl_type::void_type, avail);
+   ir_factory body(&sig->body, mem_ctx);
+   sig->is_defined = true;
+
+   exec_list sig_parameters;
+
+   ir_variable *const r13AE = new(mem_ctx) ir_variable(glsl_type::uint_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r13AE);
+   ir_variable *const r13AF = new(mem_ctx) ir_variable(glsl_type::int_type, "count", ir_var_function_in);
+   sig_parameters.push_tail(r13AF);
+   ir_variable *const r13B0 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zPtr", ir_var_function_inout);
+   sig_parameters.push_tail(r13B0);
+   ir_variable *const r13B1 = new(mem_ctx) ir_variable(glsl_type::uint_type, "z", ir_var_auto);
+   body.emit(r13B1);
+   /* IF CONDITION */
+   ir_expression *const r13B3 = equal(r13AF, body.constant(int(0)));
+   ir_if *f13B2 = new(mem_ctx) ir_if(operand(r13B3).val);
+   exec_list *const f13B2_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f13B2->then_instructions;
+
+      body.emit(assign(r13B1, r13AE, 0x01));
+
+
+      /* ELSE INSTRUCTIONS */
+      body.instructions = &f13B2->else_instructions;
+
+      /* IF CONDITION */
+      ir_expression *const r13B5 = less(r13AF, body.constant(int(32)));
+      ir_if *f13B4 = new(mem_ctx) ir_if(operand(r13B5).val);
+      exec_list *const f13B4_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f13B4->then_instructions;
+
+         ir_expression *const r13B6 = rshift(r13AE, r13AF);
+         ir_expression *const r13B7 = neg(r13AF);
+         ir_expression *const r13B8 = bit_and(r13B7, body.constant(int(31)));
+         ir_expression *const r13B9 = lshift(r13AE, r13B8);
+         ir_expression *const r13BA = nequal(r13B9, body.constant(0u));
+         ir_expression *const r13BB = expr(ir_unop_b2i, r13BA);
+         ir_expression *const r13BC = expr(ir_unop_i2u, r13BB);
+         body.emit(assign(r13B1, bit_or(r13B6, r13BC), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f13B4->else_instructions;
+
+         ir_expression *const r13BD = nequal(r13AE, body.constant(0u));
+         ir_expression *const r13BE = expr(ir_unop_b2i, r13BD);
+         body.emit(assign(r13B1, expr(ir_unop_i2u, r13BE), 0x01));
+
+
+      body.instructions = f13B4_parent_instructions;
+      body.emit(f13B4);
+
+      /* END IF */
+
+
+   body.instructions = f13B2_parent_instructions;
+   body.emit(f13B2);
+
+   /* END IF */
+
+   body.emit(assign(r13B0, r13B1, 0x01));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+roundAndPackFloat32(void *mem_ctx, builtin_available_predicate avail)
+{
+   ir_function_signature *const sig =
+      new(mem_ctx) ir_function_signature(glsl_type::uint_type, avail);
+   ir_factory body(&sig->body, mem_ctx);
+   sig->is_defined = true;
+
+   exec_list sig_parameters;
+
+   ir_variable *const r13BF = new(mem_ctx) ir_variable(glsl_type::uint_type, "zSign", ir_var_function_in);
+   sig_parameters.push_tail(r13BF);
+   ir_variable *const r13C0 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zExp", ir_var_function_in);
+   sig_parameters.push_tail(r13C0);
+   ir_variable *const r13C1 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zFrac", ir_var_function_in);
+   sig_parameters.push_tail(r13C1);
+   ir_variable *const r13C2 = body.make_temp(glsl_type::bool_type, "execute_flag");
+   body.emit(assign(r13C2, body.constant(true), 0x01));
+
+   ir_variable *const r13C3 = body.make_temp(glsl_type::uint_type, "return_value");
+   ir_variable *const r13C4 = new(mem_ctx) ir_variable(glsl_type::uint_type, "roundBits", ir_var_auto);
+   body.emit(r13C4);
+   body.emit(assign(r13C4, bit_and(r13C1, body.constant(127u)), 0x01));
+
+   /* IF CONDITION */
+   ir_expression *const r13C6 = lequal(body.constant(253u), r13C0);
+   ir_if *f13C5 = new(mem_ctx) ir_if(operand(r13C6).val);
+   exec_list *const f13C5_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f13C5->then_instructions;
+
+      /* IF CONDITION */
+      ir_expression *const r13C8 = less(body.constant(253u), r13C0);
+      ir_expression *const r13C9 = equal(r13C0, body.constant(253u));
+      ir_expression *const r13CA = less(r13C1, body.constant(4294967232u));
+      ir_expression *const r13CB = logic_and(r13C9, r13CA);
+      ir_expression *const r13CC = logic_or(r13C8, r13CB);
+      ir_if *f13C7 = new(mem_ctx) ir_if(operand(r13CC).val);
+      exec_list *const f13C7_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f13C7->then_instructions;
+
+         ir_expression *const r13CD = lshift(r13BF, body.constant(int(31)));
+         body.emit(assign(r13C3, add(r13CD, body.constant(2139095040u)), 0x01));
+
+         body.emit(assign(r13C2, body.constant(false), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f13C7->else_instructions;
+
+         /* IF CONDITION */
+         ir_expression *const r13CF = less(r13C0, body.constant(0u));
+         ir_if *f13CE = new(mem_ctx) ir_if(operand(r13CF).val);
+         exec_list *const f13CE_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f13CE->then_instructions;
+
+            ir_variable *const r13D0 = body.make_temp(glsl_type::int_type, "count");
+            ir_expression *const r13D1 = expr(ir_unop_u2i, r13C0);
+            body.emit(assign(r13D0, neg(r13D1), 0x01));
+
+            ir_variable *const r13D2 = new(mem_ctx) ir_variable(glsl_type::uint_type, "z", ir_var_auto);
+            body.emit(r13D2);
+            /* IF CONDITION */
+            ir_expression *const r13D4 = equal(r13D0, body.constant(int(0)));
+            ir_if *f13D3 = new(mem_ctx) ir_if(operand(r13D4).val);
+            exec_list *const f13D3_parent_instructions = body.instructions;
+
+               /* THEN INSTRUCTIONS */
+               body.instructions = &f13D3->then_instructions;
+
+               body.emit(assign(r13D2, r13C1, 0x01));
+
+
+               /* ELSE INSTRUCTIONS */
+               body.instructions = &f13D3->else_instructions;
+
+               /* IF CONDITION */
+               ir_expression *const r13D6 = less(r13D0, body.constant(int(32)));
+               ir_if *f13D5 = new(mem_ctx) ir_if(operand(r13D6).val);
+               exec_list *const f13D5_parent_instructions = body.instructions;
+
+                  /* THEN INSTRUCTIONS */
+                  body.instructions = &f13D5->then_instructions;
+
+                  ir_expression *const r13D7 = rshift(r13C1, r13D0);
+                  ir_expression *const r13D8 = neg(r13D0);
+                  ir_expression *const r13D9 = bit_and(r13D8, body.constant(int(31)));
+                  ir_expression *const r13DA = lshift(r13C1, r13D9);
+                  ir_expression *const r13DB = nequal(r13DA, body.constant(0u));
+                  ir_expression *const r13DC = expr(ir_unop_b2i, r13DB);
+                  ir_expression *const r13DD = expr(ir_unop_i2u, r13DC);
+                  body.emit(assign(r13D2, bit_or(r13D7, r13DD), 0x01));
+
+
+                  /* ELSE INSTRUCTIONS */
+                  body.instructions = &f13D5->else_instructions;
+
+                  ir_expression *const r13DE = nequal(r13C1, body.constant(0u));
+                  ir_expression *const r13DF = expr(ir_unop_b2i, r13DE);
+                  body.emit(assign(r13D2, expr(ir_unop_i2u, r13DF), 0x01));
+
+
+               body.instructions = f13D5_parent_instructions;
+               body.emit(f13D5);
+
+               /* END IF */
+
+
+            body.instructions = f13D3_parent_instructions;
+            body.emit(f13D3);
+
+            /* END IF */
+
+            body.emit(assign(r13C1, r13D2, 0x01));
+
+            body.emit(assign(r13C0, body.constant(0u), 0x01));
+
+            body.emit(assign(r13C4, bit_and(r13D2, body.constant(127u)), 0x01));
+
+
+         body.instructions = f13CE_parent_instructions;
+         body.emit(f13CE);
+
+         /* END IF */
+
+
+      body.instructions = f13C7_parent_instructions;
+      body.emit(f13C7);
+
+      /* END IF */
+
+
+   body.instructions = f13C5_parent_instructions;
+   body.emit(f13C5);
+
+   /* END IF */
+
+   /* IF CONDITION */
+   ir_if *f13E0 = new(mem_ctx) ir_if(operand(r13C2).val);
+   exec_list *const f13E0_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f13E0->then_instructions;
+
+      ir_expression *const r13E1 = add(r13C1, body.constant(64u));
+      body.emit(assign(r13C1, rshift(r13E1, body.constant(int(7))), 0x01));
+
+      ir_expression *const r13E2 = bit_xor(r13C4, body.constant(64u));
+      ir_expression *const r13E3 = equal(r13E2, body.constant(0u));
+      ir_expression *const r13E4 = expr(ir_unop_b2i, r13E3);
+      ir_expression *const r13E5 = expr(ir_unop_i2u, r13E4);
+      ir_expression *const r13E6 = bit_and(r13E5, body.constant(1u));
+      ir_expression *const r13E7 = expr(ir_unop_bit_not, r13E6);
+      body.emit(assign(r13C1, bit_and(r13C1, r13E7), 0x01));
+
+      /* IF CONDITION */
+      ir_expression *const r13E9 = equal(r13C1, body.constant(0u));
+      ir_if *f13E8 = new(mem_ctx) ir_if(operand(r13E9).val);
+      exec_list *const f13E8_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f13E8->then_instructions;
+
+         body.emit(assign(r13C0, body.constant(0u), 0x01));
+
+
+      body.instructions = f13E8_parent_instructions;
+      body.emit(f13E8);
+
+      /* END IF */
+
+      ir_expression *const r13EA = lshift(r13BF, body.constant(int(31)));
+      ir_expression *const r13EB = lshift(r13C0, body.constant(int(23)));
+      ir_expression *const r13EC = add(r13EA, r13EB);
+      body.emit(assign(r13C3, add(r13EC, r13C1), 0x01));
+
+      body.emit(assign(r13C2, body.constant(false), 0x01));
+
+
+   body.instructions = f13E0_parent_instructions;
+   body.emit(f13E0);
+
+   /* END IF */
+
+   body.emit(ret(r13C3));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+fp64_to_fp32(void *mem_ctx, builtin_available_predicate avail)
+{
+   ir_function_signature *const sig =
+      new(mem_ctx) ir_function_signature(glsl_type::uint_type, avail);
+   ir_factory body(&sig->body, mem_ctx);
+   sig->is_defined = true;
+
+   exec_list sig_parameters;
+
+   ir_variable *const r13ED = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r13ED);
+   ir_variable *const r13EE = body.make_temp(glsl_type::uint_type, "return_value");
+   ir_variable *const r13EF = new(mem_ctx) ir_variable(glsl_type::uint_type, "zFrac", ir_var_auto);
+   body.emit(r13EF);
+   body.emit(assign(r13EF, body.constant(0u), 0x01));
+
+   ir_variable *const r13F0 = body.make_temp(glsl_type::uvec2_type, "vec_ctor");
+   body.emit(assign(r13F0, bit_and(swizzle_x(r13ED), body.constant(1048575u)), 0x01));
+
+   body.emit(assign(r13F0, swizzle_y(r13ED), 0x02));
+
+   ir_variable *const r13F1 = body.make_temp(glsl_type::uint_type, "extractFloat64Exp_retval");
+   ir_expression *const r13F2 = rshift(swizzle_x(r13ED), body.constant(int(20)));
+   body.emit(assign(r13F1, bit_and(r13F2, body.constant(2047u)), 0x01));
+
+   ir_variable *const r13F3 = body.make_temp(glsl_type::uint_type, "extractFloat64Sign_retval");
+   body.emit(assign(r13F3, rshift(swizzle_x(r13ED), body.constant(int(31))), 0x01));
+
+   /* IF CONDITION */
+   ir_expression *const r13F5 = equal(r13F1, body.constant(2047u));
+   ir_if *f13F4 = new(mem_ctx) ir_if(operand(r13F5).val);
+   exec_list *const f13F4_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f13F4->then_instructions;
+
+      /* IF CONDITION */
+      ir_expression *const r13F7 = bit_or(swizzle_x(r13F0), swizzle_y(r13ED));
+      ir_expression *const r13F8 = nequal(r13F7, body.constant(0u));
+      ir_if *f13F6 = new(mem_ctx) ir_if(operand(r13F8).val);
+      exec_list *const f13F6_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f13F6->then_instructions;
+
+         ir_expression *const r13F9 = lshift(r13F3, body.constant(int(31)));
+         ir_expression *const r13FA = bit_or(r13F9, body.constant(2143289344u));
+         ir_expression *const r13FB = bit_and(swizzle_x(r13F0), body.constant(1048575u));
+         ir_expression *const r13FC = lshift(r13FB, body.constant(int(3)));
+         ir_expression *const r13FD = bit_or(r13FA, r13FC);
+         ir_expression *const r13FE = rshift(swizzle_y(r13ED), body.constant(int(29)));
+         body.emit(assign(r13EE, bit_or(r13FD, r13FE), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f13F6->else_instructions;
+
+         ir_expression *const r13FF = lshift(r13F3, body.constant(int(31)));
+         body.emit(assign(r13EE, add(r13FF, body.constant(2139095040u)), 0x01));
+
+
+      body.instructions = f13F6_parent_instructions;
+      body.emit(f13F6);
+
+      /* END IF */
+
+
+      /* ELSE INSTRUCTIONS */
+      body.instructions = &f13F4->else_instructions;
+
+      ir_variable *const r1400 = new(mem_ctx) ir_variable(glsl_type::uint_type, "z1", ir_var_auto);
+      body.emit(r1400);
+      ir_variable *const r1401 = new(mem_ctx) ir_variable(glsl_type::uint_type, "z0", ir_var_auto);
+      body.emit(r1401);
+      ir_expression *const r1402 = lshift(swizzle_x(r13F0), body.constant(int(10)));
+      ir_expression *const r1403 = rshift(swizzle_y(r13ED), body.constant(int(22)));
+      ir_expression *const r1404 = bit_or(r1402, r1403);
+      ir_expression *const r1405 = lshift(swizzle_y(r13ED), body.constant(int(10)));
+      ir_expression *const r1406 = nequal(r1405, body.constant(0u));
+      ir_expression *const r1407 = expr(ir_unop_b2i, r1406);
+      ir_expression *const r1408 = expr(ir_unop_i2u, r1407);
+      body.emit(assign(r1400, bit_or(r1404, r1408), 0x01));
+
+      body.emit(assign(r1401, rshift(swizzle_x(r13F0), body.constant(int(22))), 0x01));
+
+      body.emit(assign(r13EF, r1400, 0x01));
+
+      /* IF CONDITION */
+      ir_expression *const r140A = nequal(r13F1, body.constant(0u));
+      ir_if *f1409 = new(mem_ctx) ir_if(operand(r140A).val);
+      exec_list *const f1409_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f1409->then_instructions;
+
+         body.emit(assign(r13EF, bit_or(r1400, body.constant(1073741824u)), 0x01));
+
+
+      body.instructions = f1409_parent_instructions;
+      body.emit(f1409);
+
+      /* END IF */
+
+      ir_variable *const r140B = body.make_temp(glsl_type::uint_type, "zExp");
+      body.emit(assign(r140B, add(r13F1, body.constant(4294966399u)), 0x01));
+
+      ir_variable *const r140C = body.make_temp(glsl_type::uint_type, "zFrac");
+      body.emit(assign(r140C, r13EF, 0x01));
+
+      ir_variable *const r140D = body.make_temp(glsl_type::bool_type, "execute_flag");
+      body.emit(assign(r140D, body.constant(true), 0x01));
+
+      ir_variable *const r140E = body.make_temp(glsl_type::uint_type, "return_value");
+      ir_variable *const r140F = new(mem_ctx) ir_variable(glsl_type::uint_type, "roundBits", ir_var_auto);
+      body.emit(r140F);
+      body.emit(assign(r140F, bit_and(r13EF, body.constant(127u)), 0x01));
+
+      /* IF CONDITION */
+      ir_expression *const r1411 = lequal(body.constant(253u), r140B);
+      ir_if *f1410 = new(mem_ctx) ir_if(operand(r1411).val);
+      exec_list *const f1410_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f1410->then_instructions;
+
+         /* IF CONDITION */
+         ir_expression *const r1413 = less(body.constant(253u), r140B);
+         ir_expression *const r1414 = equal(r140B, body.constant(253u));
+         ir_expression *const r1415 = less(r13EF, body.constant(4294967232u));
+         ir_expression *const r1416 = logic_and(r1414, r1415);
+         ir_expression *const r1417 = logic_or(r1413, r1416);
+         ir_if *f1412 = new(mem_ctx) ir_if(operand(r1417).val);
+         exec_list *const f1412_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f1412->then_instructions;
+
+            ir_expression *const r1418 = lshift(r13F3, body.constant(int(31)));
+            body.emit(assign(r140E, add(r1418, body.constant(2139095040u)), 0x01));
+
+            body.emit(assign(r140D, body.constant(false), 0x01));
+
+
+            /* ELSE INSTRUCTIONS */
+            body.instructions = &f1412->else_instructions;
+
+            /* IF CONDITION */
+            ir_expression *const r141A = less(r140B, body.constant(0u));
+            ir_if *f1419 = new(mem_ctx) ir_if(operand(r141A).val);
+            exec_list *const f1419_parent_instructions = body.instructions;
+
+               /* THEN INSTRUCTIONS */
+               body.instructions = &f1419->then_instructions;
+
+               ir_variable *const r141B = body.make_temp(glsl_type::int_type, "count");
+               ir_expression *const r141C = expr(ir_unop_u2i, r140B);
+               body.emit(assign(r141B, neg(r141C), 0x01));
+
+               ir_variable *const r141D = new(mem_ctx) ir_variable(glsl_type::uint_type, "z", ir_var_auto);
+               body.emit(r141D);
+               /* IF CONDITION */
+               ir_expression *const r141F = equal(r141B, body.constant(int(0)));
+               ir_if *f141E = new(mem_ctx) ir_if(operand(r141F).val);
+               exec_list *const f141E_parent_instructions = body.instructions;
+
+                  /* THEN INSTRUCTIONS */
+                  body.instructions = &f141E->then_instructions;
+
+                  body.emit(assign(r141D, r13EF, 0x01));
+
+
+                  /* ELSE INSTRUCTIONS */
+                  body.instructions = &f141E->else_instructions;
+
+                  /* IF CONDITION */
+                  ir_expression *const r1421 = less(r141B, body.constant(int(32)));
+                  ir_if *f1420 = new(mem_ctx) ir_if(operand(r1421).val);
+                  exec_list *const f1420_parent_instructions = body.instructions;
+
+                     /* THEN INSTRUCTIONS */
+                     body.instructions = &f1420->then_instructions;
+
+                     ir_expression *const r1422 = rshift(r13EF, r141B);
+                     ir_expression *const r1423 = neg(r141B);
+                     ir_expression *const r1424 = bit_and(r1423, body.constant(int(31)));
+                     ir_expression *const r1425 = lshift(r13EF, r1424);
+                     ir_expression *const r1426 = nequal(r1425, body.constant(0u));
+                     ir_expression *const r1427 = expr(ir_unop_b2i, r1426);
+                     ir_expression *const r1428 = expr(ir_unop_i2u, r1427);
+                     body.emit(assign(r141D, bit_or(r1422, r1428), 0x01));
+
+
+                     /* ELSE INSTRUCTIONS */
+                     body.instructions = &f1420->else_instructions;
+
+                     ir_expression *const r1429 = nequal(r13EF, body.constant(0u));
+                     ir_expression *const r142A = expr(ir_unop_b2i, r1429);
+                     body.emit(assign(r141D, expr(ir_unop_i2u, r142A), 0x01));
+
+
+                  body.instructions = f1420_parent_instructions;
+                  body.emit(f1420);
+
+                  /* END IF */
+
+
+               body.instructions = f141E_parent_instructions;
+               body.emit(f141E);
+
+               /* END IF */
+
+               body.emit(assign(r140C, r141D, 0x01));
+
+               body.emit(assign(r140B, body.constant(0u), 0x01));
+
+               body.emit(assign(r140F, bit_and(r141D, body.constant(127u)), 0x01));
+
+
+            body.instructions = f1419_parent_instructions;
+            body.emit(f1419);
+
+            /* END IF */
+
+
+         body.instructions = f1412_parent_instructions;
+         body.emit(f1412);
+
+         /* END IF */
+
+
+      body.instructions = f1410_parent_instructions;
+      body.emit(f1410);
+
+      /* END IF */
+
+      /* IF CONDITION */
+      ir_if *f142B = new(mem_ctx) ir_if(operand(r140D).val);
+      exec_list *const f142B_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f142B->then_instructions;
+
+         ir_expression *const r142C = add(r140C, body.constant(64u));
+         body.emit(assign(r140C, rshift(r142C, body.constant(int(7))), 0x01));
+
+         ir_expression *const r142D = bit_xor(r140F, body.constant(64u));
+         ir_expression *const r142E = equal(r142D, body.constant(0u));
+         ir_expression *const r142F = expr(ir_unop_b2i, r142E);
+         ir_expression *const r1430 = expr(ir_unop_i2u, r142F);
+         ir_expression *const r1431 = bit_and(r1430, body.constant(1u));
+         ir_expression *const r1432 = expr(ir_unop_bit_not, r1431);
+         body.emit(assign(r140C, bit_and(r140C, r1432), 0x01));
+
+         /* IF CONDITION */
+         ir_expression *const r1434 = equal(r140C, body.constant(0u));
+         ir_if *f1433 = new(mem_ctx) ir_if(operand(r1434).val);
+         exec_list *const f1433_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f1433->then_instructions;
+
+            body.emit(assign(r140B, body.constant(0u), 0x01));
+
+
+         body.instructions = f1433_parent_instructions;
+         body.emit(f1433);
+
+         /* END IF */
+
+         ir_expression *const r1435 = lshift(r13F3, body.constant(int(31)));
+         ir_expression *const r1436 = lshift(r140B, body.constant(int(23)));
+         ir_expression *const r1437 = add(r1435, r1436);
+         body.emit(assign(r140E, add(r1437, r140C), 0x01));
+
+         body.emit(assign(r140D, body.constant(false), 0x01));
+
+
+      body.instructions = f142B_parent_instructions;
+      body.emit(f142B);
+
+      /* END IF */
+
+      body.emit(assign(r13EE, r140E, 0x01));
+
+
+   body.instructions = f13F4_parent_instructions;
+   body.emit(f13F4);
+
+   /* END IF */
+
+   body.emit(ret(r13EE));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index 17192b63f2..a88ceeb955 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -3165,6 +3165,10 @@ builtin_builder::create_builtins()
                 generate_ir::fp32_to_fp64(mem_ctx, integer_functions_supported),
                 NULL);
 
+   add_function("__builtin_fp64_to_fp32",
+                generate_ir::fp64_to_fp32(mem_ctx, integer_functions_supported),
+                NULL);
+
 #undef F
 #undef FI
 #undef FIUD_VEC
diff --git a/src/compiler/glsl/builtin_functions.h b/src/compiler/glsl/builtin_functions.h
index a228f17596..3845c5e79f 100644
--- a/src/compiler/glsl/builtin_functions.h
+++ b/src/compiler/glsl/builtin_functions.h
@@ -90,6 +90,9 @@ fdiv64(void *mem_ctx, builtin_available_predicate avail);
 ir_function_signature *
 fp32_to_fp64(void *mem_ctx, builtin_available_predicate avail);
 
+ir_function_signature *
+fp64_to_fp32(void *mem_ctx, builtin_available_predicate avail);
+
 }
 
 #endif /* BULITIN_FUNCTIONS_H */
diff --git a/src/compiler/glsl/float64.glsl b/src/compiler/glsl/float64.glsl
index ee9224c293..3f790dec83 100644
--- a/src/compiler/glsl/float64.glsl
+++ b/src/compiler/glsl/float64.glsl
@@ -1243,3 +1243,136 @@ fp32_to_fp64( uint a )
 
     return packFloat64( aSign, aExp + 0x380u, aFrac>>3, aFrac<<29 );
 }
+
+/* Packs the sign `zSign', exponent `zExp', and significand `zFrac' into a
+ * single-precision floating-point value, returning the result.  After being
+ * shifted into the proper positions, the three fields are simply added
+ * together to form the result.  This means that any integer portion of `zSig'
+ * will be added into the exponent.  Since a properly normalized significand
+ * will have an integer portion equal to 1, the `zExp' input should be 1 less
+ * than the desired result exponent whenever `zFrac' is a complete, normalized
+ * significand.
+ */
+uint
+packFloat32( uint zSign, uint zExp, uint zFrac )
+{
+    return ( zSign<<31 ) + ( zExp<<23 ) + zFrac;
+}
+
+/* Shifts `a' right by the number of bits given in `count'.  If any nonzero
+ * bits are shifted off, they are "jammed" into the least significant bit of
+ * the result by setting the least significant bit to 1.  The value of `count'
+ * can be arbitrarily large; in particular, if `count' is greater than 32, the
+ * result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+ * The result is stored in the location pointed to by `zPtr'.
+ */
+void
+shift32RightJamming( uint a, int count, inout uint zPtr )
+{
+    uint z;
+
+    if( count == 0 ) {
+        z = a;
+    } else if( count < 32 ) {
+        z = ( a>>count ) | uint ( ( a<<( ( - count ) & 31 ) ) != 0u );
+    } else {
+        z = uint ( a != 0u );
+    }
+    zPtr = z;
+}
+
+/* Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+ * and significand `zFrac', and returns the proper single-precision floating-
+ * point value corresponding to the abstract input.  Ordinarily, the abstract
+ * value is simply rounded and packed into the single-precision format, with
+ * the inexact exception raised if the abstract input cannot be represented
+ * exactly.  However, if the abstract value is too large, the overflow and
+ * inexact exceptions are raised and an infinity or maximal finite value is
+ * returned.  If the abstract value is too small, the input value is rounded to
+ * a subnormal number, and the underflow and inexact exceptions are raised if
+ * the abstract input cannot be represented exactly as a subnormal single-
+ * precision floating-point number.
+ *     The input significand `zFrac' has its binary point between bits 30
+ * and 29, which is 7 bits to the left of the usual location.  This shifted
+ * significand must be normalized or smaller.  If `zFrac' is not normalized,
+ * `zExp' must be 0; in that case, the result returned is a subnormal number,
+ * and it must not require rounding.  In the usual case that `zFrac' is
+ * normalized, `zExp' must be 1 less than the "true" floating-point exponent.
+ * The handling of underflow and overflow follows the IEEE Standard for
+ * Floating-Point Arithmetic.
+ */
+uint
+roundAndPackFloat32( uint zSign, uint zExp, uint zFrac )
+{
+    uint roundNearestEven;
+    uint roundIncrement;
+    uint roundBits;
+
+    roundNearestEven = uint ( FLOAT_ROUNDING_MODE == FLOAT_ROUND_NEAREST_EVEN );
+    roundIncrement = 0x40u;
+    if ( roundNearestEven == 0u ) {
+        if ( FLOAT_ROUNDING_MODE == FLOAT_ROUND_TO_ZERO ) {
+            roundIncrement = 0u;
+        } else {
+            roundIncrement = 0x7Fu;
+            if ( zSign != 0u ) {
+                if ( FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP ) {
+                      roundIncrement = 0u;
+                }
+            } else {
+                if ( FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN ) {
+                      roundIncrement = 0u;
+                }
+            }
+        }
+    }
+    roundBits = zFrac & 0x7Fu;
+    if ( 0xFDu <= zExp ) {
+        if ( ( 0xFDu < zExp ) ||
+            ( ( zExp == 0xFDu ) && ( ( zFrac + roundIncrement ) < 0u ) ) ) {
+            return packFloat32(
+                zSign, 0xFFu, 0u ) - uint ( roundIncrement == 0u );
+        }
+        if ( zExp < 0u ) {
+            shift32RightJamming( zFrac, - int (zExp), zFrac );
+            zExp = 0u;
+            roundBits = zFrac & 0x7Fu;
+        }
+    }
+    zFrac = ( zFrac + roundIncrement )>>7;
+    zFrac &= ~ ( uint ( ( roundBits ^ 0x40u ) == 0u ) & roundNearestEven );
+    if ( zFrac == 0u ) {
+        zExp = 0u;
+    }
+    return packFloat32( zSign, zExp, zFrac );
+}
+
+/* Returns the result of converting the double-precision floating-point value
+ * `a' to the single-precision floating-point format.  The conversion is
+ * performed according to the IEEE Standard for Floating-Point Arithmetic.
+ */
+uint
+fp64_to_fp32( uvec2 a )
+{
+    uint aSign;
+    uint aExp;
+    uint zFrac = 0u;
+    uint allZero = 0u;
+    uvec2 aFrac;
+
+    aFrac = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( aExp == 0x7FFu ) {
+        if ( ( aFrac.x | aFrac.y ) != 0u ) {
+            return ( aSign<<31 ) | 0x7FC00000u |
+                ( ( aFrac.x & 0x000FFFFFu )<<3 ) | ( aFrac.y>>29 );
+        }
+        return packFloat32( aSign, 0xFFu, 0u );
+    }
+    shift64RightJamming( aFrac, 22, allZero, zFrac );
+    if ( aExp != 0u ) {
+        zFrac |= 0x40000000u;
+    }
+    return roundAndPackFloat32( aSign, aExp - 0x381u, zFrac );
+}
-- 
2.11.0



More information about the mesa-dev mailing list