From d229ba6542aa009185b28530c55887d14c76b163 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 21 May 2017 18:50:24 +1000 Subject: shifts have different semantics to JS, use add luaV_shiftl --- src/lobject.js | 4 ++-- src/lvm.js | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/lobject.js b/src/lobject.js index d6ced0b..ec88e34 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -527,8 +527,8 @@ const intarith = function(L, op, v1, v2) { case defs.LUA_OPBAND: return (v1 & v2); case defs.LUA_OPBOR: return (v1 | v2); case defs.LUA_OPBXOR: return (v1 ^ v2); - case defs.LUA_OPSHL: return (v1 << v2); - case defs.LUA_OPSHR: return (v1 >>> v2)|0; + case defs.LUA_OPSHL: return lvm.luaV_shiftl(v1, v2); + case defs.LUA_OPSHR: return lvm.luaV_shiftl(v1, -v2); case defs.LUA_OPUNM: return (0 - v1)|0; case defs.LUA_OPBNOT: return (~0 ^ v1); default: assert(0); diff --git a/src/lvm.js b/src/lvm.js index 3d17966..300b080 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -352,7 +352,7 @@ const luaV_execute = function(L) { let numberop2 = tointeger(op2); if (numberop1 !== false && numberop2 !== false) { - L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (numberop1 << numberop2)); // TODO: luaV_shiftl ? + L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, luaV_shiftl(numberop1, numberop2)); } else { ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_SHL); } @@ -365,8 +365,7 @@ const luaV_execute = function(L) { let numberop2 = tointeger(op2); if (numberop1 !== false && numberop2 !== false) { - // >>> to have same overflow semantic as lua - L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (numberop1 >>> numberop2)|0); + L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, luaV_shiftl(numberop1, -numberop2)); } else { ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_SHR); } @@ -933,6 +932,19 @@ const luaV_objlen = function(L, ra, rb) { ltm.luaT_callTM(L, tm, rb, rb, ra, 1); }; +const NBITS = 32; + +const luaV_shiftl = function(x, y) { + if (y < 0) { /* shift right? */ + if (y <= -NBITS) return 0; + else return x >>> -y; + } + else { /* shift left */ + if (y >= NBITS) return 0; + else return x << y; + } +}; + const tostring = function(L, i) { let o = L.stack[i]; @@ -1107,6 +1119,7 @@ module.exports.luaV_lessequal = luaV_lessequal; module.exports.luaV_lessthan = luaV_lessthan; module.exports.luaV_objlen = luaV_objlen; module.exports.luaV_rawequalobj = luaV_rawequalobj; +module.exports.luaV_shiftl = luaV_shiftl; module.exports.luaV_tointeger = luaV_tointeger; module.exports.settable = settable; module.exports.tointeger = tointeger; -- cgit v1.2.3-54-g00ecf