diff options
author | daurnimator <quae@daurnimator.com> | 2018-01-07 05:00:04 +1100 |
---|---|---|
committer | daurnimator <quae@daurnimator.com> | 2018-01-07 05:02:26 +1100 |
commit | 2968965c7e531ec0121190d5a5d0e66e0774306b (patch) | |
tree | 7f4a40c8c0b340a745975e7ee5618f6f4a38624d | |
parent | e0089c7adee8e313f7ff7b5d84ff0ea892c05287 (diff) | |
download | fengari-2968965c7e531ec0121190d5a5d0e66e0774306b.tar.gz fengari-2968965c7e531ec0121190d5a5d0e66e0774306b.tar.bz2 fengari-2968965c7e531ec0121190d5a5d0e66e0774306b.zip |
src/lvm.js: Add Math.imul shim; export new luaV_imul function
-rw-r--r-- | src/lobject.js | 2 | ||||
-rw-r--r-- | src/lvm.js | 16 |
2 files changed, 16 insertions, 2 deletions
diff --git a/src/lobject.js b/src/lobject.js index 641473e..ec4a9b3 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -667,7 +667,7 @@ const intarith = function(L, op, v1, v2) { switch (op) { case defs.LUA_OPADD: return (v1 + v2)|0; case defs.LUA_OPSUB: return (v1 - v2)|0; - case defs.LUA_OPMUL: return Math.imul(v1, v2); + case defs.LUA_OPMUL: return lvm.luaV_imul(v1, v2); case defs.LUA_OPMOD: return lvm.luaV_mod(L, v1, v2); case defs.LUA_OPIDIV: return lvm.luaV_div(L, v1, v2); case defs.LUA_OPBAND: return (v1 & v2); @@ -229,7 +229,7 @@ const luaV_execute = function(L) { let numberop1, numberop2; if (op1.ttisinteger() && op2.ttisinteger()) { - L.stack[ra].setivalue(Math.imul(op1.value, op2.value)); + L.stack[ra].setivalue(luaV_imul(op1.value, op2.value)); } else if ((numberop1 = tonumber(op1)) !== false && (numberop2 = tonumber(op2)) !== false) { L.stack[ra].setfltvalue(numberop1 * numberop2); } else { @@ -847,6 +847,19 @@ const luaV_objlen = function(L, ra, rb) { ltm.luaT_callTM(L, tm, rb, rb, ra, 1); }; +/* Shim taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul */ +const luaV_imul = Math.imul || function(a, b) { + let aHi = (a >>> 16) & 0xffff; + let aLo = a & 0xffff; + let bHi = (b >>> 16) & 0xffff; + let bLo = b & 0xffff; + /* + ** the shift by 0 fixes the sign on the high part + ** the final |0 converts the unsigned value into a signed value + */ + return ((aLo * bLo) + (((aHi * bLo + aLo * bHi) << 16) >>> 0) | 0); +}; + const luaV_div = function(L, m, n) { if (n === 0) ldebug.luaG_runerror(L, defs.to_luastring("attempt to divide by zero")); @@ -1059,6 +1072,7 @@ module.exports.luaV_div = luaV_div; module.exports.luaV_equalobj = luaV_equalobj; module.exports.luaV_execute = luaV_execute; module.exports.luaV_finishOp = luaV_finishOp; +module.exports.luaV_imul = luaV_imul; module.exports.luaV_lessequal = luaV_lessequal; module.exports.luaV_lessthan = luaV_lessthan; module.exports.luaV_mod = luaV_mod; |