compiler_rt implementations for __fixuns* functions
* add u128 and i128 integer types * add f128 floating point type * implement big integer multiplication (See #405)master
parent
cf46cd5f2b
commit
6a98bf3dba
|
@ -239,10 +239,10 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/dwarf.zig" DESTINATION "${ZIG_STD_DEST}")
|
|||
install(FILES "${CMAKE_SOURCE_DIR}/std/elf.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/empty.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/endian.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/fmt/index.zig" DESTINATION "${ZIG_STD_DEST}/fmt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/fmt/errol/index.zig" DESTINATION "${ZIG_STD_DEST}/fmt/errol")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/fmt/errol/enum3.zig" DESTINATION "${ZIG_STD_DEST}/fmt/errol")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/fmt/errol/index.zig" DESTINATION "${ZIG_STD_DEST}/fmt/errol")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/fmt/errol/lookup.zig" DESTINATION "${ZIG_STD_DEST}/fmt/errol")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/fmt/index.zig" DESTINATION "${ZIG_STD_DEST}/fmt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/hash_map.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/index.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/io.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
|
@ -303,15 +303,27 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux.zig" DESTINATION "${ZIG_STD_DEST
|
|||
install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}/os")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}/os")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/os/path.zig" DESTINATION "${ZIG_STD_DEST}/os")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/error.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_file_template.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixuint.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunsdfdi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunsdfsi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunsdfti.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunssfdi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunssfsi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunssfti.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunstfdi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunstfsi.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/fixunstfti.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/index.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/udivti3.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/umodti3.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/zigrt.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
|
||||
|
|
|
@ -1386,7 +1386,7 @@ struct CodeGen {
|
|||
|
||||
struct {
|
||||
TypeTableEntry *entry_bool;
|
||||
TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64]
|
||||
TypeTableEntry *entry_int[2][5]; // [signed,unsigned][8,16,32,64,128]
|
||||
TypeTableEntry *entry_c_int[CIntTypeCount];
|
||||
TypeTableEntry *entry_c_longdouble;
|
||||
TypeTableEntry *entry_c_void;
|
||||
|
@ -1394,14 +1394,17 @@ struct CodeGen {
|
|||
TypeTableEntry *entry_u16;
|
||||
TypeTableEntry *entry_u32;
|
||||
TypeTableEntry *entry_u64;
|
||||
TypeTableEntry *entry_u128;
|
||||
TypeTableEntry *entry_i8;
|
||||
TypeTableEntry *entry_i16;
|
||||
TypeTableEntry *entry_i32;
|
||||
TypeTableEntry *entry_i64;
|
||||
TypeTableEntry *entry_i128;
|
||||
TypeTableEntry *entry_isize;
|
||||
TypeTableEntry *entry_usize;
|
||||
TypeTableEntry *entry_f32;
|
||||
TypeTableEntry *entry_f64;
|
||||
TypeTableEntry *entry_f128;
|
||||
TypeTableEntry *entry_void;
|
||||
TypeTableEntry *entry_unreachable;
|
||||
TypeTableEntry *entry_type;
|
||||
|
|
|
@ -3085,6 +3085,8 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_b
|
|||
index = 2;
|
||||
} else if (size_in_bits == 64) {
|
||||
index = 3;
|
||||
} else if (size_in_bits == 128) {
|
||||
index = 4;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -373,7 +373,6 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
|
|||
bigint_normalize(dest);
|
||||
return;
|
||||
}
|
||||
// TODO this code path is untested
|
||||
size_t i = 1;
|
||||
uint64_t first_digit = dest->data.digit;
|
||||
dest->data.digits = allocate_nonzero<uint64_t>(max(op1->digit_count, op2->digit_count) + 1);
|
||||
|
@ -397,17 +396,14 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
|
|||
}
|
||||
|
||||
dest->data.digits[i] = x;
|
||||
x += 1;
|
||||
i += 1;
|
||||
|
||||
if (!found_digit) {
|
||||
break;
|
||||
dest->digit_count = i;
|
||||
bigint_normalize(dest);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (overflow > 0) {
|
||||
dest->data.digits[i] = overflow;
|
||||
}
|
||||
bigint_normalize(dest);
|
||||
return;
|
||||
}
|
||||
const BigInt *op_pos;
|
||||
const BigInt *op_neg;
|
||||
|
@ -500,12 +496,49 @@ static void mul_overflow(uint64_t x, uint64_t y, uint64_t *result, uint64_t *car
|
|||
*carry = 0;
|
||||
return;
|
||||
}
|
||||
zig_panic("TODO bigint_mul with big numbers");
|
||||
|
||||
//unsigned __int128 big_x = x;
|
||||
//unsigned __int128 big_y = y;
|
||||
//unsigned __int128 big_result = big_x * big_y;
|
||||
//*carry = big_result >> 64;
|
||||
unsigned __int128 big_x = x;
|
||||
unsigned __int128 big_y = y;
|
||||
unsigned __int128 big_result = big_x * big_y;
|
||||
*carry = big_result >> 64;
|
||||
}
|
||||
|
||||
static void mul_scalar(BigInt *dest, const BigInt *op, uint64_t scalar) {
|
||||
bigint_init_unsigned(dest, 0);
|
||||
|
||||
BigInt bi_64;
|
||||
bigint_init_unsigned(&bi_64, 64);
|
||||
|
||||
const uint64_t *op_digits = bigint_ptr(op);
|
||||
size_t i = op->digit_count - 1;
|
||||
|
||||
for (;;) {
|
||||
BigInt shifted;
|
||||
bigint_shl(&shifted, dest, &bi_64);
|
||||
|
||||
uint64_t result_scalar;
|
||||
uint64_t carry_scalar;
|
||||
mul_overflow(scalar, op_digits[i], &result_scalar, &carry_scalar);
|
||||
|
||||
BigInt result;
|
||||
bigint_init_unsigned(&result, result_scalar);
|
||||
|
||||
BigInt carry;
|
||||
bigint_init_unsigned(&carry, carry_scalar);
|
||||
|
||||
BigInt carry_shifted;
|
||||
bigint_shl(&carry_shifted, &carry, &bi_64);
|
||||
|
||||
BigInt tmp;
|
||||
bigint_add(&tmp, &shifted, &carry_shifted);
|
||||
|
||||
bigint_add(dest, &tmp, &result);
|
||||
|
||||
if (i == 0) {
|
||||
break;
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2) {
|
||||
|
@ -523,7 +556,30 @@ void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2) {
|
|||
bigint_normalize(dest);
|
||||
return;
|
||||
}
|
||||
zig_panic("TODO bigint_mul with big numbers");
|
||||
|
||||
bigint_init_unsigned(dest, 0);
|
||||
|
||||
BigInt bi_64;
|
||||
bigint_init_unsigned(&bi_64, 64);
|
||||
|
||||
size_t i = op2->digit_count - 1;
|
||||
for (;;) {
|
||||
BigInt shifted;
|
||||
bigint_shl(&shifted, dest, &bi_64);
|
||||
|
||||
BigInt scalar_result;
|
||||
mul_scalar(&scalar_result, op1, op2_digits[i]);
|
||||
|
||||
bigint_add(dest, &scalar_result, &shifted);
|
||||
|
||||
if (i == 0) {
|
||||
break;
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
|
||||
dest->is_negative = (op1->is_negative != op2->is_negative);
|
||||
bigint_normalize(dest);
|
||||
}
|
||||
|
||||
void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
|
||||
|
|
|
@ -4208,6 +4208,7 @@ static const uint8_t int_sizes_in_bits[] = {
|
|||
16,
|
||||
32,
|
||||
64,
|
||||
128,
|
||||
};
|
||||
|
||||
struct CIntTypeInfo {
|
||||
|
@ -4390,6 +4391,19 @@ static void define_builtin_types(CodeGen *g) {
|
|||
g->builtin_types.entry_f64 = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->type_ref = LLVMFP128Type();
|
||||
buf_init_from_str(&entry->name, "f128");
|
||||
entry->data.floating.bit_count = 128;
|
||||
|
||||
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
|
||||
entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
|
||||
debug_size_in_bits,
|
||||
ZigLLVMEncoding_DW_ATE_float());
|
||||
g->builtin_types.entry_f128 = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->type_ref = LLVMX86FP80Type();
|
||||
|
@ -4435,10 +4449,12 @@ static void define_builtin_types(CodeGen *g) {
|
|||
g->builtin_types.entry_u16 = get_int_type(g, false, 16);
|
||||
g->builtin_types.entry_u32 = get_int_type(g, false, 32);
|
||||
g->builtin_types.entry_u64 = get_int_type(g, false, 64);
|
||||
g->builtin_types.entry_u128 = get_int_type(g, false, 128);
|
||||
g->builtin_types.entry_i8 = get_int_type(g, true, 8);
|
||||
g->builtin_types.entry_i16 = get_int_type(g, true, 16);
|
||||
g->builtin_types.entry_i32 = get_int_type(g, true, 32);
|
||||
g->builtin_types.entry_i64 = get_int_type(g, true, 64);
|
||||
g->builtin_types.entry_i128 = get_int_type(g, true, 128);
|
||||
|
||||
{
|
||||
g->builtin_types.entry_c_void = get_opaque_type(g, nullptr, nullptr, "c_void");
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
This compiler-rt library is ported from [LLVM](http://compiler-rt.llvm.org/).
|
||||
|
||||
It's needed because LLVM emits library calls to compiler-rt when hardware lacks
|
||||
functionality, for example, 64-bit integer multiplication on 32-bit x86.
|
||||
|
||||
This library is automatically built as-needed for the compilation target and
|
||||
then statically linked and therefore is a transparent dependency for the
|
||||
programmer.
|
||||
|
||||
Any bugs should be solved by trying to duplicate the bug upstream.
|
||||
* If the bug exists upstream, get it fixed with the LLVM team and then port
|
||||
the fix downstream to Zig.
|
||||
* If the bug only exists in Zig, something went wrong porting the code,
|
||||
and you can run the C code and Zig code side by side in a debugger
|
||||
to figure out what's happening differently.
|
|
@ -0,0 +1,50 @@
|
|||
pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) -> fixuint_t {
|
||||
@setDebugSafety(this, true); // TODO
|
||||
|
||||
const rep_t = switch (fp_t) {
|
||||
f32 => u32,
|
||||
f64 => u64,
|
||||
f128 => u128,
|
||||
else => unreachable,
|
||||
};
|
||||
const srep_t = @IntType(true, rep_t.bit_count);
|
||||
const significandBits = switch (fp_t) {
|
||||
f32 => 23,
|
||||
f64 => 52,
|
||||
f128 => 112,
|
||||
else => unreachable,
|
||||
};
|
||||
const typeWidth = rep_t.bit_count;
|
||||
const exponentBits = (typeWidth - significandBits - 1);
|
||||
const signBit = (rep_t(1) << (significandBits + exponentBits));
|
||||
const maxExponent = ((1 << exponentBits) - 1);
|
||||
const exponentBias = (maxExponent >> 1);
|
||||
|
||||
const implicitBit = (rep_t(1) << significandBits);
|
||||
const significandMask = (implicitBit - 1);
|
||||
|
||||
// Break a into sign, exponent, significand
|
||||
const aRep: rep_t = @bitCast(rep_t, a);
|
||||
const absMask = signBit - 1;
|
||||
const aAbs: rep_t = aRep & absMask;
|
||||
|
||||
const sign = if ((aRep & signBit) != 0) i32(-1) else i32(1);
|
||||
const exponent = i32(aAbs >> significandBits) - exponentBias;
|
||||
const significand: rep_t = (aAbs & significandMask) | implicitBit;
|
||||
|
||||
// If either the value or the exponent is negative, the result is zero.
|
||||
if (sign == -1 or exponent < 0)
|
||||
return 0;
|
||||
|
||||
// If the value is too large for the integer type, saturate.
|
||||
if (c_uint(exponent) >= fixuint_t.bit_count)
|
||||
return ~fixuint_t(0);
|
||||
|
||||
// If 0 <= exponent < significandBits, right shift to get the result.
|
||||
// Otherwise, shift left.
|
||||
if (exponent < significandBits) {
|
||||
return fixuint_t(significand >> rep_t(significandBits - exponent));
|
||||
} else {
|
||||
return fixuint_t(significand) << fixuint_t(exponent - significandBits);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunsdfdi(a: f64) -> u64 {
|
||||
return fixuint(f64, u64, a);
|
||||
}
|
||||
|
||||
test "import fixunsdfdi" {
|
||||
_ = @import("fixunsdfdi_test.zig");
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
|
||||
const assert = @import("../../debug.zig").assert;
|
||||
|
||||
fn test__fixunsdfdi(a: f64, expected: u64) {
|
||||
const x = __fixunsdfdi(a);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "fixunsdfdi" {
|
||||
test__fixunsdfdi(0.0, 0);
|
||||
test__fixunsdfdi(0.5, 0);
|
||||
test__fixunsdfdi(0.99, 0);
|
||||
test__fixunsdfdi(1.0, 1);
|
||||
test__fixunsdfdi(1.5, 1);
|
||||
test__fixunsdfdi(1.99, 1);
|
||||
test__fixunsdfdi(2.0, 2);
|
||||
test__fixunsdfdi(2.01, 2);
|
||||
test__fixunsdfdi(-0.5, 0);
|
||||
test__fixunsdfdi(-0.99, 0);
|
||||
test__fixunsdfdi(-1.0, 0);
|
||||
test__fixunsdfdi(-1.5, 0);
|
||||
test__fixunsdfdi(-1.99, 0);
|
||||
test__fixunsdfdi(-2.0, 0);
|
||||
test__fixunsdfdi(-2.01, 0);
|
||||
|
||||
test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
|
||||
test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
|
||||
|
||||
test__fixunsdfdi(-0x1.FFFFFEp+62, 0);
|
||||
test__fixunsdfdi(-0x1.FFFFFCp+62, 0);
|
||||
|
||||
test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
|
||||
test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000);
|
||||
test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
|
||||
test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
|
||||
|
||||
test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
|
||||
test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunsdfsi(a: f64) -> u32 {
|
||||
return fixuint(f64, u32, a);
|
||||
}
|
||||
|
||||
test "import fixunsdfsi" {
|
||||
_ = @import("fixunsdfsi_test.zig");
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;
|
||||
const assert = @import("../../debug.zig").assert;
|
||||
|
||||
fn test__fixunsdfsi(a: f64, expected: u32) {
|
||||
const x = __fixunsdfsi(a);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "fixunsdfsi" {
|
||||
test__fixunsdfsi(0.0, 0);
|
||||
|
||||
test__fixunsdfsi(0.5, 0);
|
||||
test__fixunsdfsi(0.99, 0);
|
||||
test__fixunsdfsi(1.0, 1);
|
||||
test__fixunsdfsi(1.5, 1);
|
||||
test__fixunsdfsi(1.99, 1);
|
||||
test__fixunsdfsi(2.0, 2);
|
||||
test__fixunsdfsi(2.01, 2);
|
||||
test__fixunsdfsi(-0.5, 0);
|
||||
test__fixunsdfsi(-0.99, 0);
|
||||
test__fixunsdfsi(-1.0, 0);
|
||||
test__fixunsdfsi(-1.5, 0);
|
||||
test__fixunsdfsi(-1.99, 0);
|
||||
test__fixunsdfsi(-2.0, 0);
|
||||
test__fixunsdfsi(-2.01, 0);
|
||||
|
||||
test__fixunsdfsi(0x1.000000p+31, 0x80000000);
|
||||
test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF);
|
||||
test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00);
|
||||
test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
|
||||
test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
|
||||
|
||||
test__fixunsdfsi(-0x1.FFFFFEp+30, 0);
|
||||
test__fixunsdfsi(-0x1.FFFFFCp+30, 0);
|
||||
|
||||
test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF);
|
||||
test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF);
|
||||
test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunsdfti(a: f64) -> u128 {
|
||||
return fixuint(f64, u128, a);
|
||||
}
|
||||
|
||||
test "import fixunsdfti" {
|
||||
_ = @import("fixunsdfti_test.zig");
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
|
||||
const assert = @import("../../debug.zig").assert;
|
||||
|
||||
fn test__fixunsdfti(a: f64, expected: u128) {
|
||||
const x = __fixunsdfti(a);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "fixunsdfti" {
|
||||
test__fixunsdfti(0.0, 0);
|
||||
|
||||
test__fixunsdfti(0.5, 0);
|
||||
test__fixunsdfti(0.99, 0);
|
||||
test__fixunsdfti(1.0, 1);
|
||||
test__fixunsdfti(1.5, 1);
|
||||
test__fixunsdfti(1.99, 1);
|
||||
test__fixunsdfti(2.0, 2);
|
||||
test__fixunsdfti(2.01, 2);
|
||||
test__fixunsdfti(-0.5, 0);
|
||||
test__fixunsdfti(-0.99, 0);
|
||||
test__fixunsdfti(-1.0, 0);
|
||||
test__fixunsdfti(-1.5, 0);
|
||||
test__fixunsdfti(-1.99, 0);
|
||||
test__fixunsdfti(-2.0, 0);
|
||||
test__fixunsdfti(-2.01, 0);
|
||||
|
||||
test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
|
||||
test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
|
||||
|
||||
test__fixunsdfti(-0x1.FFFFFEp+62, 0);
|
||||
test__fixunsdfti(-0x1.FFFFFCp+62, 0);
|
||||
|
||||
test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800);
|
||||
test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000);
|
||||
test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
|
||||
test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
|
||||
|
||||
test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000);
|
||||
test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000);
|
||||
test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
|
||||
test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
|
||||
test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
|
||||
test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0);
|
||||
test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunssfdi(a: f32) -> u64 {
|
||||
return fixuint(f32, u64, a);
|
||||
}
|
||||
|
||||
test "import fixunssfdi" {
|
||||
_ = @import("fixunssfdi_test.zig");
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;
|
||||
const assert = @import("../../debug.zig").assert;
|
||||
|
||||
fn test__fixunssfdi(a: f32, expected: u64) {
|
||||
const x = __fixunssfdi(a);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "fixunssfdi" {
|
||||
test__fixunssfdi(0.0, 0);
|
||||
|
||||
test__fixunssfdi(0.5, 0);
|
||||
test__fixunssfdi(0.99, 0);
|
||||
test__fixunssfdi(1.0, 1);
|
||||
test__fixunssfdi(1.5, 1);
|
||||
test__fixunssfdi(1.99, 1);
|
||||
test__fixunssfdi(2.0, 2);
|
||||
test__fixunssfdi(2.01, 2);
|
||||
test__fixunssfdi(-0.5, 0);
|
||||
test__fixunssfdi(-0.99, 0);
|
||||
|
||||
test__fixunssfdi(-1.0, 0);
|
||||
test__fixunssfdi(-1.5, 0);
|
||||
test__fixunssfdi(-1.99, 0);
|
||||
test__fixunssfdi(-2.0, 0);
|
||||
test__fixunssfdi(-2.01, 0);
|
||||
|
||||
test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
|
||||
test__fixunssfdi(0x1.000000p+63, 0x8000000000000000);
|
||||
test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
|
||||
test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
|
||||
|
||||
test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000);
|
||||
test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunssfsi(a: f32) -> u32 {
|
||||
return fixuint(f32, u32, a);
|
||||
}
|
||||
|
||||
test "import fixunssfsi" {
|
||||
_ = @import("fixunssfsi_test.zig");
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;
|
||||
const assert = @import("../../debug.zig").assert;
|
||||
|
||||
fn test__fixunssfsi(a: f32, expected: u32) {
|
||||
const x = __fixunssfsi(a);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "fixunssfsi" {
|
||||
test__fixunssfsi(0.0, 0);
|
||||
|
||||
test__fixunssfsi(0.5, 0);
|
||||
test__fixunssfsi(0.99, 0);
|
||||
test__fixunssfsi(1.0, 1);
|
||||
test__fixunssfsi(1.5, 1);
|
||||
test__fixunssfsi(1.99, 1);
|
||||
test__fixunssfsi(2.0, 2);
|
||||
test__fixunssfsi(2.01, 2);
|
||||
test__fixunssfsi(-0.5, 0);
|
||||
test__fixunssfsi(-0.99, 0);
|
||||
|
||||
test__fixunssfsi(-1.0, 0);
|
||||
test__fixunssfsi(-1.5, 0);
|
||||
test__fixunssfsi(-1.99, 0);
|
||||
test__fixunssfsi(-2.0, 0);
|
||||
test__fixunssfsi(-2.01, 0);
|
||||
|
||||
test__fixunssfsi(0x1.000000p+31, 0x80000000);
|
||||
test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF);
|
||||
test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00);
|
||||
test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
|
||||
test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
|
||||
|
||||
test__fixunssfsi(-0x1.FFFFFEp+30, 0);
|
||||
test__fixunssfsi(-0x1.FFFFFCp+30, 0);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunssfti(a: f32) -> u128 {
|
||||
return fixuint(f32, u128, a);
|
||||
}
|
||||
|
||||
test "import fixunssfti" {
|
||||
_ = @import("fixunssfti_test.zig");
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;
|
||||
const assert = @import("../../debug.zig").assert;
|
||||
|
||||
fn test__fixunssfti(a: f32, expected: u128) {
|
||||
const x = __fixunssfti(a);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "fixunssfti" {
|
||||
test__fixunssfti(0.0, 0);
|
||||
|
||||
test__fixunssfti(0.5, 0);
|
||||
test__fixunssfti(0.99, 0);
|
||||
test__fixunssfti(1.0, 1);
|
||||
test__fixunssfti(1.5, 1);
|
||||
test__fixunssfti(1.99, 1);
|
||||
test__fixunssfti(2.0, 2);
|
||||
test__fixunssfti(2.01, 2);
|
||||
test__fixunssfti(-0.5, 0);
|
||||
test__fixunssfti(-0.99, 0);
|
||||
|
||||
test__fixunssfti(-1.0, 0);
|
||||
test__fixunssfti(-1.5, 0);
|
||||
test__fixunssfti(-1.99, 0);
|
||||
test__fixunssfti(-2.0, 0);
|
||||
test__fixunssfti(-2.01, 0);
|
||||
|
||||
test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000);
|
||||
test__fixunssfti(0x1.000000p+63, 0x8000000000000000);
|
||||
test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
|
||||
test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
|
||||
test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000);
|
||||
test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000);
|
||||
test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000);
|
||||
test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000);
|
||||
|
||||
test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000);
|
||||
test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000);
|
||||
test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000);
|
||||
test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunstfdi(a: f128) -> u64 {
|
||||
return fixuint(f128, u64, a);
|
||||
}
|
||||
|
||||
test "import fixunstfdi" {
|
||||
_ = @import("fixunstfdi_test.zig");
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;
|
||||
const assert = @import("../../debug.zig").assert;
|
||||
|
||||
fn test__fixunstfdi(a: f128, expected: u64) {
|
||||
const x = __fixunstfdi(a);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "fixunstfdi" {
|
||||
test__fixunstfdi(0.0, 0);
|
||||
|
||||
test__fixunstfdi(0.5, 0);
|
||||
test__fixunstfdi(0.99, 0);
|
||||
test__fixunstfdi(1.0, 1);
|
||||
test__fixunstfdi(1.5, 1);
|
||||
test__fixunstfdi(1.99, 1);
|
||||
test__fixunstfdi(2.0, 2);
|
||||
test__fixunstfdi(2.01, 2);
|
||||
test__fixunstfdi(-0.5, 0);
|
||||
test__fixunstfdi(-0.99, 0);
|
||||
test__fixunstfdi(-1.0, 0);
|
||||
test__fixunstfdi(-1.5, 0);
|
||||
test__fixunstfdi(-1.99, 0);
|
||||
test__fixunstfdi(-2.0, 0);
|
||||
test__fixunstfdi(-2.01, 0);
|
||||
|
||||
test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
|
||||
test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
|
||||
|
||||
test__fixunstfdi(-0x1.FFFFFEp+62, 0);
|
||||
test__fixunstfdi(-0x1.FFFFFCp+62, 0);
|
||||
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
|
||||
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
|
||||
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
|
||||
test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);
|
||||
test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
|
||||
test__fixunstfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
test__fixunstfdi(-0x1.0000000000000000p+63, 0);
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunstfsi(a: f128) -> u32 {
|
||||
return fixuint(f128, u32, a);
|
||||
}
|
||||
|
||||
test "fixunstfsi" {
|
||||
_ = @import("fixunstfsi_test.zig");
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
const fixuint = @import("fixuint.zig").fixuint;
|
||||
|
||||
export fn __fixunstfti(a: f128) -> u128 {
|
||||
return fixuint(f128, u128, a);
|
||||
}
|
||||
|
||||
test "fixunstfti" {
|
||||
_ = @import("fixunstfti_test.zig");
|
||||
}
|
||||
|
|
@ -1,6 +1,20 @@
|
|||
// Find all the exported functions.
|
||||
comptime {
|
||||
_ = @import("fixunsdfdi.zig");
|
||||
_ = @import("fixunsdfsi.zig");
|
||||
_ = @import("fixunsdfti.zig");
|
||||
_ = @import("fixunssfdi.zig");
|
||||
_ = @import("fixunssfsi.zig");
|
||||
_ = @import("fixunssfti.zig");
|
||||
_ = @import("fixunstfdi.zig");
|
||||
_ = @import("fixunstfsi.zig");
|
||||
_ = @import("fixunstfti.zig");
|
||||
_ = @import("udivti3.zig");
|
||||
_ = @import("umodti3.zig");
|
||||
}
|
||||
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const CHAR_BIT = 8;
|
||||
const du_int = u64;
|
||||
const di_int = i64;
|
||||
const si_int = c_int;
|
||||
|
@ -23,8 +37,8 @@ fn du_int_to_udwords(x: du_int) -> udwords {
|
|||
export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
@setDebugSafety(this, false);
|
||||
|
||||
const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;
|
||||
const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;
|
||||
const n_uword_bits = su_int.bit_count;
|
||||
const n_udword_bits = du_int.bit_count;
|
||||
var n = du_int_to_udwords(a);
|
||||
var d = du_int_to_udwords(b);
|
||||
var q: udwords = undefined;
|
||||
|
@ -219,6 +233,7 @@ fn isArmArch() -> bool {
|
|||
builtin.Arch.armv8_2a,
|
||||
builtin.Arch.armv8_1a,
|
||||
builtin.Arch.armv8,
|
||||
builtin.Arch.armv8r,
|
||||
builtin.Arch.armv8m_baseline,
|
||||
builtin.Arch.armv8m_mainline,
|
||||
builtin.Arch.armv7,
|
||||
|
@ -278,7 +293,7 @@ export fn __aeabi_uidiv(n: su_int, d: su_int) -> su_int {
|
|||
export fn __udivsi3(n: su_int, d: su_int) -> su_int {
|
||||
@setDebugSafety(this, false);
|
||||
|
||||
const n_uword_bits: c_uint = @sizeOf(su_int) * CHAR_BIT;
|
||||
const n_uword_bits: c_uint = su_int.bit_count;
|
||||
// special cases
|
||||
if (d == 0)
|
||||
return 0; // ?!
|
||||
|
|
|
@ -284,3 +284,29 @@ fn testShrExact(x: u8) {
|
|||
const shifted = @shrExact(x, 2);
|
||||
assert(shifted == 0b00101101);
|
||||
}
|
||||
|
||||
test "big number addition" {
|
||||
comptime {
|
||||
assert(
|
||||
35361831660712422535336160538497375248 +
|
||||
101752735581729509668353361206450473702 ==
|
||||
137114567242441932203689521744947848950);
|
||||
assert(
|
||||
594491908217841670578297176641415611445982232488944558774612 +
|
||||
390603545391089362063884922208143568023166603618446395589768 ==
|
||||
985095453608931032642182098849559179469148836107390954364380);
|
||||
}
|
||||
}
|
||||
|
||||
test "big number multiplication" {
|
||||
comptime {
|
||||
assert(
|
||||
45960427431263824329884196484953148229 *
|
||||
128339149605334697009938835852565949723 ==
|
||||
5898522172026096622534201617172456926982464453350084962781392314016180490567);
|
||||
assert(
|
||||
594491908217841670578297176641415611445982232488944558774612 *
|
||||
390603545391089362063884922208143568023166603618446395589768 ==
|
||||
232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue