diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-02-01 16:54:44 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-02-01 16:54:44 -0800 |
commit | f42fd56f4d3451a9ef0cb83248258749e33d22e3 (patch) | |
tree | 99b246e4ee893dcd0c835b9744fe498fe231ebda /src | |
parent | 4971364806bea54262ea5169e2af6c6222983964 (diff) |
re-enable support for non-fixed i64 bitshifts
Diffstat (limited to 'src')
-rw-r--r-- | src/parseTools.js | 37 | ||||
-rw-r--r-- | src/runtime.js | 35 |
2 files changed, 60 insertions, 12 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index a53ff1c0..815d1a1b 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1616,7 +1616,9 @@ function processMathop(item) { case 'shl': case 'ashr': case 'lshr': { - assert(isNumber(ident2)); + if (!isNumber(ident2)) { + return 'Runtime.bitshift64(' + ident1 + ',"' + op + '",' + stripCorrections(ident2) + '[0]|0)'; + } bits = parseInt(ident2); var ander = Math.pow(2, bits)-1; if (bits < 32) { @@ -1892,17 +1894,28 @@ function finalizeBlockAddress(param) { function stripCorrections(param) { var m; - if (m = /^\((.*)\)$/.exec(param)) { - param = m[1]; - } - if (m = /^\((\w+)\)&\d+$/.exec(param)) { - param = m[1]; - } - if (m = /^\((\w+)\)\|0$/.exec(param)) { - param = m[1]; - } - if (m = /CHECK_OVERFLOW\(([^,)]*),.*/.exec(param)) { - param = m[1]; + while (true) { + if (m = /^\((.*)\)$/.exec(param)) { + param = m[1]; + continue; + } + if (m = /^\(([$_\w]+)\)&\d+$/.exec(param)) { + param = m[1]; + continue; + } + if (m = /^\(([$_\w()]+)\)\|0$/.exec(param)) { + param = m[1]; + continue; + } + if (m = /^\(([$_\w()]+)\)\>>>0$/.exec(param)) { + param = m[1]; + continue; + } + if (m = /CHECK_OVERFLOW\(([^,)]*),.*/.exec(param)) { + param = m[1]; + continue; + } + break; } return param; } diff --git a/src/runtime.js b/src/runtime.js index 8e5238da..39aed12c 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -118,6 +118,41 @@ var Runtime = { INT_TYPES: set('i1', 'i8', 'i16', 'i32', 'i64'), FLOAT_TYPES: set('float', 'double'), + // Mirrors processMathop's treatment of constants (which we optimize directly) + bitshift64: function(value, op, bits) { + var ander = Math.pow(2, bits)-1; + if (bits < 32) { + switch (op) { + case 'shl': + return [value[0] << bits, (value[1] << bits) | ((value[0]&(ander << (32 - bits))) >>> (32 - bits))]; + case 'ashr': + return [(((value[0] >>> bits ) | ((value[1]&ander) << (32 - bits))) >> 0) >>> 0, (value[1] >> bits) >>> 0]; + case 'lshr': + return [((value[0] >>> bits) | ((value[1]&ander) << (32 - bits))) >>> 0, value[1] >>> bits]; + } + } else if (bits == 32) { + switch (op) { + case 'shl': + return [0, value[0]]; + case 'ashr': + return [value[1], (value[1]|0) < 0 ? ander : 0]; + case 'lshr': + return [value[1], 0]; + } + } else { // bits > 32 + switch (op) { + case 'shl': + return [0, value[0] << (bits - 32)]; + case 'ashr': + return [(value[1] >> (bits - 32)) >>> 0, (value[1]|0) < 0 ? ander : 0]; + case 'lshr': + return [value[1] >>> (bits - 32) , 0]; + } + } + abort('unknown bitshift64 op: ' + [value, op, bits]); + }, + + // Imprecise bitops utilities or64: function(x, y) { var l = (x | 0) | (y | 0); var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296; |