commit
f0cdfae184
@ -1,6 +1,8 @@
|
|||||||
local Numeric = {}
|
local Numeric = {}
|
||||||
|
|
||||||
local NUM_ZERO, NUM_ONE, NUM_SIX_FOUR
|
local NUM_ZERO = Vector3.zero
|
||||||
|
local NUM_ONE, NUM_SIX_FOUR
|
||||||
|
|
||||||
local NUM_BIT_26, NUM_BIT_52
|
local NUM_BIT_26, NUM_BIT_52
|
||||||
|
|
||||||
local bit_lshift = bit32.lshift
|
local bit_lshift = bit32.lshift
|
||||||
@ -18,7 +20,7 @@ local bit_replace = bit32.replace
|
|||||||
local from_u32, from_u64, into_u64
|
local from_u32, from_u64, into_u64
|
||||||
local num_subtract, num_divide_unsigned, num_negate
|
local num_subtract, num_divide_unsigned, num_negate
|
||||||
local num_or, num_shift_left, num_shift_right_unsigned
|
local num_or, num_shift_left, num_shift_right_unsigned
|
||||||
local num_is_negative, num_is_zero, num_is_less_unsigned
|
local num_is_less_unsigned
|
||||||
|
|
||||||
-- X: a[0 ..21]
|
-- X: a[0 ..21]
|
||||||
-- Y: a[22..31]
|
-- Y: a[22..31]
|
||||||
@ -34,6 +36,10 @@ function Numeric.from_u32(data_1, data_2)
|
|||||||
return constructor(x, y, z)
|
return constructor(x, y, z)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function num_is_zero(value)
|
||||||
|
return value == NUM_ZERO
|
||||||
|
end
|
||||||
|
|
||||||
local function load_d1(value)
|
local function load_d1(value)
|
||||||
return bit_replace(bit_and(value.X, 0x3FFFFF), value.Z, 22, 10)
|
return bit_replace(bit_and(value.X, 0x3FFFFF), value.Z, 22, 10)
|
||||||
end
|
end
|
||||||
@ -42,21 +48,26 @@ local function load_d2(value)
|
|||||||
return bit_replace(bit_and(value.Y, 0x3FFFFF), bit_rshift(value.Z, 10), 22, 10)
|
return bit_replace(bit_and(value.Y, 0x3FFFFF), bit_rshift(value.Z, 10), 22, 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Numeric.into_u32(value)
|
local function into_u32(value)
|
||||||
return load_d1(value), load_d2(value)
|
local x, y, z = value.X, value.Y, value.Z
|
||||||
|
return bit_replace(bit_and(x, 0x3FFFFF), z, 22, 10), bit_replace(bit_and(y, 0x3FFFFF), bit_rshift(z, 10), 22, 10)
|
||||||
end
|
end
|
||||||
|
Numeric.into_u32 = into_u32
|
||||||
|
|
||||||
function Numeric.from_u64(value)
|
function Numeric.from_u64(value)
|
||||||
return from_u32(bit_and(value % 0x100000000), bit_and(value / 0x100000000))
|
return from_u32(bit_and(value % 0x100000000), bit_and(value / 0x100000000))
|
||||||
end
|
end
|
||||||
|
|
||||||
function Numeric.into_u64(value)
|
function Numeric.into_u64(value)
|
||||||
return load_d1(value) + load_d2(value) * 0x100000000
|
local value_1, value_2 = into_u32(value)
|
||||||
|
return value_1 + value_2 * 0x100000000
|
||||||
end
|
end
|
||||||
|
|
||||||
function Numeric.add(lhs, rhs)
|
function Numeric.add(lhs, rhs)
|
||||||
local data_1 = load_d1(lhs) + load_d1(rhs)
|
local lhs_1, lhs_2 = into_u32(lhs)
|
||||||
local data_2 = load_d2(lhs) + load_d2(rhs)
|
local rhs_1, rhs_2 = into_u32(rhs)
|
||||||
|
local data_1 = lhs_1 + rhs_1
|
||||||
|
local data_2 = lhs_2 + rhs_2
|
||||||
|
|
||||||
if data_1 >= 0x100000000 then
|
if data_1 >= 0x100000000 then
|
||||||
data_1 = data_1 - 0x100000000
|
data_1 = data_1 - 0x100000000
|
||||||
@ -71,8 +82,10 @@ function Numeric.add(lhs, rhs)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Numeric.subtract(lhs, rhs)
|
function Numeric.subtract(lhs, rhs)
|
||||||
local data_1 = load_d1(lhs) - load_d1(rhs)
|
local lhs_1, lhs_2 = into_u32(lhs)
|
||||||
local data_2 = load_d2(lhs) - load_d2(rhs)
|
local rhs_1, rhs_2 = into_u32(rhs)
|
||||||
|
local data_1 = lhs_1 - rhs_1
|
||||||
|
local data_2 = lhs_2 - rhs_2
|
||||||
|
|
||||||
if data_1 < 0 then
|
if data_1 < 0 then
|
||||||
data_1 = data_1 + 0x100000000
|
data_1 = data_1 + 0x100000000
|
||||||
@ -95,8 +108,8 @@ function Numeric.multiply(lhs, rhs)
|
|||||||
|
|
||||||
-- Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
|
-- Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
|
||||||
-- We can skip products that would overflow.
|
-- We can skip products that would overflow.
|
||||||
local lhs_1, lhs_2 = load_d1(lhs), load_d2(lhs)
|
local lhs_1, lhs_2 = into_u32(lhs)
|
||||||
local rhs_1, rhs_2 = load_d1(rhs), load_d2(rhs)
|
local rhs_1, rhs_2 = into_u32(rhs)
|
||||||
|
|
||||||
local a48 = bit_rshift(lhs_2, 16)
|
local a48 = bit_rshift(lhs_2, 16)
|
||||||
local a32 = bit_and(lhs_2, 0xFFFF)
|
local a32 = bit_and(lhs_2, 0xFFFF)
|
||||||
@ -155,11 +168,10 @@ function Numeric.divide_unsigned(lhs, rhs)
|
|||||||
local quotient = NUM_ZERO
|
local quotient = NUM_ZERO
|
||||||
local remainder = NUM_ZERO
|
local remainder = NUM_ZERO
|
||||||
|
|
||||||
local num_1, num_2 = load_d1(lhs), load_d2(lhs)
|
local num_1, num_2 = into_u32(lhs)
|
||||||
|
|
||||||
for i = 63, 0, -1 do
|
for i = 63, 0, -1 do
|
||||||
local temp = num_shift_left(remainder, NUM_ONE)
|
local rem_1, rem_2 = into_u32(num_shift_left(remainder, NUM_ONE))
|
||||||
local rem_1, rem_2 = load_d1(temp), load_d2(temp)
|
|
||||||
|
|
||||||
if i > 31 then
|
if i > 31 then
|
||||||
rem_1 = bit_or(rem_1, bit_extract(num_2, i - 32, 1))
|
rem_1 = bit_or(rem_1, bit_extract(num_2, i - 32, 1))
|
||||||
@ -178,6 +190,10 @@ function Numeric.divide_unsigned(lhs, rhs)
|
|||||||
return quotient, remainder
|
return quotient, remainder
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function num_is_negative(value)
|
||||||
|
return value.Z >= 0x80000
|
||||||
|
end
|
||||||
|
|
||||||
function Numeric.divide_signed(lhs, rhs)
|
function Numeric.divide_signed(lhs, rhs)
|
||||||
local left_negative = num_is_negative(lhs)
|
local left_negative = num_is_negative(lhs)
|
||||||
local right_negative = num_is_negative(rhs)
|
local right_negative = num_is_negative(rhs)
|
||||||
@ -204,8 +220,9 @@ function Numeric.divide_signed(lhs, rhs)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Numeric.negate(value)
|
function Numeric.negate(value)
|
||||||
local data_1 = bit_not(load_d1(value)) + 1
|
local value_1, value_2 = into_u32(value)
|
||||||
local data_2 = bit_not(load_d2(value))
|
local data_1 = bit_not(value_1) + 1
|
||||||
|
local data_2 = bit_not(value_2)
|
||||||
|
|
||||||
if data_1 >= 0x100000000 then
|
if data_1 >= 0x100000000 then
|
||||||
data_1 = data_1 - 0x100000000
|
data_1 = data_1 - 0x100000000
|
||||||
@ -258,7 +275,7 @@ function Numeric.shift_left(lhs, rhs)
|
|||||||
return lhs
|
return lhs
|
||||||
elseif count < 32 then
|
elseif count < 32 then
|
||||||
local pad = 32 - count
|
local pad = 32 - count
|
||||||
local lhs_1, lhs_2 = load_d1(lhs), load_d2(lhs)
|
local lhs_1, lhs_2 = into_u32(lhs)
|
||||||
|
|
||||||
local data_1 = bit_lshift(lhs_1, count)
|
local data_1 = bit_lshift(lhs_1, count)
|
||||||
local data_2 = bit_replace(bit_rshift(lhs_1, pad), lhs_2, count, pad)
|
local data_2 = bit_replace(bit_rshift(lhs_1, pad), lhs_2, count, pad)
|
||||||
@ -277,7 +294,7 @@ function Numeric.shift_right_unsigned(lhs, rhs)
|
|||||||
if count == 0 then
|
if count == 0 then
|
||||||
return lhs
|
return lhs
|
||||||
elseif count < 32 then
|
elseif count < 32 then
|
||||||
local lhs_1, lhs_2 = load_d1(lhs), load_d2(lhs)
|
local lhs_1, lhs_2 = into_u32(lhs)
|
||||||
|
|
||||||
local data_1 = bit_replace(bit_rshift(lhs_1, count), lhs_2, 32 - count, count)
|
local data_1 = bit_replace(bit_rshift(lhs_1, count), lhs_2, 32 - count, count)
|
||||||
local data_2 = bit_rshift(lhs_2, count)
|
local data_2 = bit_rshift(lhs_2, count)
|
||||||
@ -296,7 +313,7 @@ function Numeric.shift_right_signed(lhs, rhs)
|
|||||||
if count == 0 then
|
if count == 0 then
|
||||||
return lhs
|
return lhs
|
||||||
elseif count < 32 then
|
elseif count < 32 then
|
||||||
local lhs_1, lhs_2 = load_d1(lhs), load_d2(lhs)
|
local lhs_1, lhs_2 = into_u32(lhs)
|
||||||
|
|
||||||
local data_1 = bit_replace(bit_rshift(lhs_1, count), lhs_2, 32 - count, count)
|
local data_1 = bit_replace(bit_rshift(lhs_1, count), lhs_2, 32 - count, count)
|
||||||
local data_2 = bit_arshift(lhs_2, count)
|
local data_2 = bit_arshift(lhs_2, count)
|
||||||
@ -334,16 +351,8 @@ function Numeric.rotate_right(lhs, rhs)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Numeric.is_negative(value)
|
|
||||||
return value.Z >= 0x80000
|
|
||||||
end
|
|
||||||
|
|
||||||
function Numeric.is_zero(value)
|
|
||||||
return value.X == 0 and value.Y == 0 and value.Z == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function Numeric.is_equal(lhs, rhs)
|
function Numeric.is_equal(lhs, rhs)
|
||||||
return lhs.X == rhs.X and lhs.Y == rhs.Y and lhs.Z == rhs.Z
|
return lhs == rhs
|
||||||
end
|
end
|
||||||
|
|
||||||
function Numeric.is_less_unsigned(lhs, rhs)
|
function Numeric.is_less_unsigned(lhs, rhs)
|
||||||
@ -398,11 +407,10 @@ num_or = Numeric.bit_or
|
|||||||
num_shift_left = Numeric.shift_left
|
num_shift_left = Numeric.shift_left
|
||||||
num_shift_right_unsigned = Numeric.shift_right_unsigned
|
num_shift_right_unsigned = Numeric.shift_right_unsigned
|
||||||
|
|
||||||
num_is_negative = Numeric.is_negative
|
Numeric.is_negative = num_is_negative
|
||||||
num_is_zero = Numeric.is_zero
|
Numeric.is_zero = num_is_zero
|
||||||
num_is_less_unsigned = Numeric.is_less_unsigned
|
num_is_less_unsigned = Numeric.is_less_unsigned
|
||||||
|
|
||||||
NUM_ZERO = from_u64(0)
|
|
||||||
NUM_ONE = from_u64(1)
|
NUM_ONE = from_u64(1)
|
||||||
NUM_SIX_FOUR = from_u64(64)
|
NUM_SIX_FOUR = from_u64(64)
|
||||||
NUM_BIT_26 = from_u64(0x4000000)
|
NUM_BIT_26 = from_u64(0x4000000)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
local module = {}
|
local module = {}
|
||||||
|
|
||||||
local bit_and = bit32.band
|
local bit_and = bit32.band
|
||||||
|
local bit_or = bit32.bor
|
||||||
local bit_xor = bit32.bxor
|
local bit_xor = bit32.bxor
|
||||||
local bit_lshift = bit32.lshift
|
local bit_lshift = bit32.lshift
|
||||||
local bit_rshift = bit32.rshift
|
local bit_rshift = bit32.rshift
|
||||||
@ -44,16 +45,16 @@ do
|
|||||||
local num_divide_unsigned = Integer.divide_unsigned
|
local num_divide_unsigned = Integer.divide_unsigned
|
||||||
|
|
||||||
function add.i32(lhs, rhs)
|
function add.i32(lhs, rhs)
|
||||||
return bit_and(lhs + rhs, 0xFFFFFFFF)
|
return bit_or(lhs + rhs, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function sub.i32(lhs, rhs)
|
function sub.i32(lhs, rhs)
|
||||||
return bit_and(lhs - rhs, 0xFFFFFFFF)
|
return bit_or(lhs - rhs, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mul.i32(lhs, rhs)
|
function mul.i32(lhs, rhs)
|
||||||
if (lhs + rhs) < 0x8000000 then
|
if (lhs + rhs) < 0x8000000 then
|
||||||
return bit_and(lhs * rhs, 0xFFFFFFFF)
|
return bit_or(lhs * rhs, 0)
|
||||||
else
|
else
|
||||||
local a16 = bit_rshift(lhs, 16)
|
local a16 = bit_rshift(lhs, 16)
|
||||||
local a00 = bit_and(lhs, 0xFFFF)
|
local a00 = bit_and(lhs, 0xFFFF)
|
||||||
@ -63,7 +64,7 @@ do
|
|||||||
local c00 = a00 * b00
|
local c00 = a00 * b00
|
||||||
local c16 = a16 * b00 + a00 * b16
|
local c16 = a16 * b00 + a00 * b16
|
||||||
|
|
||||||
return bit_and(c00 + bit_lshift(c16, 16), 0xFFFFFFFF)
|
return bit_or(c00 + bit_lshift(c16, 16), 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -73,13 +74,13 @@ do
|
|||||||
lhs = to_i32(lhs)
|
lhs = to_i32(lhs)
|
||||||
rhs = to_i32(rhs)
|
rhs = to_i32(rhs)
|
||||||
|
|
||||||
return bit_and(math_modf(lhs / rhs), 0xFFFFFFFF)
|
return bit_or(math_modf(lhs / rhs), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function div.u32(lhs, rhs)
|
function div.u32(lhs, rhs)
|
||||||
assert(rhs ~= 0, "division by zero")
|
assert(rhs ~= 0, "division by zero")
|
||||||
|
|
||||||
return bit_and(math_modf(lhs / rhs), 0xFFFFFFFF)
|
return bit_or(math_modf(lhs / rhs), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function rem.i32(lhs, rhs)
|
function rem.i32(lhs, rhs)
|
||||||
@ -88,7 +89,7 @@ do
|
|||||||
lhs = to_i32(lhs)
|
lhs = to_i32(lhs)
|
||||||
rhs = to_i32(rhs)
|
rhs = to_i32(rhs)
|
||||||
|
|
||||||
return bit_and(math_fmod(lhs, rhs), 0xFFFFFFFF)
|
return bit_or(math_fmod(lhs, rhs), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
add.i64 = Integer.add
|
add.i64 = Integer.add
|
||||||
@ -182,14 +183,12 @@ do
|
|||||||
local bit_countrz = bit32.countrz
|
local bit_countrz = bit32.countrz
|
||||||
|
|
||||||
local function popcnt_i32(num)
|
local function popcnt_i32(num)
|
||||||
local count = 0
|
num = num - bit_and(bit_rshift(num, 1), 0x55555555)
|
||||||
|
num = bit_and(num, 0x33333333) + bit_and(bit_rshift(num, 2), 0x33333333)
|
||||||
while num ~= 0 do
|
num = bit_and((num + bit_rshift(num, 4)), 0x0F0F0F0F)
|
||||||
num = bit_and(num, num - 1)
|
num = num + bit_rshift(num, 8)
|
||||||
count = count + 1
|
num = num + bit_rshift(num, 16)
|
||||||
end
|
return bit_and(num, 0x0000003F)
|
||||||
|
|
||||||
return count
|
|
||||||
end
|
end
|
||||||
|
|
||||||
popcnt.i32 = popcnt_i32
|
popcnt.i32 = popcnt_i32
|
||||||
@ -397,7 +396,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
function truncate.i32_f32(num)
|
function truncate.i32_f32(num)
|
||||||
return bit_and(truncate_f64(num), 0xFFFFFFFF)
|
return bit_or(truncate_f64(num), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
truncate.i32_f64 = truncate.i32_f32
|
truncate.i32_f64 = truncate.i32_f32
|
||||||
@ -433,7 +432,7 @@ do
|
|||||||
function saturate.i32_f32(num)
|
function saturate.i32_f32(num)
|
||||||
local temp = math_clamp(truncate_f64(num), -0x80000000, 0x7FFFFFFF)
|
local temp = math_clamp(truncate_f64(num), -0x80000000, 0x7FFFFFFF)
|
||||||
|
|
||||||
return bit_and(temp, 0xFFFFFFFF)
|
return bit_or(temp, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
saturate.i32_f64 = saturate.i32_f32
|
saturate.i32_f64 = saturate.i32_f32
|
||||||
@ -476,7 +475,7 @@ do
|
|||||||
num = bit_and(num, 0xFF)
|
num = bit_and(num, 0xFF)
|
||||||
|
|
||||||
if num >= 0x80 then
|
if num >= 0x80 then
|
||||||
return bit_and(num - 0x100, 0xFFFFFFFF)
|
return bit_or(num - 0x100, 0)
|
||||||
else
|
else
|
||||||
return num
|
return num
|
||||||
end
|
end
|
||||||
@ -486,7 +485,7 @@ do
|
|||||||
num = bit_and(num, 0xFFFF)
|
num = bit_and(num, 0xFFFF)
|
||||||
|
|
||||||
if num >= 0x8000 then
|
if num >= 0x8000 then
|
||||||
return bit_and(num - 0x10000, 0xFFFFFFFF)
|
return bit_or(num - 0x10000, 0)
|
||||||
else
|
else
|
||||||
return num
|
return num
|
||||||
end
|
end
|
||||||
@ -650,7 +649,7 @@ do
|
|||||||
local buffer_write_f64 = buffer.writef64
|
local buffer_write_f64 = buffer.writef64
|
||||||
|
|
||||||
function load.i32_i8(memory, addr)
|
function load.i32_i8(memory, addr)
|
||||||
return bit_and(buffer_read_i8(memory.data, addr), 0xFFFFFFFF)
|
return bit_or(buffer_read_i8(memory.data, addr), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function load.i32_u8(memory, addr)
|
function load.i32_u8(memory, addr)
|
||||||
@ -658,7 +657,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
function load.i32_i16(memory, addr)
|
function load.i32_i16(memory, addr)
|
||||||
return bit_and(buffer_read_i16(memory.data, addr), 0xFFFFFFFF)
|
return bit_or(buffer_read_i16(memory.data, addr), 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function load.i32_u16(memory, addr)
|
function load.i32_u16(memory, addr)
|
||||||
|
@ -20,6 +20,7 @@ fn do_runtime(lock: &mut dyn Write) -> Result<()> {
|
|||||||
let runtime = codegen_luau::RUNTIME;
|
let runtime = codegen_luau::RUNTIME;
|
||||||
let numeric = codegen_luau::NUMERIC;
|
let numeric = codegen_luau::NUMERIC;
|
||||||
|
|
||||||
|
writeln!(lock, "--!optimize 2")?;
|
||||||
writeln!(lock, "local Integer = (function()")?;
|
writeln!(lock, "local Integer = (function()")?;
|
||||||
writeln!(lock, "{numeric}")?;
|
writeln!(lock, "{numeric}")?;
|
||||||
writeln!(lock, "end)()")?;
|
writeln!(lock, "end)()")?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user