aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaurnimator <quae@daurnimator.com>2017-05-21 18:50:24 +1000
committerdaurnimator <quae@daurnimator.com>2017-05-21 19:12:47 +1000
commitd229ba6542aa009185b28530c55887d14c76b163 (patch)
tree2ac878961644dfaab23850c803890b4b94aa54a4
parent02cb89ce61c58e0d9281a6fd163375399aaed40e (diff)
downloadfengari-d229ba6542aa009185b28530c55887d14c76b163.tar.gz
fengari-d229ba6542aa009185b28530c55887d14c76b163.tar.bz2
fengari-d229ba6542aa009185b28530c55887d14c76b163.zip
shifts have different semantics to JS, use add luaV_shiftl
-rw-r--r--src/lobject.js4
-rw-r--r--src/lvm.js19
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;