diff --git a/codegen/luajit/runtime/runtime.lua b/codegen/luajit/runtime/runtime.lua index 2755c02..7891b33 100644 --- a/codegen/luajit/runtime/runtime.lua +++ b/codegen/luajit/runtime/runtime.lua @@ -10,6 +10,7 @@ local i64 = ffi.typeof("int64_t") local math_ceil = math.ceil local math_floor = math.floor local to_number = tonumber +local to_signed = bit.tobit local NUM_ZERO = i64(0) local NUM_ONE = i64(1) @@ -34,8 +35,6 @@ do local copysign = {} local nearest = {} - local to_signed = bit.tobit - local math_abs = math.abs local math_min = math.min local math_max = math.max @@ -396,6 +395,7 @@ end do local wrap = {} local truncate = {} + local saturate = {} local extend = {} local convert = {} local promote = {} @@ -404,6 +404,10 @@ do local bit_and = bit.band + local NUM_MIN_I64 = bit.lshift(NUM_ONE, 63) + local NUM_MAX_I64 = bit.bnot(NUM_MIN_I64) + local NUM_MAX_U64 = bit.bnot(NUM_ZERO) + -- This would surely be an issue in a multi-thread environment... -- ... thankfully this isn't one. local RE_INSTANCE = ffi.new([[union { @@ -421,13 +425,66 @@ do truncate.i32_f32 = truncate_f64 truncate.i32_f64 = truncate_f64 + + function truncate.u32_f32(num) + return (to_signed(truncate_f64(num))) + end + + truncate.u32_f64 = truncate.u32_f32 + truncate.i64_f32 = i64 truncate.i64_f64 = i64 truncate.u64_f32 = i64 - truncate.u64_f64 = i64 + + function truncate.u64_f64(num) + return (i64(u64(num))) + end + truncate.f32 = truncate_f64 truncate.f64 = truncate_f64 + function saturate.i32_f64(num) + if num <= -0x80000000 then + return -0x80000000 + elseif num >= 0x7FFFFFFF then + return 0x7FFFFFFF + else + return to_signed(truncate_f64(num)) + end + end + + function saturate.u32_f64(num) + if num <= 0 then + return 0 + elseif num >= 0xFFFFFFFF then + return -1 + else + return to_signed(truncate_f64(num)) + end + end + + function saturate.i64_f64(num) + if num >= 2 ^ 63 - 1 then + return NUM_MAX_I64 + elseif num <= -2 ^ 63 then + return NUM_MIN_I64 + elseif num ~= num then + return NUM_ZERO + else + return i64(num) + end + end + + function saturate.u64_f64(num) + if num >= 2 ^ 64 then + return NUM_MAX_U64 + elseif num <= 0 or num ~= num then + return NUM_ZERO + else + return i64(u64(num)) + end + end + function extend.i32_n8(num) num = bit_and(num, 0xFF) @@ -535,6 +592,7 @@ do module.wrap = wrap module.truncate = truncate + module.saturate = saturate module.extend = extend module.convert = convert module.demote = demote diff --git a/codegen/luau/runtime/runtime.lua b/codegen/luau/runtime/runtime.lua index 5992716..9a8c2d7 100644 --- a/codegen/luau/runtime/runtime.lua +++ b/codegen/luau/runtime/runtime.lua @@ -364,6 +364,7 @@ end do local wrap = {} local truncate = {} + local saturate = {} local extend = {} local convert = {} local demote = {} @@ -372,55 +373,23 @@ do local math_ceil = math.ceil local math_floor = math.floor + local math_clamp = math.clamp local string_pack = string.pack local string_unpack = string.unpack + local NUM_ZERO = Integer.ZERO + local NUM_MIN_I64 = num_from_u32(0, 0x80000000) + local NUM_MAX_I64 = num_from_u32(0xFFFFFFFF, 0x7FFFFFFF) + local NUM_MAX_U64 = num_from_u32(0xFFFFFFFF, 0xFFFFFFFF) + local num_from_u64 = Integer.from_u64 local num_into_u64 = Integer.into_u64 local num_negate = Integer.negate local num_is_negative = Integer.is_negative - function wrap.i32_i64(num) - local data_1, _ = num_into_u32(num) - - return data_1 - end - - truncate.i32_f32 = to_u32 - truncate.i32_f64 = to_u32 - truncate.u32_f32 = no_op - truncate.u32_f64 = no_op - - function truncate.i64_f32(num) - if num < 0 then - local temp = num_from_u64(-math_ceil(num)) - - return num_negate(temp) - else - local temp = math_floor(num) - - return num_from_u64(temp) - end - end - - function truncate.i64_f64(num) - if num < 0 then - local temp = num_from_u64(-math_ceil(num)) - - return num_negate(temp) - else - local temp = math_floor(num) - - return num_from_u64(temp) - end - end - - truncate.u64_f32 = num_from_u64 - truncate.u64_f64 = num_from_u64 - - function truncate.f32(num) + local function truncate_f64(num) if num >= 0 then return math_floor(num) else @@ -428,7 +397,78 @@ do end end - truncate.f64 = truncate.f32 + function wrap.i32_i64(num) + local data_1, _ = num_into_u32(num) + + return data_1 + end + + function truncate.i32_f32(num) + return to_u32(truncate_f64(num)) + end + + truncate.i32_f64 = to_u32 + truncate.u32_f32 = truncate_f64 + truncate.u32_f64 = truncate_f64 + + function truncate.i64_f32(num) + if num < 0 then + local temp = num_from_u64(-num) + + return num_negate(temp) + else + return num_from_u64(num) + end + end + + truncate.i64_f64 = truncate.i64_f32 + + function truncate.u64_f32(num) + if num <= 0 then + return NUM_ZERO + else + return num_from_u64(math_floor(num)) + end + end + + truncate.u64_f64 = truncate.u64_f32 + + truncate.f32 = truncate_f64 + truncate.f64 = truncate_f64 + + function saturate.i32_f64(num) + local temp = math_clamp(truncate_f64(num), -0x80000000, 0x7FFFFFFF) + + return to_u32(temp) + end + + function saturate.u32_f64(num) + local temp = math_clamp(truncate_f64(num), 0, 0xFFFFFFFF) + + return to_u32(temp) + end + + local truncate_i64_f64 = truncate.i64_f64 + + function saturate.i64_f64(num) + if num >= 2 ^ 63 - 1 then + return NUM_MAX_I64 + elseif num <= -2 ^ 63 then + return NUM_MIN_I64 + else + return truncate_i64_f64(num) + end + end + + function saturate.u64_f64(num) + if num >= 2 ^ 64 then + return NUM_MAX_U64 + elseif num <= 0 then + return NUM_ZERO + else + return truncate_i64_f64(num) + end + end function extend.i32_n8(num) num = bit_and(num, 0xFF) @@ -504,7 +544,7 @@ do return num_from_u32(num, 0) end - convert.f32_i32 = no_op + convert.f32_i32 = to_i32 convert.f32_u32 = no_op function convert.f32_i64(num) @@ -520,17 +560,7 @@ do convert.f32_u64 = num_into_u64 convert.f64_i32 = to_i32 convert.f64_u32 = no_op - - function convert.f64_i64(num) - if num_is_negative(num) then - local temp = num_negate(num) - - return -num_into_u64(temp) - else - return num_into_u64(num) - end - end - + convert.f64_i64 = convert.f32_i64 convert.f64_u64 = num_into_u64 demote.f32_f64 = no_op @@ -565,6 +595,7 @@ do module.wrap = wrap module.truncate = truncate + module.saturate = saturate module.extend = extend module.convert = convert module.demote = demote