- /* Extra scope because lp_build_min needs a build context, le sigh */
- {
- /* Constants */
- LLVMValueRef i32_13 = lp_build_const_int_vec(gallivm, i32_type, 13);
- LLVMValueRef i32_16 = lp_build_const_int_vec(gallivm, i32_type, 16);
- LLVMValueRef i32_mask_fabs = lp_build_const_int_vec(gallivm, i32_type, 0x7fffffff);
- LLVMValueRef i32_f32infty = lp_build_const_int_vec(gallivm, i32_type, 0xff << 23);
- LLVMValueRef i32_expinf = lp_build_const_int_vec(gallivm, i32_type, 0xe0 << 23);
- LLVMValueRef i32_f16max = lp_build_const_int_vec(gallivm, i32_type, 0x8f << 23);
- LLVMValueRef i32_magic = lp_build_const_int_vec(gallivm, i32_type, 0x0f << 23);
-
- /* Cast from float32 to int32 */
- LLVMValueRef f = LLVMBuildBitCast(builder, src, int_vec_type, "");
-
- /* Remove sign */
- LLVMValueRef fabs = LLVMBuildAnd(builder, i32_mask_fabs, f, "");
-
- /* Magic conversion */
- LLVMValueRef clamped = lp_build_min(&bld, i32_f16max, fabs);
- LLVMValueRef scaled = LLVMBuildMul(builder, clamped, i32_magic, "");
-
- /* Make sure Inf/NaN and unormalised survive */
- LLVMValueRef infnancase = LLVMBuildXor(builder, i32_expinf, fabs, "");
- LLVMValueRef b_notnormal = lp_build_compare(gallivm, i32_type, PIPE_FUNC_GREATER, fabs, i32_f32infty);
-
- /* Merge normal / unnormal case */
- LLVMValueRef merge1 = LLVMBuildAnd(builder, infnancase, b_notnormal, "");
- LLVMValueRef merge2 = LLVMBuildNot(builder, LLVMBuildAnd(builder, b_notnormal, scaled, ""), "");
- LLVMValueRef merged = LLVMBuildOr(builder, merge1, merge2, "");
- LLVMValueRef shifted = LLVMBuildLShr(builder, merged, i32_13, "");
-
- /* Sign bit */
- LLVMValueRef justsign = LLVMBuildXor(builder, f, fabs, "");
- LLVMValueRef signshifted = LLVMBuildLShr(builder, justsign, i32_16, "");
-
- /* Combine result */
- result = LLVMBuildOr(builder, shifted, signshifted, "");