forked from Hyperion/HyperionOS
138 lines
2.7 KiB
Plaintext
138 lines
2.7 KiB
Plaintext
--:Minify:--
|
|
|
|
local bit32 = {}
|
|
|
|
local MOD32 = 2^32
|
|
local MOD31 = 2^31
|
|
|
|
local function norm(x)
|
|
return x % MOD32
|
|
end
|
|
|
|
-- Convert number to bit table
|
|
local function tobits(x)
|
|
x = norm(x)
|
|
local t = {}
|
|
for i = 0, 31 do
|
|
local b = x % 2
|
|
t[i] = b
|
|
x = (x - b) / 2
|
|
end
|
|
return t
|
|
end
|
|
|
|
-- Convert bit table to number
|
|
local function frombits(t)
|
|
local x = 0
|
|
local p = 1
|
|
for i = 0, 31 do
|
|
if t[i] == 1 then
|
|
x = x + p
|
|
end
|
|
p = p * 2
|
|
end
|
|
return norm(x)
|
|
end
|
|
|
|
-- ===== Logical ops =====
|
|
|
|
function bit32.band(...)
|
|
local args = {...}
|
|
if #args == 0 then return 0xFFFFFFFF end
|
|
local bits = tobits(args[1])
|
|
for i = 2, #args do
|
|
local b = tobits(args[i])
|
|
for j = 0, 31 do
|
|
bits[j] = (bits[j] == 1 and b[j] == 1) and 1 or 0
|
|
end
|
|
end
|
|
return frombits(bits)
|
|
end
|
|
|
|
function bit32.bor(...)
|
|
local args = {...}
|
|
if #args == 0 then return 0 end
|
|
local bits = tobits(args[1])
|
|
for i = 2, #args do
|
|
local b = tobits(args[i])
|
|
for j = 0, 31 do
|
|
bits[j] = (bits[j] == 1 or b[j] == 1) and 1 or 0
|
|
end
|
|
end
|
|
return frombits(bits)
|
|
end
|
|
|
|
function bit32.bxor(...)
|
|
local args = {...}
|
|
if #args == 0 then return 0 end
|
|
local bits = tobits(args[1])
|
|
for i = 2, #args do
|
|
local b = tobits(args[i])
|
|
for j = 0, 31 do
|
|
bits[j] = (bits[j] ~= b[j]) and 1 or 0
|
|
end
|
|
end
|
|
return frombits(bits)
|
|
end
|
|
|
|
function bit32.bnot(x)
|
|
local bits = tobits(x)
|
|
for i = 0, 31 do
|
|
bits[i] = bits[i] == 1 and 0 or 1
|
|
end
|
|
return frombits(bits)
|
|
end
|
|
|
|
-- ===== Shifts =====
|
|
|
|
function bit32.lshift(x, n)
|
|
return norm(norm(x) * 2^n)
|
|
end
|
|
|
|
function bit32.rshift(x, n)
|
|
return math.floor(norm(x) / 2^n)
|
|
end
|
|
|
|
function bit32.arshift(x, n)
|
|
x = norm(x)
|
|
if x >= MOD31 then
|
|
return math.floor((x - MOD32) / 2^n)
|
|
else
|
|
return math.floor(x / 2^n)
|
|
end
|
|
end
|
|
|
|
-- ===== Rotates =====
|
|
|
|
function bit32.lrotate(x, n)
|
|
n = n % 32
|
|
x = norm(x)
|
|
local left = (x * 2^n) % MOD32
|
|
local right = math.floor(x / 2^(32 - n))
|
|
return norm(left + right)
|
|
end
|
|
|
|
function bit32.rrotate(x, n)
|
|
n = n % 32
|
|
x = norm(x)
|
|
local right = math.floor(x / 2^n)
|
|
local left = (x * 2^(32 - n)) % MOD32
|
|
return norm(left + right)
|
|
end
|
|
|
|
-- ===== Bit fields =====
|
|
|
|
function bit32.extract(x, field, width)
|
|
width = width or 1
|
|
return bit32.band(bit32.rshift(x, field), 2^width - 1)
|
|
end
|
|
|
|
function bit32.replace(x, v, field, width)
|
|
width = width or 1
|
|
local mask = bit32.lshift(2^width - 1, field)
|
|
x = bit32.band(x, bit32.bnot(mask))
|
|
return bit32.bor(x, bit32.lshift(v, field))
|
|
end
|
|
|
|
return bit32
|