From 14cda27b640651829b1d8af996392b650c7835a5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Sep 2017 01:44:22 -0400 Subject: depend on embedded SoftFloat-3d instead of __float128 See #302 See #467 --- src/ir.cpp | 110 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 41 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 6b887a6d83..ffe49179ca 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12,8 +12,8 @@ #include "ir_print.hpp" #include "os.hpp" #include "parsec.hpp" -#include "quadmath.hpp" #include "range_set.hpp" +#include "softfloat.hpp" struct IrExecContext { ConstExprValue *mem_slot_list; @@ -6439,7 +6439,11 @@ static bool float_has_fraction(ConstExprValue *const_val) { case 64: return floor(const_val->data.x_f64) != const_val->data.x_f64; case 128: - return floorq(const_val->data.x_f128) != const_val->data.x_f128; + { + float128_t floored; + f128M_roundToInt(&const_val->data.x_f128, softfloat_round_minMag, false, &floored); + return !f128M_eq(&floored, &const_val->data.x_f128); + } default: zig_unreachable(); } @@ -6461,10 +6465,16 @@ static void float_append_buf(Buf *buf, ConstExprValue *const_val) { break; case 128: { + // TODO actual implementation const size_t extra_len = 100; size_t old_len = buf_len(buf); buf_resize(buf, old_len + extra_len); - int len = quadmath_snprintf(buf_ptr(buf) + old_len, extra_len, "%Qf", const_val->data.x_f128); + + float64_t f64_value = f128M_to_f64(&const_val->data.x_f128); + double double_value; + memcpy(&double_value, &f64_value, sizeof(double)); + + int len = snprintf(buf_ptr(buf) + old_len, extra_len, "%f", double_value); assert(len > 0); buf_resize(buf, old_len + len); break; @@ -6499,11 +6509,10 @@ static void float_init_bigint(BigInt *bigint, ConstExprValue *const_val) { } break; case 128: - if (const_val->data.x_f128 >= 0) { - bigint_init_u128(bigint, (uint128_t)(const_val->data.x_f128)); - } else { - bigint_init_u128(bigint, (uint128_t)(-const_val->data.x_f128)); - bigint->is_negative = true; + { + BigFloat tmp_float; + bigfloat_init_128(&tmp_float, const_val->data.x_f128); + bigint_init_bigfloat(bigint, &tmp_float); } break; default: @@ -6548,8 +6557,12 @@ static void float_init_f32(ConstExprValue *dest_val, float x) { dest_val->data.x_f64 = x; break; case 128: - dest_val->data.x_f128 = x; - break; + { + float32_t x_f32; + memcpy(&x_f32, &x, sizeof(float)); + f32_to_f128M(x_f32, &dest_val->data.x_f128); + break; + } default: zig_unreachable(); } @@ -6570,8 +6583,12 @@ static void float_init_f64(ConstExprValue *dest_val, double x) { dest_val->data.x_f64 = x; break; case 128: - dest_val->data.x_f128 = x; - break; + { + float64_t x_f64; + memcpy(&x_f64, &x, sizeof(double)); + f64_to_f128M(x_f64, &dest_val->data.x_f128); + break; + } default: zig_unreachable(); } @@ -6580,20 +6597,28 @@ static void float_init_f64(ConstExprValue *dest_val, double x) { } } -static void float_init_f128(ConstExprValue *dest_val, __float128 x) { +static void float_init_f128(ConstExprValue *dest_val, float128_t x) { if (dest_val->type->id == TypeTableEntryIdNumLitFloat) { bigfloat_init_128(&dest_val->data.x_bigfloat, x); } else if (dest_val->type->id == TypeTableEntryIdFloat) { switch (dest_val->type->data.floating.bit_count) { case 32: - dest_val->data.x_f32 = x; - break; + { + float32_t f32_val = f128M_to_f32(&x); + memcpy(&dest_val->data.x_f32, &f32_val, sizeof(float)); + break; + } case 64: - dest_val->data.x_f64 = x; - break; + { + float64_t f64_val = f128M_to_f64(&x); + memcpy(&dest_val->data.x_f64, &f64_val, sizeof(double)); + break; + } case 128: - dest_val->data.x_f128 = x; - break; + { + memcpy(&dest_val->data.x_f128, &x, sizeof(float128_t)); + break; + } default: zig_unreachable(); } @@ -6647,12 +6672,12 @@ static Cmp float_cmp(ConstExprValue *op1, ConstExprValue *op2) { return CmpEQ; } case 128: - if (op1->data.x_f128 > op2->data.x_f128) { - return CmpGT; - } else if (op1->data.x_f128 < op2->data.x_f128) { + if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) { return CmpLT; - } else { + } else if (f128M_eq(&op1->data.x_f128, &op2->data.x_f128)) { return CmpEQ; + } else { + return CmpGT; } default: zig_unreachable(); @@ -6684,12 +6709,14 @@ static Cmp float_cmp_zero(ConstExprValue *op) { return CmpEQ; } case 128: - if (op->data.x_f128 < 0.0) { + float128_t zero_float; + ui32_to_f128M(0, &zero_float); + if (f128M_lt(&op->data.x_f128, &zero_float)) { return CmpLT; - } else if (op->data.x_f128 > 0.0) { - return CmpGT; - } else { + } else if (f128M_eq(&op->data.x_f128, &zero_float)) { return CmpEQ; + } else { + return CmpGT; } default: zig_unreachable(); @@ -6713,7 +6740,7 @@ static void float_add(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal out_val->data.x_f64 = op1->data.x_f64 + op2->data.x_f64; return; case 128: - out_val->data.x_f128 = op1->data.x_f128 + op2->data.x_f128; + f128M_add(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6737,7 +6764,7 @@ static void float_sub(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal out_val->data.x_f64 = op1->data.x_f64 - op2->data.x_f64; return; case 128: - out_val->data.x_f128 = op1->data.x_f128 - op2->data.x_f128; + f128M_sub(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6761,7 +6788,7 @@ static void float_mul(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal out_val->data.x_f64 = op1->data.x_f64 * op2->data.x_f64; return; case 128: - out_val->data.x_f128 = op1->data.x_f128 * op2->data.x_f128; + f128M_mul(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6785,7 +6812,7 @@ static void float_div(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64; return; case 128: - out_val->data.x_f128 = op1->data.x_f128 / op2->data.x_f128; + f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6819,12 +6846,8 @@ static void float_div_trunc(ConstExprValue *out_val, ConstExprValue *op1, ConstE } return; case 128: - out_val->data.x_f128 = op1->data.x_f128 / op2->data.x_f128; - if (out_val->data.x_f128 >= 0.0) { - out_val->data.x_f128 = floorq(out_val->data.x_f128); - } else { - out_val->data.x_f128 = ceilq(out_val->data.x_f128); - } + f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); + f128M_roundToInt(&out_val->data.x_f128, softfloat_round_minMag, false, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6848,7 +6871,8 @@ static void float_div_floor(ConstExprValue *out_val, ConstExprValue *op1, ConstE out_val->data.x_f64 = floor(op1->data.x_f64 / op2->data.x_f64); return; case 128: - out_val->data.x_f128 = floorq(op1->data.x_f128 / op2->data.x_f128); + f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); + f128M_roundToInt(&out_val->data.x_f128, softfloat_round_min, false, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6872,7 +6896,7 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal out_val->data.x_f64 = fmod(op1->data.x_f64, op2->data.x_f64); return; case 128: - out_val->data.x_f128 = fmodq(op1->data.x_f128, op2->data.x_f128); + f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6896,7 +6920,9 @@ static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64); return; case 128: - out_val->data.x_f128 = fmodq(fmodq(op1->data.x_f128, op2->data.x_f128) + op2->data.x_f128, op2->data.x_f128); + f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); + f128M_add(&out_val->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); + f128M_rem(&out_val->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); @@ -6919,7 +6945,9 @@ static void float_negate(ConstExprValue *out_val, ConstExprValue *op) { out_val->data.x_f64 = -op->data.x_f64; return; case 128: - out_val->data.x_f128 = -op->data.x_f128; + float128_t zero_f128; + ui32_to_f128M(0, &zero_f128); + f128M_sub(&zero_f128, &op->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); -- cgit v1.2.3