summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm2asm.h277
-rw-r--r--test/float-ops.2asm.js294
-rw-r--r--test/wasm2asm/float-ops.wast84
3 files changed, 554 insertions, 101 deletions
diff --git a/src/wasm2asm.h b/src/wasm2asm.h
index fd7a03234..346c1c677 100644
--- a/src/wasm2asm.h
+++ b/src/wasm2asm.h
@@ -1400,6 +1400,12 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
visit(curr->value, EXPRESSION_RESULT)
);
break;
+ case PromoteFloat32:
+ return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
+ ASM_DOUBLE);
+ case DemoteFloat64:
+ return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
+ ASM_FLOAT);
// TODO: more complex unary conversions
default:
std::cerr << "Unhandled unary float operator: " << curr
@@ -1438,112 +1444,181 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
Ref left = visit(curr->left, EXPRESSION_RESULT);
Ref right = visit(curr->right, EXPRESSION_RESULT);
Ref ret;
- switch (curr->op) {
- case AddInt32:
- ret = ValueBuilder::makeBinary(left, PLUS, right);
- break;
- case SubInt32:
- ret = ValueBuilder::makeBinary(left, MINUS, right);
- break;
- case MulInt32: {
- if (curr->type == i32) {
- // TODO: when one operand is a small int, emit a multiply
- return ValueBuilder::makeCall(MATH_IMUL, left, right);
- } else {
- return ValueBuilder::makeBinary(left, MUL, right);
+ switch (curr->type) {
+ case i32: {
+ switch (curr->op) {
+ case AddInt32:
+ ret = ValueBuilder::makeBinary(left, PLUS, right);
+ break;
+ case SubInt32:
+ ret = ValueBuilder::makeBinary(left, MINUS, right);
+ break;
+ case MulInt32: {
+ if (curr->type == i32) {
+ // TODO: when one operand is a small int, emit a multiply
+ return ValueBuilder::makeCall(MATH_IMUL, left, right);
+ } else {
+ return ValueBuilder::makeBinary(left, MUL, right);
+ }
+ }
+ case DivSInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV,
+ makeSigning(right, ASM_SIGNED));
+ break;
+ case DivUInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV,
+ makeSigning(right, ASM_UNSIGNED));
+ break;
+ case RemSInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD,
+ makeSigning(right, ASM_SIGNED));
+ break;
+ case RemUInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD,
+ makeSigning(right, ASM_UNSIGNED));
+ break;
+ case AndInt32:
+ ret = ValueBuilder::makeBinary(left, AND, right);
+ break;
+ case OrInt32:
+ ret = ValueBuilder::makeBinary(left, OR, right);
+ break;
+ case XorInt32:
+ ret = ValueBuilder::makeBinary(left, XOR, right);
+ break;
+ case ShlInt32:
+ ret = ValueBuilder::makeBinary(left, LSHIFT, right);
+ break;
+ case ShrUInt32:
+ ret = ValueBuilder::makeBinary(left, TRSHIFT, right);
+ break;
+ case ShrSInt32:
+ ret = ValueBuilder::makeBinary(left, RSHIFT, right);
+ break;
+ case EqInt32: {
+ // TODO: check if this condition is still valid/necessary
+ if (curr->left->type == i32) {
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ,
+ makeSigning(right, ASM_SIGNED));
+ } else {
+ return ValueBuilder::makeBinary(left, EQ, right);
+ }
+ }
+ case NeInt32: {
+ if (curr->left->type == i32) {
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE,
+ makeSigning(right, ASM_SIGNED));
+ } else {
+ return ValueBuilder::makeBinary(left, NE, right);
+ }
+ }
+ case LtSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT,
+ makeSigning(right, ASM_SIGNED));
+ case LtUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT,
+ makeSigning(right, ASM_UNSIGNED));
+ case LeSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE,
+ makeSigning(right, ASM_SIGNED));
+ case LeUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE,
+ makeSigning(right, ASM_UNSIGNED));
+ case GtSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT,
+ makeSigning(right, ASM_SIGNED));
+ case GtUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT,
+ makeSigning(right, ASM_UNSIGNED));
+ case GeSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE,
+ makeSigning(right, ASM_SIGNED));
+ case GeUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE,
+ makeSigning(right, ASM_UNSIGNED));
+ case RotLInt32:
+ return makeSigning(ValueBuilder::makeCall(WASM_ROTL32, left, right),
+ ASM_SIGNED);
+ case RotRInt32:
+ return makeSigning(ValueBuilder::makeCall(WASM_ROTR32, left, right),
+ ASM_SIGNED);
+ case EqFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, EQ, right),
+ ASM_FLOAT);
+ case EqFloat64:
+ return ValueBuilder::makeBinary(left, EQ, right);
+ case NeFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, NE, right),
+ ASM_FLOAT);
+ case NeFloat64:
+ return ValueBuilder::makeBinary(left, NE, right);
+ case GeFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, GE, right),
+ ASM_FLOAT);
+ case GeFloat64:
+ return ValueBuilder::makeBinary(left, GE, right);
+ case GtFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, GT, right),
+ ASM_FLOAT);
+ case GtFloat64:
+ return ValueBuilder::makeBinary(left, GT, right);
+ case LeFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, LE, right),
+ ASM_FLOAT);
+ case LeFloat64:
+ return ValueBuilder::makeBinary(left, LE, right);
+ case LtFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, LT, right),
+ ASM_FLOAT);
+ case LtFloat64:
+ return ValueBuilder::makeBinary(left, LT, right);
+ default: {
+ std::cerr << "Unhandled i32 binary operator: " << curr << std::endl;
+ abort();
+ }
}
- }
- case DivSInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV,
- makeSigning(right, ASM_SIGNED));
- break;
- case DivUInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV,
- makeSigning(right, ASM_UNSIGNED));
- break;
- case RemSInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD,
- makeSigning(right, ASM_SIGNED));
- break;
- case RemUInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD,
- makeSigning(right, ASM_UNSIGNED));
- break;
- case AndInt32:
- ret = ValueBuilder::makeBinary(left, AND, right);
- break;
- case OrInt32:
- ret = ValueBuilder::makeBinary(left, OR, right);
- break;
- case XorInt32:
- ret = ValueBuilder::makeBinary(left, XOR, right);
- break;
- case ShlInt32:
- ret = ValueBuilder::makeBinary(left, LSHIFT, right);
break;
- case ShrUInt32:
- ret = ValueBuilder::makeBinary(left, TRSHIFT, right);
- break;
- case ShrSInt32:
- ret = ValueBuilder::makeBinary(left, RSHIFT, right);
- break;
- case MinFloat32:
- ret = ValueBuilder::makeCall(MATH_MIN, left, right);
- break;
- case MaxFloat32:
- ret = ValueBuilder::makeCall(MATH_MAX, left, right);
- break;
- case EqInt32: {
- // TODO: check if this condition is still valid/necessary
- if (curr->left->type == i32) {
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ,
- makeSigning(right, ASM_SIGNED));
- } else {
- return ValueBuilder::makeBinary(left, EQ, right);
- }
}
- case NeInt32: {
- if (curr->left->type == i32) {
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE,
- makeSigning(right, ASM_SIGNED));
- } else {
- return ValueBuilder::makeBinary(left, NE, right);
+ case f32:
+ case f64:
+ switch (curr->op) {
+ case AddFloat32:
+ case AddFloat64:
+ ret = ValueBuilder::makeBinary(left, PLUS, right);
+ break;
+ case SubFloat32:
+ case SubFloat64:
+ ret = ValueBuilder::makeBinary(left, MINUS, right);
+ break;
+ case MulFloat32:
+ case MulFloat64:
+ ret = ValueBuilder::makeBinary(left, MUL, right);
+ break;
+ case DivFloat32:
+ case DivFloat64:
+ ret = ValueBuilder::makeBinary(left, DIV, right);
+ break;
+ case MinFloat32:
+ case MinFloat64:
+ ret = ValueBuilder::makeCall(MATH_MIN, left, right);
+ break;
+ case MaxFloat32:
+ case MaxFloat64:
+ ret = ValueBuilder::makeCall(MATH_MAX, left, right);
+ break;
+ case CopySignFloat32:
+ case CopySignFloat64:
+ default:
+ std::cerr << "Unhandled binary float operator: " << curr << std::endl;
+ abort();
}
- }
- case LtSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT,
- makeSigning(right, ASM_SIGNED));
- case LtUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT,
- makeSigning(right, ASM_UNSIGNED));
- case LeSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE,
- makeSigning(right, ASM_SIGNED));
- case LeUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE,
- makeSigning(right, ASM_UNSIGNED));
- case GtSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT,
- makeSigning(right, ASM_SIGNED));
- case GtUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT,
- makeSigning(right, ASM_UNSIGNED));
- case GeSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE,
- makeSigning(right, ASM_SIGNED));
- case GeUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE,
- makeSigning(right, ASM_UNSIGNED));
- case RotLInt32:
- return makeSigning(ValueBuilder::makeCall(WASM_ROTL32, left, right),
- ASM_SIGNED);
- case RotRInt32:
- return makeSigning(ValueBuilder::makeCall(WASM_ROTR32, left, right),
- ASM_SIGNED);
- default: {
- std::cerr << "Unhandled binary operator: " << curr << std::endl;
+ if (curr->type == f32) {
+ return makeAsmCoercion(ret, ASM_FLOAT);
+ }
+ return ret;
+ default:
+ std::cerr << "Unhandled type in binary: " << curr << std::endl;
abort();
- }
}
return makeAsmCoercion(ret, wasmToAsmType(curr->type));
}
diff --git a/test/float-ops.2asm.js b/test/float-ops.2asm.js
new file mode 100644
index 000000000..5cad310f9
--- /dev/null
+++ b/test/float-ops.2asm.js
@@ -0,0 +1,294 @@
+function asmFunc(global, env, buffer) {
+ "use asm";
+ var HEAP8 = new global.Int8Array(buffer);
+ var HEAP16 = new global.Int16Array(buffer);
+ var HEAP32 = new global.Int32Array(buffer);
+ var HEAPU8 = new global.Uint8Array(buffer);
+ var HEAPU16 = new global.Uint16Array(buffer);
+ var HEAPU32 = new global.Uint32Array(buffer);
+ var HEAPF32 = new global.Float32Array(buffer);
+ var HEAPF64 = new global.Float64Array(buffer);
+ var Math_imul = global.Math.imul;
+ var Math_fround = global.Math.fround;
+ var Math_abs = global.Math.abs;
+ var Math_clz32 = global.Math.clz32;
+ function dummy() {
+
+ }
+
+ function $$1($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = Math_fround(0), wasm2asm_f32$0 = Math_fround(0);
+ return Math_fround(Math_fround($$0 + $$1));
+ return Math_fround(wasm2asm_f32$0);
+ }
+
+ function $$2($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = Math_fround(0), wasm2asm_f32$0 = Math_fround(0);
+ return Math_fround(Math_fround($$0 - $$1));
+ return Math_fround(wasm2asm_f32$0);
+ }
+
+ function $$3($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = Math_fround(0), wasm2asm_f32$0 = Math_fround(0);
+ return Math_fround(Math_fround($$0 * $$1));
+ return Math_fround(wasm2asm_f32$0);
+ }
+
+ function $$4($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = Math_fround(0), wasm2asm_f32$0 = Math_fround(0);
+ return Math_fround(Math_fround($$0 / $$1));
+ return Math_fround(wasm2asm_f32$0);
+ }
+
+ function $$5($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0.0, wasm2asm_f64$0 = 0.0;
+ return +($$0 + $$1);
+ return +wasm2asm_f64$0;
+ }
+
+ function $$6($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0.0, wasm2asm_f64$0 = 0.0;
+ return +($$0 - $$1);
+ return +wasm2asm_f64$0;
+ }
+
+ function $$7($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0.0, wasm2asm_f64$0 = 0.0;
+ return +($$0 * $$1);
+ return +wasm2asm_f64$0;
+ }
+
+ function $$8($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0.0, wasm2asm_f64$0 = 0.0;
+ return +($$0 / $$1);
+ return +wasm2asm_f64$0;
+ }
+
+ function $$9($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = 0, wasm2asm_i32$0 = 0;
+ return Math_fround($$0 == $$1) | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$10($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = 0, wasm2asm_i32$0 = 0;
+ return Math_fround($$0 != $$1) | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$11($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = 0, wasm2asm_i32$0 = 0;
+ return Math_fround($$0 >= $$1) | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$12($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = 0, wasm2asm_i32$0 = 0;
+ return Math_fround($$0 > $$1) | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$13($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = 0, wasm2asm_i32$0 = 0;
+ return Math_fround($$0 <= $$1) | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$14($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = 0, wasm2asm_i32$0 = 0;
+ return Math_fround($$0 < $$1) | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$15($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0, wasm2asm_i32$0 = 0;
+ return $$0 == $$1 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$16($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0, wasm2asm_i32$0 = 0;
+ return $$0 != $$1 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$17($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0, wasm2asm_i32$0 = 0;
+ return $$0 >= $$1 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$18($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0, wasm2asm_i32$0 = 0;
+ return $$0 > $$1 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$19($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0, wasm2asm_i32$0 = 0;
+ return $$0 <= $$1 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$20($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0, wasm2asm_i32$0 = 0;
+ return $$0 < $$1 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function $$21($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = Math_fround(0), wasm2asm_f32$0 = Math_fround(0);
+ return Math_fround(Math_fround(Math_min($$0, $$1)));
+ return Math_fround(wasm2asm_f32$0);
+ }
+
+ function $$22($$0, $$1) {
+ $$0 = Math_fround($$0);
+ $$1 = Math_fround($$1);
+ var $$2 = Math_fround(0), $$3 = Math_fround(0), $$4 = Math_fround(0), wasm2asm_f32$0 = Math_fround(0);
+ return Math_fround(Math_fround(Math_max($$0, $$1)));
+ return Math_fround(wasm2asm_f32$0);
+ }
+
+ function $$23($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0.0, wasm2asm_f64$0 = 0.0;
+ return +Math_min($$0, $$1);
+ return +wasm2asm_f64$0;
+ }
+
+ function $$24($$0, $$1) {
+ $$0 = +$$0;
+ $$1 = +$$1;
+ var $$2 = 0.0, $$3 = 0.0, $$4 = 0.0, wasm2asm_f64$0 = 0.0;
+ return +Math_max($$0, $$1);
+ return +wasm2asm_f64$0;
+ }
+
+ function $$25($$0) {
+ $$0 = Math_fround($$0);
+ var $$1 = Math_fround(0), $$2 = 0.0, wasm2asm_f64$0 = 0.0;
+ return +(+$$0);
+ return +wasm2asm_f64$0;
+ }
+
+ function $$26($$0) {
+ $$0 = +$$0;
+ var $$1 = 0.0, $$2 = Math_fround(0), wasm2asm_f32$0 = Math_fround(0);
+ return Math_fround(Math_fround($$0));
+ return Math_fround(wasm2asm_f32$0);
+ }
+
+ function __wasm_ctz_i32(x) {
+ x = x | 0;
+ var $$1 = 0, $$2 = 0, $$3 = 0, $$4 = 0, $$5 = 0, $$6 = 0, $$7 = 0, $$8 = 0, $$9 = 0, $$10 = 0;
+ if ((x | 0) == (0 | 0)) $$9 = 32; else $$9 = 31 - Math_clz32(x ^ (x - 1 | 0) | 0) | 0;
+ return $$9 | 0;
+ }
+
+ function __wasm_popcnt_i32(x) {
+ x = x | 0;
+ var count = 0, $$2 = 0, $$3 = 0, $$4 = 0, $$5 = 0, $$6 = 0, $$7 = 0, $$8 = 0, $$9 = 0, $$10 = 0, $$11 = 0, $$12 = 0, $$13 = 0, $$14 = 0, $$15 = 0;
+ count = 0;
+ b : {
+ l : do {
+ $$5 = count;
+ if ((x | 0) == (0 | 0)) break b;
+ x = x & (x - 1 | 0) | 0;
+ count = count + 1 | 0;
+ continue l;
+ break l;
+ } while (1);
+ };
+ return $$5 | 0;
+ }
+
+ function __wasm_rotl_i32(x, k) {
+ x = x | 0;
+ k = k | 0;
+ var $$2 = 0, $$3 = 0, $$4 = 0, $$5 = 0, $$6 = 0, $$7 = 0, $$8 = 0, $$9 = 0, $$10 = 0, $$11 = 0, $$12 = 0, $$13 = 0, $$14 = 0, $$15 = 0, $$16 = 0, $$17 = 0, $$18 = 0, $$19 = 0, $$20 = 0, wasm2asm_i32$0 = 0;
+ return ((4294967295 >>> (k & 31 | 0) | 0) & x | 0) << (k & 31 | 0) | 0 | (((4294967295 << (32 - (k & 31 | 0) | 0) | 0) & x | 0) >>> (32 - (k & 31 | 0) | 0) | 0) | 0 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ function __wasm_rotr_i32(x, k) {
+ x = x | 0;
+ k = k | 0;
+ var $$2 = 0, $$3 = 0, $$4 = 0, $$5 = 0, $$6 = 0, $$7 = 0, $$8 = 0, $$9 = 0, $$10 = 0, $$11 = 0, $$12 = 0, $$13 = 0, $$14 = 0, $$15 = 0, $$16 = 0, $$17 = 0, $$18 = 0, $$19 = 0, $$20 = 0, wasm2asm_i32$0 = 0;
+ return ((4294967295 << (k & 31 | 0) | 0) & x | 0) >>> (k & 31 | 0) | 0 | (((4294967295 >>> (32 - (k & 31 | 0) | 0) | 0) & x | 0) << (32 - (k & 31 | 0) | 0) | 0) | 0 | 0;
+ return wasm2asm_i32$0 | 0;
+ }
+
+ return {
+ "f32.add": $$1,
+ "f32.sub": $$2,
+ "f32.mul": $$3,
+ "f32.div": $$4,
+ "f64.add": $$5,
+ "f64.sub": $$6,
+ "f64.mul": $$7,
+ "f64.div": $$8,
+ "f32.eq": $$9,
+ "f32.ne": $$10,
+ "f32.ge": $$11,
+ "f32.gt": $$12,
+ "f32.le": $$13,
+ "f32.lt": $$14,
+ "f64.eq": $$15,
+ "f64.ne": $$16,
+ "f64.ge": $$17,
+ "f64.gt": $$18,
+ "f64.le": $$19,
+ "f64.lt": $$20,
+ "f32.min": $$21,
+ "f32.max": $$22,
+ "f64.min": $$23,
+ "f64.max": $$24,
+ "f64.promote": $$25,
+ "f32.demote": $$26
+ };
+}
+
diff --git a/test/wasm2asm/float-ops.wast b/test/wasm2asm/float-ops.wast
new file mode 100644
index 000000000..ee8f899e8
--- /dev/null
+++ b/test/wasm2asm/float-ops.wast
@@ -0,0 +1,84 @@
+(module
+ (func $dummy)
+
+ (func (export "f32.add") (param $0 f32) (param $1 f32) (result f32)
+ (f32.add (get_local $0) (get_local $1)))
+
+ (func (export "f32.sub") (param $0 f32) (param $1 f32) (result f32)
+ (f32.sub (get_local $0) (get_local $1)))
+
+ (func (export "f32.mul") (param $0 f32) (param $1 f32) (result f32)
+ (f32.mul (get_local $0) (get_local $1)))
+
+ (func (export "f32.div") (param $0 f32) (param $1 f32) (result f32)
+ (f32.div (get_local $0) (get_local $1)))
+
+ (func (export "f64.add") (param $0 f64) (param $1 f64) (result f64)
+ (f64.add (get_local $0) (get_local $1)))
+
+ (func (export "f64.sub") (param $0 f64) (param $1 f64) (result f64)
+ (f64.sub (get_local $0) (get_local $1)))
+
+ (func (export "f64.mul") (param $0 f64) (param $1 f64) (result f64)
+ (f64.mul (get_local $0) (get_local $1)))
+
+ (func (export "f64.div") (param $0 f64) (param $1 f64) (result f64)
+ (f64.div (get_local $0) (get_local $1)))
+
+ ;; comparisons
+ (func (export "f32.eq") (param $0 f32) (param $1 f32) (result i32)
+ (f32.eq (get_local $0) (get_local $1)))
+
+ (func (export "f32.ne") (param $0 f32) (param $1 f32) (result i32)
+ (f32.ne (get_local $0) (get_local $1)))
+
+ (func (export "f32.ge") (param $0 f32) (param $1 f32) (result i32)
+ (f32.ge (get_local $0) (get_local $1)))
+
+ (func (export "f32.gt") (param $0 f32) (param $1 f32) (result i32)
+ (f32.gt (get_local $0) (get_local $1)))
+
+ (func (export "f32.le") (param $0 f32) (param $1 f32) (result i32)
+ (f32.le (get_local $0) (get_local $1)))
+
+ (func (export "f32.lt") (param $0 f32) (param $1 f32) (result i32)
+ (f32.lt (get_local $0) (get_local $1)))
+
+ (func (export "f64.eq") (param $0 f64) (param $1 f64) (result i32)
+ (f64.eq (get_local $0) (get_local $1)))
+
+ (func (export "f64.ne") (param $0 f64) (param $1 f64) (result i32)
+ (f64.ne (get_local $0) (get_local $1)))
+
+ (func (export "f64.ge") (param $0 f64) (param $1 f64) (result i32)
+ (f64.ge (get_local $0) (get_local $1)))
+
+ (func (export "f64.gt") (param $0 f64) (param $1 f64) (result i32)
+ (f64.gt (get_local $0) (get_local $1)))
+
+ (func (export "f64.le") (param $0 f64) (param $1 f64) (result i32)
+ (f64.le (get_local $0) (get_local $1)))
+
+ (func (export "f64.lt") (param $0 f64) (param $1 f64) (result i32)
+ (f64.lt (get_local $0) (get_local $1)))
+
+ ;; min/max
+ (func (export "f32.min") (param $0 f32) (param $1 f32) (result f32)
+ (f32.min (get_local $0) (get_local $1)))
+
+ (func (export "f32.max") (param $0 f32) (param $1 f32) (result f32)
+ (f32.max (get_local $0) (get_local $1)))
+
+ (func (export "f64.min") (param $0 f64) (param $1 f64) (result f64)
+ (f64.min (get_local $0) (get_local $1)))
+
+ (func (export "f64.max") (param $0 f64) (param $1 f64) (result f64)
+ (f64.max (get_local $0) (get_local $1)))
+
+ ;; promotion/demotion
+ (func (export "f64.promote") (param $0 f32) (result f64)
+ (f64.promote/f32 (get_local $0)))
+
+ (func (export "f32.demote") (param $0 f64) (result f32)
+ (f32.demote/f64 (get_local $0)))
+)