From 5ebc409cc717102d312df3bebabefd827e60039a Mon Sep 17 00:00:00 2001 From: Firebolt <24422634+Fireboltofdeath@users.noreply.github.com> Date: Wed, 20 Oct 2021 19:19:09 -0400 Subject: [PATCH 1/4] Unaligned R/W --- runtime/luau.lua | 58 +++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/runtime/luau.lua b/runtime/luau.lua index 89847b6..2feee77 100644 --- a/runtime/luau.lua +++ b/runtime/luau.lua @@ -38,6 +38,17 @@ local function rip_u64(x) return math.floor(x / 0x100000000), x % 0x100000000 en local function merge_u64(hi, lo) return hi * 0x100000000 + lo end +local function load_byte(memory, addr) + local offset = addr % 4 + return bit32.rshift(memory.data[(addr - offset) / 4] or 0, 8 * offset) +end + +local function store_byte(memory, addr, value) + local offset = addr % 4; + local base = (addr - offset) / 4; + memory.data[base] = bit32.bor(memory.data[base] or 0, bit32.lshift(value, 8 * offset)); +end + -- Runtime functions local function grow_page_num(memory, num) local old = memory.min @@ -97,9 +108,18 @@ extend.i32_u64 = no_op function wrap.i64_i32(i) return i % 2 ^ 32 end function load.i32(memory, addr) - if addr % 4 ~= 0 then error('unaligned read') end - - return memory.data[addr / 4] or 0 + if addr % 4 == 0 then + -- aligned read + return memory.data[addr / 4] or 0 + else + -- unaligned read + return bit32.bor( + load_byte(memory, addr), + bit32.lshift(load_byte(memory, addr + 1), 8), + bit32.lshift(load_byte(memory, addr + 2), 16), + bit32.lshift(load_byte(memory, addr + 3), 24) + ) + end end function load.i32_u8(memory, addr) @@ -109,36 +129,34 @@ function load.i32_u8(memory, addr) end function load.i64(memory, addr) - if addr % 4 ~= 0 then error('unaligned read') end - - local hi = memory.data[addr / 4 + 1] or 0 - local lo = memory.data[addr / 4] or 0 + local hi = load.i32(memory, addr) + local lo = load.i32(memory, addr + 4) return merge_u64(hi, lo) end function store.i32(memory, addr, value) - if addr % 4 ~= 0 then error('unaligned write') end - - memory.data[addr / 4] = value + if addr % 4 == 0 then + -- aligned write + memory.data[addr / 4] = value + else + -- unaligned write + store_byte(memory, addr, value) + store_byte(memory, addr + 1, bit32.rshift(value, 8)) + store_byte(memory, addr + 2, bit32.rshift(value, 16)) + store_byte(memory, addr + 3, bit32.rshift(value, 24)) + end end function store.i32_n8(memory, addr, value) - if addr % 4 ~= 0 then error('unaligned write') end - - local old = bit32.band(memory.data[addr / 4] or 0, 0xFFFFFF00) - local new = bit32.band(value, 0xFF) - - memory.data[addr / 4] = bit32.bor(old, new) + store.i32(memory, addr, bit32.band(value, 0xFF)) end function store.i64(memory, addr, value) - if addr % 4 ~= 0 then error('unaligned write') end - local hi, lo = rip_u64(value) - memory.data[addr / 4] = lo - memory.data[addr / 4 + 1] = hi + store.i32(memory, addr, lo) + store.i32(memory, addr + 4, hi) end return { From f7c8c44b6ad6913f5d37266ae0a30697687cd9e5 Mon Sep 17 00:00:00 2001 From: Firebolt <24422634+Fireboltofdeath@users.noreply.github.com> Date: Wed, 20 Oct 2021 19:21:32 -0400 Subject: [PATCH 2/4] Remove semicolons --- runtime/luau.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/luau.lua b/runtime/luau.lua index 2feee77..3a5c18d 100644 --- a/runtime/luau.lua +++ b/runtime/luau.lua @@ -44,9 +44,9 @@ local function load_byte(memory, addr) end local function store_byte(memory, addr, value) - local offset = addr % 4; - local base = (addr - offset) / 4; - memory.data[base] = bit32.bor(memory.data[base] or 0, bit32.lshift(value, 8 * offset)); + local offset = addr % 4 + local base = (addr - offset) / 4 + memory.data[base] = bit32.bor(memory.data[base] or 0, bit32.lshift(value, 8 * offset)) end -- Runtime functions From d30462867512172530001bf5793232eb2cc40de3 Mon Sep 17 00:00:00 2001 From: Firebolt <24422634+Fireboltofdeath@users.noreply.github.com> Date: Wed, 20 Oct 2021 20:02:41 -0400 Subject: [PATCH 3/4] Reset bits when stored --- runtime/luau.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/runtime/luau.lua b/runtime/luau.lua index 3a5c18d..bab1e50 100644 --- a/runtime/luau.lua +++ b/runtime/luau.lua @@ -38,6 +38,11 @@ local function rip_u64(x) return math.floor(x / 0x100000000), x % 0x100000000 en local function merge_u64(hi, lo) return hi * 0x100000000 + lo end +local function clear_byte(value, offset) + offset *= 8; + return bit32.band(value, bit32.bnot(bit32.lshift(0xFF, offset))); +end + local function load_byte(memory, addr) local offset = addr % 4 return bit32.rshift(memory.data[(addr - offset) / 4] or 0, 8 * offset) @@ -46,7 +51,8 @@ end local function store_byte(memory, addr, value) local offset = addr % 4 local base = (addr - offset) / 4 - memory.data[base] = bit32.bor(memory.data[base] or 0, bit32.lshift(value, 8 * offset)) + local old = clear_byte(memory.data[base] or 0, offset); + memory.data[base] = bit32.bor(old, bit32.lshift(value, 8 * offset)) end -- Runtime functions From 76511d9e20d7fcef602134f525b658c0f761b1e8 Mon Sep 17 00:00:00 2001 From: Firebolt <24422634+Fireboltofdeath@users.noreply.github.com> Date: Wed, 20 Oct 2021 20:11:25 -0400 Subject: [PATCH 4/4] fix i32_n8 --- runtime/luau.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runtime/luau.lua b/runtime/luau.lua index bab1e50..8a9a8fc 100644 --- a/runtime/luau.lua +++ b/runtime/luau.lua @@ -39,8 +39,8 @@ local function rip_u64(x) return math.floor(x / 0x100000000), x % 0x100000000 en local function merge_u64(hi, lo) return hi * 0x100000000 + lo end local function clear_byte(value, offset) - offset *= 8; - return bit32.band(value, bit32.bnot(bit32.lshift(0xFF, offset))); + offset *= 8 + return bit32.band(value, bit32.bnot(bit32.lshift(0xFF, offset))) end local function load_byte(memory, addr) @@ -51,7 +51,7 @@ end local function store_byte(memory, addr, value) local offset = addr % 4 local base = (addr - offset) / 4 - local old = clear_byte(memory.data[base] or 0, offset); + local old = clear_byte(memory.data[base] or 0, offset) memory.data[base] = bit32.bor(old, bit32.lshift(value, 8 * offset)) end @@ -155,7 +155,7 @@ function store.i32(memory, addr, value) end function store.i32_n8(memory, addr, value) - store.i32(memory, addr, bit32.band(value, 0xFF)) + store_byte(memory, addr, bit32.band(value, 0xFF)) end function store.i64(memory, addr, value)