aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js26
-rw-r--r--src/parseTools.js2
-rw-r--r--src/runtime.js20
3 files changed, 29 insertions, 19 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index d0229612..14677edc 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -387,13 +387,6 @@ function analyzer(data, sidePass) {
case 'mathop': {
var toAdd = [];
var sourceBits = getBits(value.param1.type);
- var sourceElements;
- if (sourceBits <= 32) {
- // The input is a legal type
- sourceElements = [{ ident: value.param1.ident, bits: sourceBits }];
- } else {
- sourceElements = getLegalVars(value.param1.ident, sourceBits);
- }
// All mathops can be parametrized by how many shifts we do, and how big the source is
var shifts = 0;
var targetBits = sourceBits;
@@ -428,6 +421,7 @@ function analyzer(data, sidePass) {
break;
}
case 'select': {
+ sourceBits = targetBits = getBits(value.param2.type);
var otherElementsA = getLegalVars(value.param2.ident, sourceBits);
var otherElementsB = getLegalVars(value.param3.ident, sourceBits);
processor = function(result, j) {
@@ -464,7 +458,23 @@ function analyzer(data, sidePass) {
default: throw 'Invalid mathop for legalization: ' + [value.op, item.lineNum, dump(item)];
}
// Do the legalization
- assert(isNumber(shifts), 'TODO: handle nonconstant shifts');
+ var sourceElements;
+ if (sourceBits <= 32) {
+ // The input is a legal type
+ sourceElements = [{ ident: value.param1.ident, bits: sourceBits }];
+ } else {
+ sourceElements = getLegalVars(value.param1.ident, sourceBits);
+ }
+ if (!isNumber(shifts)) {
+ // We can't statically legalize this, do the operation at runtime TODO: optimize
+ assert(sourceBits == 64, 'TODO: handle nonconstant shifts on != 64 bits');
+ value.intertype = 'value';
+ value.ident = 'Runtime.bitshift64(' + sourceElements[0].ident + ', ' +
+ sourceElements[1].ident + ',"' + value.op + '",' + value.param2.ident + '$0);' +
+ 'var ' + value.assignTo + '$0 = ' + value.assignTo + '[0], ' + value.assignTo + '$1 = ' + value.assignTo + '[1];';
+ i++;
+ continue;
+ }
var targetElements = getLegalVars(item.assignTo, targetBits);
var sign = shifts >= 0 ? 1 : -1;
var shiftOp = shifts >= 0 ? 'shl' : 'lshr';
diff --git a/src/parseTools.js b/src/parseTools.js
index e1072308..70a6ba5a 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1600,7 +1600,7 @@ function processMathop(item) {
case 'ashr':
case 'lshr': {
if (!isNumber(ident2)) {
- return 'Runtime.bitshift64(' + ident1 + ',"' + op + '",' + stripCorrections(ident2) + '[0]|0)';
+ return 'Runtime.bitshift64(' + ident1 + '[0], ' + ident1 + '[1],"' + op + '",' + stripCorrections(ident2) + '[0]|0)';
}
bits = parseInt(ident2);
var ander = Math.pow(2, bits)-1;
diff --git a/src/runtime.js b/src/runtime.js
index 803407c6..852d08d8 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -123,34 +123,34 @@ var Runtime = {
FLOAT_TYPES: set('float', 'double'),
// Mirrors processMathop's treatment of constants (which we optimize directly)
- bitshift64: function(value, op, bits) {
+ bitshift64: function(low, high, 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))];
+ return [low << bits, (high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits))];
case 'ashr':
- return [(((value[0] >>> bits ) | ((value[1]&ander) << (32 - bits))) >> 0) >>> 0, (value[1] >> bits) >>> 0];
+ return [(((low >>> bits ) | ((high&ander) << (32 - bits))) >> 0) >>> 0, (high >> bits) >>> 0];
case 'lshr':
- return [((value[0] >>> bits) | ((value[1]&ander) << (32 - bits))) >>> 0, value[1] >>> bits];
+ return [((low >>> bits) | ((high&ander) << (32 - bits))) >>> 0, high >>> bits];
}
} else if (bits == 32) {
switch (op) {
case 'shl':
- return [0, value[0]];
+ return [0, low];
case 'ashr':
- return [value[1], (value[1]|0) < 0 ? ander : 0];
+ return [high, (high|0) < 0 ? ander : 0];
case 'lshr':
- return [value[1], 0];
+ return [high, 0];
}
} else { // bits > 32
switch (op) {
case 'shl':
- return [0, value[0] << (bits - 32)];
+ return [0, low << (bits - 32)];
case 'ashr':
- return [(value[1] >> (bits - 32)) >>> 0, (value[1]|0) < 0 ? ander : 0];
+ return [(high >> (bits - 32)) >>> 0, (high|0) < 0 ? ander : 0];
case 'lshr':
- return [value[1] >>> (bits - 32) , 0];
+ return [high >>> (bits - 32) , 0];
}
}
abort('unknown bitshift64 op: ' + [value, op, bits]);