From b38a8cfb12fc37c19a9cb2fb27ef4806d232ff23 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 1 Jun 2019 12:26:54 +0100 Subject: [PATCH] Move internal 128-bit stuff to a windows specific file --- core/runtime/internal.odin | 201 ---------------------------- core/runtime/internal_windows.odin | 202 +++++++++++++++++++++++++++++ src/check_type.cpp | 10 +- 3 files changed, 209 insertions(+), 204 deletions(-) create mode 100644 core/runtime/internal_windows.odin diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index b6fff0864..d3ef1f94d 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -509,204 +509,3 @@ quo_complex128 :: proc(n, m: complex128) -> complex128 { return complex(e, f); } - -@(default_calling_convention="none") -foreign { - @(link_name="llvm.cttz.i8") _ctz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 --- - @(link_name="llvm.cttz.i16") _ctz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 --- - @(link_name="llvm.cttz.i32") _ctz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 --- - @(link_name="llvm.cttz.i64") _ctz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 --- -} -_ctz :: proc{ - _ctz_u8, - _ctz_u16, - _ctz_u32, - _ctz_u64, -}; - -@(default_calling_convention="none") -foreign { - @(link_name="llvm.ctlz.i8") _clz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 --- - @(link_name="llvm.ctlz.i16") _clz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 --- - @(link_name="llvm.ctlz.i32") _clz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 --- - @(link_name="llvm.ctlz.i64") _clz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 --- -} -_clz :: proc{ - _clz_u8, - _clz_u16, - _clz_u32, - _clz_u64, -}; - - -udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { - n := transmute([2]u64)a; - d := transmute([2]u64)b; - q, r: [2]u64 = ---, ---; - sr: u32 = 0; - - low :: ODIN_ENDIAN == "big" ? 1 : 0; - high :: 1 - low; - U64_BITS :: 8*size_of(u64); - U128_BITS :: 8*size_of(u128); - - // Special Cases - - if n[high] == 0 { - if d[high] == 0 { - if rem != nil { - rem^ = u128(n[low] % d[low]); - } - return u128(n[low] / d[low]); - } - - if rem != nil { - rem^ = u128(n[low]); - } - return 0; - } - - if d[low] == 0 { - if d[high] == 0 { - if rem != nil { - rem^ = u128(n[high] % d[low]); - } - return u128(n[high] / d[low]); - } - if n[low] == 0 { - if rem != nil { - r[high] = n[high] % d[high]; - r[low] = 0; - rem^ = transmute(u128)r; - } - return u128(n[high] / d[high]); - } - - if d[high] & (d[high]-1) == 0 { - if rem != nil { - r[low] = n[low]; - r[high] = n[high] & (d[high] - 1); - rem^ = transmute(u128)r; - } - return u128(n[high] >> _ctz(d[high])); - } - - sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); - if sr > U64_BITS - 2 { - if rem != nil { - rem^ = a; - } - return 0; - } - - sr += 1; - - q[low] = 0; - q[high] = n[low] << u64(U64_BITS - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); - } else { - if d[high] == 0 { - if d[low] & (d[low] - 1) == 0 { - if rem != nil { - rem^ = u128(n[low] & (d[low] - 1)); - } - if d[low] == 1 { - return a; - } - sr = u32(_ctz(d[low])); - q[high] = n[high] >> sr; - q[low] = (n[high] << (U64_BITS-sr)) | (n[low] >> sr); - return transmute(u128)q; - } - - sr = 1 + U64_BITS + u32(_clz(d[low])) - u32(_clz(n[high])); - - switch { - case sr == U64_BITS: - q[low] = 0; - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - case sr < U64_BITS: - q[low] = 0; - q[high] = n[low] << (U64_BITS - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); - case: - q[low] = n[low] << (U128_BITS - sr); - q[high] = (n[high] << (U128_BITS - sr)) | (n[low] >> (sr - U64_BITS)); - r[high] = 0; - r[low] = n[high] >> (sr - U64_BITS); - } - } else { - sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); - - if sr > U64_BITS - 1 { - if rem != nil { - rem^ = a; - } - return 0; - } - - sr += 1; - - q[low] = 0; - if sr == U64_BITS { - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - } else { - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); - q[high] = n[low] << (U64_BITS - sr); - } - } - } - - carry: u32 = 0; - r_all: u128 = ---; - - for ; sr > 0; sr -= 1 { - r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1)); - r[low] = (r[low] << 1) | (q[high] >> (U64_BITS - 1)); - q[high] = (q[high] << 1) | (q[low] >> (U64_BITS - 1)); - q[low] = (q[low] << 1) | u64(carry); - - r_all = transmute(u128)r; - s := i128(b - r_all - 1) >> (U128_BITS - 1); - carry = u32(s & 1); - r_all -= b & transmute(u128)s; - r = transmute([2]u64)r_all; - } - - q_all := ((transmute(u128)q) << 1) | u128(carry); - if rem != nil { - rem^ = r_all; - } - - return q_all; -} - -@(link_name="__umodti3") -umodti3 :: proc "c" (a, b: i128) -> i128 { - s_a := a >> (128 - 1); - s_b := b >> (128 - 1); - an := (a ~ s_a) - s_a; - bn := (b ~ s_b) - s_b; - - r: u128 = ---; - _ = udivmod128(transmute(u128)an, transmute(u128)bn, &r); - return (transmute(i128)r ~ s_a) - s_a; -} - - -@(link_name="__udivmodti4") -udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { - return udivmod128(a, b, rem); -} - -@(link_name="__udivti3") -udivti3 :: proc "c" (a, b: u128) -> u128 { - return udivmodti4(a, b, nil); -} diff --git a/core/runtime/internal_windows.odin b/core/runtime/internal_windows.odin new file mode 100644 index 000000000..913eec36f --- /dev/null +++ b/core/runtime/internal_windows.odin @@ -0,0 +1,202 @@ +package runtime + +@(default_calling_convention="none") +foreign { + @(link_name="llvm.cttz.i8") _ctz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 --- + @(link_name="llvm.cttz.i16") _ctz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 --- + @(link_name="llvm.cttz.i32") _ctz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 --- + @(link_name="llvm.cttz.i64") _ctz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 --- +} +_ctz :: proc{ + _ctz_u8, + _ctz_u16, + _ctz_u32, + _ctz_u64, +}; + +@(default_calling_convention="none") +foreign { + @(link_name="llvm.ctlz.i8") _clz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 --- + @(link_name="llvm.ctlz.i16") _clz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 --- + @(link_name="llvm.ctlz.i32") _clz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 --- + @(link_name="llvm.ctlz.i64") _clz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 --- +} +_clz :: proc{ + _clz_u8, + _clz_u16, + _clz_u32, + _clz_u64, +}; + + +udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { + n := transmute([2]u64)a; + d := transmute([2]u64)b; + q, r: [2]u64 = ---, ---; + sr: u32 = 0; + + low :: ODIN_ENDIAN == "big" ? 1 : 0; + high :: 1 - low; + U64_BITS :: 8*size_of(u64); + U128_BITS :: 8*size_of(u128); + + // Special Cases + + if n[high] == 0 { + if d[high] == 0 { + if rem != nil { + rem^ = u128(n[low] % d[low]); + } + return u128(n[low] / d[low]); + } + + if rem != nil { + rem^ = u128(n[low]); + } + return 0; + } + + if d[low] == 0 { + if d[high] == 0 { + if rem != nil { + rem^ = u128(n[high] % d[low]); + } + return u128(n[high] / d[low]); + } + if n[low] == 0 { + if rem != nil { + r[high] = n[high] % d[high]; + r[low] = 0; + rem^ = transmute(u128)r; + } + return u128(n[high] / d[high]); + } + + if d[high] & (d[high]-1) == 0 { + if rem != nil { + r[low] = n[low]; + r[high] = n[high] & (d[high] - 1); + rem^ = transmute(u128)r; + } + return u128(n[high] >> _ctz(d[high])); + } + + sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); + if sr > U64_BITS - 2 { + if rem != nil { + rem^ = a; + } + return 0; + } + + sr += 1; + + q[low] = 0; + q[high] = n[low] << u64(U64_BITS - sr); + r[high] = n[high] >> sr; + r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); + } else { + if d[high] == 0 { + if d[low] & (d[low] - 1) == 0 { + if rem != nil { + rem^ = u128(n[low] & (d[low] - 1)); + } + if d[low] == 1 { + return a; + } + sr = u32(_ctz(d[low])); + q[high] = n[high] >> sr; + q[low] = (n[high] << (U64_BITS-sr)) | (n[low] >> sr); + return transmute(u128)q; + } + + sr = 1 + U64_BITS + u32(_clz(d[low])) - u32(_clz(n[high])); + + switch { + case sr == U64_BITS: + q[low] = 0; + q[high] = n[low]; + r[high] = 0; + r[low] = n[high]; + case sr < U64_BITS: + q[low] = 0; + q[high] = n[low] << (U64_BITS - sr); + r[high] = n[high] >> sr; + r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); + case: + q[low] = n[low] << (U128_BITS - sr); + q[high] = (n[high] << (U128_BITS - sr)) | (n[low] >> (sr - U64_BITS)); + r[high] = 0; + r[low] = n[high] >> (sr - U64_BITS); + } + } else { + sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); + + if sr > U64_BITS - 1 { + if rem != nil { + rem^ = a; + } + return 0; + } + + sr += 1; + + q[low] = 0; + if sr == U64_BITS { + q[high] = n[low]; + r[high] = 0; + r[low] = n[high]; + } else { + r[high] = n[high] >> sr; + r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); + q[high] = n[low] << (U64_BITS - sr); + } + } + } + + carry: u32 = 0; + r_all: u128 = ---; + + for ; sr > 0; sr -= 1 { + r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1)); + r[low] = (r[low] << 1) | (q[high] >> (U64_BITS - 1)); + q[high] = (q[high] << 1) | (q[low] >> (U64_BITS - 1)); + q[low] = (q[low] << 1) | u64(carry); + + r_all = transmute(u128)r; + s := i128(b - r_all - 1) >> (U128_BITS - 1); + carry = u32(s & 1); + r_all -= b & transmute(u128)s; + r = transmute([2]u64)r_all; + } + + q_all := ((transmute(u128)q) << 1) | u128(carry); + if rem != nil { + rem^ = r_all; + } + + return q_all; +} + +@(link_name="__umodti3") +umodti3 :: proc "c" (a, b: i128) -> i128 { + s_a := a >> (128 - 1); + s_b := b >> (128 - 1); + an := (a ~ s_a) - s_a; + bn := (b ~ s_b) - s_b; + + r: u128 = ---; + _ = udivmod128(transmute(u128)an, transmute(u128)bn, &r); + return (transmute(i128)r ~ s_a) - s_a; +} + + +@(link_name="__udivmodti4") +udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { + return udivmod128(a, b, rem); +} + +@(link_name="__udivti3") +udivti3 :: proc "c" (a, b: u128) -> u128 { + return udivmodti4(a, b, nil); +} diff --git a/src/check_type.cpp b/src/check_type.cpp index f7d577a54..555b54e78 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1853,9 +1853,13 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCall if (is_type_simd_vector(original_type)) { return new_type; } - if (build_context.word_size == 8) { + if (build_context.ODIN_ARCH == "amd64") { if (is_type_integer_128bit(original_type)) { - return alloc_type_simd_vector(2, t_u64); + if (build_context.ODIN_OS == "windows") { + return alloc_type_simd_vector(2, t_u64); + } else { + return original_type; + } } } @@ -1971,7 +1975,7 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCal } if (build_context.ODIN_OS == "windows") { - if (build_context.word_size == 8) { + if (build_context.ODIN_ARCH == "amd64") { if (is_type_integer_128bit(single_type)) { if (cc == ProcCC_None) { return original_type;