summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanjie Wu <hanjiew@andrew.cmu.edu>2022-12-08 17:45:55 -0500
committerHanjie Wu <hanjiew@andrew.cmu.edu>2022-12-08 17:45:55 -0500
commita054755b62e660d3d8aba42fdb0a992e2d215599 (patch)
tree5f2e793527f75240800b31025f4c4c1f58be23ab
JIT implementation
-rw-r--r--.clang-format226
-rw-r--r--.gitignore5
-rw-r--r--Makefile33
-rw-r--r--common.c143
-rw-r--r--common.h54
-rw-r--r--disass.c431
-rw-r--r--disass.h41
-rwxr-xr-xgrade.sh121
-rw-r--r--illegal.h124
-rw-r--r--ir.c88
-rw-r--r--ir.h41
-rw-r--r--noderun.js106
-rwxr-xr-xnoderun.sh3
-rw-r--r--parse.c449
-rw-r--r--rewrite.c141
-rwxr-xr-xtests/proj2/grade.sh121
-rw-r--r--tests/proj2/tests/add0.runs7
-rw-r--r--tests/proj2/tests/add0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/add0.wat5
-rw-r--r--tests/proj2/tests/add0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/br0.expect1
-rw-r--r--tests/proj2/tests/br0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/br0.wat8
-rw-r--r--tests/proj2/tests/br0.wee.wasmbin0 -> 53 bytes
-rw-r--r--tests/proj2/tests/br1.expect1
-rw-r--r--tests/proj2/tests/br1.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/br1.wat6
-rw-r--r--tests/proj2/tests/br1.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/br2.expect1
-rw-r--r--tests/proj2/tests/br2.wasmbin0 -> 46 bytes
-rw-r--r--tests/proj2/tests/br2.wat9
-rw-r--r--tests/proj2/tests/br2.wee.wasmbin0 -> 57 bytes
-rw-r--r--tests/proj2/tests/br3.expect1
-rw-r--r--tests/proj2/tests/br3.wasmbin0 -> 49 bytes
-rw-r--r--tests/proj2/tests/br3.wat11
-rw-r--r--tests/proj2/tests/br3.wee.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/br_if0.runs3
-rw-r--r--tests/proj2/tests/br_if0.wasmbin0 -> 45 bytes
-rw-r--r--tests/proj2/tests/br_if0.wat8
-rw-r--r--tests/proj2/tests/br_if0.wee.wasmbin0 -> 56 bytes
-rw-r--r--tests/proj2/tests/br_if1.runs7
-rw-r--r--tests/proj2/tests/br_if1.wasmbin0 -> 54 bytes
-rw-r--r--tests/proj2/tests/br_if1.wat11
-rw-r--r--tests/proj2/tests/br_if1.wee.wasmbin0 -> 68 bytes
-rw-r--r--tests/proj2/tests/br_if2.runs8
-rw-r--r--tests/proj2/tests/br_if2.wasmbin0 -> 64 bytes
-rw-r--r--tests/proj2/tests/br_if2.wat16
-rw-r--r--tests/proj2/tests/br_if2.wee.wasmbin0 -> 81 bytes
-rw-r--r--tests/proj2/tests/br_table0.runs3
-rw-r--r--tests/proj2/tests/br_table0.wasmbin0 -> 44 bytes
-rw-r--r--tests/proj2/tests/br_table0.wat6
-rw-r--r--tests/proj2/tests/br_table0.wee.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/br_table1.runs6
-rw-r--r--tests/proj2/tests/br_table1.wasmbin0 -> 45 bytes
-rw-r--r--tests/proj2/tests/br_table1.wat6
-rw-r--r--tests/proj2/tests/br_table1.wee.wasmbin0 -> 62 bytes
-rw-r--r--tests/proj2/tests/br_table2.runs12
-rw-r--r--tests/proj2/tests/br_table2.wasmbin0 -> 54 bytes
-rw-r--r--tests/proj2/tests/br_table2.wat6
-rw-r--r--tests/proj2/tests/br_table2.wee.wasmbin0 -> 98 bytes
-rw-r--r--tests/proj2/tests/br_table3.runs6
-rw-r--r--tests/proj2/tests/br_table3.wasmbin0 -> 56 bytes
-rw-r--r--tests/proj2/tests/br_table3.wat12
-rw-r--r--tests/proj2/tests/br_table3.wee.wasmbin0 -> 73 bytes
-rw-r--r--tests/proj2/tests/br_table4.runs24
-rw-r--r--tests/proj2/tests/br_table4.wasmbin0 -> 96 bytes
-rw-r--r--tests/proj2/tests/br_table4.wat19
-rw-r--r--tests/proj2/tests/br_table4.wee.wasmbin0 -> 161 bytes
-rwxr-xr-xtests/proj2/tests/build.sh35
-rw-r--r--tests/proj2/tests/call0.expect1
-rw-r--r--tests/proj2/tests/call0.wasmbin0 -> 44 bytes
-rw-r--r--tests/proj2/tests/call0.wat6
-rw-r--r--tests/proj2/tests/call0.wee.wasmbin0 -> 56 bytes
-rw-r--r--tests/proj2/tests/call1.runs2
-rw-r--r--tests/proj2/tests/call1.wasmbin0 -> 46 bytes
-rw-r--r--tests/proj2/tests/call1.wat6
-rw-r--r--tests/proj2/tests/call1.wee.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/call2.runs2
-rw-r--r--tests/proj2/tests/call2.wasmbin0 -> 52 bytes
-rw-r--r--tests/proj2/tests/call2.wat8
-rw-r--r--tests/proj2/tests/call2.wee.wasmbin0 -> 64 bytes
-rw-r--r--tests/proj2/tests/call3.runs2
-rw-r--r--tests/proj2/tests/call3.wasmbin0 -> 81 bytes
-rw-r--r--tests/proj2/tests/call3.wat15
-rw-r--r--tests/proj2/tests/call3.wee.wasmbin0 -> 93 bytes
-rw-r--r--tests/proj2/tests/call4.expect1
-rw-r--r--tests/proj2/tests/call4.wasmbin0 -> 61 bytes
-rw-r--r--tests/proj2/tests/call4.wat8
-rw-r--r--tests/proj2/tests/call4.wee.wasmbin0 -> 81 bytes
-rw-r--r--tests/proj2/tests/call_indirect0.runs7
-rw-r--r--tests/proj2/tests/call_indirect0.wasmbin0 -> 51 bytes
-rw-r--r--tests/proj2/tests/call_indirect0.wat7
-rw-r--r--tests/proj2/tests/call_indirect0.wee.wasmbin0 -> 59 bytes
-rw-r--r--tests/proj2/tests/call_indirect1.runs7
-rw-r--r--tests/proj2/tests/call_indirect1.wasmbin0 -> 61 bytes
-rw-r--r--tests/proj2/tests/call_indirect1.wat7
-rw-r--r--tests/proj2/tests/call_indirect1.wee.wasmbin0 -> 69 bytes
-rw-r--r--tests/proj2/tests/call_indirect2.runs8
-rw-r--r--tests/proj2/tests/call_indirect2.wasmbin0 -> 89 bytes
-rw-r--r--tests/proj2/tests/call_indirect2.wat13
-rw-r--r--tests/proj2/tests/call_indirect2.wee.wasmbin0 -> 113 bytes
-rw-r--r--tests/proj2/tests/call_indirect3.runs5
-rw-r--r--tests/proj2/tests/call_indirect3.wasmbin0 -> 108 bytes
-rw-r--r--tests/proj2/tests/call_indirect3.wat13
-rw-r--r--tests/proj2/tests/call_indirect3.wee.wasmbin0 -> 132 bytes
-rw-r--r--tests/proj2/tests/const0.expect1
-rw-r--r--tests/proj2/tests/const0.wasmbin0 -> 37 bytes
-rw-r--r--tests/proj2/tests/const0.wat5
-rw-r--r--tests/proj2/tests/const0.wee.wasmbin0 -> 45 bytes
-rw-r--r--tests/proj2/tests/const1.expect1
-rw-r--r--tests/proj2/tests/const1.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/const1.wat5
-rw-r--r--tests/proj2/tests/const1.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/const2_d.expect1
-rw-r--r--tests/proj2/tests/const2_d.wasmbin0 -> 44 bytes
-rw-r--r--tests/proj2/tests/const2_d.wat5
-rw-r--r--tests/proj2/tests/const2_d.wee.wasmbin0 -> 52 bytes
-rw-r--r--tests/proj2/tests/div0.runs5
-rw-r--r--tests/proj2/tests/div0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/div0.wat5
-rw-r--r--tests/proj2/tests/div0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/ec_putd0.expect1
-rw-r--r--tests/proj2/tests/ec_putd0.wasmbin0 -> 71 bytes
-rw-r--r--tests/proj2/tests/ec_putd0.wat7
-rw-r--r--tests/proj2/tests/ec_putd0.wee.wasmbin0 -> 79 bytes
-rw-r--r--tests/proj2/tests/ec_putd1.expect1
-rw-r--r--tests/proj2/tests/ec_putd1.wasmbin0 -> 93 bytes
-rw-r--r--tests/proj2/tests/ec_putd1.wat9
-rw-r--r--tests/proj2/tests/ec_putd1.wee.wasmbin0 -> 101 bytes
-rw-r--r--tests/proj2/tests/ec_puti0.expect1
-rw-r--r--tests/proj2/tests/ec_puti0.wasmbin0 -> 63 bytes
-rw-r--r--tests/proj2/tests/ec_puti0.wat7
-rw-r--r--tests/proj2/tests/ec_puti0.wee.wasmbin0 -> 71 bytes
-rw-r--r--tests/proj2/tests/ec_puti1.expect1
-rw-r--r--tests/proj2/tests/ec_puti1.wasmbin0 -> 74 bytes
-rw-r--r--tests/proj2/tests/ec_puti1.wat9
-rw-r--r--tests/proj2/tests/ec_puti1.wee.wasmbin0 -> 82 bytes
-rw-r--r--tests/proj2/tests/ec_puts0.expect2
-rw-r--r--tests/proj2/tests/ec_puts0.wasmbin0 -> 94 bytes
-rw-r--r--tests/proj2/tests/ec_puts0.wat9
-rw-r--r--tests/proj2/tests/ec_puts0.wee.wasmbin0 -> 102 bytes
-rw-r--r--tests/proj2/tests/f64.add0_d.runs3
-rw-r--r--tests/proj2/tests/f64.add0_d.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.add0_d.wat5
-rw-r--r--tests/proj2/tests/f64.add0_d.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.convert_i32_s0_d.runs4
-rw-r--r--tests/proj2/tests/f64.convert_i32_s0_d.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/f64.convert_i32_s0_d.wat5
-rw-r--r--tests/proj2/tests/f64.convert_i32_s0_d.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/f64.convert_i32_u0_d.runs4
-rw-r--r--tests/proj2/tests/f64.convert_i32_u0_d.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/f64.convert_i32_u0_d.wat5
-rw-r--r--tests/proj2/tests/f64.convert_i32_u0_d.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/f64.div0_d.runs2
-rw-r--r--tests/proj2/tests/f64.div0_d.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.div0_d.wat5
-rw-r--r--tests/proj2/tests/f64.div0_d.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.eq0.runs3
-rw-r--r--tests/proj2/tests/f64.eq0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.eq0.wat5
-rw-r--r--tests/proj2/tests/f64.eq0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.ge0.runs4
-rw-r--r--tests/proj2/tests/f64.ge0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.ge0.wat5
-rw-r--r--tests/proj2/tests/f64.ge0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.gt0.runs4
-rw-r--r--tests/proj2/tests/f64.gt0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.gt0.wat5
-rw-r--r--tests/proj2/tests/f64.gt0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.le0.runs4
-rw-r--r--tests/proj2/tests/f64.le0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.le0.wat5
-rw-r--r--tests/proj2/tests/f64.le0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.lt0.runs4
-rw-r--r--tests/proj2/tests/f64.lt0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.lt0.wat5
-rw-r--r--tests/proj2/tests/f64.lt0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.mul0_d.runs3
-rw-r--r--tests/proj2/tests/f64.mul0_d.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.mul0_d.wat5
-rw-r--r--tests/proj2/tests/f64.mul0_d.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.ne0.runs3
-rw-r--r--tests/proj2/tests/f64.ne0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.ne0.wat5
-rw-r--r--tests/proj2/tests/f64.ne0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/f64.store0.runs16
-rw-r--r--tests/proj2/tests/f64.store0.wasmbin0 -> 61 bytes
-rw-r--r--tests/proj2/tests/f64.store0.wat7
-rw-r--r--tests/proj2/tests/f64.store0.wee.wasmbin0 -> 69 bytes
-rw-r--r--tests/proj2/tests/f64.sub0_d.runs3
-rw-r--r--tests/proj2/tests/f64.sub0_d.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/f64.sub0_d.wat5
-rw-r--r--tests/proj2/tests/f64.sub0_d.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/fib.runs9
-rw-r--r--tests/proj2/tests/fib.wasmbin0 -> 65 bytes
-rw-r--r--tests/proj2/tests/fib.wat29
-rw-r--r--tests/proj2/tests/fib.wee.wasmbin0 -> 76 bytes
-rwxr-xr-xtests/proj2/tests/gen.sh436
-rw-r--r--tests/proj2/tests/global0.expect1
-rw-r--r--tests/proj2/tests/global0.wasmbin0 -> 45 bytes
-rw-r--r--tests/proj2/tests/global0.wat6
-rw-r--r--tests/proj2/tests/global0.wee.wasmbin0 -> 53 bytes
-rw-r--r--tests/proj2/tests/global1_d.expect1
-rw-r--r--tests/proj2/tests/global1_d.wasmbin0 -> 52 bytes
-rw-r--r--tests/proj2/tests/global1_d.wat6
-rw-r--r--tests/proj2/tests/global1_d.wee.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/global2.runs2
-rw-r--r--tests/proj2/tests/global2.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/global2.wat7
-rw-r--r--tests/proj2/tests/global2.wee.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/global3_d.runs2
-rw-r--r--tests/proj2/tests/global3_d.wasmbin0 -> 57 bytes
-rw-r--r--tests/proj2/tests/global3_d.wat7
-rw-r--r--tests/proj2/tests/global3_d.wee.wasmbin0 -> 65 bytes
-rw-r--r--tests/proj2/tests/i32.add0.runs7
-rw-r--r--tests/proj2/tests/i32.add0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.add0.wat5
-rw-r--r--tests/proj2/tests/i32.add0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.and0.runs4
-rw-r--r--tests/proj2/tests/i32.and0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.and0.wat5
-rw-r--r--tests/proj2/tests/i32.and0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.clz0.runs5
-rw-r--r--tests/proj2/tests/i32.clz0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.clz0.wat5
-rw-r--r--tests/proj2/tests/i32.clz0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.ctz0.runs5
-rw-r--r--tests/proj2/tests/i32.ctz0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.ctz0.wat5
-rw-r--r--tests/proj2/tests/i32.ctz0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.div_s0.runs5
-rw-r--r--tests/proj2/tests/i32.div_s0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.div_s0.wat5
-rw-r--r--tests/proj2/tests/i32.div_s0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.div_u0.runs5
-rw-r--r--tests/proj2/tests/i32.div_u0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.div_u0.wat5
-rw-r--r--tests/proj2/tests/i32.div_u0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.eq0.runs5
-rw-r--r--tests/proj2/tests/i32.eq0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.eq0.wat5
-rw-r--r--tests/proj2/tests/i32.eq0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.eqz0.runs4
-rw-r--r--tests/proj2/tests/i32.eqz0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.eqz0.wat5
-rw-r--r--tests/proj2/tests/i32.eqz0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.extend16_s0.runs6
-rw-r--r--tests/proj2/tests/i32.extend16_s0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.extend16_s0.wat5
-rw-r--r--tests/proj2/tests/i32.extend16_s0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.extend8_s0.runs5
-rw-r--r--tests/proj2/tests/i32.extend8_s0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.extend8_s0.wat5
-rw-r--r--tests/proj2/tests/i32.extend8_s0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.ge_s0.runs12
-rw-r--r--tests/proj2/tests/i32.ge_s0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.ge_s0.wat5
-rw-r--r--tests/proj2/tests/i32.ge_s0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.ge_u0.runs12
-rw-r--r--tests/proj2/tests/i32.ge_u0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.ge_u0.wat5
-rw-r--r--tests/proj2/tests/i32.ge_u0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.gt_s0.runs12
-rw-r--r--tests/proj2/tests/i32.gt_s0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.gt_s0.wat5
-rw-r--r--tests/proj2/tests/i32.gt_s0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.gt_u0.runs12
-rw-r--r--tests/proj2/tests/i32.gt_u0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.gt_u0.wat5
-rw-r--r--tests/proj2/tests/i32.gt_u0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.le_s0.runs12
-rw-r--r--tests/proj2/tests/i32.le_s0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.le_s0.wat5
-rw-r--r--tests/proj2/tests/i32.le_s0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.le_u0.runs12
-rw-r--r--tests/proj2/tests/i32.le_u0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.le_u0.wat5
-rw-r--r--tests/proj2/tests/i32.le_u0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.load0.runs6
-rw-r--r--tests/proj2/tests/i32.load0.wasmbin0 -> 46 bytes
-rw-r--r--tests/proj2/tests/i32.load0.wat6
-rw-r--r--tests/proj2/tests/i32.load0.wee.wasmbin0 -> 54 bytes
-rw-r--r--tests/proj2/tests/i32.load1.runs7
-rw-r--r--tests/proj2/tests/i32.load1.wasmbin0 -> 46 bytes
-rw-r--r--tests/proj2/tests/i32.load1.wat6
-rw-r--r--tests/proj2/tests/i32.load1.wee.wasmbin0 -> 54 bytes
-rw-r--r--tests/proj2/tests/i32.load16_s0.runs13
-rw-r--r--tests/proj2/tests/i32.load16_s0.wasmbin0 -> 59 bytes
-rw-r--r--tests/proj2/tests/i32.load16_s0.wat7
-rw-r--r--tests/proj2/tests/i32.load16_s0.wee.wasmbin0 -> 67 bytes
-rw-r--r--tests/proj2/tests/i32.load16_u0.runs13
-rw-r--r--tests/proj2/tests/i32.load16_u0.wasmbin0 -> 59 bytes
-rw-r--r--tests/proj2/tests/i32.load16_u0.wat7
-rw-r--r--tests/proj2/tests/i32.load16_u0.wee.wasmbin0 -> 67 bytes
-rw-r--r--tests/proj2/tests/i32.load16_u1.runs13
-rw-r--r--tests/proj2/tests/i32.load16_u1.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/i32.load16_u1.wat7
-rw-r--r--tests/proj2/tests/i32.load16_u1.wee.wasmbin0 -> 68 bytes
-rw-r--r--tests/proj2/tests/i32.load2.runs11
-rw-r--r--tests/proj2/tests/i32.load2.wasmbin0 -> 46 bytes
-rw-r--r--tests/proj2/tests/i32.load2.wat6
-rw-r--r--tests/proj2/tests/i32.load2.wee.wasmbin0 -> 54 bytes
-rw-r--r--tests/proj2/tests/i32.load3.runs3
-rw-r--r--tests/proj2/tests/i32.load3.wasmbin0 -> 48 bytes
-rw-r--r--tests/proj2/tests/i32.load3.wat6
-rw-r--r--tests/proj2/tests/i32.load3.wee.wasmbin0 -> 56 bytes
-rw-r--r--tests/proj2/tests/i32.load4.runs13
-rw-r--r--tests/proj2/tests/i32.load4.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/i32.load4.wat7
-rw-r--r--tests/proj2/tests/i32.load4.wee.wasmbin0 -> 66 bytes
-rw-r--r--tests/proj2/tests/i32.load8_s0.runs13
-rw-r--r--tests/proj2/tests/i32.load8_s0.wasmbin0 -> 59 bytes
-rw-r--r--tests/proj2/tests/i32.load8_s0.wat7
-rw-r--r--tests/proj2/tests/i32.load8_s0.wee.wasmbin0 -> 67 bytes
-rw-r--r--tests/proj2/tests/i32.load8_u0.runs13
-rw-r--r--tests/proj2/tests/i32.load8_u0.wasmbin0 -> 59 bytes
-rw-r--r--tests/proj2/tests/i32.load8_u0.wat7
-rw-r--r--tests/proj2/tests/i32.load8_u0.wee.wasmbin0 -> 67 bytes
-rw-r--r--tests/proj2/tests/i32.load8_u1.runs13
-rw-r--r--tests/proj2/tests/i32.load8_u1.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/i32.load8_u1.wat7
-rw-r--r--tests/proj2/tests/i32.load8_u1.wee.wasmbin0 -> 68 bytes
-rw-r--r--tests/proj2/tests/i32.lt_s0.runs12
-rw-r--r--tests/proj2/tests/i32.lt_s0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.lt_s0.wat5
-rw-r--r--tests/proj2/tests/i32.lt_s0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.lt_u0.runs12
-rw-r--r--tests/proj2/tests/i32.lt_u0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.lt_u0.wat5
-rw-r--r--tests/proj2/tests/i32.lt_u0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.mul0.runs9
-rw-r--r--tests/proj2/tests/i32.mul0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.mul0.wat5
-rw-r--r--tests/proj2/tests/i32.mul0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.ne0.runs5
-rw-r--r--tests/proj2/tests/i32.ne0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.ne0.wat5
-rw-r--r--tests/proj2/tests/i32.ne0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.or0.runs4
-rw-r--r--tests/proj2/tests/i32.or0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.or0.wat5
-rw-r--r--tests/proj2/tests/i32.or0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.popcnt0.runs6
-rw-r--r--tests/proj2/tests/i32.popcnt0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.popcnt0.wat5
-rw-r--r--tests/proj2/tests/i32.popcnt0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.rem_s0.runs8
-rw-r--r--tests/proj2/tests/i32.rem_s0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.rem_s0.wat5
-rw-r--r--tests/proj2/tests/i32.rem_s0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.rem_u0.runs5
-rw-r--r--tests/proj2/tests/i32.rem_u0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.rem_u0.wat5
-rw-r--r--tests/proj2/tests/i32.rem_u0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.rotl0.runs5
-rw-r--r--tests/proj2/tests/i32.rotl0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.rotl0.wat5
-rw-r--r--tests/proj2/tests/i32.rotl0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.rotr0.runs5
-rw-r--r--tests/proj2/tests/i32.rotr0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.rotr0.wat5
-rw-r--r--tests/proj2/tests/i32.rotr0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.shl0.runs5
-rw-r--r--tests/proj2/tests/i32.shl0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.shl0.wat5
-rw-r--r--tests/proj2/tests/i32.shl0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.shr_s0.runs7
-rw-r--r--tests/proj2/tests/i32.shr_s0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.shr_s0.wat5
-rw-r--r--tests/proj2/tests/i32.shr_s0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.shr_u0.runs6
-rw-r--r--tests/proj2/tests/i32.shr_u0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.shr_u0.wat5
-rw-r--r--tests/proj2/tests/i32.shr_u0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.store0.runs10
-rw-r--r--tests/proj2/tests/i32.store0.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/i32.store0.wat7
-rw-r--r--tests/proj2/tests/i32.store0.wee.wasmbin0 -> 66 bytes
-rw-r--r--tests/proj2/tests/i32.store1.runs10
-rw-r--r--tests/proj2/tests/i32.store1.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/i32.store1.wat7
-rw-r--r--tests/proj2/tests/i32.store1.wee.wasmbin0 -> 66 bytes
-rw-r--r--tests/proj2/tests/i32.store16_0.runs10
-rw-r--r--tests/proj2/tests/i32.store16_0.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/i32.store16_0.wat7
-rw-r--r--tests/proj2/tests/i32.store16_0.wee.wasmbin0 -> 66 bytes
-rw-r--r--tests/proj2/tests/i32.store8_0.runs10
-rw-r--r--tests/proj2/tests/i32.store8_0.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/i32.store8_0.wat7
-rw-r--r--tests/proj2/tests/i32.store8_0.wee.wasmbin0 -> 66 bytes
-rw-r--r--tests/proj2/tests/i32.sub0.runs8
-rw-r--r--tests/proj2/tests/i32.sub0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.sub0.wat5
-rw-r--r--tests/proj2/tests/i32.sub0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/i32.trunc_f64_s0.runs8
-rw-r--r--tests/proj2/tests/i32.trunc_f64_s0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.trunc_f64_s0.wat5
-rw-r--r--tests/proj2/tests/i32.trunc_f64_s0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.trunc_f64_u0.runs7
-rw-r--r--tests/proj2/tests/i32.trunc_f64_u0.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj2/tests/i32.trunc_f64_u0.wat5
-rw-r--r--tests/proj2/tests/i32.trunc_f64_u0.wee.wasmbin0 -> 47 bytes
-rw-r--r--tests/proj2/tests/i32.xor0.runs4
-rw-r--r--tests/proj2/tests/i32.xor0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/i32.xor0.wat5
-rw-r--r--tests/proj2/tests/i32.xor0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/load_oob0.runs12
-rw-r--r--tests/proj2/tests/load_oob0.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/load_oob0.wat7
-rw-r--r--tests/proj2/tests/load_oob0.wee.wasmbin0 -> 68 bytes
-rw-r--r--tests/proj2/tests/load_oob1.runs16
-rw-r--r--tests/proj2/tests/load_oob1.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/load_oob1.wat7
-rw-r--r--tests/proj2/tests/load_oob1.wee.wasmbin0 -> 68 bytes
-rw-r--r--tests/proj2/tests/load_oob2.runs12
-rw-r--r--tests/proj2/tests/load_oob2.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/load_oob2.wat7
-rw-r--r--tests/proj2/tests/load_oob2.wee.wasmbin0 -> 68 bytes
-rw-r--r--tests/proj2/tests/load_oob3.runs12
-rw-r--r--tests/proj2/tests/load_oob3.wasmbin0 -> 62 bytes
-rw-r--r--tests/proj2/tests/load_oob3.wat7
-rw-r--r--tests/proj2/tests/load_oob3.wee.wasmbin0 -> 70 bytes
-rw-r--r--tests/proj2/tests/load_oob5.runs12
-rw-r--r--tests/proj2/tests/load_oob5.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/load_oob5.wat8
-rw-r--r--tests/proj2/tests/load_oob5.wee.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/load_oob6.runs12
-rw-r--r--tests/proj2/tests/load_oob6.wasmbin0 -> 52 bytes
-rw-r--r--tests/proj2/tests/load_oob6.wat8
-rw-r--r--tests/proj2/tests/load_oob6.wee.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj2/tests/mul0.runs9
-rw-r--r--tests/proj2/tests/mul0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/mul0.wat5
-rw-r--r--tests/proj2/tests/mul0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/rec.runs1
-rw-r--r--tests/proj2/tests/rec.wasmbin0 -> 65 bytes
-rw-r--r--tests/proj2/tests/rec.wat11
-rw-r--r--tests/proj2/tests/rec.wee.wasmbin0 -> 76 bytes
-rw-r--r--tests/proj2/tests/return0.expect1
-rw-r--r--tests/proj2/tests/return0.wasmbin0 -> 38 bytes
-rw-r--r--tests/proj2/tests/return0.wat6
-rw-r--r--tests/proj2/tests/return0.wee.wasmbin0 -> 46 bytes
-rw-r--r--tests/proj2/tests/return1.expect1
-rw-r--r--tests/proj2/tests/return1.wasmbin0 -> 40 bytes
-rw-r--r--tests/proj2/tests/return1.wat7
-rw-r--r--tests/proj2/tests/return1.wee.wasmbin0 -> 48 bytes
-rw-r--r--tests/proj2/tests/return2.expect1
-rw-r--r--tests/proj2/tests/return2.wasmbin0 -> 58 bytes
-rw-r--r--tests/proj2/tests/return2.wat16
-rw-r--r--tests/proj2/tests/return2.wee.wasmbin0 -> 66 bytes
-rw-r--r--tests/proj2/tests/start0.expect1
-rw-r--r--tests/proj2/tests/start0.wasmbin0 -> 59 bytes
-rw-r--r--tests/proj2/tests/start0.wat8
-rw-r--r--tests/proj2/tests/start0.wee.wasmbin0 -> 71 bytes
-rw-r--r--tests/proj2/tests/store_oob0.runs12
-rw-r--r--tests/proj2/tests/store_oob0.wasmbin0 -> 64 bytes
-rw-r--r--tests/proj2/tests/store_oob0.wat8
-rw-r--r--tests/proj2/tests/store_oob0.wee.wasmbin0 -> 72 bytes
-rw-r--r--tests/proj2/tests/store_oob2.runs12
-rw-r--r--tests/proj2/tests/store_oob2.wasmbin0 -> 65 bytes
-rw-r--r--tests/proj2/tests/store_oob2.wat8
-rw-r--r--tests/proj2/tests/store_oob2.wee.wasmbin0 -> 73 bytes
-rw-r--r--tests/proj2/tests/sub0.runs8
-rw-r--r--tests/proj2/tests/sub0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj2/tests/sub0.wat5
-rw-r--r--tests/proj2/tests/sub0.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj2/tests/vobj0.runs5
-rw-r--r--tests/proj2/tests/vobj0.wasmbin0 -> 139 bytes
-rw-r--r--tests/proj2/tests/vobj0.wat15
-rw-r--r--tests/proj2/tests/vobj0.wee.wasmbin0 -> 147 bytes
-rwxr-xr-xtests/proj3/grade.sh121
-rw-r--r--tests/proj3/tests/array_get0.runs7
-rw-r--r--tests/proj3/tests/array_get0.wasmbin0 -> 230 bytes
-rw-r--r--tests/proj3/tests/array_get0.wat26
-rw-r--r--tests/proj3/tests/array_get0.wee.wasmbin0 -> 249 bytes
-rw-r--r--tests/proj3/tests/array_sparse0.runs9
-rw-r--r--tests/proj3/tests/array_sparse0.wasmbin0 -> 232 bytes
-rw-r--r--tests/proj3/tests/array_sparse0.wat26
-rw-r--r--tests/proj3/tests/array_sparse0.wee.wasmbin0 -> 251 bytes
-rw-r--r--tests/proj3/tests/array_sparse1.runs4
-rw-r--r--tests/proj3/tests/array_sparse1.wasmbin0 -> 241 bytes
-rw-r--r--tests/proj3/tests/array_sparse1.wat28
-rw-r--r--tests/proj3/tests/array_sparse1.wee.wasmbin0 -> 260 bytes
-rw-r--r--tests/proj3/tests/array_sum0.runs8
-rw-r--r--tests/proj3/tests/array_sum0.wasmbin0 -> 256 bytes
-rw-r--r--tests/proj3/tests/array_sum0.wat32
-rw-r--r--tests/proj3/tests/array_sum0.wee.wasmbin0 -> 278 bytes
-rw-r--r--tests/proj3/tests/array_sum1.runs8
-rw-r--r--tests/proj3/tests/array_sum1.wasmbin0 -> 259 bytes
-rw-r--r--tests/proj3/tests/array_sum1.wat32
-rw-r--r--tests/proj3/tests/array_sum1.wee.wasmbin0 -> 281 bytes
-rw-r--r--tests/proj3/tests/br0.expect1
-rw-r--r--tests/proj3/tests/br0.wasmbin0 -> 42 bytes
-rw-r--r--tests/proj3/tests/br0.wat8
-rw-r--r--tests/proj3/tests/br0.wee.wasmbin0 -> 53 bytes
-rw-r--r--tests/proj3/tests/br1.expect1
-rw-r--r--tests/proj3/tests/br1.wasmbin0 -> 39 bytes
-rw-r--r--tests/proj3/tests/br1.wat6
-rw-r--r--tests/proj3/tests/br1.wee.wasmbin0 -> 50 bytes
-rw-r--r--tests/proj3/tests/br2.expect1
-rw-r--r--tests/proj3/tests/br2.wasmbin0 -> 46 bytes
-rw-r--r--tests/proj3/tests/br2.wat9
-rw-r--r--tests/proj3/tests/br2.wee.wasmbin0 -> 57 bytes
-rw-r--r--tests/proj3/tests/br3.expect1
-rw-r--r--tests/proj3/tests/br3.wasmbin0 -> 49 bytes
-rw-r--r--tests/proj3/tests/br3.wat11
-rw-r--r--tests/proj3/tests/br3.wee.wasmbin0 -> 60 bytes
-rw-r--r--tests/proj3/tests/br_if0.runs3
-rw-r--r--tests/proj3/tests/br_if0.wasmbin0 -> 45 bytes
-rw-r--r--tests/proj3/tests/br_if0.wat8
-rw-r--r--tests/proj3/tests/br_if0.wee.wasmbin0 -> 56 bytes
-rw-r--r--tests/proj3/tests/br_if1.runs7
-rw-r--r--tests/proj3/tests/br_if1.wasmbin0 -> 54 bytes
-rw-r--r--tests/proj3/tests/br_if1.wat11
-rw-r--r--tests/proj3/tests/br_if1.wee.wasmbin0 -> 68 bytes
-rw-r--r--tests/proj3/tests/br_if2.runs8
-rw-r--r--tests/proj3/tests/br_if2.wasmbin0 -> 64 bytes
-rw-r--r--tests/proj3/tests/br_if2.wat16
-rw-r--r--tests/proj3/tests/br_if2.wee.wasmbin0 -> 81 bytes
-rw-r--r--tests/proj3/tests/br_table4.runs24
-rw-r--r--tests/proj3/tests/br_table4.wasmbin0 -> 96 bytes
-rw-r--r--tests/proj3/tests/br_table4.wat19
-rw-r--r--tests/proj3/tests/br_table4.wee.wasmbin0 -> 161 bytes
-rwxr-xr-xtests/proj3/tests/build.sh35
-rw-r--r--tests/proj3/tests/call_indirect0.runs7
-rw-r--r--tests/proj3/tests/call_indirect0.wasmbin0 -> 54 bytes
-rw-r--r--tests/proj3/tests/call_indirect0.wat10
-rw-r--r--tests/proj3/tests/call_indirect0.wee.wasmbin0 -> 62 bytes
-rw-r--r--tests/proj3/tests/call_indirect1.runs7
-rw-r--r--tests/proj3/tests/call_indirect1.wasmbin0 -> 64 bytes
-rw-r--r--tests/proj3/tests/call_indirect1.wat9
-rw-r--r--tests/proj3/tests/call_indirect1.wee.wasmbin0 -> 72 bytes
-rw-r--r--tests/proj3/tests/call_indirect2.runs7
-rw-r--r--tests/proj3/tests/call_indirect2.wasmbin0 -> 74 bytes
-rw-r--r--tests/proj3/tests/call_indirect2.wat13
-rw-r--r--tests/proj3/tests/call_indirect2.wee.wasmbin0 -> 86 bytes
-rw-r--r--tests/proj3/tests/call_indirect3.runs7
-rw-r--r--tests/proj3/tests/call_indirect3.wasmbin0 -> 94 bytes
-rw-r--r--tests/proj3/tests/call_indirect3.wat14
-rw-r--r--tests/proj3/tests/call_indirect3.wee.wasmbin0 -> 106 bytes
-rw-r--r--tests/proj3/tests/call_indirect4.runs7
-rw-r--r--tests/proj3/tests/call_indirect4.wasmbin0 -> 98 bytes
-rw-r--r--tests/proj3/tests/call_indirect4.wat15
-rw-r--r--tests/proj3/tests/call_indirect4.wee.wasmbin0 -> 110 bytes
-rw-r--r--tests/proj3/tests/call_indirect5.runs7
-rw-r--r--tests/proj3/tests/call_indirect5.wasmbin0 -> 100 bytes
-rw-r--r--tests/proj3/tests/call_indirect5.wat15
-rw-r--r--tests/proj3/tests/call_indirect5.wee.wasmbin0 -> 112 bytes
-rw-r--r--tests/proj3/tests/ec_puti0.expect1
-rw-r--r--tests/proj3/tests/ec_puti0.wasmbin0 -> 63 bytes
-rw-r--r--tests/proj3/tests/ec_puti0.wat7
-rw-r--r--tests/proj3/tests/ec_puti0.wee.wasmbin0 -> 71 bytes
-rw-r--r--tests/proj3/tests/ec_puti1.expect1
-rw-r--r--tests/proj3/tests/ec_puti1.wasmbin0 -> 74 bytes
-rw-r--r--tests/proj3/tests/ec_puti1.wat9
-rw-r--r--tests/proj3/tests/ec_puti1.wee.wasmbin0 -> 82 bytes
-rw-r--r--tests/proj3/tests/eq_null0.expect1
-rw-r--r--tests/proj3/tests/eq_null0.wasmbin0 -> 91 bytes
-rw-r--r--tests/proj3/tests/eq_null0.wat9
-rw-r--r--tests/proj3/tests/eq_null0.wee.wasmbin0 -> 99 bytes
-rw-r--r--tests/proj3/tests/eq_null1.expect1
-rw-r--r--tests/proj3/tests/eq_null1.wasmbin0 -> 89 bytes
-rw-r--r--tests/proj3/tests/eq_null1.wat8
-rw-r--r--tests/proj3/tests/eq_null1.wee.wasmbin0 -> 97 bytes
-rw-r--r--tests/proj3/tests/eqn.expect1
-rw-r--r--tests/proj3/tests/eqn.wasmbin0 -> 161 bytes
-rw-r--r--tests/proj3/tests/eqn.wat28
-rw-r--r--tests/proj3/tests/eqn.wee.wasmbin0 -> 176 bytes
-rw-r--r--tests/proj3/tests/eqn2.expect1
-rw-r--r--tests/proj3/tests/eqn2.wasmbin0 -> 170 bytes
-rw-r--r--tests/proj3/tests/eqn2.wat28
-rw-r--r--tests/proj3/tests/eqn2.wee.wasmbin0 -> 185 bytes
-rw-r--r--tests/proj3/tests/eqn3.expect1
-rw-r--r--tests/proj3/tests/eqn3.wasmbin0 -> 184 bytes
-rw-r--r--tests/proj3/tests/eqn3.wat28
-rw-r--r--tests/proj3/tests/eqn3.wee.wasmbin0 -> 199 bytes
-rw-r--r--tests/proj3/tests/f64.add0_d.runs3
-rw-r--r--tests/proj3/tests/f64.add0_d.wasmbin0 -> 105 bytes
-rw-r--r--tests/proj3/tests/f64.add0_d.wat8
-rw-r--r--tests/proj3/tests/f64.add0_d.wee.wasmbin0 -> 113 bytes
-rw-r--r--tests/proj3/tests/f64.add1_d.runs3
-rw-r--r--tests/proj3/tests/f64.add1_d.wasmbin0 -> 101 bytes
-rw-r--r--tests/proj3/tests/f64.add1_d.wat8
-rw-r--r--tests/proj3/tests/f64.add1_d.wee.wasmbin0 -> 109 bytes
-rw-r--r--tests/proj3/tests/f64_box_unbox0_d.runs2
-rw-r--r--tests/proj3/tests/f64_box_unbox0_d.wasmbin0 -> 97 bytes
-rw-r--r--tests/proj3/tests/f64_box_unbox0_d.wat7
-rw-r--r--tests/proj3/tests/f64_box_unbox0_d.wee.wasmbin0 -> 105 bytes
-rw-r--r--tests/proj3/tests/f64_key0_d.runs3
-rw-r--r--tests/proj3/tests/f64_key0_d.wasmbin0 -> 201 bytes
-rw-r--r--tests/proj3/tests/f64_key0_d.wat16
-rw-r--r--tests/proj3/tests/f64_key0_d.wee.wasmbin0 -> 209 bytes
-rw-r--r--tests/proj3/tests/f64_key1_d.runs3
-rw-r--r--tests/proj3/tests/f64_key1_d.wasmbin0 -> 199 bytes
-rw-r--r--tests/proj3/tests/f64_key1_d.wat14
-rw-r--r--tests/proj3/tests/f64_key1_d.wee.wasmbin0 -> 207 bytes
-rw-r--r--tests/proj3/tests/f64_key2_d.runs3
-rw-r--r--tests/proj3/tests/f64_key2_d.wasmbin0 -> 227 bytes
-rw-r--r--tests/proj3/tests/f64_key2_d.wat15
-rw-r--r--tests/proj3/tests/f64_key2_d.wee.wasmbin0 -> 235 bytes
-rw-r--r--tests/proj3/tests/fib.runs9
-rw-r--r--tests/proj3/tests/fib.wasmbin0 -> 65 bytes
-rw-r--r--tests/proj3/tests/fib.wat29
-rw-r--r--tests/proj3/tests/fib.wee.wasmbin0 -> 76 bytes
-rw-r--r--tests/proj3/tests/i32_box_unbox0.runs2
-rw-r--r--tests/proj3/tests/i32_box_unbox0.wasmbin0 -> 97 bytes
-rw-r--r--tests/proj3/tests/i32_box_unbox0.wat7
-rw-r--r--tests/proj3/tests/i32_box_unbox0.wee.wasmbin0 -> 105 bytes
-rw-r--r--tests/proj3/tests/junk0_d.runs3
-rw-r--r--tests/proj3/tests/junk0_d.wasmbin0 -> 264 bytes
-rw-r--r--tests/proj3/tests/junk0_d.wat19
-rw-r--r--tests/proj3/tests/junk0_d.wee.wasmbin0 -> 275 bytes
-rw-r--r--tests/proj3/tests/junk1_d.runs3
-rw-r--r--tests/proj3/tests/junk1_d.wasmbin0 -> 277 bytes
-rw-r--r--tests/proj3/tests/junk1_d.wat20
-rw-r--r--tests/proj3/tests/junk1_d.wee.wasmbin0 -> 288 bytes
-rw-r--r--tests/proj3/tests/list0.runs4
-rw-r--r--tests/proj3/tests/list0.wasmbin0 -> 293 bytes
-rw-r--r--tests/proj3/tests/list0.wat44
-rw-r--r--tests/proj3/tests/list0.wee.wasmbin0 -> 323 bytes
-rw-r--r--tests/proj3/tests/list1.runs7
-rw-r--r--tests/proj3/tests/list1.wasmbin0 -> 327 bytes
-rw-r--r--tests/proj3/tests/list1.wat55
-rw-r--r--tests/proj3/tests/list1.wee.wasmbin0 -> 366 bytes
-rw-r--r--tests/proj3/tests/obj.eq0.expect1
-rw-r--r--tests/proj3/tests/obj.eq0.wasmbin0 -> 69 bytes
-rw-r--r--tests/proj3/tests/obj.eq0.wat7
-rw-r--r--tests/proj3/tests/obj.eq0.wee.wasmbin0 -> 77 bytes
-rw-r--r--tests/proj3/tests/obj.eq1.runs2
-rw-r--r--tests/proj3/tests/obj.eq1.wasmbin0 -> 99 bytes
-rw-r--r--tests/proj3/tests/obj.eq1.wat7
-rw-r--r--tests/proj3/tests/obj.eq1.wee.wasmbin0 -> 107 bytes
-rw-r--r--tests/proj3/tests/obj.eq2.runs3
-rw-r--r--tests/proj3/tests/obj.eq2.wasmbin0 -> 106 bytes
-rw-r--r--tests/proj3/tests/obj.eq2.wat7
-rw-r--r--tests/proj3/tests/obj.eq2.wee.wasmbin0 -> 114 bytes
-rw-r--r--tests/proj3/tests/obj.get0.expect1
-rw-r--r--tests/proj3/tests/obj.get0.wasmbin0 -> 73 bytes
-rw-r--r--tests/proj3/tests/obj.get0.wat8
-rw-r--r--tests/proj3/tests/obj.get0.wee.wasmbin0 -> 81 bytes
-rw-r--r--tests/proj3/tests/obj.get1.expect1
-rw-r--r--tests/proj3/tests/obj.get1.wasmbin0 -> 88 bytes
-rw-r--r--tests/proj3/tests/obj.get1.wat8
-rw-r--r--tests/proj3/tests/obj.get1.wee.wasmbin0 -> 96 bytes
-rw-r--r--tests/proj3/tests/obj.getset0.runs2
-rw-r--r--tests/proj3/tests/obj.getset0.wasmbin0 -> 189 bytes
-rw-r--r--tests/proj3/tests/obj.getset0.wat15
-rw-r--r--tests/proj3/tests/obj.getset0.wee.wasmbin0 -> 197 bytes
-rw-r--r--tests/proj3/tests/obj.getset1.runs2
-rw-r--r--tests/proj3/tests/obj.getset1.wasmbin0 -> 193 bytes
-rw-r--r--tests/proj3/tests/obj.getset1.wat13
-rw-r--r--tests/proj3/tests/obj.getset1.wee.wasmbin0 -> 201 bytes
-rw-r--r--tests/proj3/tests/obj.getset2.expect1
-rw-r--r--tests/proj3/tests/obj.getset2.wasmbin0 -> 203 bytes
-rw-r--r--tests/proj3/tests/obj.getset2.wat16
-rw-r--r--tests/proj3/tests/obj.getset2.wee.wasmbin0 -> 211 bytes
-rw-r--r--tests/proj3/tests/obj.getset3_d.runs2
-rw-r--r--tests/proj3/tests/obj.getset3_d.wasmbin0 -> 189 bytes
-rw-r--r--tests/proj3/tests/obj.getset3_d.wat15
-rw-r--r--tests/proj3/tests/obj.getset3_d.wee.wasmbin0 -> 197 bytes
-rw-r--r--tests/proj3/tests/obj.getset4_d.runs3
-rw-r--r--tests/proj3/tests/obj.getset4_d.wasmbin0 -> 201 bytes
-rw-r--r--tests/proj3/tests/obj.getset4_d.wat15
-rw-r--r--tests/proj3/tests/obj.getset4_d.wee.wasmbin0 -> 209 bytes
-rw-r--r--tests/proj3/tests/obj.getset5.runs3
-rw-r--r--tests/proj3/tests/obj.getset5.wasmbin0 -> 217 bytes
-rw-r--r--tests/proj3/tests/obj.getset5.wat14
-rw-r--r--tests/proj3/tests/obj.getset5.wee.wasmbin0 -> 225 bytes
-rw-r--r--tests/proj3/tests/obj.getset6.runs4
-rw-r--r--tests/proj3/tests/obj.getset6.wasmbin0 -> 218 bytes
-rw-r--r--tests/proj3/tests/obj.getset6.wat14
-rw-r--r--tests/proj3/tests/obj.getset6.wee.wasmbin0 -> 226 bytes
-rw-r--r--tests/proj3/tests/obj.inflate0.expect1
-rw-r--r--tests/proj3/tests/obj.inflate0.wasmbin0 -> 203 bytes
-rw-r--r--tests/proj3/tests/obj.inflate0.wat18
-rw-r--r--tests/proj3/tests/obj.inflate0.wee.wasmbin0 -> 211 bytes
-rw-r--r--tests/proj3/tests/obj.new0.expect1
-rw-r--r--tests/proj3/tests/obj.new0.wasmbin0 -> 65 bytes
-rw-r--r--tests/proj3/tests/obj.new0.wat7
-rw-r--r--tests/proj3/tests/obj.new0.wee.wasmbin0 -> 73 bytes
-rw-r--r--tests/proj3/tests/obj.set1.expect1
-rw-r--r--tests/proj3/tests/obj.set1.wasmbin0 -> 96 bytes
-rw-r--r--tests/proj3/tests/obj.set1.wat9
-rw-r--r--tests/proj3/tests/obj.set1.wee.wasmbin0 -> 104 bytes
-rw-r--r--tests/proj3/tests/pick0.runs4
-rw-r--r--tests/proj3/tests/pick0.wasmbin0 -> 146 bytes
-rw-r--r--tests/proj3/tests/pick0.wat27
-rw-r--r--tests/proj3/tests/pick0.wee.wasmbin0 -> 164 bytes
-rw-r--r--tests/proj3/tests/rec.runs1
-rw-r--r--tests/proj3/tests/rec.wasmbin0 -> 65 bytes
-rw-r--r--tests/proj3/tests/rec.wat11
-rw-r--r--tests/proj3/tests/rec.wee.wasmbin0 -> 76 bytes
-rw-r--r--tests/proj3/tests/swap0.expect1
-rw-r--r--tests/proj3/tests/swap0.wasmbin0 -> 115 bytes
-rw-r--r--tests/proj3/tests/swap0.wat17
-rw-r--r--tests/proj3/tests/swap0.wee.wasmbin0 -> 127 bytes
-rw-r--r--tests/proj3/tests/swap1.expect1
-rw-r--r--tests/proj3/tests/swap1.wasmbin0 -> 115 bytes
-rw-r--r--tests/proj3/tests/swap1.wat17
-rw-r--r--tests/proj3/tests/swap1.wee.wasmbin0 -> 127 bytes
-rw-r--r--tests/proj3/tests/tree0.runs6
-rw-r--r--tests/proj3/tests/tree0.wasmbin0 -> 404 bytes
-rw-r--r--tests/proj3/tests/tree0.wat67
-rw-r--r--tests/proj3/tests/tree0.wee.wasmbin0 -> 452 bytes
-rw-r--r--tests/proj3/tests/tree1.runs6
-rw-r--r--tests/proj3/tests/tree1.wasmbin0 -> 351 bytes
-rw-r--r--tests/proj3/tests/tree1.wat58
-rw-r--r--tests/proj3/tests/tree1.wee.wasmbin0 -> 391 bytes
-rw-r--r--tests/proj3/tests/tree2.runs6
-rw-r--r--tests/proj3/tests/tree2.wasmbin0 -> 343 bytes
-rw-r--r--tests/proj3/tests/tree2.wat58
-rw-r--r--tests/proj3/tests/tree2.wee.wasmbin0 -> 383 bytes
-rw-r--r--vm.h20
-rwxr-xr-xweeifybin0 -> 38896 bytes
-rw-r--r--weeify.c647
-rw-r--r--weerun.c68
-rw-r--r--weerun.hpp255
-rw-r--r--weerun_dis.cpp314
-rw-r--r--weerun_inst.cpp978
-rw-r--r--weerun_jit.cpp1726
-rw-r--r--weerun_jit.hpp216
-rw-r--r--weerun_parse.cpp394
-rw-r--r--weerun_runtime.cpp300
-rw-r--r--weewasm.h102
-rw-r--r--xbyak/COPYRIGHT27
-rw-r--r--xbyak/xbyak.h2951
-rw-r--r--xbyak/xbyak_bin2hex.h258
-rw-r--r--xbyak/xbyak_mnemonic.h2329
-rw-r--r--xbyak/xbyak_util.h998
729 files changed, 17174 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..767d53a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,226 @@
+---
+Language: Cpp
+# BasedOnStyle: Chromium
+AccessModifierOffset: -1
+AlignAfterOpenBracket: Align
+AlignArrayOfStructures: None
+AlignConsecutiveMacros: None
+AlignConsecutiveAssignments: None
+AlignConsecutiveBitFields: None
+AlignConsecutiveDeclarations: None
+AlignEscapedNewlines: Left
+AlignOperands: Align
+AlignTrailingComments: true
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortEnumsOnASingleLine: true
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortLambdasOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: true
+AlwaysBreakTemplateDeclarations: Yes
+AttributeMacros:
+ - __capability
+BinPackArguments: true
+BinPackParameters: false
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: Never
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ AfterExternBlock: false
+ BeforeCatch: false
+ BeforeElse: false
+ BeforeLambdaBody: false
+ BeforeWhile: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeConceptDeclarations: true
+BreakBeforeBraces: Attach
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+QualifierAlignment: Leave
+CompactNamespaces: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DeriveLineEnding: true
+DerivePointerAlignment: false
+DisableFormat: false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
+ExperimentalAutoDetectBinPacking: false
+PackConstructorInitializers: NextLine
+BasedOnStyle: ''
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+AllowAllConstructorInitializersOnNextLine: true
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IfMacros:
+ - KJ_IF_MAYBE
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^<ext/.*\.h>'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^<.*\.h>'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^<.*'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '.*'
+ Priority: 3
+ SortPriority: 0
+ CaseSensitive: false
+IncludeIsMainRegex: '([-_](test|unittest))?$'
+IncludeIsMainSourceRegex: ''
+IndentAccessModifiers: false
+IndentCaseLabels: true
+IndentCaseBlocks: false
+IndentGotoLabels: true
+IndentPPDirectives: None
+IndentExternBlock: AfterExternBlock
+IndentRequires: false
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+InsertTrailingCommas: None
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+LambdaBodyIndentation: Signature
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBinPackProtocolList: Never
+ObjCBlockIndentWidth: 2
+ObjCBreakBeforeNestedBlockParam: true
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakOpenParenthesis: 0
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PenaltyIndentedWhitespace: 0
+PointerAlignment: Left
+PPIndentWidth: -1
+RawStringFormats:
+ - Language: Cpp
+ Delimiters:
+ - cc
+ - CC
+ - cpp
+ - Cpp
+ - CPP
+ - 'c++'
+ - 'C++'
+ CanonicalDelimiter: ''
+ BasedOnStyle: google
+ - Language: TextProto
+ Delimiters:
+ - pb
+ - PB
+ - proto
+ - PROTO
+ EnclosingFunctions:
+ - EqualsProto
+ - EquivToProto
+ - PARSE_PARTIAL_TEXT_PROTO
+ - PARSE_TEST_PROTO
+ - PARSE_TEXT_PROTO
+ - ParseTextOrDie
+ - ParseTextProtoOrDie
+ - ParseTestProto
+ - ParsePartialTestProto
+ CanonicalDelimiter: pb
+ BasedOnStyle: google
+ReferenceAlignment: Pointer
+ReflowComments: true
+RemoveBracesLLVM: false
+SeparateDefinitionBlocks: Leave
+ShortNamespaceLines: 1
+SortIncludes: CaseSensitive
+SortJavaStaticImport: Before
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeParensOptions:
+ AfterControlStatements: true
+ AfterForeachMacros: true
+ AfterFunctionDefinitionName: false
+ AfterFunctionDeclarationName: false
+ AfterIfMacros: true
+ AfterOverloadedOperator: false
+ BeforeNonEmptyParentheses: false
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles: Never
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInLineCommentPrefix:
+ Minimum: 1
+ Maximum: -1
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpaceBeforeSquareBrackets: false
+BitFieldColonSpacing: Both
+Standard: Auto
+StatementAttributeLikeMacros:
+ - Q_EMIT
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 8
+UseCRLF: false
+UseTab: Never
+WhitespaceSensitiveMacros:
+ - STRINGIZE
+ - PP_STRINGIZE
+ - BOOST_PP_STRINGIZE
+ - NS_SWIFT_NAME
+ - CF_SWIFT_NAME
+...
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c36729f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+weerun
+.vscode
+xbyak_github
+.gdb_history
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fa6909a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,33 @@
+.PHONY: all clean
+
+CC = gcc
+CXX = g++
+
+ifdef DEBUG
+ OPT = -g -O0
+else
+ OPT = -O3
+endif
+
+CFLAGS = $(OPT) -Wall
+CXXFLAGS = $(OPT) -Wall -std=c++11 -Wno-extern-c-compat -I.
+
+all: weerun
+
+clean:
+ rm -f weerun *.o
+
+test: weerun
+ ./weerun -test
+
+#weerun: vm.h weerun.c common.h common.c ir.c weewasm.h illegal.h weerun.hpp weerun_dis.cpp weerun_inst.cpp weerun_parse.cpp weerun_runtime.cpp
+# cc -g -O0 -Wall -c weerun.c common.c ir.c
+# c++ -g -O0 -Wall -std=c++11 -Wno-extern-c-compat -o weerun -I. \
+# weerun.o common.o ir.o \
+# weerun_dis.cpp weerun_inst.cpp weerun_parse.cpp weerun_jit.cpp weerun_runtime.cpp
+#
+weeify: vm.h weeify.c common.h common.c weewasm.h illegal.h
+ cc -o weeify weeify.c common.c
+
+weerun: weerun.o common.o ir.o weerun_dis.o weerun_inst.o weerun_jit.o weerun_parse.o weerun_runtime.o
+ $(CXX) -o $@ $^
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..3ed85b0
--- /dev/null
+++ b/common.c
@@ -0,0 +1,143 @@
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "common.h"
+
+// The global trace flag
+int g_trace = 0;
+// The global disassembly flag
+int g_disassemble = 0;
+// The global indentation amount
+int g_indent = 0;
+
+#define MORE(b) (((b) & 0x80) != 0)
+#define ERROR (len != NULL ? *len = -(ptr - start) : 0), 0
+
+#define BODY(type, mask, legal) \
+ const uint8_t* start = ptr; \
+ type result = 0, shift = 0; \
+ while (ptr < limit) { \
+ uint8_t b = *ptr; \
+ ptr++; \
+ result = result | (((type)b & 0x7F) << shift); \
+ shift += 7; \
+ if (shift > (8*sizeof(type))) { \
+ if (MORE(b) != 0) return ERROR; /* overlong */ \
+ uint8_t upper = b & mask; \
+ if (upper != 0 && upper != legal) return ERROR; /* out of range */ \
+ if (len != NULL) *len = (ptr - start); \
+ return result; \
+ } \
+ if (MORE(b)) continue; \
+ type rem = ((8*sizeof(type)) - shift); \
+ if (len != NULL) *len = (ptr - start); \
+ return ((0x7F & mask) == legal) ? (result << rem) >> rem : result; \
+ } \
+ return ERROR;
+
+int32_t decode_i32leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) {
+ BODY(int32_t, 0xF8, 0x78);
+}
+
+uint32_t decode_u32leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) {
+ BODY(uint32_t, 0xF8, 0x08);
+}
+
+int64_t decode_i64leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) {
+ BODY(int64_t, 0xFF, 0x7F);
+}
+
+uint64_t decode_u64leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) {
+ BODY(int64_t, 0xFF, 0x01);
+}
+
+uint32_t decode_u32(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) {
+ ssize_t remain = limit - ptr;
+ if (remain < 4) {
+ if (remain > 0) *len = -remain;
+ else *len = remain;
+ return 0;
+ }
+ uint32_t b0 = ptr[0];
+ uint32_t b1 = ptr[1];
+ uint32_t b2 = ptr[2];
+ uint32_t b3 = ptr[3];
+ *len = 4;
+ return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+}
+
+ssize_t load_file(const char* path, uint8_t** start, uint8_t** end) {
+ // Open the file for reading.
+ int fd = open(path, O_RDONLY);
+ if (fd < 0) return fd;
+
+ // Query the size of the file in bytes.
+ struct stat statbuf;
+ int r = fstat(fd, &statbuf);
+ if (r < 0) { // stat call failed.
+ close(fd);
+ return r;
+ }
+
+ // Reject overly large files.
+ off_t size = statbuf.st_size;
+ if (size > MAX_FILE_SIZE) { // too large.
+ close(fd);
+ return -1;
+ }
+
+ // Allocate memory to store the bytes.
+ *start = (uint8_t*)malloc(size);
+ *end = *start + size;
+ off_t remain = size;
+ // Read the bytes from the file until done.
+ for (uint8_t* p = *start; remain > 0; ) {
+ r = read(fd, p, remain);
+ if (r < 0) { // reading failed.
+ close(fd);
+ return -2;
+ }
+ remain -= r;
+ p += r;
+ }
+ return (int)size;
+}
+
+// Read an unsigned 32-bit LEB, advancing the buffer.
+uint32_t read_u32leb(buffer_t* buf) {
+ ssize_t leblen = 0;
+ if (buf->ptr >= buf->end) return 0;
+ uint32_t val = decode_u32leb(buf->ptr, buf->end, &leblen);
+ if (leblen <= 0) buf->ptr = buf->end; // force failure
+ else buf->ptr += leblen;
+ return val;
+}
+
+// Read a signed 32-bit LEB, advancing the buffer.
+int32_t read_i32leb(buffer_t* buf) {
+ ssize_t leblen = 0;
+ if (buf->ptr >= buf->end) return 0;
+ int32_t val = decode_i32leb(buf->ptr, buf->end, &leblen);
+ if (leblen <= 0) buf->ptr = buf->end; // force failure
+ else buf->ptr += leblen;
+ return val;
+}
+
+// Read an unsigned 8-bit byte, advancing the buffer.
+uint32_t read_u8(buffer_t* buf) {
+ if (buf->ptr >= buf->end) return 0;
+ byte val = *buf->ptr;
+ buf->ptr++;
+ return val;
+}
+
+
+ssize_t unload_file(uint8_t** start, uint8_t** end) {
+ free(*start);
+ *start = NULL;
+ *end = NULL;
+ return 0;
+}
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..7616b67
--- /dev/null
+++ b/common.h
@@ -0,0 +1,54 @@
+#pragma once
+#include <stdint.h>
+
+typedef uint8_t byte;
+
+// Limit file size to something reasonable.
+#define MAX_FILE_SIZE 2000000000
+
+// Decode LEB128 values, enforcing the specified signedness and maximum range.
+// The argument {ptr} will be advanced to point after the decoded value.
+// If an error occurs (e.g. unterminated LEB, invalid value), {ptr} will be set to
+// NULL.
+int32_t decode_i32leb(const byte* ptr, const byte* limit, ssize_t* len);
+uint32_t decode_u32leb(const byte* ptr, const byte* limit, ssize_t* len);
+int64_t decode_i64leb(const byte* ptr, const byte* limit, ssize_t* len);
+uint64_t decode_u64leb(const byte* ptr, const byte* limit, ssize_t* len);
+
+// Decode fixed-size integer values.
+uint32_t decode_u32(const byte* ptr, const byte* limit, ssize_t* len);
+
+// Load a file into memory, initializing pointers to the start and end of
+// the memory range containing the data. Returns < 0 on failure.
+ssize_t load_file(const char* path, byte** start, byte** end);
+
+// Unload a file previously loaded into memory using {load_file}.
+ssize_t unload_file(byte** start, byte** end);
+
+// The global trace flag.
+extern int g_trace;
+extern int g_disassemble;
+extern int g_indent;
+
+// Helper macros to trace and to print errors.
+#define TRACE(...) do { if(g_trace) fprintf(stderr, __VA_ARGS__); } while(0)
+#define TRACE_INDENT(...) do { for (int i = 0; i < g_indent; i++) fprintf(stderr, " "); TRACE(__VA_ARGS__); } while(0)
+#define DISASS(...) do { if(g_disassemble) fprintf(stderr, __VA_ARGS__); } while(0)
+#define ERR(...) fprintf(stderr, __VA_ARGS__)
+
+// A helper struct that keeps track of the start and the current pointer of
+// a buffer.
+typedef struct {
+ const byte* start;
+ const byte* ptr;
+ const byte* end;
+} buffer_t;
+
+// Read an unsigned 32-bit LEB, advancing the {ptr} in the buffer.
+uint32_t read_u32leb(buffer_t* buf);
+
+// Read a signed 32-bit LEB, advancing the {ptr} in the buffer.
+int32_t read_i32leb(buffer_t* buf);
+
+// Read an unsigned 8-bit byte, advancing the {ptr} in the buffer.
+uint32_t read_u8(buffer_t* buf);
diff --git a/disass.c b/disass.c
new file mode 100644
index 0000000..cc65495
--- /dev/null
+++ b/disass.c
@@ -0,0 +1,431 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "common.h"
+#include "vm.h"
+#include "test.h"
+#include "weewasm.h"
+#include "illegal.h"
+#include "ir.h"
+#include "disass.h"
+
+#define OUT(...) fprintf(stdout, __VA_ARGS__)
+
+// Returns the string name of a section code.
+const char* section_name(byte code) {
+ switch (code) {
+ case WASM_SECT_TYPE: return "type";
+ case WASM_SECT_IMPORT: return "import";
+ case WASM_SECT_FUNCTION: return "function";
+ case WASM_SECT_TABLE: return "table";
+ case WASM_SECT_MEMORY: return "memory";
+ case WASM_SECT_GLOBAL: return "global";
+ case WASM_SECT_EXPORT: return "export";
+ case WASM_SECT_START: return "start";
+ case WASM_SECT_ELEMENT: return "element";
+ case WASM_SECT_CODE: return "code";
+ case WASM_SECT_DATA: return "data";
+ case 0: return "custom";
+ default:
+ return "unknown";
+ }
+}
+
+// Returns a constant that represents the type code.
+const char* type_name(uint32_t code) {
+ switch (code) {
+ case WASM_TYPE_I32: return "i32";
+ case WASM_TYPE_I64: return "<!illegal i64>";
+ case WASM_TYPE_F32: return "<!illegal f32>";
+ case WASM_TYPE_F64: return "f64";
+ case WASM_TYPE_V128: return "<!illegal v128>";
+ case WASM_TYPE_EXTERNREF: return "externref";
+ case WASM_TYPE_FUNCREF: return "funcref";
+ default: return "<!unknown type>";
+ }
+}
+
+// Returns a constant that represents a type declaration code.
+const char* type_decl_name(uint32_t code) {
+ if (code == 0x60) return "sig";
+ else return "<!unknown type decl>";
+}
+
+// Returns the name of an import kind.
+const char* import_kind_name(uint32_t code) {
+ switch (code) {
+ case WASM_IMPORT_FUNC: return "func";
+ case WASM_IMPORT_TABLE: return "table";
+ case WASM_IMPORT_MEMORY: return "memory";
+ case WASM_IMPORT_GLOBAL: return "global";
+ default: return "<!unknown import kind>";
+ }
+}
+
+// Prints data as hexadecimal.
+void print_data(buffer_t* buf, uint32_t count) {
+ OUT("\n");
+ for (uint32_t i = 0; i < count && buf->ptr < buf->end; i++) {
+ byte b = read_u8(buf);
+ OUT(" %02X", b);
+ if (i % 16 == 15) OUT("\n");
+ }
+ OUT("\n");
+}
+
+// Metadata for disassembling bytecode.
+typedef struct {
+ const char* mnemonic;
+ int immkind;
+ int illegal;
+} opcode_imm_t;
+
+#define IMM_NONE 0
+#define IMM_BLOCKT 1
+#define IMM_LABEL 2
+#define IMM_LABELS 3
+#define IMM_FUNC 4
+#define IMM_SIG_TABLE 5
+#define IMM_LOCAL 6
+#define IMM_GLOBAL 7
+#define IMM_TABLE 8
+#define IMM_MEMARG 9
+#define IMM_I32 10
+#define IMM_F64 11
+#define IMM_MEMORY 12
+#define IMM_TAG 13
+#define IMM_I64 14
+#define IMM_F32 15
+#define IMM_REFNULLT 16
+#define IMM_VALTS 17
+#define IMM_PCDELTA 18
+#define IMM_PCDELTAS 19
+
+opcode_imm_t opcode_imm_table[256] = {
+ [WASM_OP_UNREACHABLE] = {"unreachable" },
+ [WASM_OP_NOP] = {"nop" },
+ [WASM_OP_BLOCK] = {"block", IMM_BLOCKT },
+ [WASM_OP_LOOP] = {"loop", IMM_BLOCKT },
+ [WASM_OP_IF] = {"if", IMM_BLOCKT },
+ [WASM_OP_ELSE] = {"else" },
+ [WASM_OP_END] = {"end" },
+ [WASM_OP_BR] = {"br", IMM_LABEL },
+ [WASM_OP_BR_IF] = {"br_if", IMM_LABEL },
+ [WASM_OP_BR_TABLE] = {"br_table", IMM_LABELS },
+ [WASM_OP_RETURN] = {"return" },
+ [WASM_OP_CALL] = {"call", IMM_FUNC },
+ [WASM_OP_CALL_INDIRECT] = {"call_indirect", IMM_SIG_TABLE },
+ [WASM_OP_DROP] = {"drop" },
+ [WASM_OP_SELECT] = {"select" },
+ [WASM_OP_LOCAL_GET] = {"local.get", IMM_LOCAL },
+ [WASM_OP_LOCAL_SET] = {"local.set", IMM_LOCAL },
+ [WASM_OP_LOCAL_TEE] = {"local.tee", IMM_LOCAL },
+ [WASM_OP_GLOBAL_GET] = {"global.get", IMM_GLOBAL },
+ [WASM_OP_GLOBAL_SET] = {"global.set", IMM_GLOBAL },
+ [WASM_OP_TABLE_GET] = {"table.get", IMM_TABLE },
+ [WASM_OP_TABLE_SET] = {"table.set", IMM_TABLE },
+ [WASM_OP_I32_LOAD] = {"i32.load", IMM_MEMARG },
+ [WASM_OP_F64_LOAD] = {"f64.load", IMM_MEMARG },
+ [WASM_OP_I32_LOAD8_S] = {"i32.load8_s", IMM_MEMARG },
+ [WASM_OP_I32_LOAD8_U] = {"i32.load8_u", IMM_MEMARG },
+ [WASM_OP_I32_LOAD16_S] = {"i32.load16_s", IMM_MEMARG },
+ [WASM_OP_I32_LOAD16_U] = {"i32.load16_u", IMM_MEMARG },
+ [WASM_OP_I32_STORE] = {"i32.store", IMM_MEMARG },
+ [WASM_OP_F64_STORE] = {"f64.store", IMM_MEMARG },
+ [WASM_OP_I32_STORE8] = {"i32.store8", IMM_MEMARG },
+ [WASM_OP_I32_STORE16] = {"i32.store16", IMM_MEMARG },
+ [WASM_OP_I32_CONST] = {"i32.const", IMM_I32 },
+ [WASM_OP_F64_CONST] = {"f64.const", IMM_F64 },
+ [WASM_OP_I32_EQZ] = {"i32.eqz" },
+ [WASM_OP_I32_EQ] = {"i32.eq" },
+ [WASM_OP_I32_NE] = {"i32.ne" },
+ [WASM_OP_I32_LT_S] = {"i32.lt_s" },
+ [WASM_OP_I32_LT_U] = {"i32.lt_u" },
+ [WASM_OP_I32_GT_S] = {"i32.gt_s" },
+ [WASM_OP_I32_GT_U] = {"i32.gt_u" },
+ [WASM_OP_I32_LE_S] = {"i32.le_s" },
+ [WASM_OP_I32_LE_U] = {"i32.le_u" },
+ [WASM_OP_I32_GE_S] = {"i32.ge_s" },
+ [WASM_OP_I32_GE_U] = {"i32.ge_u" },
+ [WASM_OP_F64_EQ] = {"f64.eq" },
+ [WASM_OP_F64_NE] = {"f64.ne" },
+ [WASM_OP_F64_LT] = {"f64.lt" },
+ [WASM_OP_F64_GT] = {"f64.gt" },
+ [WASM_OP_F64_LE] = {"f64.le" },
+ [WASM_OP_F64_GE] = {"f64.ge" },
+ [WASM_OP_I32_CLZ] = {"i32.clz" },
+ [WASM_OP_I32_CTZ] = {"i32.ctz" },
+ [WASM_OP_I32_POPCNT] = {"i32.popcnt" },
+ [WASM_OP_I32_ADD] = {"i32.add" },
+ [WASM_OP_I32_SUB] = {"i32.sub" },
+ [WASM_OP_I32_MUL] = {"i32.mul" },
+ [WASM_OP_I32_DIV_S] = {"i32.div_s" },
+ [WASM_OP_I32_DIV_U] = {"i32.div_u" },
+ [WASM_OP_I32_REM_S] = {"i32.rem_s" },
+ [WASM_OP_I32_REM_U] = {"i32.rem_u" },
+ [WASM_OP_I32_AND] = {"i32.and" },
+ [WASM_OP_I32_OR] = {"i32.or" },
+ [WASM_OP_I32_XOR] = {"i32.xor" },
+ [WASM_OP_I32_SHL] = {"i32.shl" },
+ [WASM_OP_I32_SHR_S] = {"i32.shr_s" },
+ [WASM_OP_I32_SHR_U] = {"i32.shr_u" },
+ [WASM_OP_I32_ROTL] = {"i32.rotl" },
+ [WASM_OP_I32_ROTR] = {"i32.rotr" },
+ [WASM_OP_F64_ADD] = {"f64.add" },
+ [WASM_OP_F64_SUB] = {"f64.sub" },
+ [WASM_OP_F64_MUL] = {"f64.mul" },
+ [WASM_OP_F64_DIV] = {"f64.div" },
+ [WASM_OP_I32_TRUNC_F64_S] = {"i32.trunc_f64_s" },
+ [WASM_OP_I32_TRUNC_F64_U] = {"i32.trunc_f64_u" },
+ [WASM_OP_F64_CONVERT_I32_S] = {"f64.convert_i32_s" },
+ [WASM_OP_F64_CONVERT_I32_U] = {"f64.convert_i32_u" },
+ [WASM_OP_I32_EXTEND8_S] = {"i32.extend8_s" },
+ [WASM_OP_I32_EXTEND16_S] = {"i32.extend16_s" },
+ [WASM_OP_JMP] = {"jmp", IMM_PCDELTA },
+ [WASM_OP_JMP_IF] = {"jmp_if", IMM_PCDELTA },
+ [WASM_OP_JMP_TABLE] = {"jmp_table", IMM_PCDELTAS },
+ // illegal bytecodes
+ [WASM_OP_TRY] = {"try", IMM_BLOCKT, -1},
+ [WASM_OP_CATCH] = {"catch", IMM_TAG, -1},
+ [WASM_OP_THROW] = {"throw", IMM_TAG, -1},
+ [WASM_OP_RETHROW] = {"rethrow", IMM_NONE, -1},
+ [WASM_OP_RETURN_CALL] = {"return_call", IMM_FUNC, -1},
+ [WASM_OP_RETURN_CALL_INDIRECT]= {"return_call_indirect", IMM_SIG_TABLE, -1},
+ [WASM_OP_CALL_REF] = {"call_ref", IMM_NONE, -1},
+ [WASM_OP_RETURN_CALL_REF] = {"return_call_ref", IMM_NONE, -1},
+ [WASM_OP_DELEGATE] = {"delegate", IMM_NONE, -1},
+ [WASM_OP_CATCH_ALL] = {"catch_all", IMM_NONE, -1},
+ [WASM_OP_SELECT_T] = {"select", IMM_VALTS, -1},
+ [WASM_OP_I64_LOAD] = {"i64.load", IMM_MEMARG, -1},
+ [WASM_OP_F32_LOAD] = {"f32.load", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD8_S] = {"i64.load8_s", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD8_U] = {"i64.load8_u", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD16_S] = {"i64.load16_s", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD16_U] = {"i64.load16_u", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD32_S] = {"i64.load32_s", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD32_U] = {"i64.load32_u", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE] = {"i64.store", IMM_MEMARG, -1},
+ [WASM_OP_F32_STORE] = {"f32.store", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE8] = {"i64.store8", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE16] = {"i64.store16", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE32] = {"i64.store32", IMM_MEMARG, -1},
+ [WASM_OP_MEMORY_SIZE] = {"memory.size", IMM_MEMORY, -1},
+ [WASM_OP_MEMORY_GROW] = {"memory.grow", IMM_MEMORY, -1},
+ [WASM_OP_I64_CONST] = {"i64.const", IMM_I64, -1},
+ [WASM_OP_F32_CONST] = {"f32.const", IMM_F32, -1},
+ [WASM_OP_I64_EQZ] = {"i64.eqz", IMM_NONE, -1},
+ [WASM_OP_I64_EQ] = {"i64.eq", IMM_NONE, -1},
+ [WASM_OP_I64_NE] = {"i64.ne", IMM_NONE, -1},
+ [WASM_OP_I64_LT_S] = {"i64.lt_s", IMM_NONE, -1},
+ [WASM_OP_I64_LT_U] = {"i64.lt_u", IMM_NONE, -1},
+ [WASM_OP_I64_GT_S] = {"i64.gt_s", IMM_NONE, -1},
+ [WASM_OP_I64_GT_U] = {"i64.gt_u", IMM_NONE, -1},
+ [WASM_OP_I64_LE_S] = {"i64.le_s", IMM_NONE, -1},
+ [WASM_OP_I64_LE_U] = {"i64.le_u", IMM_NONE, -1},
+ [WASM_OP_I64_GE_S] = {"i64.ge_s", IMM_NONE, -1},
+ [WASM_OP_I64_GE_U] = {"i64.ge_u", IMM_NONE, -1},
+ [WASM_OP_F32_EQ] = {"f32.eq", IMM_NONE, -1},
+ [WASM_OP_F32_NE] = {"f32.ne", IMM_NONE, -1},
+ [WASM_OP_F32_LT] = {"f32.lt", IMM_NONE, -1},
+ [WASM_OP_F32_GT] = {"f32.gt", IMM_NONE, -1},
+ [WASM_OP_F32_LE] = {"f32.le", IMM_NONE, -1},
+ [WASM_OP_F32_GE] = {"f32.ge", IMM_NONE, -1},
+ [WASM_OP_I64_CLZ] = {"i64.clz", IMM_NONE, -1},
+ [WASM_OP_I64_CTZ] = {"i64.ctz", IMM_NONE, -1},
+ [WASM_OP_I64_POPCNT] = {"i64.popcnt", IMM_NONE, -1},
+ [WASM_OP_I64_ADD] = {"i64.add", IMM_NONE, -1},
+ [WASM_OP_I64_SUB] = {"i64.sub", IMM_NONE, -1},
+ [WASM_OP_I64_MUL] = {"i64.mul", IMM_NONE, -1},
+ [WASM_OP_I64_DIV_S] = {"i64.div_s", IMM_NONE, -1},
+ [WASM_OP_I64_DIV_U] = {"i64.div_u", IMM_NONE, -1},
+ [WASM_OP_I64_REM_S] = {"i64.rem_s", IMM_NONE, -1},
+ [WASM_OP_I64_REM_U] = {"i64.rem_u", IMM_NONE, -1},
+ [WASM_OP_I64_AND] = {"i64.and", IMM_NONE, -1},
+ [WASM_OP_I64_OR] = {"i64.or", IMM_NONE, -1},
+ [WASM_OP_I64_XOR] = {"i64.xor", IMM_NONE, -1},
+ [WASM_OP_I64_SHL] = {"i64.shl", IMM_NONE, -1},
+ [WASM_OP_I64_SHR_S] = {"i64.shr_s", IMM_NONE, -1},
+ [WASM_OP_I64_SHR_U] = {"i64.shr_u", IMM_NONE, -1},
+ [WASM_OP_I64_ROTL] = {"i64.rotl", IMM_NONE, -1},
+ [WASM_OP_I64_ROTR] = {"i64.rotr", IMM_NONE, -1},
+ [WASM_OP_F32_ABS] = {"f32.abs", IMM_NONE, -1},
+ [WASM_OP_F32_NEG] = {"f32.neg", IMM_NONE, -1},
+ [WASM_OP_F32_CEIL] = {"f32.ceil", IMM_NONE, -1},
+ [WASM_OP_F32_FLOOR] = {"f32.floor", IMM_NONE, -1},
+ [WASM_OP_F32_TRUNC] = {"f32.trunc", IMM_NONE, -1},
+ [WASM_OP_F32_NEAREST] = {"f32.nearest", IMM_NONE, -1},
+ [WASM_OP_F32_SQRT] = {"f32.sqrt", IMM_NONE, -1},
+ [WASM_OP_F32_ADD] = {"f32.add", IMM_NONE, -1},
+ [WASM_OP_F32_SUB] = {"f32.sub", IMM_NONE, -1},
+ [WASM_OP_F32_MUL] = {"f32.mul", IMM_NONE, -1},
+ [WASM_OP_F32_DIV] = {"f32.div", IMM_NONE, -1},
+ [WASM_OP_F32_MIN] = {"f32.min", IMM_NONE, -1},
+ [WASM_OP_F32_MAX] = {"f32.max", IMM_NONE, -1},
+ [WASM_OP_F32_COPYSIGN] = {"f32.copysign", IMM_NONE, -1},
+ [WASM_OP_F64_ABS] = {"f64.abs", IMM_NONE, -1},
+ [WASM_OP_F64_NEG] = {"f64.neg", IMM_NONE, -1},
+ [WASM_OP_F64_CEIL] = {"f64.ceil", IMM_NONE, -1},
+ [WASM_OP_F64_FLOOR] = {"f64.floor", IMM_NONE, -1},
+ [WASM_OP_F64_TRUNC] = {"f64.trunc", IMM_NONE, -1},
+ [WASM_OP_F64_NEAREST] = {"f64.nearest", IMM_NONE, -1},
+ [WASM_OP_F64_SQRT] = {"f64.sqrt", IMM_NONE, -1},
+ [WASM_OP_F64_MIN] = {"f64.min", IMM_NONE, -1},
+ [WASM_OP_F64_MAX] = {"f64.max", IMM_NONE, -1},
+ [WASM_OP_F64_COPYSIGN] = {"f64.copysign", IMM_NONE, -1},
+ [WASM_OP_I32_WRAP_I64] = {"i32.wrap_i64", IMM_NONE, -1},
+ [WASM_OP_I32_TRUNC_F32_S] = {"i32.trunc_f32_s", IMM_NONE, -1},
+ [WASM_OP_I32_TRUNC_F32_U] = {"i32.trunc_f32_u", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND_I32_S] = {"i64.extend_i32_s", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND_I32_U] = {"i64.extend_i32_u", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F32_S] = {"i64.trunc_f32_s", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F32_U] = {"i64.trunc_f32_u", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F64_S] = {"i64.trunc_f64_s", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F64_U] = {"i64.trunc_f64_u", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I32_S] = {"f32.convert_i32_s", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I32_U] = {"f32.convert_i32_u", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I64_S] = {"f32.convert_i64_s", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I64_U] = {"f32.convert_i64_u", IMM_NONE, -1},
+ [WASM_OP_F64_CONVERT_I64_S] = {"f64.convert_i64_s" , IMM_NONE, -1},
+ [WASM_OP_F64_CONVERT_I64_U] = {"f64.convert_i64_u" , IMM_NONE, -1},
+ [WASM_OP_F32_DEMOTE_F64] = {"f32.demote_f64", IMM_NONE, -1},
+ [WASM_OP_F64_PROMOTE_F32] = {"f64.promote_f32", IMM_NONE, -1},
+ [WASM_OP_I32_REINTERPRET_F32] = {"i32.reinterpret_f32", IMM_NONE, -1},
+ [WASM_OP_I64_REINTERPRET_F64] = {"i64.reinterpret_f64", IMM_NONE, -1},
+ [WASM_OP_F32_REINTERPRET_I32] = {"f32.reinterpret_i32", IMM_NONE, -1},
+ [WASM_OP_F64_REINTERPRET_I64] = {"f64.reinterpret_i64", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND8_S] = {"i64.extend8_s", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND16_S] = {"i64.extend16_s", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND32_S] = {"i64.extend32_s", IMM_NONE, -1},
+ [WASM_OP_REF_NULL] = {"ref.null", IMM_REFNULLT, -1},
+ [WASM_OP_REF_IS_NULL] = {"ref.is_null", IMM_NONE, -1},
+ [WASM_OP_REF_FUNC] = {"ref.func", IMM_FUNC, -1},
+ [WASM_OP_REF_AS_NON_NULL] = {"ref.as_non_null", IMM_NONE, -1},
+ [WASM_OP_BR_ON_NULL] = {"br_on_null", IMM_LABEL, -1},
+ [WASM_OP_REF_EQ] = {"ref.eq", IMM_NONE, -1},
+ [WASM_OP_BR_ON_NON_NULL] = {"br_on_non_null", IMM_LABEL, -1},
+};
+
+#define PRINT(...) do { if(print) fprintf(stdout, __VA_ARGS__); } while(0)
+
+const char* bytecode_name(byte code) {
+ opcode_imm_t* entry = &opcode_imm_table[code];
+ if (entry->mnemonic == NULL) return "<unknown>";
+ return entry->mnemonic;
+}
+
+void do_bytecode(int print, buffer_t* buf) {
+ for (int i = 0; i < g_indent; i++) PRINT(" ");
+ byte code = read_u8(buf);
+ opcode_imm_t* entry = &opcode_imm_table[code];
+ if (entry->mnemonic == NULL) {
+ PRINT("<!illegal bytecode %02X>", code);
+ } else if (entry->illegal) {
+ PRINT("<!illegal %s>", entry->mnemonic);
+ } else {
+ PRINT("%s", entry->mnemonic);
+ }
+ switch (entry->immkind) {
+ case IMM_LABEL: // fallthru
+ case IMM_FUNC: // fallthru
+ case IMM_LOCAL: // fallthru
+ case IMM_GLOBAL: // fallthru
+ case IMM_MEMORY: // fallthru
+ case IMM_TAG: // fallthru
+ case IMM_REFNULLT:
+ case IMM_TABLE: {
+ uint32_t imm = read_u32leb(buf);
+ PRINT(" %u", imm);
+ break;
+ }
+
+ case IMM_NONE: break;
+ case IMM_BLOCKT: {
+ int32_t imm = read_i32leb(buf);
+ if (imm != -64) {
+ PRINT(" <!illegal blocktype %d>", imm);
+ }
+ break;
+ }
+ case IMM_LABELS: {
+ uint32_t count = read_u32leb(buf);
+ PRINT(" %u", count);
+ for (uint32_t i = 0; i <= count && buf->ptr < buf->end; i++) {
+ uint32_t lbl = read_u32leb(buf);
+ PRINT(" %u", lbl);
+ }
+ break;
+ }
+ case IMM_SIG_TABLE: {
+ uint32_t sig = read_u32leb(buf);
+ PRINT(" %d", sig);
+ uint32_t tbl = read_u32leb(buf);
+ if (tbl != 0) {
+ PRINT(" <!illegal table %d>", tbl);
+ }
+ break;
+ }
+ case IMM_MEMARG: {
+ byte b = read_u8(buf);
+ uint32_t offset = read_u32leb(buf);
+ PRINT(" %u", offset);
+ break;
+ }
+ case IMM_I32: {
+ int32_t imm = read_i32leb(buf);
+ PRINT(" %d", imm);
+ break;
+ }
+ case IMM_F64: {
+ if (buf->end - buf->ptr >= 8) {
+ uint64_t val = *((uint64_t*)buf->ptr);
+ PRINT(" %016" PRIx64, val);
+ buf->ptr += 8;
+ } else {
+ PRINT(" <!invalid f64>");
+ }
+ break;
+ }
+ case IMM_I64: {
+ ssize_t leblen = 0;
+ if (buf->ptr >= buf->end) break;
+ int64_t imm = decode_i64leb(buf->ptr, buf->end, &leblen);
+ if (leblen <= 0) buf->ptr = buf->end; // force failure
+ else buf->ptr += leblen;
+ PRINT(" %" PRId64 "", imm);
+ break;
+ }
+ case IMM_F32: {
+ for (int i = 0; i < 4; i++) {
+ byte b = read_u8(buf);
+ PRINT(" %02X", b);
+ }
+ break;
+ }
+ case IMM_VALTS: {
+ int32_t tcode = read_i32leb(buf);
+ PRINT(" %s", type_name(tcode));
+ break;
+ }
+ default: break;
+ }
+ PRINT("\n");
+}
+
+void skip_bytecode(buffer_t* buf) {
+ do_bytecode(0, buf);
+}
+
+void print_bytecode(buffer_t* buf) {
+ do_bytecode(1, buf);
+}
+
+void skip_local_decls(buffer_t* buf) {
+ uint32_t cnt = read_u32leb(buf);
+ for (uint32_t i = 0; i < cnt; i++) {
+ uint32_t cnt = read_u32leb(buf);
+ int32_t type = read_i32leb(buf);
+ }
+}
diff --git a/disass.h b/disass.h
new file mode 100644
index 0000000..4de8d25
--- /dev/null
+++ b/disass.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#define WASM_TYPE_I32 -1
+#define WASM_TYPE_I64 -2
+#define WASM_TYPE_F32 -3
+#define WASM_TYPE_F64 -4
+#define WASM_TYPE_V128 -5
+#define WASM_TYPE_EXTERNREF -17
+#define WASM_TYPE_FUNCREF -16
+
+#define WASM_IMPORT_FUNC 0
+#define WASM_IMPORT_TABLE 1
+#define WASM_IMPORT_MEMORY 2
+#define WASM_IMPORT_GLOBAL 3
+
+// Returns the string name of a section code.
+const char* section_name(byte code);
+
+// Returns the string name of a type code.
+const char* type_name(uint32_t code);
+
+// Returns the string name of a type declaration code.
+const char* type_decl_name(uint32_t code);
+
+// Returns the name of an import kind.
+const char* import_kind_name(uint32_t code);
+
+// Returns the mnemonic name of a bytecode.
+const char* bytecode_name(byte b);
+
+// Prints a bytecode to standard out.
+void print_bytecode(buffer_t* buf);
+
+// Skips to the next bytecode.
+void skip_bytecode(buffer_t* buf);
+
+// Skips over local declarations.
+void skip_local_decls(buffer_t* buf);
+
+// Prints data as hexadecimal.
+void print_data(buffer_t* buf, uint32_t count);
diff --git a/grade.sh b/grade.sh
new file mode 100755
index 0000000..5378138
--- /dev/null
+++ b/grade.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+if [ $# = 0 ]; then
+ WEERUN='./weerun'
+else
+ WEERUN=$1
+ shift
+fi
+
+T=${OUT:=/tmp/$USER/cs17670/$STUDENT/proj2-test/}
+mkdir -p $T
+
+
+if [ ! -x "$WEERUN" ]; then
+ printf "##+weerun\n"
+ printf "##-fail, weerun not found: %s\n" $WEERUN
+ exit 1
+fi
+
+if [ $# = 0 ]; then
+ TESTS=$(ls tests/*.wee.wasm)
+else
+ TESTS=$@
+fi
+
+# substitute for the "timeout" command on MacOS
+function xtimeout {
+ timeout=$1
+ shift
+ command=("$@")
+ (
+ "${command[@]}" &
+ runnerpid=$!
+ trap -- '' SIGTERM
+ ( # killer job
+ sleep $timeout
+ if ps -p $runnerpid > /dev/null; then
+ echo "Timed out, killing"
+ kill -SIGKILL $runnerpid 2>/dev/null
+ fi
+ ) &
+ killerpid=$!
+ wait $runnerpid
+ kill -SIGKILL $killerpid
+ )
+}
+
+function run_one() {
+ echo $WEERUN $f $ARGS
+ xtimeout 5s $WEERUN $f $ARGS > $OUT 2>$ERR
+ # ignore case
+ diff --strip-trailing-cr -i $EXP $OUT > $DIFF
+ OK=$?
+ if [ ! -s $DIFF ]; then
+ # remove empty diffs
+ rm $DIFF
+ else
+ cat $DIFF
+ fi
+
+ if [ $OK = 0 ]; then
+ return 0
+ else
+ echo diff $EXP $OUT
+ printf "##-fail: $ARGS\n"
+ return 1
+ fi
+
+}
+
+for f in $TESTS; do
+ # replace slashes with _
+ t=${f//\//_}
+ # replace .wasm with .runs
+ runs=${f/%.wee.wasm/.runs}
+
+ printf "##+%s\n" $t
+
+ OUT=$T/$t.out
+ ERR=$T/$t.err
+ EXP=$T/$t.expect
+ DIFF=$T/$t.diff
+
+ if [ -f $runs ]; then
+ # do multiple runs for this test
+ ok=1
+ while IFS= read -r line
+ do
+ ARGS=$(echo $line | cut -d= -f1)
+ EXPECT=$(echo $line | cut -d= -f2)
+ echo $EXPECT > $EXP
+
+ run_one
+
+ if [ $? != 0 ]; then
+ ok=0
+ break;
+ fi
+ done < $runs
+ if [ $ok = 1 ]; then
+ printf "##-ok\n"
+ fi
+ else
+ # do one run
+ e=${f/%.wee.wasm/.expect}
+ args=${f/%.wee.wasm/.args}
+ cp $e $EXP
+
+ if [ -f $args ]; then
+ ARGS=$(cat $args)
+ else
+ ARGS=""
+ fi
+
+ run_one
+
+ if [ $? = 0 ]; then
+ printf "##-ok\n"
+ fi
+ fi
+done
diff --git a/illegal.h b/illegal.h
new file mode 100644
index 0000000..1f9c135
--- /dev/null
+++ b/illegal.h
@@ -0,0 +1,124 @@
+#pragma once
+
+#define WASM_OP_IF 0x04 /* "if" BLOCKT */
+#define WASM_OP_ELSE 0x05 /* "else" */
+#define WASM_OP_TRY 0x06 /* "try", ImmSigs.BLOCKT */
+#define WASM_OP_CATCH 0x07 /* "catch", ImmSigs.TAG */
+#define WASM_OP_THROW 0x08 /* "throw", ImmSigs.TAG */
+#define WASM_OP_RETHROW 0x09 /* "rethrow", ImmSigs.NONE */
+#define WASM_OP_RETURN_CALL 0x12 /* "return_call", ImmSigs.FUNC */
+#define WASM_OP_RETURN_CALL_INDIRECT 0x13 /* "return_call_indirect", ImmSigs.SIG_TABLE */
+#define WASM_OP_CALL_REF 0x14 /* "call_ref", ImmSigs.NONE */
+#define WASM_OP_RETURN_CALL_REF 0x15 /* "return_call_ref", ImmSigs.NONE */
+#define WASM_OP_DELEGATE 0x18 /* "delegate", ImmSigs.NONE */
+#define WASM_OP_CATCH_ALL 0x19 /* "catch_all", ImmSigs.NONE */
+#define WASM_OP_SELECT_T 0x1C /* "select", ImmSigs.VALTS */
+#define WASM_OP_TABLE_GET 0x25 /* "table.get" TABLE */
+#define WASM_OP_TABLE_SET 0x26 /* "table.set" TABLE */
+#define WASM_OP_I64_LOAD 0x29 /* "i64.load", ImmSigs.MEMARG */
+#define WASM_OP_F32_LOAD 0x2A /* "f32.load", ImmSigs.MEMARG */
+#define WASM_OP_I64_LOAD8_S 0x30 /* "i64.load8_s", ImmSigs.MEMARG */
+#define WASM_OP_I64_LOAD8_U 0x31 /* "i64.load8_u", ImmSigs.MEMARG */
+#define WASM_OP_I64_LOAD16_S 0x32 /* "i64.load16_s", ImmSigs.MEMARG */
+#define WASM_OP_I64_LOAD16_U 0x33 /* "i64.load16_u", ImmSigs.MEMARG */
+#define WASM_OP_I64_LOAD32_S 0x34 /* "i64.load32_s", ImmSigs.MEMARG */
+#define WASM_OP_I64_LOAD32_U 0x35 /* "i64.load32_u", ImmSigs.MEMARG */
+#define WASM_OP_I64_STORE 0x37 /* "i64.store", ImmSigs.MEMARG */
+#define WASM_OP_F32_STORE 0x38 /* "f32.store", ImmSigs.MEMARG */
+#define WASM_OP_I64_STORE8 0x3C /* "i64.store8", ImmSigs.MEMARG */
+#define WASM_OP_I64_STORE16 0x3D /* "i64.store16", ImmSigs.MEMARG */
+#define WASM_OP_I64_STORE32 0x3E /* "i64.store32", ImmSigs.MEMARG */
+#define WASM_OP_MEMORY_SIZE 0x3F /* "memory.size", ImmSigs.MEMORY */
+#define WASM_OP_MEMORY_GROW 0x40 /* "memory.grow", ImmSigs.MEMORY */
+#define WASM_OP_I64_CONST 0x42 /* "i64.const", ImmSigs.I64 */
+#define WASM_OP_F32_CONST 0x43 /* "f32.const", ImmSigs.F32 */
+#define WASM_OP_I64_EQZ 0x50 /* "i64.eqz", ImmSigs.NONE */
+#define WASM_OP_I64_EQ 0x51 /* "i64.eq", ImmSigs.NONE */
+#define WASM_OP_I64_NE 0x52 /* "i64.ne", ImmSigs.NONE */
+#define WASM_OP_I64_LT_S 0x53 /* "i64.lt_s", ImmSigs.NONE */
+#define WASM_OP_I64_LT_U 0x54 /* "i64.lt_u", ImmSigs.NONE */
+#define WASM_OP_I64_GT_S 0x55 /* "i64.gt_s", ImmSigs.NONE */
+#define WASM_OP_I64_GT_U 0x56 /* "i64.gt_u", ImmSigs.NONE */
+#define WASM_OP_I64_LE_S 0x57 /* "i64.le_s", ImmSigs.NONE */
+#define WASM_OP_I64_LE_U 0x58 /* "i64.le_u", ImmSigs.NONE */
+#define WASM_OP_I64_GE_S 0x59 /* "i64.ge_s", ImmSigs.NONE */
+#define WASM_OP_I64_GE_U 0x5A /* "i64.ge_u", ImmSigs.NONE */
+#define WASM_OP_F32_EQ 0x5B /* "f32.eq", ImmSigs.NONE */
+#define WASM_OP_F32_NE 0x5C /* "f32.ne", ImmSigs.NONE */
+#define WASM_OP_F32_LT 0x5D /* "f32.lt", ImmSigs.NONE */
+#define WASM_OP_F32_GT 0x5E /* "f32.gt", ImmSigs.NONE */
+#define WASM_OP_F32_LE 0x5F /* "f32.le", ImmSigs.NONE */
+#define WASM_OP_F32_GE 0x60 /* "f32.ge", ImmSigs.NONE */
+#define WASM_OP_I64_CLZ 0x79 /* "i64.clz", ImmSigs.NONE */
+#define WASM_OP_I64_CTZ 0x7A /* "i64.ctz", ImmSigs.NONE */
+#define WASM_OP_I64_POPCNT 0x7B /* "i64.popcnt", ImmSigs.NONE */
+#define WASM_OP_I64_ADD 0x7C /* "i64.add", ImmSigs.NONE */
+#define WASM_OP_I64_SUB 0x7D /* "i64.sub", ImmSigs.NONE */
+#define WASM_OP_I64_MUL 0x7E /* "i64.mul", ImmSigs.NONE */
+#define WASM_OP_I64_DIV_S 0x7F /* "i64.div_s", ImmSigs.NONE */
+#define WASM_OP_I64_DIV_U 0x80 /* "i64.div_u", ImmSigs.NONE */
+#define WASM_OP_I64_REM_S 0x81 /* "i64.rem_s", ImmSigs.NONE */
+#define WASM_OP_I64_REM_U 0x82 /* "i64.rem_u", ImmSigs.NONE */
+#define WASM_OP_I64_AND 0x83 /* "i64.and", ImmSigs.NONE */
+#define WASM_OP_I64_OR 0x84 /* "i64.or", ImmSigs.NONE */
+#define WASM_OP_I64_XOR 0x85 /* "i64.xor", ImmSigs.NONE */
+#define WASM_OP_I64_SHL 0x86 /* "i64.shl", ImmSigs.NONE */
+#define WASM_OP_I64_SHR_S 0x87 /* "i64.shr_s", ImmSigs.NONE */
+#define WASM_OP_I64_SHR_U 0x88 /* "i64.shr_u", ImmSigs.NONE */
+#define WASM_OP_I64_ROTL 0x89 /* "i64.rotl", ImmSigs.NONE */
+#define WASM_OP_I64_ROTR 0x8A /* "i64.rotr", ImmSigs.NONE */
+#define WASM_OP_F32_ABS 0x8B /* "f32.abs", ImmSigs.NONE */
+#define WASM_OP_F32_NEG 0x8C /* "f32.neg", ImmSigs.NONE */
+#define WASM_OP_F32_CEIL 0x8D /* "f32.ceil", ImmSigs.NONE */
+#define WASM_OP_F32_FLOOR 0x8E /* "f32.floor", ImmSigs.NONE */
+#define WASM_OP_F32_TRUNC 0x8F /* "f32.trunc", ImmSigs.NONE */
+#define WASM_OP_F32_NEAREST 0x90 /* "f32.nearest", ImmSigs.NONE */
+#define WASM_OP_F32_SQRT 0x91 /* "f32.sqrt", ImmSigs.NONE */
+#define WASM_OP_F32_ADD 0x92 /* "f32.add", ImmSigs.NONE */
+#define WASM_OP_F32_SUB 0x93 /* "f32.sub", ImmSigs.NONE */
+#define WASM_OP_F32_MUL 0x94 /* "f32.mul", ImmSigs.NONE */
+#define WASM_OP_F32_DIV 0x95 /* "f32.div", ImmSigs.NONE */
+#define WASM_OP_F32_MIN 0x96 /* "f32.min", ImmSigs.NONE */
+#define WASM_OP_F32_MAX 0x97 /* "f32.max", ImmSigs.NONE */
+#define WASM_OP_F32_COPYSIGN 0x98 /* "f32.copysign", ImmSigs.NONE */
+#define WASM_OP_F64_ABS 0x99 /* "f64.abs", ImmSigs.NONE */
+#define WASM_OP_F64_NEG 0x9A /* "f64.neg", ImmSigs.NONE */
+#define WASM_OP_F64_CEIL 0x9B /* "f64.ceil", ImmSigs.NONE */
+#define WASM_OP_F64_FLOOR 0x9C /* "f64.floor", ImmSigs.NONE */
+#define WASM_OP_F64_TRUNC 0x9D /* "f64.trunc", ImmSigs.NONE */
+#define WASM_OP_F64_NEAREST 0x9E /* "f64.nearest", ImmSigs.NONE */
+#define WASM_OP_F64_SQRT 0x9F /* "f64.sqrt", ImmSigs.NONE */
+#define WASM_OP_F64_MIN 0xA4 /* "f64.min", ImmSigs.NONE */
+#define WASM_OP_F64_MAX 0xA5 /* "f64.max", ImmSigs.NONE */
+#define WASM_OP_F64_COPYSIGN 0xA6 /* "f64.copysign", ImmSigs.NONE */
+#define WASM_OP_I32_WRAP_I64 0xA7 /* "i32.wrap_i64", ImmSigs.NONE */
+#define WASM_OP_I32_TRUNC_F32_S 0xA8 /* "i32.trunc_f32_s", ImmSigs.NONE */
+#define WASM_OP_I32_TRUNC_F32_U 0xA9 /* "i32.trunc_f32_u", ImmSigs.NONE */
+#define WASM_OP_I64_EXTEND_I32_S 0xAC /* "i64.extend_i32_s", ImmSigs.NONE */
+#define WASM_OP_I64_EXTEND_I32_U 0xAD /* "i64.extend_i32_u", ImmSigs.NONE */
+#define WASM_OP_I64_TRUNC_F32_S 0xAE /* "i64.trunc_f32_s", ImmSigs.NONE */
+#define WASM_OP_I64_TRUNC_F32_U 0xAF /* "i64.trunc_f32_u", ImmSigs.NONE */
+#define WASM_OP_I64_TRUNC_F64_S 0xB0 /* "i64.trunc_f64_s", ImmSigs.NONE */
+#define WASM_OP_I64_TRUNC_F64_U 0xB1 /* "i64.trunc_f64_u", ImmSigs.NONE */
+#define WASM_OP_F32_CONVERT_I32_S 0xB2 /* "f32.convert_i32_s", ImmSigs.NONE */
+#define WASM_OP_F32_CONVERT_I32_U 0xB3 /* "f32.convert_i32_u", ImmSigs.NONE */
+#define WASM_OP_F32_CONVERT_I64_S 0xB4 /* "f32.convert_i64_s", ImmSigs.NONE */
+#define WASM_OP_F32_CONVERT_I64_U 0xB5 /* "f32.convert_i64_u", ImmSigs.NONE */
+#define WASM_OP_F32_DEMOTE_F64 0xB6 /* "f32.demote_f64", ImmSigs.NONE */
+#define WASM_OP_F64_CONVERT_I64_S 0xB9 /* "f64.convert_i64_s" */
+#define WASM_OP_F64_CONVERT_I64_U 0xBA /* "f64.convert_i64_u" */
+#define WASM_OP_F64_PROMOTE_F32 0xBB /* "f64.promote_f32", ImmSigs.NONE */
+#define WASM_OP_I32_REINTERPRET_F32 0xBC /* "i32.reinterpret_f32", ImmSigs.NONE */
+#define WASM_OP_I64_REINTERPRET_F64 0xBD /* "i64.reinterpret_f64", ImmSigs.NONE */
+#define WASM_OP_F32_REINTERPRET_I32 0xBE /* "f32.reinterpret_i32", ImmSigs.NONE */
+#define WASM_OP_F64_REINTERPRET_I64 0xBF /* "f64.reinterpret_i64", ImmSigs.NONE */
+#define WASM_OP_I64_EXTEND8_S 0xC2 /* "i64.extend8_s", ImmSigs.NONE */
+#define WASM_OP_I64_EXTEND16_S 0xC3 /* "i64.extend16_s", ImmSigs.NONE */
+#define WASM_OP_I64_EXTEND32_S 0xC4 /* "i64.extend32_s", ImmSigs.NONE */
+#define WASM_OP_REF_NULL 0xD0 /* "ref.null", ImmSigs.REFNULLT */
+#define WASM_OP_REF_IS_NULL 0xD1 /* "ref.is_null", ImmSigs.NONE */
+#define WASM_OP_REF_FUNC 0xD2 /* "ref.func", ImmSigs.FUNC */
+#define WASM_OP_REF_AS_NON_NULL 0xD3 /* "ref.as_non_null", ImmSigs.NONE */
+#define WASM_OP_BR_ON_NULL 0xD4 /* "br_on_null", ImmSigs.LABEL */
+#define WASM_OP_REF_EQ 0xD5 /* "ref.eq", ImmSigs.NONE */
+#define WASM_OP_BR_ON_NON_NULL 0xD6 /* "br_on_non_null", ImmSigs.LABEL */
diff --git a/ir.c b/ir.c
new file mode 100644
index 0000000..e5a5aa8
--- /dev/null
+++ b/ir.c
@@ -0,0 +1,88 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "ir.h"
+
+wasm_value_t parse_wasm_value(char* str) {
+ int len = strlen(str);
+ if (len > 0) {
+ if (str[len - 1] == 'd' || str[len - 1] == 'D') {
+ // treat the input as a double
+ char* end = NULL;
+ double result = strtod(str, &end);
+ if (end == (str + len - 1))
+ return wasm_f64_value(result);
+ } else {
+ // treat the input as an integer
+ char* end = NULL;
+ int base = 10;
+ if (len >= 2 && (str[1] == 'x' || str[1] == 'X'))
+ base = 16;
+ long result = strtol(str, &end, base);
+ if (end == (str + len))
+ return wasm_i32_value(result);
+ }
+ }
+ wasm_value_t orig_string = {
+ .val.ref = str,
+ };
+ return orig_string;
+}
+
+void print_wasm_value(wasm_typed_value_t val) {
+ switch (val.tag) {
+ case I32:
+ printf("%d", val.val.val.i32);
+ break;
+ case F64:
+ printf("%lf", val.val.val.f64);
+ break;
+ case EXTERNREF:
+ if (val.val.val.ref == NULL)
+ printf("null");
+ else
+ printf("%p", val.val.val.ref);
+ break;
+ }
+}
+
+void trace_wasm_value(wasm_typed_value_t val) {
+ switch (val.tag) {
+ case I32:
+ TRACE("%d", val.val.val.i32);
+ break;
+ case F64:
+ TRACE("%lf", val.val.val.f64);
+ break;
+ case EXTERNREF:
+ if (val.val.val.ref == NULL)
+ printf("null");
+ else
+ TRACE("%p", val.val.val.ref);
+ break;
+ }
+}
+
+wasm_value_t wasm_i32_value(int32_t val) {
+ wasm_value_t r = {
+ .val.i32 = val,
+ };
+ return r;
+}
+
+wasm_value_t wasm_f64_value(double val) {
+ wasm_value_t r = {
+ .val.f64 = val,
+ };
+ return r;
+}
+
+wasm_value_t wasm_ref_value(void* val) {
+ wasm_value_t r = {
+ .val.ref = val,
+ };
+ return r;
+}
diff --git a/ir.h b/ir.h
new file mode 100644
index 0000000..18b8303
--- /dev/null
+++ b/ir.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <stdint.h>
+
+typedef uint8_t byte;
+
+typedef enum {
+ I32 = 0x7f,
+ F64 = 0x7c,
+ EXTERNREF = 0x6f,
+ FUNCREF = 0x70
+} wasm_type_t;
+
+typedef enum { FUNC, GLOBAL, TABLE, MEMORY } wasm_import_kind_t;
+
+typedef struct {
+ union {
+ uint32_t i32;
+ double f64;
+ void* ref;
+ uint64_t i64;
+ } val;
+} wasm_value_t;
+
+typedef struct {
+ uint64_t tag;
+ wasm_value_t val;
+} wasm_typed_value_t;
+
+typedef struct {
+ int32_t length; // < 0 indicates a trap or error
+ wasm_value_t* vals;
+} wasm_values;
+
+wasm_value_t parse_wasm_value(char* string);
+void print_wasm_value(wasm_typed_value_t val);
+void trace_wasm_value(wasm_typed_value_t val);
+
+wasm_value_t wasm_i32_value(int32_t val);
+wasm_value_t wasm_f64_value(double val);
+wasm_value_t wasm_ref_value(void* val);
diff --git a/noderun.js b/noderun.js
new file mode 100644
index 0000000..8e5ab75
--- /dev/null
+++ b/noderun.js
@@ -0,0 +1,106 @@
+const fs = require("fs");
+
+var args = process.argv.slice(3);
+const filename = process.argv[2];
+const bytes = fs.readFileSync(filename);
+const wasm = new WebAssembly.Module(bytes);
+
+function log(s) {
+// process.stdout.write(s + "\n");
+}
+
+// The imports for Wee-O-Wasm, implemented in JavaScript.
+const imports = {weewasm: {
+ puti: v => process.stdout.write("" + (v | 0)),
+ putd: v => process.stdout.write("" + (+v)),
+ // TODO: puts requires the module to export its memory, which is currently disallowed in WeeWasm.
+
+ // Allocates a new WeeWasm object.
+ "obj.new": () => new WeakMap(),
+ // Gets a property from a WeeWasm object, given the key.
+ "obj.get": function(ref, key) {
+ var obj = toWeeObject(ref);
+ log("obj.get(" + obj + ", " + key + ")");
+ if (key == null) throw new Error("null key");
+ var v;
+ if ((typeof key) == "number") {
+ v = obj[key];
+ } else if (key instanceof F64Box) { // F64s must be unboxed and stored separately
+ v = getF64s(obj)[key.val];
+ } else {
+ v = obj.get(key);
+ }
+ return v == undefined ? null : v;
+ },
+ // Sets a property from a WeeWasm object, given the key and the value
+ "obj.set": function(ref, key, val) {
+ var obj = toWeeObject(ref);
+ log("obj.set(" + obj + ", " + key + ", " + val + ")");
+ if (key == null) throw new Error("null key");
+ if ((typeof key) == "number") {
+ obj[key] = val;
+ } else if (key instanceof F64Box) { // F64s must be unboxed and stored separately
+ getF64s(obj)[key.val] = val;
+ } else {
+ obj.set(key, val);
+ }
+ },
+ // Converts an i32 into a WeeWasm reference.
+ "obj.box_i32": v => v | 0, // ints are represented as regular JS numbers
+ // Converts an f64 into a WeeWasm reference.
+ "obj.box_f64": v => new F64Box(+v), // floats are boxed to distinguish from ints
+ // Converts a reference back to an i32.
+ "i32.unbox": function(v) {
+ if (typeof v == "number") return v | 0;
+ throw new Error("not an i32");
+ },
+ // Converts a reference back to an f64.
+ "f64.unbox": function(v) {
+ if (v instanceof F64Box) return +v.val;
+ throw new Error("not an f64");
+ },
+ // Compare two references for equality.
+ "obj.eq": (a, b) => {
+ if (a instanceof F64Box) return (b instanceof F64Box) && a.val == b.val;
+ return a === b;
+ }
+}};
+
+function toWeeObject(obj) {
+ if (obj == null) throw new Error("null reference");
+ if (!(obj instanceof WeakMap)) throw new Error("not a wee object");
+ return obj;
+}
+
+function getF64s(obj) {
+ var elems = obj.f64s;
+ if (elems == undefined) elems = obj.f64s = new Object();
+ return elems;
+}
+
+// F64s represented boxed floats, to distinguish from int
+function F64Box(v) {
+ this.val = v;
+}
+
+const instance = new WebAssembly.Instance(wasm, imports);
+
+var main = instance.exports["main"];
+
+for (var i = 0; i < args.length; i++) {
+ var a = args[i];
+ if (a.endsWith("d")) { // double
+ args[i] = +(a.substring(0, a.length - 1));
+ } else { // integer
+ args[i] = a | 0;
+ }
+}
+
+try {
+ var result = main(...args);
+ if (filename.search("_d.wee.wasm") >= 0) console.log(result.toFixed(6)); // to match C's printf
+ else console.log(result);
+} catch (e) {
+ console.log("!trap");
+ process.stderr.write("" + e + "\n");
+}
diff --git a/noderun.sh b/noderun.sh
new file mode 100755
index 0000000..3f474b3
--- /dev/null
+++ b/noderun.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+NODE=${NODE:=$(which node)}
+exec $NODE --experimental-wasm-reftypes noderun.js "$@"
diff --git a/parse.c b/parse.c
new file mode 100644
index 0000000..8b2ac81
--- /dev/null
+++ b/parse.c
@@ -0,0 +1,449 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "common.h"
+#include "vm.h"
+#include "test.h"
+#include "weewasm.h"
+#include "illegal.h"
+#include "ir.h"
+#include "disass.h"
+
+#define CHECK(x) do { if(!(x)) return -2; } while(0)
+
+// Read a string and print its length and UTF-8 chars.
+int read_and_copy_string(buffer_t* buf, const char** nameptr, const byte* sectend) {
+ uint32_t namelen = read_u32leb(buf);
+ DISASS("%u ", namelen);
+ if (nameptr != NULL) *nameptr = strndup((const char*)buf->ptr, namelen);
+ CHECK((sectend - buf->ptr) >= namelen);
+ DISASS("\"%.*s\"", namelen, buf->ptr);
+ buf->ptr += namelen;
+ return 0;
+}
+
+wasm_type_t read_value_type(buffer_t* buf) {
+ int32_t type = read_i32leb(buf);
+ DISASS(" %s", type_name(type));
+ switch (type) {
+ case WASM_TYPE_I32: return I32;
+ case WASM_TYPE_F64: return F64;
+ case WASM_TYPE_EXTERNREF: return EXTERNREF;
+ default:
+ ERR("!illegal type (%s)", type_name(type));
+ return EXTERNREF;
+ }
+}
+
+wasm_value_t read_init_expr(buffer_t* buf) {
+ wasm_value_t val = wasm_i32_value(0);
+ byte b = read_u8(buf);
+ switch (b) {
+ case WASM_OP_I32_CONST: {
+ val = wasm_i32_value(read_i32leb(buf));
+ break;
+ }
+ case WASM_OP_F64_CONST: {
+ double* p = (double*)buf->ptr;
+ buf->ptr += 8;
+ val = wasm_f64_value(*p);
+ break;
+ }
+ default: {
+ ERR("!illegal init expr bytecode 0x%02X (%s)", b, bytecode_name(b));
+ break;
+ }
+ }
+ b = read_u8(buf);
+ if (b != WASM_OP_END) ERR("!illegal init expr bytecode 0x%02X", b);
+ return val;
+}
+
+// Read minimimum and optional maximum.
+void read_limits(buffer_t* buf, wasm_limits_t* dest) {
+ byte val = read_u8(buf);
+ dest->initial = read_u32leb(buf);
+ if ((val & 1) == 1) {
+ dest->max = read_u32leb(buf);
+ dest->has_max = 1;
+ DISASS(" %u %u \t\t\t; initial and max\n", dest->initial, dest->max);
+ } else {
+ dest->max = 0xFFFFFFFFu;
+ dest->has_max = 0;
+ DISASS(" %u \t\t\t; initial\n", dest->initial);
+ }
+}
+
+// Reads a section code, skipping custom sections.
+int read_section_code(buffer_t* buf, wasm_module_t* module, uint32_t* sectlen) {
+ while (buf->ptr < buf->end) {
+ byte code = read_u8(buf);
+ if (code != 0) {
+ DISASS("%s ", section_name(code));
+ // read a normal section
+ *sectlen = read_u32leb(buf);
+ CHECK((buf->end - buf->ptr) >= *sectlen);
+ return code;
+ }
+ // print custom section
+ DISASS("custom ");
+ uint32_t sectlen = read_u32leb(buf);
+ DISASS("%u ", sectlen);
+ CHECK((buf->end - buf->ptr) >= sectlen);
+ const byte* sectend = buf->ptr + sectlen;
+ read_and_copy_string(buf, NULL, sectend);
+ DISASS("\n");
+ buf->ptr = sectend;
+ }
+ // reached the end of the file, or there was a nested error
+ return -1;
+}
+
+void read_type_decl(buffer_t* buf, wasm_sig_decl_t* dest, const byte* sectend) {
+ byte code = read_u8(buf);
+ DISASS(" %s", type_decl_name(code));
+ if (code != 0x60) ERR("!expected signature declaration (0x60), got 0x%02X", code);
+ uint32_t pcount = read_u32leb(buf);
+ DISASS(" %u", pcount);
+ dest->num_params = pcount;
+ dest->params = (wasm_type_t*)malloc(pcount * sizeof(wasm_type_t));
+ for (uint32_t i = 0; i < pcount && (buf->ptr < buf->end); i++) {
+ wasm_type_t t = read_value_type(buf);
+ dest->params[i] = t;
+ }
+ uint32_t rcount = read_u32leb(buf);
+ dest->num_results = rcount;
+ dest->results = (wasm_type_t*)malloc(rcount * sizeof(wasm_type_t));
+ DISASS(" %u", rcount);
+ if (rcount > 1) ERR("!expected result count <= 1, got %d", rcount);
+ for (uint32_t i = 0; i < rcount && (buf->ptr < buf->end); i++) {
+ wasm_type_t t = read_value_type(buf);
+ dest->results[i] = t;
+ }
+ DISASS("\n");
+}
+
+uint8_t bind_import(wasm_module_t* module, wasm_import_decl_t* decl) {
+ if (strcmp(decl->mod_name, "weewasm") != 0) ERR("!unrecognized import module: %s", decl->mod_name);
+ if (strcmp(decl->member_name, "puti") == 0) return WEEWASM_INTRINSIC_PUTI; // TODO: check signature
+ if (strcmp(decl->member_name, "putd") == 0) return WEEWASM_INTRINSIC_PUTD;
+ if (strcmp(decl->member_name, "puts") == 0) return WEEWASM_INTRINSIC_PUTS;
+ ERR("!unrecognized weewasm import: %s", decl->member_name);
+ return 0;
+}
+
+void read_import_decl(buffer_t* buf, wasm_module_t* module, uint32_t import_index, uint32_t func_index, const byte* sectend) {
+ DISASS(" ");
+ wasm_import_decl_t* dest = &module->imports[import_index];
+ read_and_copy_string(buf, &dest->mod_name, sectend);
+ DISASS(" ");
+ read_and_copy_string(buf, &dest->member_name, sectend);
+ uint32_t code = read_u8(buf);
+ DISASS(" %s", import_kind_name(code));
+ switch (code) {
+ case WASM_IMPORT_FUNC: {
+ uint32_t sig = read_u32leb(buf);
+ DISASS(" %u", sig);
+ dest->kind = FUNC;
+ dest->index = func_index;
+ wasm_func_decl_t* func = &module->funcs[func_index];
+ func->sig_index = sig;
+ func->intrinsic = bind_import(module, dest);
+ break;
+ }
+ case WASM_IMPORT_TABLE: {
+ ERR("!illegal table import");
+ break;
+ }
+ case WASM_IMPORT_MEMORY: {
+ ERR("!illegal memory import");
+ break;
+ }
+ case WASM_IMPORT_GLOBAL: {
+ ERR("!illegal global import");
+ break;
+ }
+ }
+ DISASS("\n");
+}
+
+void read_func_decl(buffer_t* buf, wasm_func_decl_t* dest, const byte* sectend) {
+ uint32_t index = read_u32leb(buf);
+ dest->sig_index = index;
+ DISASS(" %u \t\t\t; signature index\n", index);
+}
+
+void read_table_decl(buffer_t* buf, wasm_table_decl_t* dest, const byte* sectend) {
+ int32_t type = read_i32leb(buf);
+ DISASS(" %s", type_name(type));
+ if (type != WASM_TYPE_FUNCREF) ERR("!invalid table type %s", type_name(type));
+ read_limits(buf, &dest->limits);
+ DISASS("\n");
+}
+
+void read_memory_decl(buffer_t* buf, wasm_limits_t* limits, const byte* sectend) {
+ read_limits(buf, limits);
+ DISASS("\n");
+}
+
+void read_global_decl(buffer_t* buf, wasm_global_decl_t* dest, const byte* sectend) {
+ dest->type = read_value_type(buf);
+ byte mut = read_u8(buf);
+ dest->mutable = mut != 0;
+ if (mut != 0) DISASS(" mutable");
+ DISASS("\n");
+ dest->init = read_init_expr(buf);
+}
+
+void read_export_decl(buffer_t* buf, wasm_module_t* module, const byte* sectend) {
+ DISASS(" ");
+ uint32_t namelen = 0;
+ const char* name = NULL;
+ read_and_copy_string(buf, &name, sectend);
+ if (strcmp(name, "main") != 0) ERR("!expected export name \"main\", got %s", name);
+ free((char*)name); // XXX: avoid copy?
+
+ uint32_t code = read_u8(buf);
+ DISASS(" %s", import_kind_name(code));
+ uint32_t index = read_u32leb(buf);
+ DISASS(" %u \t\t\t; export index\n", index);
+ switch (code) {
+ case WASM_IMPORT_FUNC: {
+ module->main_func = (int32_t)index;
+ break;
+ }
+ case WASM_IMPORT_TABLE: {
+ ERR("!illegal table export");
+ break;
+ }
+ case WASM_IMPORT_MEMORY: {
+ ERR("!illegal memory export");
+ break;
+ }
+ case WASM_IMPORT_GLOBAL: {
+ ERR("!illegal global export");
+ break;
+ }
+ }
+}
+
+uint32_t read_offset_expr(buffer_t* buf) {
+ uint32_t val = 0;
+ while (buf->ptr < buf->end) {
+ byte b = read_u8(buf);
+ if (b == WASM_OP_I32_CONST) {
+ val = (uint32_t)read_i32leb(buf);
+ DISASS(" %u \t\t\t; offset\n", val);
+ } else if (b == WASM_OP_END) {
+ break;
+ } else {
+ DISASS("<!unexpected bytecode %02X>", b);
+ break;
+ }
+ }
+ return val;
+}
+
+void read_elems_decl(buffer_t* buf, wasm_elems_decl_t* dest, const byte* sectend) {
+ byte b = read_u32leb(buf);
+ if (b != 0) {
+ DISASS(" <!invalid elem flags %d>", b);
+ } else {
+ DISASS(" ");
+ dest->table_offset = read_offset_expr(buf);
+ uint32_t count = read_u32leb(buf);
+ dest->length = count;
+ dest->func_indexes = (uint32_t*)malloc(dest->length * sizeof(uint32_t));
+ DISASS(" %u \t\t\t; count\n ", count);
+ for (uint32_t i = 0; i < count && buf->ptr < buf->end; i++) {
+ uint32_t f = read_u32leb(buf);
+ DISASS(" %u", f);
+ dest->func_indexes[i] = f;
+ }
+ }
+ DISASS("\n");
+}
+
+void read_code_decl(buffer_t* buf, wasm_func_decl_t* dest, const byte* sectend) {
+ uint32_t len = read_u32leb(buf);
+ dest->code_start = (uint32_t)(buf->ptr - buf->start);
+ const byte* codeend = buf->ptr + len;
+ DISASS("body %u \t\t\t; length\n", len);
+ uint32_t cnt = read_u32leb(buf);
+ DISASS(" %u \t\t\t; locals count\n", cnt);
+ for (uint32_t i = 0; i < cnt; i++) {
+ uint32_t cnt = read_u32leb(buf);
+ DISASS(" %u", cnt);
+ int32_t type = read_i32leb(buf);
+ DISASS(" %s\n", type_name(type));
+ }
+ if (g_disassemble) {
+ // disassemble code
+ while (buf->ptr < codeend && buf->ptr < buf->end) {
+ print_bytecode(buf);
+ }
+ }
+ buf->ptr = codeend;
+ dest->code_end = (uint32_t)(buf->ptr - buf->start);
+}
+
+void read_data_decl(buffer_t* buf, wasm_data_decl_t* dest, const byte* sectend) {
+ byte b = read_u32leb(buf);
+ if (b != 0) {
+ DISASS(" <!invalid data flags %d>", b);
+ } else {
+ dest->mem_offset = read_offset_expr(buf);
+ uint32_t count = read_u32leb(buf);
+ DISASS(" %u \t\t\t; bytes count\n", count);
+ dest->bytes_start = (uint32_t)(buf->ptr - buf->start);
+ if (g_disassemble) {
+ print_data(buf, count);
+ } else {
+ buf->ptr += count;
+ if (buf->ptr > buf->end) {
+ ERR("!too much data, %d bytes", count);
+ buf->ptr = buf->end;
+ }
+ }
+ dest->bytes_end = (uint32_t)(buf->ptr - buf->start);
+ }
+ DISASS("\n");
+}
+
+void allocMoreItems(void** ptr, uint32_t* nptr, size_t item_size, uint32_t add) {
+ byte* curbuf = *ptr;
+ uint32_t curcnt = *nptr;
+ size_t cursize = curcnt * item_size;
+ uint32_t newcnt = curcnt + add;
+ size_t newsize = newcnt * item_size;
+ byte* newbuf = (byte*)realloc(curbuf, newsize);
+ memset(newbuf + cursize, 0, newsize - cursize);
+ *ptr = newbuf;
+ *nptr = newcnt;
+}
+
+uint32_t read_count(buffer_t* buf, uint32_t max, byte sectcode) {
+ uint32_t count = read_u32leb(buf);
+ DISASS("%u \t\t\t; count\n", count);
+ if (count > max) ERR("!expected count <= %d for %s section, got %d", max, section_name(sectcode), count);
+ return count;
+}
+
+// A macro to read the count of entries, expand internal storage, and call {read_func} in a loop.
+#define READ_ENTRIES(count_field, ptr_field, entry_type, read_func) do { \
+ uint32_t count = read_count(buf, 100000, sectcode); \
+ uint32_t j = module->count_field; \
+ allocMoreItems((void**)&module->ptr_field, &module->count_field, sizeof(entry_type), count); \
+ for (uint32_t i = 0; i < count; i++, j++) { \
+ read_func(buf, &module->ptr_field[j], sectend); \
+ } \
+ } while (0)
+
+
+// The main parsing routine.
+int parse_wasm_module(buffer_t* buf, wasm_module_t* module) {
+ ssize_t len = 0;
+
+ //==== Check magic word =============================================
+ uint32_t magic = decode_u32(buf->ptr, buf->end, &len);
+ DISASS("read_magic = %x\n", magic);
+ if (len != 4 || magic != WASM_MAGIC) {
+ ERR("!invalid magic word, expected %x\n", WASM_MAGIC);
+ return -1;
+ }
+ buf->ptr += 4;
+
+ //==== Check Wasm Version ===========================================
+ uint32_t version = decode_u32(buf->ptr, buf->end, &len);
+ DISASS("read_version = %x\n", version);
+ if (len != 4 || version != WASM_VERSION) {
+ ERR("!invalid Wasm version, expected %x\n", WASM_VERSION);
+ return -2;
+ }
+ buf->ptr += 4;
+
+ //==== Read Wasm sections ===========================================
+ while (buf->ptr < buf->end) {
+ uint32_t sectlen = 0;
+ int sectcode = read_section_code(buf, module, &sectlen);
+ if (sectcode < 0) return -3;
+ const byte* sectend = buf->ptr + sectlen;
+
+ switch (sectcode) {
+ case WASM_SECT_TYPE: {
+ READ_ENTRIES(num_sigs, sigs, wasm_sig_decl_t, read_type_decl);
+ break;
+ }
+ case WASM_SECT_IMPORT: {
+ uint32_t count = read_count(buf, 1000, sectcode);
+ uint32_t import_index = module->num_imports;
+ uint32_t func_index = module->num_funcs;
+ // all imports must be functions.
+ allocMoreItems((void**)&module->imports, &module->num_imports, sizeof(wasm_import_decl_t), count);
+ allocMoreItems((void**)&module->funcs, &module->num_funcs, sizeof(wasm_func_decl_t), count);
+ for (uint32_t i = 0; i < count; i++, import_index++, func_index++) {
+ read_import_decl(buf, module, import_index, func_index, sectend);
+ }
+ break;
+ }
+ case WASM_SECT_FUNCTION: {
+ READ_ENTRIES(num_funcs, funcs, wasm_func_decl_t, read_func_decl);
+ break;
+ }
+ case WASM_SECT_TABLE: {
+ read_count(buf, 1, sectcode);
+ if (module->table != NULL) ERR("!repeated table section");
+ module->table = (wasm_table_decl_t*)malloc(sizeof(wasm_table_decl_t));
+ read_table_decl(buf, module->table, sectend);
+ break;
+ }
+ case WASM_SECT_MEMORY: {
+ read_count(buf, 1, sectcode);
+ read_memory_decl(buf, &module->mem_limits, sectend);
+ break;
+ }
+ case WASM_SECT_GLOBAL: {
+ READ_ENTRIES(num_globals, globals, wasm_global_decl_t, read_global_decl);
+ break;
+ }
+ case WASM_SECT_EXPORT: {
+ read_count(buf, 1, sectcode);
+ read_export_decl(buf, module, sectend);
+ break;
+ }
+ case WASM_SECT_START: {
+ uint32_t entry = read_u32leb(buf);
+ module->start_func = (int32_t)entry;
+ DISASS("%u\n", entry);
+ break;
+ }
+ case WASM_SECT_ELEMENT: {
+ READ_ENTRIES(num_elems, elems, wasm_elems_decl_t, read_elems_decl);
+ break;
+ }
+ case WASM_SECT_CODE: {
+ uint32_t num_bodies = module->num_funcs - module->num_imports;
+ uint32_t count = read_count(buf, num_bodies, sectcode);
+ if (count != num_bodies) ERR("!expected %d function bodies, got %d", num_bodies, count);
+ uint32_t func_index = module->num_imports;
+ for (uint32_t i = 0; i < count; i++, func_index++) {
+ read_code_decl(buf, &module->funcs[func_index], sectend);
+ }
+ break;
+ }
+ case WASM_SECT_DATA: {
+ READ_ENTRIES(num_data, data, wasm_data_decl_t, read_data_decl);
+ break;
+ }
+ default:
+ ERR("!unknown section constant 0x%02x\n", sectcode);
+ return -4;
+ }
+ CHECK(buf->ptr == sectend); // internal check
+ }
+ return 0;
+}
+
diff --git a/rewrite.c b/rewrite.c
new file mode 100644
index 0000000..21cf9ef
--- /dev/null
+++ b/rewrite.c
@@ -0,0 +1,141 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "common.h"
+#include "vm.h"
+#include "test.h"
+#include "weewasm.h"
+#include "illegal.h"
+#include "ir.h"
+#include "disass.h"
+
+typedef struct {
+ unsigned is_loop: 1;
+ uint32_t start_pc;
+ uint32_t num_refs;
+ uint32_t capacity;
+ int32_t** refs;
+} control_entry_t;
+
+void ref_entry(control_entry_t* entry, byte* pcdelta) {
+ if (entry->num_refs >= entry->capacity) {
+ uint32_t ncapacity = 4 + entry->capacity * 2;
+ TRACE("ncapacity = %u\n", ncapacity);
+ entry->refs = (int32_t**)realloc(entry->refs, sizeof(int32_t*) * ncapacity);
+ entry->capacity = ncapacity;
+ }
+ entry->refs[entry->num_refs++] = (int32_t*)pcdelta;
+}
+
+// Reads what should be a 4-byte LEB indicating a depth.
+uint32_t read_label(buffer_t* buf) {
+ const byte* before = buf->ptr;
+ uint32_t result = read_u32leb(buf);
+ uint32_t size = (uint32_t)(buf->ptr - before);
+ if (size != 4) ERR("invalid weewasm @+%d: expected 4 byte label, got %u bytes", (int)(before - buf->start), size);
+ return result;
+}
+
+// Rewrites "br*" to "jmp*"
+void rewrite_brs(byte* start, byte* end) {
+ buffer_t onstack_buf = { start, start, end };
+ buffer_t* buf = &onstack_buf;
+
+ uint32_t control_sp = 0;
+ uint32_t capacity = 16;
+ control_entry_t* control_stack = calloc(sizeof(control_entry_t), 16);
+
+ {
+ // push the initial control entry
+ control_entry_t* entry = &control_stack[control_sp++];
+ entry->start_pc = (uint32_t)(buf->ptr - buf->start);
+ entry->num_refs = 0;
+ }
+
+ // process all bytecodes, ignoring all but control flow
+ while (buf->ptr < buf->end) {
+ int pc = (int)(buf->ptr - buf->start);
+ byte b = *buf->ptr;
+ switch (b) {
+ case WASM_OP_BLOCK: // fall through
+ case WASM_OP_LOOP: {
+ TRACE("-> +%3d rewrite: control_block, depth=%d\n", pc, control_sp);
+ if (control_sp >= capacity) {
+ uint32_t ncapacity = capacity * 2;
+ control_stack = (control_entry_t*)realloc(control_stack, sizeof(control_entry_t) * ncapacity);
+ memset(&control_stack[control_sp], 0, sizeof(control_entry_t) * (ncapacity - control_sp));
+ }
+ control_entry_t* entry = &control_stack[control_sp++];
+ entry->is_loop = b == WASM_OP_LOOP;
+ entry->start_pc = (uint32_t)(buf->ptr - buf->start);
+ entry->num_refs = 0;
+ buf->ptr++;
+ read_i32leb(buf); // skip block type
+ break;
+ }
+ case WASM_OP_END: {
+ TRACE("-> +%-3d rewrite: end, depth=%d\n", pc, control_sp);
+ control_entry_t* entry = &control_stack[control_sp - 1];
+ int32_t target_pc = entry->is_loop ? (int32_t)entry->start_pc : (int32_t)(buf->ptr - buf->start);
+ for (uint32_t i = 0; i < entry->num_refs; i++) {
+ int32_t ref_pc = (int32_t)((const byte*)entry->refs[i] - buf->start);
+ TRACE("-> +%-3d rewrite: patch => %d\n", ref_pc, (target_pc - ref_pc));
+ *(entry->refs[i]) = target_pc - ref_pc;
+ }
+ buf->ptr++;
+ control_sp--;
+ break;
+ }
+ case WASM_OP_BR: {
+ *(byte*)buf->ptr = WASM_OP_JMP;
+ buf->ptr++;
+ byte* pcdelta = (byte*)buf->ptr;
+ uint32_t depth = read_label(buf);
+ TRACE("-> +%-3d rewrite: br %u\n", (int)(pcdelta - buf->start), depth);
+ if ((buf->ptr - pcdelta) < 4) ERR("!unpadded br");
+ control_entry_t* entry = &control_stack[control_sp - depth - 1];
+ ref_entry(entry, pcdelta);
+ break;
+ }
+ case WASM_OP_BR_IF: {
+ *(byte*)buf->ptr = WASM_OP_JMP_IF;
+ buf->ptr++;
+ byte* pcdelta = (byte*)buf->ptr;
+ uint32_t depth = read_label(buf);
+ TRACE("-> +%-3d rewrite: br_if %u\n", (int)(pcdelta - buf->start), depth);
+ if ((buf->ptr - pcdelta) < 4) ERR("!unpadded br_if");
+ control_entry_t* entry = &control_stack[control_sp - depth - 1];
+ ref_entry(entry, pcdelta);
+ break;
+ }
+ case WASM_OP_BR_TABLE: {
+ *(byte*)buf->ptr = WASM_OP_JMP_TABLE;
+ buf->ptr++;
+ uint32_t count = read_u32leb(buf);
+ for (uint32_t i = 0; i < count + 1; i++) {
+ byte* pcdelta = (byte*)buf->ptr;
+ uint32_t depth = read_label(buf);
+ TRACE("-> +%-3d rewrite: br_table[%u] %u\n", (int)(pcdelta - buf->start), i, depth);
+ if ((buf->ptr - pcdelta) < 4) ERR("!unpadded br_table");
+ control_entry_t* entry = &control_stack[control_sp - depth - 1];
+ ref_entry(entry, pcdelta);
+ }
+ break;
+ }
+ default: {
+ TRACE("-> +%-3d rewrite: ...\n", pc);
+ skip_bytecode(buf);
+ break;
+ }
+ }
+ }
+
+ // free control stack memory
+ for (uint32_t i = 0; i < capacity; i++) {
+ free(control_stack[i].refs);
+ }
+ free(control_stack);
+}
diff --git a/tests/proj2/grade.sh b/tests/proj2/grade.sh
new file mode 100755
index 0000000..66359e7
--- /dev/null
+++ b/tests/proj2/grade.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+if [ $# = 0 ]; then
+ WEERUN='../../weerun'
+else
+ WEERUN=$1
+ shift
+fi
+
+T=${OUT:=/tmp/$USER/cs17670/$STUDENT/proj2-test/}
+mkdir -p $T
+
+
+if [ ! -x "$WEERUN" ]; then
+ printf "##+weerun\n"
+ printf "##-fail, weerun not found: %s\n" $WEERUN
+ exit 1
+fi
+
+if [ $# = 0 ]; then
+ TESTS=$(ls tests/*.wee.wasm)
+else
+ TESTS=$@
+fi
+
+# substitute for the "timeout" command on MacOS
+function xtimeout {
+ timeout=$1
+ shift
+ command=("$@")
+ (
+ "${command[@]}" &
+ runnerpid=$!
+ trap -- '' SIGTERM
+ ( # killer job
+ sleep $timeout
+ if ps -p $runnerpid > /dev/null; then
+ echo "Timed out, killing"
+ kill -SIGKILL $runnerpid 2>/dev/null
+ fi
+ ) &
+ killerpid=$!
+ wait $runnerpid
+ kill -SIGKILL $killerpid
+ )
+}
+
+function run_one() {
+ echo $WEERUN $f $ARGS
+ xtimeout 5s $WEERUN $f $ARGS > $OUT 2>$ERR
+ # ignore case
+ diff -i $EXP $OUT > $DIFF
+ OK=$?
+ if [ ! -s $DIFF ]; then
+ # remove empty diffs
+ rm $DIFF
+ else
+ cat $DIFF
+ fi
+
+ if [ $OK = 0 ]; then
+ return 0
+ else
+ echo diff $EXP $OUT
+ printf "##-fail: $ARGS\n"
+ return 1
+ fi
+
+}
+
+for f in $TESTS; do
+ # replace slashes with _
+ t=${f//\//_}
+ # replace .wasm with .runs
+ runs=${f/%.wee.wasm/.runs}
+
+ printf "##+%s\n" $t
+
+ OUT=$T/$t.out
+ ERR=$T/$t.err
+ EXP=$T/$t.expect
+ DIFF=$T/$t.diff
+
+ if [ -f $runs ]; then
+ # do multiple runs for this test
+ ok=1
+ while IFS= read -r line
+ do
+ ARGS=$(echo $line | cut -d= -f1)
+ EXPECT=$(echo $line | cut -d= -f2)
+ echo $EXPECT > $EXP
+
+ run_one
+
+ if [ $? != 0 ]; then
+ ok=0
+ break;
+ fi
+ done < $runs
+ if [ $ok = 1 ]; then
+ printf "##-ok\n"
+ fi
+ else
+ # do one run
+ e=${f/%.wee.wasm/.expect}
+ args=${f/%.wee.wasm/.args}
+ cp $e $EXP
+
+ if [ -f $args ]; then
+ ARGS=$(cat $args)
+ else
+ ARGS=""
+ fi
+
+ run_one
+
+ if [ $? = 0 ]; then
+ printf "##-ok\n"
+ fi
+ fi
+done
diff --git a/tests/proj2/tests/add0.runs b/tests/proj2/tests/add0.runs
new file mode 100644
index 0000000..e1a7ce1
--- /dev/null
+++ b/tests/proj2/tests/add0.runs
@@ -0,0 +1,7 @@
+8 9 = 17
+33 44 = 77
+111 222 = 333
+2222 3333 = 5555
+111111111 666666666 = 777777777
+-2147483648 -2147483648 = 0
+-2129587951 -2093796557 = 71582788
diff --git a/tests/proj2/tests/add0.wasm b/tests/proj2/tests/add0.wasm
new file mode 100644
index 0000000..cca89af
--- /dev/null
+++ b/tests/proj2/tests/add0.wasm
Binary files differ
diff --git a/tests/proj2/tests/add0.wat b/tests/proj2/tests/add0.wat
new file mode 100644
index 0000000..cb46d02
--- /dev/null
+++ b/tests/proj2/tests/add0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.add (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/add0.wee.wasm b/tests/proj2/tests/add0.wee.wasm
new file mode 100644
index 0000000..d8ed0f6
--- /dev/null
+++ b/tests/proj2/tests/add0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br0.expect b/tests/proj2/tests/br0.expect
new file mode 100644
index 0000000..920a139
--- /dev/null
+++ b/tests/proj2/tests/br0.expect
@@ -0,0 +1 @@
+43
diff --git a/tests/proj2/tests/br0.wasm b/tests/proj2/tests/br0.wasm
new file mode 100644
index 0000000..c71f1fb
--- /dev/null
+++ b/tests/proj2/tests/br0.wasm
Binary files differ
diff --git a/tests/proj2/tests/br0.wat b/tests/proj2/tests/br0.wat
new file mode 100644
index 0000000..d4607f2
--- /dev/null
+++ b/tests/proj2/tests/br0.wat
@@ -0,0 +1,8 @@
+(module
+ (func (export "main") (result i32)
+ (block
+ (br 0)
+ )
+ (i32.const 43)
+ )
+)
diff --git a/tests/proj2/tests/br0.wee.wasm b/tests/proj2/tests/br0.wee.wasm
new file mode 100644
index 0000000..83ec9f9
--- /dev/null
+++ b/tests/proj2/tests/br0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br1.expect b/tests/proj2/tests/br1.expect
new file mode 100644
index 0000000..abac1ea
--- /dev/null
+++ b/tests/proj2/tests/br1.expect
@@ -0,0 +1 @@
+47
diff --git a/tests/proj2/tests/br1.wasm b/tests/proj2/tests/br1.wasm
new file mode 100644
index 0000000..bb64ae0
--- /dev/null
+++ b/tests/proj2/tests/br1.wasm
Binary files differ
diff --git a/tests/proj2/tests/br1.wat b/tests/proj2/tests/br1.wat
new file mode 100644
index 0000000..0e6e1f6
--- /dev/null
+++ b/tests/proj2/tests/br1.wat
@@ -0,0 +1,6 @@
+(module
+ (func (export "main") (result i32)
+ (i32.const 47)
+ (br 0)
+ )
+)
diff --git a/tests/proj2/tests/br1.wee.wasm b/tests/proj2/tests/br1.wee.wasm
new file mode 100644
index 0000000..75de416
--- /dev/null
+++ b/tests/proj2/tests/br1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br2.expect b/tests/proj2/tests/br2.expect
new file mode 100644
index 0000000..95f9650
--- /dev/null
+++ b/tests/proj2/tests/br2.expect
@@ -0,0 +1 @@
+49
diff --git a/tests/proj2/tests/br2.wasm b/tests/proj2/tests/br2.wasm
new file mode 100644
index 0000000..49568d1
--- /dev/null
+++ b/tests/proj2/tests/br2.wasm
Binary files differ
diff --git a/tests/proj2/tests/br2.wat b/tests/proj2/tests/br2.wat
new file mode 100644
index 0000000..05c1ad8
--- /dev/null
+++ b/tests/proj2/tests/br2.wat
@@ -0,0 +1,9 @@
+(module
+ (func (export "main") (result i32)
+ (block
+ (i32.const 49)
+ (br 1)
+ drop)
+ (i32.const 67)
+ )
+)
diff --git a/tests/proj2/tests/br2.wee.wasm b/tests/proj2/tests/br2.wee.wasm
new file mode 100644
index 0000000..cd769c4
--- /dev/null
+++ b/tests/proj2/tests/br2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br3.expect b/tests/proj2/tests/br3.expect
new file mode 100644
index 0000000..59343b0
--- /dev/null
+++ b/tests/proj2/tests/br3.expect
@@ -0,0 +1 @@
+53
diff --git a/tests/proj2/tests/br3.wasm b/tests/proj2/tests/br3.wasm
new file mode 100644
index 0000000..22be754
--- /dev/null
+++ b/tests/proj2/tests/br3.wasm
Binary files differ
diff --git a/tests/proj2/tests/br3.wat b/tests/proj2/tests/br3.wat
new file mode 100644
index 0000000..b5872ab
--- /dev/null
+++ b/tests/proj2/tests/br3.wat
@@ -0,0 +1,11 @@
+(module
+ (func (export "main") (result i32)
+ (block
+ (block
+ (i32.const 53)
+ (br 2)
+ drop)
+ )
+ (i32.const 67)
+ )
+)
diff --git a/tests/proj2/tests/br3.wee.wasm b/tests/proj2/tests/br3.wee.wasm
new file mode 100644
index 0000000..17ab547
--- /dev/null
+++ b/tests/proj2/tests/br3.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_if0.runs b/tests/proj2/tests/br_if0.runs
new file mode 100644
index 0000000..cf65396
--- /dev/null
+++ b/tests/proj2/tests/br_if0.runs
@@ -0,0 +1,3 @@
+0 = 57
+1 = 46
+87234 = 46
diff --git a/tests/proj2/tests/br_if0.wasm b/tests/proj2/tests/br_if0.wasm
new file mode 100644
index 0000000..4e6e06a
--- /dev/null
+++ b/tests/proj2/tests/br_if0.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_if0.wat b/tests/proj2/tests/br_if0.wat
new file mode 100644
index 0000000..a07f636
--- /dev/null
+++ b/tests/proj2/tests/br_if0.wat
@@ -0,0 +1,8 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.const 46)
+ (br_if 0 (local.get 0))
+ (drop)
+ (i32.const 57)
+ )
+) \ No newline at end of file
diff --git a/tests/proj2/tests/br_if0.wee.wasm b/tests/proj2/tests/br_if0.wee.wasm
new file mode 100644
index 0000000..552356f
--- /dev/null
+++ b/tests/proj2/tests/br_if0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_if1.runs b/tests/proj2/tests/br_if1.runs
new file mode 100644
index 0000000..a47419c
--- /dev/null
+++ b/tests/proj2/tests/br_if1.runs
@@ -0,0 +1,7 @@
+0 0 = 66
+1 0 = 44
+0 1 = 55
+-1 0 = 44
+0 -1 = 55
+98237 55 = 44
+0 982345 = 55
diff --git a/tests/proj2/tests/br_if1.wasm b/tests/proj2/tests/br_if1.wasm
new file mode 100644
index 0000000..e1df9fa
--- /dev/null
+++ b/tests/proj2/tests/br_if1.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_if1.wat b/tests/proj2/tests/br_if1.wat
new file mode 100644
index 0000000..82d9c07
--- /dev/null
+++ b/tests/proj2/tests/br_if1.wat
@@ -0,0 +1,11 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.const 44)
+ (br_if 0 (local.get 0))
+ (drop)
+ (i32.const 55)
+ (br_if 0 (local.get 1))
+ (drop)
+ (i32.const 66)
+ )
+) \ No newline at end of file
diff --git a/tests/proj2/tests/br_if1.wee.wasm b/tests/proj2/tests/br_if1.wee.wasm
new file mode 100644
index 0000000..5db77d6
--- /dev/null
+++ b/tests/proj2/tests/br_if1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_if2.runs b/tests/proj2/tests/br_if2.runs
new file mode 100644
index 0000000..581af19
--- /dev/null
+++ b/tests/proj2/tests/br_if2.runs
@@ -0,0 +1,8 @@
+0 0 0 = 44
+1 0 0 = 11
+0 1 0 = 22
+0 0 1 = 33
+1 0 0 = 11
+1 1 0 = 11
+1 1 1 = 11
+0 1 1 = 22
diff --git a/tests/proj2/tests/br_if2.wasm b/tests/proj2/tests/br_if2.wasm
new file mode 100644
index 0000000..08e61b5
--- /dev/null
+++ b/tests/proj2/tests/br_if2.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_if2.wat b/tests/proj2/tests/br_if2.wat
new file mode 100644
index 0000000..bd2d810
--- /dev/null
+++ b/tests/proj2/tests/br_if2.wat
@@ -0,0 +1,16 @@
+(module
+ (func (export "main") (param i32 i32 i32) (result i32)
+ (block
+ (i32.const 11)
+ (br_if 1 (local.get 0))
+ (drop)
+ (i32.const 22)
+ (br_if 1 (local.get 1))
+ (drop)
+ (i32.const 33)
+ (br_if 1 (local.get 2))
+ (drop)
+ )
+ (i32.const 44)
+ )
+)
diff --git a/tests/proj2/tests/br_if2.wee.wasm b/tests/proj2/tests/br_if2.wee.wasm
new file mode 100644
index 0000000..db48ae7
--- /dev/null
+++ b/tests/proj2/tests/br_if2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table0.runs b/tests/proj2/tests/br_table0.runs
new file mode 100644
index 0000000..deffe69
--- /dev/null
+++ b/tests/proj2/tests/br_table0.runs
@@ -0,0 +1,3 @@
+0 = 94
+-1 = 94
+23434 = 94
diff --git a/tests/proj2/tests/br_table0.wasm b/tests/proj2/tests/br_table0.wasm
new file mode 100644
index 0000000..660eb49
--- /dev/null
+++ b/tests/proj2/tests/br_table0.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table0.wat b/tests/proj2/tests/br_table0.wat
new file mode 100644
index 0000000..7aa020f
--- /dev/null
+++ b/tests/proj2/tests/br_table0.wat
@@ -0,0 +1,6 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.const 94)
+ (br_table 0 (local.get 0) )
+ )
+)
diff --git a/tests/proj2/tests/br_table0.wee.wasm b/tests/proj2/tests/br_table0.wee.wasm
new file mode 100644
index 0000000..7cf29af
--- /dev/null
+++ b/tests/proj2/tests/br_table0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table1.runs b/tests/proj2/tests/br_table1.runs
new file mode 100644
index 0000000..11d1cc5
--- /dev/null
+++ b/tests/proj2/tests/br_table1.runs
@@ -0,0 +1,6 @@
+0 = 93
+1 = 93
+2 = 93
+3 = 93
+-1 = 93
+23434 = 93
diff --git a/tests/proj2/tests/br_table1.wasm b/tests/proj2/tests/br_table1.wasm
new file mode 100644
index 0000000..dc8ae2a
--- /dev/null
+++ b/tests/proj2/tests/br_table1.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table1.wat b/tests/proj2/tests/br_table1.wat
new file mode 100644
index 0000000..31bd3c5
--- /dev/null
+++ b/tests/proj2/tests/br_table1.wat
@@ -0,0 +1,6 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.const 93)
+ (br_table 0 0 (local.get 0) )
+ )
+)
diff --git a/tests/proj2/tests/br_table1.wee.wasm b/tests/proj2/tests/br_table1.wee.wasm
new file mode 100644
index 0000000..90f6628
--- /dev/null
+++ b/tests/proj2/tests/br_table1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table2.runs b/tests/proj2/tests/br_table2.runs
new file mode 100644
index 0000000..8524df6
--- /dev/null
+++ b/tests/proj2/tests/br_table2.runs
@@ -0,0 +1,12 @@
+0 = 92
+1 = 92
+2 = 92
+3 = 92
+4 = 92
+5 = 92
+5 = 92
+6 = 92
+7 = 92
+8 = 92
+-1 = 92
+23434 = 92
diff --git a/tests/proj2/tests/br_table2.wasm b/tests/proj2/tests/br_table2.wasm
new file mode 100644
index 0000000..2912524
--- /dev/null
+++ b/tests/proj2/tests/br_table2.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table2.wat b/tests/proj2/tests/br_table2.wat
new file mode 100644
index 0000000..eb73907
--- /dev/null
+++ b/tests/proj2/tests/br_table2.wat
@@ -0,0 +1,6 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.const 92)
+ (br_table 0 0 0 0 0 0 0 0 0 0 0 (local.get 0) )
+ )
+)
diff --git a/tests/proj2/tests/br_table2.wee.wasm b/tests/proj2/tests/br_table2.wee.wasm
new file mode 100644
index 0000000..f6c9b55
--- /dev/null
+++ b/tests/proj2/tests/br_table2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table3.runs b/tests/proj2/tests/br_table3.runs
new file mode 100644
index 0000000..2bcccc4
--- /dev/null
+++ b/tests/proj2/tests/br_table3.runs
@@ -0,0 +1,6 @@
+0 = 22
+1 = 20
+11 = 20
+-1 = 20
+-100 = 20
+-1 = 20
diff --git a/tests/proj2/tests/br_table3.wasm b/tests/proj2/tests/br_table3.wasm
new file mode 100644
index 0000000..c2d8b97
--- /dev/null
+++ b/tests/proj2/tests/br_table3.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table3.wat b/tests/proj2/tests/br_table3.wat
new file mode 100644
index 0000000..e6e71a6
--- /dev/null
+++ b/tests/proj2/tests/br_table3.wat
@@ -0,0 +1,12 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (block
+ (block
+ (br_table 1 0 (local.get 0))
+ (return (i32.const 21))
+ )
+ (return (i32.const 20))
+ )
+ (i32.const 22)
+ )
+) \ No newline at end of file
diff --git a/tests/proj2/tests/br_table3.wee.wasm b/tests/proj2/tests/br_table3.wee.wasm
new file mode 100644
index 0000000..423cbdc
--- /dev/null
+++ b/tests/proj2/tests/br_table3.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table4.runs b/tests/proj2/tests/br_table4.runs
new file mode 100644
index 0000000..9c5bf64
--- /dev/null
+++ b/tests/proj2/tests/br_table4.runs
@@ -0,0 +1,24 @@
+0 = 45
+1 = 46
+2 = 47
+3 = 48
+4 = 49
+5 = 56
+6 = 56
+7 = 49
+8 = 48
+9 = 47
+10 = 46
+11 = 45
+12 = 45
+13 = 45
+14 = 46
+15 = 46
+16 = 47
+17 = 47
+18 = 47
+19 = 47
+20 = 47
+21 = 47
+22 = 47
+23 = 47
diff --git a/tests/proj2/tests/br_table4.wasm b/tests/proj2/tests/br_table4.wasm
new file mode 100644
index 0000000..5ed1ddf
--- /dev/null
+++ b/tests/proj2/tests/br_table4.wasm
Binary files differ
diff --git a/tests/proj2/tests/br_table4.wat b/tests/proj2/tests/br_table4.wat
new file mode 100644
index 0000000..6b1d0b0
--- /dev/null
+++ b/tests/proj2/tests/br_table4.wat
@@ -0,0 +1,19 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (block
+ (block
+ (block
+ (block
+ (block
+ (block
+ (br_table 0 1 2 3 4 5 5 4 3 2 1 0 0 0 1 1 2 2 (local.get 0)
+ ) (return (i32.const 44))
+ ) (return (i32.const 45))
+ ) (return (i32.const 46))
+ ) (return (i32.const 47))
+ ) (return (i32.const 48))
+ ) (return (i32.const 49))
+ )
+ (i32.const 56)
+ )
+)
diff --git a/tests/proj2/tests/br_table4.wee.wasm b/tests/proj2/tests/br_table4.wee.wasm
new file mode 100644
index 0000000..3357ef9
--- /dev/null
+++ b/tests/proj2/tests/br_table4.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/build.sh b/tests/proj2/tests/build.sh
new file mode 100755
index 0000000..a319aba
--- /dev/null
+++ b/tests/proj2/tests/build.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ]; do
+ DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+ SOURCE="$(readlink "$SOURCE")"
+ [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
+done
+DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+
+PROJ2=$(cd $DIR/.. && pwd)
+WEEIFY=$PROJ2/weeify
+
+WAT2WASM=$(which wat2wasm)
+
+if [[ ! -x $WAT2WASM ]]; then
+ echo Error: wat2asm not found in PATH
+ exit 1
+fi
+
+if [[ ! -x $WEEIFY ]]; then
+ echo Error: weeify not found $DIR
+ exit 1
+fi
+
+if [ $# = 0 ]; then
+ FILES="*.wat"
+else
+ FILES="$@"
+fi
+
+for f in $FILES; do
+ wat2wasm $f
+ $WEEIFY -o ${f/%.wat/.wee.wasm} ${f/%.wat/.wasm}
+done
diff --git a/tests/proj2/tests/call0.expect b/tests/proj2/tests/call0.expect
new file mode 100644
index 0000000..8643cf6
--- /dev/null
+++ b/tests/proj2/tests/call0.expect
@@ -0,0 +1 @@
+89
diff --git a/tests/proj2/tests/call0.wasm b/tests/proj2/tests/call0.wasm
new file mode 100644
index 0000000..6113dd9
--- /dev/null
+++ b/tests/proj2/tests/call0.wasm
Binary files differ
diff --git a/tests/proj2/tests/call0.wat b/tests/proj2/tests/call0.wat
new file mode 100644
index 0000000..89e4b50
--- /dev/null
+++ b/tests/proj2/tests/call0.wat
@@ -0,0 +1,6 @@
+(module
+ (func $k (result i32) (i32.const 89))
+ (func (export "main") (result i32)
+ (call $k)
+ )
+)
diff --git a/tests/proj2/tests/call0.wee.wasm b/tests/proj2/tests/call0.wee.wasm
new file mode 100644
index 0000000..1918f0e
--- /dev/null
+++ b/tests/proj2/tests/call0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call1.runs b/tests/proj2/tests/call1.runs
new file mode 100644
index 0000000..ba9f624
--- /dev/null
+++ b/tests/proj2/tests/call1.runs
@@ -0,0 +1,2 @@
+7 = 7
+-999 = -999
diff --git a/tests/proj2/tests/call1.wasm b/tests/proj2/tests/call1.wasm
new file mode 100644
index 0000000..3b36b7f
--- /dev/null
+++ b/tests/proj2/tests/call1.wasm
Binary files differ
diff --git a/tests/proj2/tests/call1.wat b/tests/proj2/tests/call1.wat
new file mode 100644
index 0000000..8720016
--- /dev/null
+++ b/tests/proj2/tests/call1.wat
@@ -0,0 +1,6 @@
+(module
+ (func $id (param i32) (result i32) (local.get 0))
+ (func (export "main") (param i32) (result i32)
+ (call $id (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/call1.wee.wasm b/tests/proj2/tests/call1.wee.wasm
new file mode 100644
index 0000000..e4375ef
--- /dev/null
+++ b/tests/proj2/tests/call1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call2.runs b/tests/proj2/tests/call2.runs
new file mode 100644
index 0000000..822ea93
--- /dev/null
+++ b/tests/proj2/tests/call2.runs
@@ -0,0 +1,2 @@
+7 6 = 13
+-999 -222222 = -223221
diff --git a/tests/proj2/tests/call2.wasm b/tests/proj2/tests/call2.wasm
new file mode 100644
index 0000000..78280f6
--- /dev/null
+++ b/tests/proj2/tests/call2.wasm
Binary files differ
diff --git a/tests/proj2/tests/call2.wat b/tests/proj2/tests/call2.wat
new file mode 100644
index 0000000..e7408eb
--- /dev/null
+++ b/tests/proj2/tests/call2.wat
@@ -0,0 +1,8 @@
+(module
+ (func $add (param i32 i32) (result i32)
+ (i32.add (local.get 0) (local.get 1))
+ )
+ (func (export "main") (param i32 i32) (result i32)
+ (call $add (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/call2.wee.wasm b/tests/proj2/tests/call2.wee.wasm
new file mode 100644
index 0000000..ba64251
--- /dev/null
+++ b/tests/proj2/tests/call2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call3.runs b/tests/proj2/tests/call3.runs
new file mode 100644
index 0000000..b6462f5
--- /dev/null
+++ b/tests/proj2/tests/call3.runs
@@ -0,0 +1,2 @@
+7678 = 7678
+-999333 = -999333
diff --git a/tests/proj2/tests/call3.wasm b/tests/proj2/tests/call3.wasm
new file mode 100644
index 0000000..9feb093
--- /dev/null
+++ b/tests/proj2/tests/call3.wasm
Binary files differ
diff --git a/tests/proj2/tests/call3.wat b/tests/proj2/tests/call3.wat
new file mode 100644
index 0000000..2a48f27
--- /dev/null
+++ b/tests/proj2/tests/call3.wat
@@ -0,0 +1,15 @@
+(module
+ (func $id (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32) (local.get 3))
+ (func (export "main") (param i32) (result i32)
+ (call $id
+ (i32.const 122)
+ (i32.const 223)
+ (i32.const 3424)
+ (local.get 0)
+ (i32.const 5525)
+ (i32.const 6626)
+ (i32.const 777727)
+ (i32.const 99928)
+ )
+ )
+)
diff --git a/tests/proj2/tests/call3.wee.wasm b/tests/proj2/tests/call3.wee.wasm
new file mode 100644
index 0000000..4f48e99
--- /dev/null
+++ b/tests/proj2/tests/call3.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call4.expect b/tests/proj2/tests/call4.expect
new file mode 100644
index 0000000..8124ca2
--- /dev/null
+++ b/tests/proj2/tests/call4.expect
@@ -0,0 +1 @@
+2079
diff --git a/tests/proj2/tests/call4.wasm b/tests/proj2/tests/call4.wasm
new file mode 100644
index 0000000..6513cf2
--- /dev/null
+++ b/tests/proj2/tests/call4.wasm
Binary files differ
diff --git a/tests/proj2/tests/call4.wat b/tests/proj2/tests/call4.wat
new file mode 100644
index 0000000..158966f
--- /dev/null
+++ b/tests/proj2/tests/call4.wat
@@ -0,0 +1,8 @@
+(module
+ (func $f1 (result i32) (i32.const 31))
+ (func $f2 (result i32) (i32.const 32))
+ (func $f3 (result i32) (i32.const 33))
+ (func (export "main") (result i32)
+ (i32.mul (i32.add (call $f1) (call $f2)) (call $f3))
+ )
+)
diff --git a/tests/proj2/tests/call4.wee.wasm b/tests/proj2/tests/call4.wee.wasm
new file mode 100644
index 0000000..bb9cd03
--- /dev/null
+++ b/tests/proj2/tests/call4.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect0.runs b/tests/proj2/tests/call_indirect0.runs
new file mode 100644
index 0000000..9b03289
--- /dev/null
+++ b/tests/proj2/tests/call_indirect0.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = !trap
+2 = !trap
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/call_indirect0.wasm b/tests/proj2/tests/call_indirect0.wasm
new file mode 100644
index 0000000..d7c7c67
--- /dev/null
+++ b/tests/proj2/tests/call_indirect0.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect0.wat b/tests/proj2/tests/call_indirect0.wat
new file mode 100644
index 0000000..37edb31
--- /dev/null
+++ b/tests/proj2/tests/call_indirect0.wat
@@ -0,0 +1,7 @@
+(module
+ (table 5 funcref)
+ (type $v_i (func (result i32)))
+ (func (export "main") (param i32) (result i32)
+ (call_indirect (type $v_i) (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/call_indirect0.wee.wasm b/tests/proj2/tests/call_indirect0.wee.wasm
new file mode 100644
index 0000000..48e45ef
--- /dev/null
+++ b/tests/proj2/tests/call_indirect0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect1.runs b/tests/proj2/tests/call_indirect1.runs
new file mode 100644
index 0000000..9b03289
--- /dev/null
+++ b/tests/proj2/tests/call_indirect1.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = !trap
+2 = !trap
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/call_indirect1.wasm b/tests/proj2/tests/call_indirect1.wasm
new file mode 100644
index 0000000..3b19b42
--- /dev/null
+++ b/tests/proj2/tests/call_indirect1.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect1.wat b/tests/proj2/tests/call_indirect1.wat
new file mode 100644
index 0000000..2a4fd5a
--- /dev/null
+++ b/tests/proj2/tests/call_indirect1.wat
@@ -0,0 +1,7 @@
+(module
+ (table funcref (elem $main))
+ (type $v_i (func (result i32)))
+ (func $main (export "main") (param i32) (result i32)
+ (call_indirect (type $v_i) (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/call_indirect1.wee.wasm b/tests/proj2/tests/call_indirect1.wee.wasm
new file mode 100644
index 0000000..086c0d5
--- /dev/null
+++ b/tests/proj2/tests/call_indirect1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect2.runs b/tests/proj2/tests/call_indirect2.runs
new file mode 100644
index 0000000..555bc01
--- /dev/null
+++ b/tests/proj2/tests/call_indirect2.runs
@@ -0,0 +1,8 @@
+0 = 11
+1 = 22
+2 = 33
+3 = 44
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/call_indirect2.wasm b/tests/proj2/tests/call_indirect2.wasm
new file mode 100644
index 0000000..d422ab0
--- /dev/null
+++ b/tests/proj2/tests/call_indirect2.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect2.wat b/tests/proj2/tests/call_indirect2.wat
new file mode 100644
index 0000000..a803113
--- /dev/null
+++ b/tests/proj2/tests/call_indirect2.wat
@@ -0,0 +1,13 @@
+(module
+ (table funcref (elem $f11 $f22 $f33 $f44 $main))
+ (type $v_i (func (result i32)))
+
+ (func $f11 (result i32) (i32.const 11))
+ (func $f22 (result i32) (i32.const 22))
+ (func $f33 (result i32) (i32.const 33))
+ (func $f44 (result i32) (i32.const 44))
+
+ (func $main (export "main") (param i32) (result i32)
+ (call_indirect (type $v_i) (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/call_indirect2.wee.wasm b/tests/proj2/tests/call_indirect2.wee.wasm
new file mode 100644
index 0000000..892331a
--- /dev/null
+++ b/tests/proj2/tests/call_indirect2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect3.runs b/tests/proj2/tests/call_indirect3.runs
new file mode 100644
index 0000000..c9c03d9
--- /dev/null
+++ b/tests/proj2/tests/call_indirect3.runs
@@ -0,0 +1,5 @@
+22 33 0 = 55
+11 44 1 = -33
+-5 -5 2 = 25
+-5 -5 3 = !trap
+-9 0 4 = !trap
diff --git a/tests/proj2/tests/call_indirect3.wasm b/tests/proj2/tests/call_indirect3.wasm
new file mode 100644
index 0000000..2085d03
--- /dev/null
+++ b/tests/proj2/tests/call_indirect3.wasm
Binary files differ
diff --git a/tests/proj2/tests/call_indirect3.wat b/tests/proj2/tests/call_indirect3.wat
new file mode 100644
index 0000000..c94152b
--- /dev/null
+++ b/tests/proj2/tests/call_indirect3.wat
@@ -0,0 +1,13 @@
+(module
+ (table funcref (elem $fadd $fsub $fmul $fnone))
+ (type $ii_i (func (param i32 i32) (result i32)))
+
+ (func $fadd (param i32 i32) (result i32) (i32.add (local.get 0) (local.get 1)))
+ (func $fsub (param i32 i32) (result i32) (i32.sub (local.get 0) (local.get 1)))
+ (func $fmul (param i32 i32) (result i32) (i32.mul (local.get 0) (local.get 1)))
+ (func $fnone (result i32) unreachable)
+
+ (func $main (export "main") (param i32 i32 i32) (result i32)
+ (call_indirect (type $ii_i) (local.get 0) (local.get 1) (local.get 2))
+ )
+)
diff --git a/tests/proj2/tests/call_indirect3.wee.wasm b/tests/proj2/tests/call_indirect3.wee.wasm
new file mode 100644
index 0000000..c48139b
--- /dev/null
+++ b/tests/proj2/tests/call_indirect3.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/const0.expect b/tests/proj2/tests/const0.expect
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/tests/proj2/tests/const0.expect
@@ -0,0 +1 @@
+42
diff --git a/tests/proj2/tests/const0.wasm b/tests/proj2/tests/const0.wasm
new file mode 100644
index 0000000..cf66851
--- /dev/null
+++ b/tests/proj2/tests/const0.wasm
Binary files differ
diff --git a/tests/proj2/tests/const0.wat b/tests/proj2/tests/const0.wat
new file mode 100644
index 0000000..017c6ad
--- /dev/null
+++ b/tests/proj2/tests/const0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (result i32)
+ (i32.const 42)
+ )
+)
diff --git a/tests/proj2/tests/const0.wee.wasm b/tests/proj2/tests/const0.wee.wasm
new file mode 100644
index 0000000..e104207
--- /dev/null
+++ b/tests/proj2/tests/const0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/const1.expect b/tests/proj2/tests/const1.expect
new file mode 100644
index 0000000..16eac31
--- /dev/null
+++ b/tests/proj2/tests/const1.expect
@@ -0,0 +1 @@
+-993423
diff --git a/tests/proj2/tests/const1.wasm b/tests/proj2/tests/const1.wasm
new file mode 100644
index 0000000..8dae0b9
--- /dev/null
+++ b/tests/proj2/tests/const1.wasm
Binary files differ
diff --git a/tests/proj2/tests/const1.wat b/tests/proj2/tests/const1.wat
new file mode 100644
index 0000000..946e5e3
--- /dev/null
+++ b/tests/proj2/tests/const1.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (result i32)
+ (i32.const -993423)
+ )
+)
diff --git a/tests/proj2/tests/const1.wee.wasm b/tests/proj2/tests/const1.wee.wasm
new file mode 100644
index 0000000..59d36e6
--- /dev/null
+++ b/tests/proj2/tests/const1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/const2_d.expect b/tests/proj2/tests/const2_d.expect
new file mode 100644
index 0000000..2a68415
--- /dev/null
+++ b/tests/proj2/tests/const2_d.expect
@@ -0,0 +1 @@
+-99.750000
diff --git a/tests/proj2/tests/const2_d.wasm b/tests/proj2/tests/const2_d.wasm
new file mode 100644
index 0000000..56b1adb
--- /dev/null
+++ b/tests/proj2/tests/const2_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/const2_d.wat b/tests/proj2/tests/const2_d.wat
new file mode 100644
index 0000000..49ee329
--- /dev/null
+++ b/tests/proj2/tests/const2_d.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (result f64)
+ (f64.const -99.75)
+ )
+)
diff --git a/tests/proj2/tests/const2_d.wee.wasm b/tests/proj2/tests/const2_d.wee.wasm
new file mode 100644
index 0000000..329e5c6
--- /dev/null
+++ b/tests/proj2/tests/const2_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/div0.runs b/tests/proj2/tests/div0.runs
new file mode 100644
index 0000000..931ca6c
--- /dev/null
+++ b/tests/proj2/tests/div0.runs
@@ -0,0 +1,5 @@
+5555 1111 = 5
+-77777777 11111111 = -7
+-77777777 11111 = -7000
+-2147483648 -1 = !trap
+333 0 = !trap
diff --git a/tests/proj2/tests/div0.wasm b/tests/proj2/tests/div0.wasm
new file mode 100644
index 0000000..1800629
--- /dev/null
+++ b/tests/proj2/tests/div0.wasm
Binary files differ
diff --git a/tests/proj2/tests/div0.wat b/tests/proj2/tests/div0.wat
new file mode 100644
index 0000000..98288d7
--- /dev/null
+++ b/tests/proj2/tests/div0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.div_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/div0.wee.wasm b/tests/proj2/tests/div0.wee.wasm
new file mode 100644
index 0000000..95dc30b
--- /dev/null
+++ b/tests/proj2/tests/div0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_putd0.expect b/tests/proj2/tests/ec_putd0.expect
new file mode 100644
index 0000000..53060c2
--- /dev/null
+++ b/tests/proj2/tests/ec_putd0.expect
@@ -0,0 +1 @@
+1.0987656677
diff --git a/tests/proj2/tests/ec_putd0.wasm b/tests/proj2/tests/ec_putd0.wasm
new file mode 100644
index 0000000..7ad02fa
--- /dev/null
+++ b/tests/proj2/tests/ec_putd0.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_putd0.wat b/tests/proj2/tests/ec_putd0.wat
new file mode 100644
index 0000000..7ac255d
--- /dev/null
+++ b/tests/proj2/tests/ec_putd0.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "putd" (func $putd (param f64)))
+ (func (export "main") (result i32)
+ (call $putd (f64.const 1.098765))
+ (i32.const 6677)
+ )
+)
diff --git a/tests/proj2/tests/ec_putd0.wee.wasm b/tests/proj2/tests/ec_putd0.wee.wasm
new file mode 100644
index 0000000..fb170b1
--- /dev/null
+++ b/tests/proj2/tests/ec_putd0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_putd1.expect b/tests/proj2/tests/ec_putd1.expect
new file mode 100644
index 0000000..97c54c2
--- /dev/null
+++ b/tests/proj2/tests/ec_putd1.expect
@@ -0,0 +1 @@
+1.098765-1.333333-333.4444441122
diff --git a/tests/proj2/tests/ec_putd1.wasm b/tests/proj2/tests/ec_putd1.wasm
new file mode 100644
index 0000000..b19378f
--- /dev/null
+++ b/tests/proj2/tests/ec_putd1.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_putd1.wat b/tests/proj2/tests/ec_putd1.wat
new file mode 100644
index 0000000..1c75d87
--- /dev/null
+++ b/tests/proj2/tests/ec_putd1.wat
@@ -0,0 +1,9 @@
+(module
+ (import "weewasm" "putd" (func $putd (param f64)))
+ (func (export "main") (result i32)
+ (call $putd (f64.const 1.098765))
+ (call $putd (f64.const -1.333333))
+ (call $putd (f64.const -333.444444))
+ (i32.const 1122)
+ )
+)
diff --git a/tests/proj2/tests/ec_putd1.wee.wasm b/tests/proj2/tests/ec_putd1.wee.wasm
new file mode 100644
index 0000000..d137705
--- /dev/null
+++ b/tests/proj2/tests/ec_putd1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_puti0.expect b/tests/proj2/tests/ec_puti0.expect
new file mode 100644
index 0000000..209cee3
--- /dev/null
+++ b/tests/proj2/tests/ec_puti0.expect
@@ -0,0 +1 @@
+4647
diff --git a/tests/proj2/tests/ec_puti0.wasm b/tests/proj2/tests/ec_puti0.wasm
new file mode 100644
index 0000000..8c67c22
--- /dev/null
+++ b/tests/proj2/tests/ec_puti0.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_puti0.wat b/tests/proj2/tests/ec_puti0.wat
new file mode 100644
index 0000000..a42fc37
--- /dev/null
+++ b/tests/proj2/tests/ec_puti0.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "puti" (func $puti (param i32)))
+ (func (export "main") (result i32)
+ (call $puti (i32.const 46))
+ (i32.const 47)
+ )
+)
diff --git a/tests/proj2/tests/ec_puti0.wee.wasm b/tests/proj2/tests/ec_puti0.wee.wasm
new file mode 100644
index 0000000..8b87e4b
--- /dev/null
+++ b/tests/proj2/tests/ec_puti0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_puti1.expect b/tests/proj2/tests/ec_puti1.expect
new file mode 100644
index 0000000..f45c7ba
--- /dev/null
+++ b/tests/proj2/tests/ec_puti1.expect
@@ -0,0 +1 @@
+46931111666
diff --git a/tests/proj2/tests/ec_puti1.wasm b/tests/proj2/tests/ec_puti1.wasm
new file mode 100644
index 0000000..ec0001d
--- /dev/null
+++ b/tests/proj2/tests/ec_puti1.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_puti1.wat b/tests/proj2/tests/ec_puti1.wat
new file mode 100644
index 0000000..a9288c2
--- /dev/null
+++ b/tests/proj2/tests/ec_puti1.wat
@@ -0,0 +1,9 @@
+(module
+ (import "weewasm" "puti" (func $puti (param i32)))
+ (func (export "main") (result i32)
+ (call $puti (i32.const 46))
+ (call $puti (i32.const 93))
+ (call $puti (i32.const 1111))
+ (i32.const 666)
+ )
+)
diff --git a/tests/proj2/tests/ec_puti1.wee.wasm b/tests/proj2/tests/ec_puti1.wee.wasm
new file mode 100644
index 0000000..84cbec1
--- /dev/null
+++ b/tests/proj2/tests/ec_puti1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_puts0.expect b/tests/proj2/tests/ec_puts0.expect
new file mode 100644
index 0000000..b0325db
--- /dev/null
+++ b/tests/proj2/tests/ec_puts0.expect
@@ -0,0 +1,2 @@
+Hello World!
+57
diff --git a/tests/proj2/tests/ec_puts0.wasm b/tests/proj2/tests/ec_puts0.wasm
new file mode 100644
index 0000000..5d22328
--- /dev/null
+++ b/tests/proj2/tests/ec_puts0.wasm
Binary files differ
diff --git a/tests/proj2/tests/ec_puts0.wat b/tests/proj2/tests/ec_puts0.wat
new file mode 100644
index 0000000..9c318b0
--- /dev/null
+++ b/tests/proj2/tests/ec_puts0.wat
@@ -0,0 +1,9 @@
+(module
+ (import "weewasm" "puts" (func $puts (param i32 i32)))
+ (memory 1)
+ (data (i32.const 1024) "Hello World!\n")
+ (func (export "main") (result i32)
+ (call $puts (i32.const 1024) (i32.const 13))
+ (i32.const 57)
+ )
+)
diff --git a/tests/proj2/tests/ec_puts0.wee.wasm b/tests/proj2/tests/ec_puts0.wee.wasm
new file mode 100644
index 0000000..bdcb32d
--- /dev/null
+++ b/tests/proj2/tests/ec_puts0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.add0_d.runs b/tests/proj2/tests/f64.add0_d.runs
new file mode 100644
index 0000000..51f77e8
--- /dev/null
+++ b/tests/proj2/tests/f64.add0_d.runs
@@ -0,0 +1,3 @@
+0d 1d = 1.000000
+0.25d -1.75d = -1.500000
+489728.83423d -782374.47d = -292645.635770
diff --git a/tests/proj2/tests/f64.add0_d.wasm b/tests/proj2/tests/f64.add0_d.wasm
new file mode 100644
index 0000000..b1f7bb1
--- /dev/null
+++ b/tests/proj2/tests/f64.add0_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.add0_d.wat b/tests/proj2/tests/f64.add0_d.wat
new file mode 100644
index 0000000..ca0535e
--- /dev/null
+++ b/tests/proj2/tests/f64.add0_d.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result f64)
+ (f64.add (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.add0_d.wee.wasm b/tests/proj2/tests/f64.add0_d.wee.wasm
new file mode 100644
index 0000000..7f05025
--- /dev/null
+++ b/tests/proj2/tests/f64.add0_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.runs b/tests/proj2/tests/f64.convert_i32_s0_d.runs
new file mode 100644
index 0000000..4994fdd
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_s0_d.runs
@@ -0,0 +1,4 @@
+0 = 0.000000
+1 = 1.000000
+-87234 = -87234.000000
+-2147483648 = -2147483648.000000
diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.wasm b/tests/proj2/tests/f64.convert_i32_s0_d.wasm
new file mode 100644
index 0000000..a95064a
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_s0_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.wat b/tests/proj2/tests/f64.convert_i32_s0_d.wat
new file mode 100644
index 0000000..b9d01ce
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_s0_d.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result f64)
+ (f64.convert_i32_s (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.wee.wasm b/tests/proj2/tests/f64.convert_i32_s0_d.wee.wasm
new file mode 100644
index 0000000..db6257d
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_s0_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.runs b/tests/proj2/tests/f64.convert_i32_u0_d.runs
new file mode 100644
index 0000000..575f92d
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_u0_d.runs
@@ -0,0 +1,4 @@
+0 = 0.000000
+1 = 1.000000
+-87234 = 4294880062.000000
+-2147483648 = 2147483648.000000
diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.wasm b/tests/proj2/tests/f64.convert_i32_u0_d.wasm
new file mode 100644
index 0000000..1b9cb15
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_u0_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.wat b/tests/proj2/tests/f64.convert_i32_u0_d.wat
new file mode 100644
index 0000000..931ea45
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_u0_d.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result f64)
+ (f64.convert_i32_u (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.wee.wasm b/tests/proj2/tests/f64.convert_i32_u0_d.wee.wasm
new file mode 100644
index 0000000..4aa04da
--- /dev/null
+++ b/tests/proj2/tests/f64.convert_i32_u0_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.div0_d.runs b/tests/proj2/tests/f64.div0_d.runs
new file mode 100644
index 0000000..d4581da
--- /dev/null
+++ b/tests/proj2/tests/f64.div0_d.runs
@@ -0,0 +1,2 @@
+489728.83423d -782374.47d = -0.625952
+7000000000000d 800000000000d = 8.750000
diff --git a/tests/proj2/tests/f64.div0_d.wasm b/tests/proj2/tests/f64.div0_d.wasm
new file mode 100644
index 0000000..9dab40a
--- /dev/null
+++ b/tests/proj2/tests/f64.div0_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.div0_d.wat b/tests/proj2/tests/f64.div0_d.wat
new file mode 100644
index 0000000..3fcd399
--- /dev/null
+++ b/tests/proj2/tests/f64.div0_d.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result f64)
+ (f64.div (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.div0_d.wee.wasm b/tests/proj2/tests/f64.div0_d.wee.wasm
new file mode 100644
index 0000000..3fb0352
--- /dev/null
+++ b/tests/proj2/tests/f64.div0_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.eq0.runs b/tests/proj2/tests/f64.eq0.runs
new file mode 100644
index 0000000..ad7ffa5
--- /dev/null
+++ b/tests/proj2/tests/f64.eq0.runs
@@ -0,0 +1,3 @@
+0d 1d = 0
+1.25d -1.25d = 0
+55.55d 55.5d = 0
diff --git a/tests/proj2/tests/f64.eq0.wasm b/tests/proj2/tests/f64.eq0.wasm
new file mode 100644
index 0000000..d910cc1
--- /dev/null
+++ b/tests/proj2/tests/f64.eq0.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.eq0.wat b/tests/proj2/tests/f64.eq0.wat
new file mode 100644
index 0000000..33f3e71
--- /dev/null
+++ b/tests/proj2/tests/f64.eq0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result i32)
+ (f64.eq (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.eq0.wee.wasm b/tests/proj2/tests/f64.eq0.wee.wasm
new file mode 100644
index 0000000..283172f
--- /dev/null
+++ b/tests/proj2/tests/f64.eq0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.ge0.runs b/tests/proj2/tests/f64.ge0.runs
new file mode 100644
index 0000000..d1f7c09
--- /dev/null
+++ b/tests/proj2/tests/f64.ge0.runs
@@ -0,0 +1,4 @@
+0d 1d = 0
+0d -1d = 1
+0.25d 0.5d = 0
+333.5d 333.5d = 1
diff --git a/tests/proj2/tests/f64.ge0.wasm b/tests/proj2/tests/f64.ge0.wasm
new file mode 100644
index 0000000..4c99a91
--- /dev/null
+++ b/tests/proj2/tests/f64.ge0.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.ge0.wat b/tests/proj2/tests/f64.ge0.wat
new file mode 100644
index 0000000..c164325
--- /dev/null
+++ b/tests/proj2/tests/f64.ge0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result i32)
+ (f64.ge (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.ge0.wee.wasm b/tests/proj2/tests/f64.ge0.wee.wasm
new file mode 100644
index 0000000..c01d07d
--- /dev/null
+++ b/tests/proj2/tests/f64.ge0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.gt0.runs b/tests/proj2/tests/f64.gt0.runs
new file mode 100644
index 0000000..3e821d9
--- /dev/null
+++ b/tests/proj2/tests/f64.gt0.runs
@@ -0,0 +1,4 @@
+0d 1d = 0
+0d -1d = 1
+0.25d 0.5d = 0
+333.5d 333.5d = 0
diff --git a/tests/proj2/tests/f64.gt0.wasm b/tests/proj2/tests/f64.gt0.wasm
new file mode 100644
index 0000000..a63d96c
--- /dev/null
+++ b/tests/proj2/tests/f64.gt0.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.gt0.wat b/tests/proj2/tests/f64.gt0.wat
new file mode 100644
index 0000000..81e23f8
--- /dev/null
+++ b/tests/proj2/tests/f64.gt0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result i32)
+ (f64.gt (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.gt0.wee.wasm b/tests/proj2/tests/f64.gt0.wee.wasm
new file mode 100644
index 0000000..d58886d
--- /dev/null
+++ b/tests/proj2/tests/f64.gt0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.le0.runs b/tests/proj2/tests/f64.le0.runs
new file mode 100644
index 0000000..31a2b21
--- /dev/null
+++ b/tests/proj2/tests/f64.le0.runs
@@ -0,0 +1,4 @@
+0d 1d = 1
+0d -1d = 0
+0.25d 0.5d = 1
+333.5d 333.5d = 1
diff --git a/tests/proj2/tests/f64.le0.wasm b/tests/proj2/tests/f64.le0.wasm
new file mode 100644
index 0000000..1ad8dd6
--- /dev/null
+++ b/tests/proj2/tests/f64.le0.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.le0.wat b/tests/proj2/tests/f64.le0.wat
new file mode 100644
index 0000000..5d46020
--- /dev/null
+++ b/tests/proj2/tests/f64.le0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result i32)
+ (f64.le (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.le0.wee.wasm b/tests/proj2/tests/f64.le0.wee.wasm
new file mode 100644
index 0000000..a687a26
--- /dev/null
+++ b/tests/proj2/tests/f64.le0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.lt0.runs b/tests/proj2/tests/f64.lt0.runs
new file mode 100644
index 0000000..56b5c96
--- /dev/null
+++ b/tests/proj2/tests/f64.lt0.runs
@@ -0,0 +1,4 @@
+0d 1d = 1
+0d -1d = 0
+0.25d 0.5d = 1
+333.5d 333.5d = 0
diff --git a/tests/proj2/tests/f64.lt0.wasm b/tests/proj2/tests/f64.lt0.wasm
new file mode 100644
index 0000000..b1dbac7
--- /dev/null
+++ b/tests/proj2/tests/f64.lt0.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.lt0.wat b/tests/proj2/tests/f64.lt0.wat
new file mode 100644
index 0000000..171c39f
--- /dev/null
+++ b/tests/proj2/tests/f64.lt0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result i32)
+ (f64.lt (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.lt0.wee.wasm b/tests/proj2/tests/f64.lt0.wee.wasm
new file mode 100644
index 0000000..7253f33
--- /dev/null
+++ b/tests/proj2/tests/f64.lt0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.mul0_d.runs b/tests/proj2/tests/f64.mul0_d.runs
new file mode 100644
index 0000000..0df48ca
--- /dev/null
+++ b/tests/proj2/tests/f64.mul0_d.runs
@@ -0,0 +1,3 @@
+0d 1d = 0.000000
+0.25d -1.75d = -0.437500
+3000d -70000d = -210000000.000000
diff --git a/tests/proj2/tests/f64.mul0_d.wasm b/tests/proj2/tests/f64.mul0_d.wasm
new file mode 100644
index 0000000..f02193b
--- /dev/null
+++ b/tests/proj2/tests/f64.mul0_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.mul0_d.wat b/tests/proj2/tests/f64.mul0_d.wat
new file mode 100644
index 0000000..26ddb45
--- /dev/null
+++ b/tests/proj2/tests/f64.mul0_d.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result f64)
+ (f64.mul (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.mul0_d.wee.wasm b/tests/proj2/tests/f64.mul0_d.wee.wasm
new file mode 100644
index 0000000..952853e
--- /dev/null
+++ b/tests/proj2/tests/f64.mul0_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.ne0.runs b/tests/proj2/tests/f64.ne0.runs
new file mode 100644
index 0000000..0e4dc93
--- /dev/null
+++ b/tests/proj2/tests/f64.ne0.runs
@@ -0,0 +1,3 @@
+0d 1d = 1
+1.25d -1.25d = 1
+55.55d 55.5d = 1
diff --git a/tests/proj2/tests/f64.ne0.wasm b/tests/proj2/tests/f64.ne0.wasm
new file mode 100644
index 0000000..7b0ce0a
--- /dev/null
+++ b/tests/proj2/tests/f64.ne0.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.ne0.wat b/tests/proj2/tests/f64.ne0.wat
new file mode 100644
index 0000000..6df7443
--- /dev/null
+++ b/tests/proj2/tests/f64.ne0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result i32)
+ (f64.ne (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.ne0.wee.wasm b/tests/proj2/tests/f64.ne0.wee.wasm
new file mode 100644
index 0000000..4705ee2
--- /dev/null
+++ b/tests/proj2/tests/f64.ne0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.store0.runs b/tests/proj2/tests/f64.store0.runs
new file mode 100644
index 0000000..f1b5c80
--- /dev/null
+++ b/tests/proj2/tests/f64.store0.runs
@@ -0,0 +1,16 @@
+0 = 0
+100 = 0
+4000 = 0
+4001 = 0
+4002 = 81
+4003 = 73
+4004 = 28
+4005 = 0
+4006 = 17
+4007 = 25
+4008 = 3
+4009 = 64
+4010 = 0
+4011 = 0
+4012 = 0
+4013 = 0
diff --git a/tests/proj2/tests/f64.store0.wasm b/tests/proj2/tests/f64.store0.wasm
new file mode 100644
index 0000000..bc0b048
--- /dev/null
+++ b/tests/proj2/tests/f64.store0.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.store0.wat b/tests/proj2/tests/f64.store0.wat
new file mode 100644
index 0000000..9a19625
--- /dev/null
+++ b/tests/proj2/tests/f64.store0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (f64.store (i32.const 4002) (f64.const 2.387239457))
+ (i32.load8_u (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/f64.store0.wee.wasm b/tests/proj2/tests/f64.store0.wee.wasm
new file mode 100644
index 0000000..1ba02d6
--- /dev/null
+++ b/tests/proj2/tests/f64.store0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.sub0_d.runs b/tests/proj2/tests/f64.sub0_d.runs
new file mode 100644
index 0000000..27a6c6a
--- /dev/null
+++ b/tests/proj2/tests/f64.sub0_d.runs
@@ -0,0 +1,3 @@
+0d 1d = -1.000000
+0.25d -1.75d = 2.000000
+489728.83423d -782374.47d = 1272103.304230
diff --git a/tests/proj2/tests/f64.sub0_d.wasm b/tests/proj2/tests/f64.sub0_d.wasm
new file mode 100644
index 0000000..0e25291
--- /dev/null
+++ b/tests/proj2/tests/f64.sub0_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/f64.sub0_d.wat b/tests/proj2/tests/f64.sub0_d.wat
new file mode 100644
index 0000000..3db96f3
--- /dev/null
+++ b/tests/proj2/tests/f64.sub0_d.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64 f64) (result f64)
+ (f64.sub (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/f64.sub0_d.wee.wasm b/tests/proj2/tests/f64.sub0_d.wee.wasm
new file mode 100644
index 0000000..77ad9bd
--- /dev/null
+++ b/tests/proj2/tests/f64.sub0_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/fib.runs b/tests/proj2/tests/fib.runs
new file mode 100644
index 0000000..fba1687
--- /dev/null
+++ b/tests/proj2/tests/fib.runs
@@ -0,0 +1,9 @@
+0 = 1
+1 = 1
+2 = 2
+3 = 3
+4 = 5
+5 = 8
+6 = 13
+7 = 21
+8 = 34
diff --git a/tests/proj2/tests/fib.wasm b/tests/proj2/tests/fib.wasm
new file mode 100644
index 0000000..e329719
--- /dev/null
+++ b/tests/proj2/tests/fib.wasm
Binary files differ
diff --git a/tests/proj2/tests/fib.wat b/tests/proj2/tests/fib.wat
new file mode 100644
index 0000000..920f2e5
--- /dev/null
+++ b/tests/proj2/tests/fib.wat
@@ -0,0 +1,29 @@
+(module
+ (export "main" (func $fib))
+ (func $fib (param $n i32) (result i32)
+ (block
+ (br_if 0 (i32.ge_s
+ (local.get $n)
+ (i32.const 2)
+ ))
+ (return
+ (i32.const 1)
+ ))
+ (return
+ (i32.add
+ (call $fib
+ (i32.sub
+ (local.get $n)
+ (i32.const 2)
+ )
+ )
+ (call $fib
+ (i32.sub
+ (local.get $n)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+) \ No newline at end of file
diff --git a/tests/proj2/tests/fib.wee.wasm b/tests/proj2/tests/fib.wee.wasm
new file mode 100644
index 0000000..23afd9e
--- /dev/null
+++ b/tests/proj2/tests/fib.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/gen.sh b/tests/proj2/tests/gen.sh
new file mode 100755
index 0000000..c6daf7f
--- /dev/null
+++ b/tests/proj2/tests/gen.sh
@@ -0,0 +1,436 @@
+#!/bin/bash
+
+function gen1() {
+ echo "(module"
+ echo " (func (export \"main\") (param $1) (result $2)"
+ echo " ($3 (local.get 0))"
+ echo " )"
+ echo ")"
+}
+
+function gen2() {
+ echo "(module"
+ echo " (func (export \"main\") (param $1 $2) (result $3)"
+ echo " ($4 (local.get 0) (local.get 1))"
+ echo " )"
+ echo ")"
+}
+
+i32_min=-2147483648
+i32_max=2147483647
+pt_zero=".000000"
+
+function BEGIN() {
+ export INSTR=$1
+ SUFFIX=""
+ for s in $SIG; do
+ if [ "$s" = "f64" ]; then
+ SUFFIX="_d"
+ else
+ SUFFIX=""
+ fi
+ done
+ export NAME=${1}0${SUFFIX}
+ $SIG $INSTR > $NAME.wat
+ rm -f $NAME.runs
+}
+
+function t() {
+ echo "$@" >> $NAME.runs
+}
+
+function END() {
+ # do nothing
+ NOTHING=0
+}
+
+##############################################################################
+SIG="gen1 i32 i32"
+
+BEGIN i32.eqz
+t 0 = 1
+t 1 = 0
+t $i32_min = 0
+t 897234987 = 0
+
+BEGIN i32.clz
+t 0 = 32
+t 1 = 31
+t $i32_min = 0
+t 897234987 = 2
+t 65000 = 16
+
+BEGIN i32.ctz
+t 0 = 32
+t 1 = 0
+t $i32_min = 31
+t 897234987 = 0
+t 65536 = 16
+
+BEGIN i32.popcnt
+t 0 = 0
+t 1 = 1
+t 2 = 1
+t 89721348 = 9
+t -8934345 = 23
+t $i32_min = 1
+
+BEGIN i32.extend8_s
+t 0 = 0
+t 1 = 1
+t $i32_min = 0
+t 897234987 = 43
+t 128 = -128
+
+BEGIN i32.extend16_s
+t 0 = 0
+t 1 = 1
+t $i32_min = 0
+t 897234987 = -18389
+t 128 = 128
+t 32768 = -32768
+
+
+##############################################################################
+SIG="gen2 i32 i32 i32"
+BEGIN i32.eq
+t 0 0 = 1
+t 1 0 = 0
+t 0 1 = 0
+t 5555 5555 = 1
+t -87239487 -8723487 = 0
+
+BEGIN i32.ne
+t 0 0 = 0
+t 1 0 = 1
+t 0 1 = 1
+t 5555 5555 = 0
+t -87239487 -8723487 = 1
+
+BEGIN i32.lt_s
+t -1 0 = 1
+t -1 -2 = 0
+t -55 -55 = 0
+t 30000000 40000000 = 1
+t -30000000 -40000000 = 0
+t $i32_min -1 = 1
+t $i32_min -2147483647 = 1
+t 55 54 = 0
+t 55 55 = 0
+t 55 56 = 1
+t -56 -55 = 1
+t -55 56 = 1
+
+BEGIN i32.lt_u
+t -1 0 = 0
+t -1 -2 = 0
+t -55 -55 = 0
+t 30000000 40000000 = 1
+t -30000000 -40000000 = 0
+t $i32_min -1 = 1
+t $i32_min -2147483647 = 1
+t 55 54 = 0
+t 55 55 = 0
+t 55 56 = 1
+t -56 -55 = 1
+t -55 56 = 0
+
+BEGIN i32.gt_s
+t -1 0 = 0
+t -1 -2 = 1
+t -55 -55 = 0
+t 30000000 40000000 = 0
+t -30000000 -40000000 = 1
+t $i32_min -1 = 0
+t $i32_min -2147483647 = 0
+t 55 54 = 1
+t 55 55 = 0
+t 55 56 = 0
+t -56 -55 = 0
+t -55 56 = 0
+
+BEGIN i32.gt_u
+t -1 0 = 1
+t -1 -2 = 1
+t -55 -55 = 0
+t 30000000 40000000 = 0
+t -30000000 -40000000 = 1
+t $i32_min -1 = 0
+t $i32_min -2147483647 = 0
+t 55 54 = 1
+t 55 55 = 0
+t 55 56 = 0
+t -56 -55 = 0
+t -55 56 = 1
+
+BEGIN i32.le_s
+t -1 0 = 1
+t -2 -3 = 0
+t -55 -55 = 1
+t 50000000 60000000 = 1
+t -50000000 -60000000 = 0
+t $i32_min -1 = 1
+t $i32_min -2147483647 = 1
+t 55 54 = 0
+t 55 55 = 1
+t 55 56 = 1
+t -56 -55 = 1
+t -55 56 = 1
+
+BEGIN i32.le_u
+t -1 0 = 0
+t -3 -4 = 0
+t -55 -55 = 1
+t 50000000 60000000 = 1
+t -50000000 -60000000 = 0
+t $i32_min -1 = 1
+t $i32_min -2147483647 = 1
+t 55 54 = 0
+t 55 55 = 1
+t 55 56 = 1
+t -56 -55 = 1
+t -55 56 = 0
+
+BEGIN i32.ge_s
+t -1 0 = 0
+t -1 -2 = 1
+t -55 -55 = 1
+t 30000000 40000000 = 0
+t -30000000 -40000000 = 1
+t $i32_min -1 = 0
+t $i32_min -2147483647 = 0
+t 55 54 = 1
+t 55 55 = 1
+t 55 56 = 0
+t -56 -55 = 0
+t -55 56 = 0
+
+BEGIN i32.ge_u
+t -1 0 = 1
+t -5 -6 = 1
+t -55 -55 = 1
+t 30000000 40000000 = 0
+t -20000000 -40000000 = 1
+t $i32_min -1 = 0
+t $i32_min -2147483647 = 0
+t 55 54 = 1
+t 55 55 = 1
+t 55 56 = 0
+t -56 -55 = 0
+t -55 56 = 1
+
+BEGIN i32.add
+t 8 9 = 17
+t 33 44 = 77
+t 111 222 = 333
+t 2222 3333 = 5555
+t 111111111 666666666 = 777777777
+t $i32_min $i32_min = 0
+t -2129587951 -2093796557 = 71582788
+
+BEGIN i32.sub
+t 8 9 = -1
+t 33 44 = -11
+t 111 222 = -111
+t 2222 3333 = -1111
+t 111111111 666666666 = -555555555
+t $i32_min $i32_min = 0
+t -2129587951 -2093796557 = -35791394
+t 2000000000 1 = 1999999999
+
+BEGIN i32.mul
+t 8 9 = 72
+t 33 44 = 1452
+t 111 222 = 24642
+t 2222 3333 = 7405926
+t 111111111 666666666 = 1332460582
+t $i32_min $i32_min = 0
+t -2129587951 -2093796557 = 909101411
+t 2000000000 1 = 2000000000
+t 2000000000 3 = 1705032704
+
+BEGIN i32.div_s
+t 5555 1111 = 5
+t -77777777 11111111 = -7
+t -77777777 11111 = -7000
+t $i32_min -1 = !trap
+t 333 0 = !trap
+
+BEGIN i32.div_u
+t 5555 1111 = 5
+t -77777777 11111111 = 379
+t -77777777 11111 = 379550
+t $i32_min -1 = 0
+t 3553 0 = !trap
+
+BEGIN i32.rem_s
+t 99 10 = 9
+t 107 -10 = 7
+t -107 -10 = -7
+t -107 10 = -7
+t 1 0 = !trap
+t 5559823 1 = 0
+t $i32_min -1 = 0
+t 876345 -1 = 0
+
+BEGIN i32.rem_u
+t 13338 10 = 8
+t 99 -3 = 99
+t 1 0 = !trap
+t 555 1 = 0
+t $i32_min -1 = $i32_min
+
+BEGIN i32.and
+t 876234 982134 = 810050
+t 897234 0 = 0
+t 89273498 -1 = 89273498
+t -555 $i32_min = $i32_min
+
+BEGIN i32.or
+t 876234 982134 = 1048318
+t 897234 0 = 897234
+t 89273498 -1 = -1
+t -555 $i32_min = -555
+
+BEGIN i32.xor
+t 876234 982134 = 238268
+t 897234 0 = 897234
+t 89273498 -1 = -89273499
+t -555 $i32_min = 2147483093
+
+BEGIN i32.shl
+t 1044480 0 = 1044480
+t 1044480 32 = 1044480
+t 8972134 23 = -1291845632
+t -1 31 = $i32_min
+t 1044480 36 = 16711680
+
+BEGIN i32.shr_s
+t 1044480 0 = 1044480
+t 1044480 32 = 1044480
+t 8972134 13 = 1095
+t -8972134 13 = -1096
+t 268435455 27 = 1
+t -256 4 = -16
+t 1044480 36 = 65280
+
+BEGIN i32.shr_u
+t 1044480 0 = 1044480
+t 1044480 32 = 1044480
+t 8972134 13 = 1095
+t -8972134 13 = 523192
+t -1 31 = 1
+t 1044480 36 = 65280
+
+BEGIN i32.rotl
+t 1044480 0 = 1044480
+t 1044480 32 = 1044480
+t 8972134 13 = 485277713
+t -8972134 13 = -485269522
+t -1412628189 36 = -1127214534
+
+BEGIN i32.rotr
+t 1044480 0 = 1044480
+t 1044480 32 = 1044480
+t 8972134 13 = 993002567
+t -8972134 13 = -992478280
+t -1412628189 36 = 985452562
+
+END
+
+##############################################################################
+SIG="gen2 f64 f64 i32"
+BEGIN f64.eq
+t 0d 1d = 0
+t 1.25d -1.25d = 0
+t 55.55d 55.5d = 0
+# TODO: nans and infinities
+
+BEGIN f64.ne
+t 0d 1d = 1
+t 1.25d -1.25d = 1
+t 55.55d 55.5d = 1
+
+BEGIN f64.lt
+t 0d 1d = 1
+t 0d -1d = 0
+t 0.25d 0.5d = 1
+t 333.5d 333.5d = 0
+
+BEGIN f64.gt
+t 0d 1d = 0
+t 0d -1d = 1
+t 0.25d 0.5d = 0
+t 333.5d 333.5d = 0
+
+BEGIN f64.le
+t 0d 1d = 1
+t 0d -1d = 0
+t 0.25d 0.5d = 1
+t 333.5d 333.5d = 1
+
+BEGIN f64.ge
+t 0d 1d = 0
+t 0d -1d = 1
+t 0.25d 0.5d = 0
+t 333.5d 333.5d = 1
+
+##############################################################################
+SIG="gen2 f64 f64 f64"
+BEGIN f64.add
+t 0d 1d = 1.000000
+t 0.25d -1.75d = -1.500000
+t 489728.83423d -782374.47d = -292645.635770
+# TODO: nans and infinities
+
+BEGIN f64.sub
+t 0d 1d = -1$pt_zero
+t 0.25d -1.75d = 2$pt_zero
+t 489728.83423d -782374.47d = 1272103.304230
+
+BEGIN f64.mul
+t 0d 1d = 0$pt_zero
+t 0.25d -1.75d = -0.437500
+t 3000d -70000d = -210000000.000000
+
+BEGIN f64.div
+#TODO: nans and infinities t 0d 0d = nan
+t 489728.83423d -782374.47d = -0.625952
+t 7000000000000d 800000000000d = 8.750000
+
+##############################################################################
+SIG="gen1 f64 i32"
+BEGIN i32.trunc_f64_s
+t 0d = 0
+t 0.9d = 0
+t -0.9d = 0
+t 1d = 1
+t -87234d = -87234
+t ${i32_min}d = $i32_min
+t -3000000000d = !trap
+t 3000000000d = !trap
+
+BEGIN i32.trunc_f64_u
+t 0d = 0
+t 1d = 1
+t 0.9d = 0
+t -0.9d = 0
+t -87234d = !trap
+t $i32_min = !trap
+t 3000000000d = -1294967296
+
+##############################################################################
+SIG="gen1 i32 f64"
+BEGIN f64.convert_i32_s
+t 0 = 0$pt_zero
+t 1 = 1$pt_zero
+t -87234 = -87234$pt_zero
+t $i32_min = $i32_min$pt_zero
+
+BEGIN f64.convert_i32_u
+t 0 = 0$pt_zero
+t 1 = 1$pt_zero
+t -87234 = 4294880062$pt_zero
+t $i32_min = 2147483648$pt_zero
+
+END
diff --git a/tests/proj2/tests/global0.expect b/tests/proj2/tests/global0.expect
new file mode 100644
index 0000000..a8fa06e
--- /dev/null
+++ b/tests/proj2/tests/global0.expect
@@ -0,0 +1 @@
+62
diff --git a/tests/proj2/tests/global0.wasm b/tests/proj2/tests/global0.wasm
new file mode 100644
index 0000000..4b642b1
--- /dev/null
+++ b/tests/proj2/tests/global0.wasm
Binary files differ
diff --git a/tests/proj2/tests/global0.wat b/tests/proj2/tests/global0.wat
new file mode 100644
index 0000000..06ceaab
--- /dev/null
+++ b/tests/proj2/tests/global0.wat
@@ -0,0 +1,6 @@
+(module
+ (global $g i32 (i32.const 62))
+ (func (export "main") (result i32)
+ (global.get $g)
+ )
+)
diff --git a/tests/proj2/tests/global0.wee.wasm b/tests/proj2/tests/global0.wee.wasm
new file mode 100644
index 0000000..2580fd3
--- /dev/null
+++ b/tests/proj2/tests/global0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/global1_d.expect b/tests/proj2/tests/global1_d.expect
new file mode 100644
index 0000000..69771c6
--- /dev/null
+++ b/tests/proj2/tests/global1_d.expect
@@ -0,0 +1 @@
+-77.500000
diff --git a/tests/proj2/tests/global1_d.wasm b/tests/proj2/tests/global1_d.wasm
new file mode 100644
index 0000000..c5d121b
--- /dev/null
+++ b/tests/proj2/tests/global1_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/global1_d.wat b/tests/proj2/tests/global1_d.wat
new file mode 100644
index 0000000..0b1313b
--- /dev/null
+++ b/tests/proj2/tests/global1_d.wat
@@ -0,0 +1,6 @@
+(module
+ (global $g f64 (f64.const -77.5))
+ (func (export "main") (result f64)
+ (global.get $g)
+ )
+)
diff --git a/tests/proj2/tests/global1_d.wee.wasm b/tests/proj2/tests/global1_d.wee.wasm
new file mode 100644
index 0000000..7ab6207
--- /dev/null
+++ b/tests/proj2/tests/global1_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/global2.runs b/tests/proj2/tests/global2.runs
new file mode 100644
index 0000000..899178b
--- /dev/null
+++ b/tests/proj2/tests/global2.runs
@@ -0,0 +1,2 @@
+22 = 22
+-999888777 = -999888777
diff --git a/tests/proj2/tests/global2.wasm b/tests/proj2/tests/global2.wasm
new file mode 100644
index 0000000..27d3f58
--- /dev/null
+++ b/tests/proj2/tests/global2.wasm
Binary files differ
diff --git a/tests/proj2/tests/global2.wat b/tests/proj2/tests/global2.wat
new file mode 100644
index 0000000..944d857
--- /dev/null
+++ b/tests/proj2/tests/global2.wat
@@ -0,0 +1,7 @@
+(module
+ (global $g (mut i32) (i32.const 62))
+ (func (export "main") (param i32) (result i32)
+ (global.set $g (local.get 0))
+ (global.get $g)
+ )
+)
diff --git a/tests/proj2/tests/global2.wee.wasm b/tests/proj2/tests/global2.wee.wasm
new file mode 100644
index 0000000..e74c151
--- /dev/null
+++ b/tests/proj2/tests/global2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/global3_d.runs b/tests/proj2/tests/global3_d.runs
new file mode 100644
index 0000000..ff9d6b9
--- /dev/null
+++ b/tests/proj2/tests/global3_d.runs
@@ -0,0 +1,2 @@
+22.88d = 22.880000
+-999888777.1d = -999888777.100000
diff --git a/tests/proj2/tests/global3_d.wasm b/tests/proj2/tests/global3_d.wasm
new file mode 100644
index 0000000..5422a0e
--- /dev/null
+++ b/tests/proj2/tests/global3_d.wasm
Binary files differ
diff --git a/tests/proj2/tests/global3_d.wat b/tests/proj2/tests/global3_d.wat
new file mode 100644
index 0000000..56f0f57
--- /dev/null
+++ b/tests/proj2/tests/global3_d.wat
@@ -0,0 +1,7 @@
+(module
+ (global $g (mut f64) (f64.const 62))
+ (func (export "main") (param f64) (result f64)
+ (global.set $g (local.get 0))
+ (global.get $g)
+ )
+)
diff --git a/tests/proj2/tests/global3_d.wee.wasm b/tests/proj2/tests/global3_d.wee.wasm
new file mode 100644
index 0000000..b4d43a7
--- /dev/null
+++ b/tests/proj2/tests/global3_d.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.add0.runs b/tests/proj2/tests/i32.add0.runs
new file mode 100644
index 0000000..e1a7ce1
--- /dev/null
+++ b/tests/proj2/tests/i32.add0.runs
@@ -0,0 +1,7 @@
+8 9 = 17
+33 44 = 77
+111 222 = 333
+2222 3333 = 5555
+111111111 666666666 = 777777777
+-2147483648 -2147483648 = 0
+-2129587951 -2093796557 = 71582788
diff --git a/tests/proj2/tests/i32.add0.wasm b/tests/proj2/tests/i32.add0.wasm
new file mode 100644
index 0000000..cca89af
--- /dev/null
+++ b/tests/proj2/tests/i32.add0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.add0.wat b/tests/proj2/tests/i32.add0.wat
new file mode 100644
index 0000000..cb46d02
--- /dev/null
+++ b/tests/proj2/tests/i32.add0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.add (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.add0.wee.wasm b/tests/proj2/tests/i32.add0.wee.wasm
new file mode 100644
index 0000000..d8ed0f6
--- /dev/null
+++ b/tests/proj2/tests/i32.add0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.and0.runs b/tests/proj2/tests/i32.and0.runs
new file mode 100644
index 0000000..4f3cf4a
--- /dev/null
+++ b/tests/proj2/tests/i32.and0.runs
@@ -0,0 +1,4 @@
+876234 982134 = 810050
+897234 0 = 0
+89273498 -1 = 89273498
+-555 -2147483648 = -2147483648
diff --git a/tests/proj2/tests/i32.and0.wasm b/tests/proj2/tests/i32.and0.wasm
new file mode 100644
index 0000000..77bc761
--- /dev/null
+++ b/tests/proj2/tests/i32.and0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.and0.wat b/tests/proj2/tests/i32.and0.wat
new file mode 100644
index 0000000..741abdb
--- /dev/null
+++ b/tests/proj2/tests/i32.and0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.and (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.and0.wee.wasm b/tests/proj2/tests/i32.and0.wee.wasm
new file mode 100644
index 0000000..5106aca
--- /dev/null
+++ b/tests/proj2/tests/i32.and0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.clz0.runs b/tests/proj2/tests/i32.clz0.runs
new file mode 100644
index 0000000..73adce0
--- /dev/null
+++ b/tests/proj2/tests/i32.clz0.runs
@@ -0,0 +1,5 @@
+0 = 32
+1 = 31
+-2147483648 = 0
+897234987 = 2
+65000 = 16
diff --git a/tests/proj2/tests/i32.clz0.wasm b/tests/proj2/tests/i32.clz0.wasm
new file mode 100644
index 0000000..9929ae6
--- /dev/null
+++ b/tests/proj2/tests/i32.clz0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.clz0.wat b/tests/proj2/tests/i32.clz0.wat
new file mode 100644
index 0000000..b954051
--- /dev/null
+++ b/tests/proj2/tests/i32.clz0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.clz (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.clz0.wee.wasm b/tests/proj2/tests/i32.clz0.wee.wasm
new file mode 100644
index 0000000..484462f
--- /dev/null
+++ b/tests/proj2/tests/i32.clz0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ctz0.runs b/tests/proj2/tests/i32.ctz0.runs
new file mode 100644
index 0000000..b694360
--- /dev/null
+++ b/tests/proj2/tests/i32.ctz0.runs
@@ -0,0 +1,5 @@
+0 = 32
+1 = 0
+-2147483648 = 31
+897234987 = 0
+65536 = 16
diff --git a/tests/proj2/tests/i32.ctz0.wasm b/tests/proj2/tests/i32.ctz0.wasm
new file mode 100644
index 0000000..948b44e
--- /dev/null
+++ b/tests/proj2/tests/i32.ctz0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ctz0.wat b/tests/proj2/tests/i32.ctz0.wat
new file mode 100644
index 0000000..c88bbd2
--- /dev/null
+++ b/tests/proj2/tests/i32.ctz0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.ctz (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.ctz0.wee.wasm b/tests/proj2/tests/i32.ctz0.wee.wasm
new file mode 100644
index 0000000..30e1f91
--- /dev/null
+++ b/tests/proj2/tests/i32.ctz0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.div_s0.runs b/tests/proj2/tests/i32.div_s0.runs
new file mode 100644
index 0000000..931ca6c
--- /dev/null
+++ b/tests/proj2/tests/i32.div_s0.runs
@@ -0,0 +1,5 @@
+5555 1111 = 5
+-77777777 11111111 = -7
+-77777777 11111 = -7000
+-2147483648 -1 = !trap
+333 0 = !trap
diff --git a/tests/proj2/tests/i32.div_s0.wasm b/tests/proj2/tests/i32.div_s0.wasm
new file mode 100644
index 0000000..1800629
--- /dev/null
+++ b/tests/proj2/tests/i32.div_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.div_s0.wat b/tests/proj2/tests/i32.div_s0.wat
new file mode 100644
index 0000000..98288d7
--- /dev/null
+++ b/tests/proj2/tests/i32.div_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.div_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.div_s0.wee.wasm b/tests/proj2/tests/i32.div_s0.wee.wasm
new file mode 100644
index 0000000..95dc30b
--- /dev/null
+++ b/tests/proj2/tests/i32.div_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.div_u0.runs b/tests/proj2/tests/i32.div_u0.runs
new file mode 100644
index 0000000..05bc291
--- /dev/null
+++ b/tests/proj2/tests/i32.div_u0.runs
@@ -0,0 +1,5 @@
+5555 1111 = 5
+-77777777 11111111 = 379
+-77777777 11111 = 379550
+-2147483648 -1 = 0
+3553 0 = !trap
diff --git a/tests/proj2/tests/i32.div_u0.wasm b/tests/proj2/tests/i32.div_u0.wasm
new file mode 100644
index 0000000..41d0371
--- /dev/null
+++ b/tests/proj2/tests/i32.div_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.div_u0.wat b/tests/proj2/tests/i32.div_u0.wat
new file mode 100644
index 0000000..db522a7
--- /dev/null
+++ b/tests/proj2/tests/i32.div_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.div_u (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.div_u0.wee.wasm b/tests/proj2/tests/i32.div_u0.wee.wasm
new file mode 100644
index 0000000..72be5b5
--- /dev/null
+++ b/tests/proj2/tests/i32.div_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.eq0.runs b/tests/proj2/tests/i32.eq0.runs
new file mode 100644
index 0000000..0e5c23b
--- /dev/null
+++ b/tests/proj2/tests/i32.eq0.runs
@@ -0,0 +1,5 @@
+0 0 = 1
+1 0 = 0
+0 1 = 0
+5555 5555 = 1
+-87239487 -8723487 = 0
diff --git a/tests/proj2/tests/i32.eq0.wasm b/tests/proj2/tests/i32.eq0.wasm
new file mode 100644
index 0000000..811bbdf
--- /dev/null
+++ b/tests/proj2/tests/i32.eq0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.eq0.wat b/tests/proj2/tests/i32.eq0.wat
new file mode 100644
index 0000000..69f9184
--- /dev/null
+++ b/tests/proj2/tests/i32.eq0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.eq (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.eq0.wee.wasm b/tests/proj2/tests/i32.eq0.wee.wasm
new file mode 100644
index 0000000..18895ce
--- /dev/null
+++ b/tests/proj2/tests/i32.eq0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.eqz0.runs b/tests/proj2/tests/i32.eqz0.runs
new file mode 100644
index 0000000..f13d128
--- /dev/null
+++ b/tests/proj2/tests/i32.eqz0.runs
@@ -0,0 +1,4 @@
+0 = 1
+1 = 0
+-2147483648 = 0
+897234987 = 0
diff --git a/tests/proj2/tests/i32.eqz0.wasm b/tests/proj2/tests/i32.eqz0.wasm
new file mode 100644
index 0000000..6c27e23
--- /dev/null
+++ b/tests/proj2/tests/i32.eqz0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.eqz0.wat b/tests/proj2/tests/i32.eqz0.wat
new file mode 100644
index 0000000..e966b97
--- /dev/null
+++ b/tests/proj2/tests/i32.eqz0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.eqz (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.eqz0.wee.wasm b/tests/proj2/tests/i32.eqz0.wee.wasm
new file mode 100644
index 0000000..f0f1a64
--- /dev/null
+++ b/tests/proj2/tests/i32.eqz0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.extend16_s0.runs b/tests/proj2/tests/i32.extend16_s0.runs
new file mode 100644
index 0000000..6d27b73
--- /dev/null
+++ b/tests/proj2/tests/i32.extend16_s0.runs
@@ -0,0 +1,6 @@
+0 = 0
+1 = 1
+-2147483648 = 0
+897234987 = -18389
+128 = 128
+32768 = -32768
diff --git a/tests/proj2/tests/i32.extend16_s0.wasm b/tests/proj2/tests/i32.extend16_s0.wasm
new file mode 100644
index 0000000..def3221
--- /dev/null
+++ b/tests/proj2/tests/i32.extend16_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.extend16_s0.wat b/tests/proj2/tests/i32.extend16_s0.wat
new file mode 100644
index 0000000..ac1685c
--- /dev/null
+++ b/tests/proj2/tests/i32.extend16_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.extend16_s (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.extend16_s0.wee.wasm b/tests/proj2/tests/i32.extend16_s0.wee.wasm
new file mode 100644
index 0000000..a0186e3
--- /dev/null
+++ b/tests/proj2/tests/i32.extend16_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.extend8_s0.runs b/tests/proj2/tests/i32.extend8_s0.runs
new file mode 100644
index 0000000..5f1ab42
--- /dev/null
+++ b/tests/proj2/tests/i32.extend8_s0.runs
@@ -0,0 +1,5 @@
+0 = 0
+1 = 1
+-2147483648 = 0
+897234987 = 43
+128 = -128
diff --git a/tests/proj2/tests/i32.extend8_s0.wasm b/tests/proj2/tests/i32.extend8_s0.wasm
new file mode 100644
index 0000000..e6cd61a
--- /dev/null
+++ b/tests/proj2/tests/i32.extend8_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.extend8_s0.wat b/tests/proj2/tests/i32.extend8_s0.wat
new file mode 100644
index 0000000..e64b80c
--- /dev/null
+++ b/tests/proj2/tests/i32.extend8_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.extend8_s (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.extend8_s0.wee.wasm b/tests/proj2/tests/i32.extend8_s0.wee.wasm
new file mode 100644
index 0000000..5a95da6
--- /dev/null
+++ b/tests/proj2/tests/i32.extend8_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ge_s0.runs b/tests/proj2/tests/i32.ge_s0.runs
new file mode 100644
index 0000000..458410e
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_s0.runs
@@ -0,0 +1,12 @@
+-1 0 = 0
+-1 -2 = 1
+-55 -55 = 1
+30000000 40000000 = 0
+-30000000 -40000000 = 1
+-2147483648 -1 = 0
+-2147483648 -2147483647 = 0
+55 54 = 1
+55 55 = 1
+55 56 = 0
+-56 -55 = 0
+-55 56 = 0
diff --git a/tests/proj2/tests/i32.ge_s0.wasm b/tests/proj2/tests/i32.ge_s0.wasm
new file mode 100644
index 0000000..fdd6af1
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ge_s0.wat b/tests/proj2/tests/i32.ge_s0.wat
new file mode 100644
index 0000000..de5b2c7
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.ge_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.ge_s0.wee.wasm b/tests/proj2/tests/i32.ge_s0.wee.wasm
new file mode 100644
index 0000000..e921c24
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ge_u0.runs b/tests/proj2/tests/i32.ge_u0.runs
new file mode 100644
index 0000000..a9bdfc7
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_u0.runs
@@ -0,0 +1,12 @@
+-1 0 = 1
+-5 -6 = 1
+-55 -55 = 1
+30000000 40000000 = 0
+-20000000 -40000000 = 1
+-2147483648 -1 = 0
+-2147483648 -2147483647 = 0
+55 54 = 1
+55 55 = 1
+55 56 = 0
+-56 -55 = 0
+-55 56 = 1
diff --git a/tests/proj2/tests/i32.ge_u0.wasm b/tests/proj2/tests/i32.ge_u0.wasm
new file mode 100644
index 0000000..2eb0c6c
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ge_u0.wat b/tests/proj2/tests/i32.ge_u0.wat
new file mode 100644
index 0000000..f0810d5
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.ge_u (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.ge_u0.wee.wasm b/tests/proj2/tests/i32.ge_u0.wee.wasm
new file mode 100644
index 0000000..2e3877c
--- /dev/null
+++ b/tests/proj2/tests/i32.ge_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.gt_s0.runs b/tests/proj2/tests/i32.gt_s0.runs
new file mode 100644
index 0000000..6c79f10
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_s0.runs
@@ -0,0 +1,12 @@
+-1 0 = 0
+-1 -2 = 1
+-55 -55 = 0
+30000000 40000000 = 0
+-30000000 -40000000 = 1
+-2147483648 -1 = 0
+-2147483648 -2147483647 = 0
+55 54 = 1
+55 55 = 0
+55 56 = 0
+-56 -55 = 0
+-55 56 = 0
diff --git a/tests/proj2/tests/i32.gt_s0.wasm b/tests/proj2/tests/i32.gt_s0.wasm
new file mode 100644
index 0000000..42c6e90
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.gt_s0.wat b/tests/proj2/tests/i32.gt_s0.wat
new file mode 100644
index 0000000..8be6996
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.gt_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.gt_s0.wee.wasm b/tests/proj2/tests/i32.gt_s0.wee.wasm
new file mode 100644
index 0000000..7586819
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.gt_u0.runs b/tests/proj2/tests/i32.gt_u0.runs
new file mode 100644
index 0000000..3a9f7ea
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_u0.runs
@@ -0,0 +1,12 @@
+-1 0 = 1
+-1 -2 = 1
+-55 -55 = 0
+30000000 40000000 = 0
+-30000000 -40000000 = 1
+-2147483648 -1 = 0
+-2147483648 -2147483647 = 0
+55 54 = 1
+55 55 = 0
+55 56 = 0
+-56 -55 = 0
+-55 56 = 1
diff --git a/tests/proj2/tests/i32.gt_u0.wasm b/tests/proj2/tests/i32.gt_u0.wasm
new file mode 100644
index 0000000..b80c786
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.gt_u0.wat b/tests/proj2/tests/i32.gt_u0.wat
new file mode 100644
index 0000000..e9becf8
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.gt_u (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.gt_u0.wee.wasm b/tests/proj2/tests/i32.gt_u0.wee.wasm
new file mode 100644
index 0000000..0eada3e
--- /dev/null
+++ b/tests/proj2/tests/i32.gt_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.le_s0.runs b/tests/proj2/tests/i32.le_s0.runs
new file mode 100644
index 0000000..1511108
--- /dev/null
+++ b/tests/proj2/tests/i32.le_s0.runs
@@ -0,0 +1,12 @@
+-1 0 = 1
+-2 -3 = 0
+-55 -55 = 1
+50000000 60000000 = 1
+-50000000 -60000000 = 0
+-2147483648 -1 = 1
+-2147483648 -2147483647 = 1
+55 54 = 0
+55 55 = 1
+55 56 = 1
+-56 -55 = 1
+-55 56 = 1
diff --git a/tests/proj2/tests/i32.le_s0.wasm b/tests/proj2/tests/i32.le_s0.wasm
new file mode 100644
index 0000000..3c16e28
--- /dev/null
+++ b/tests/proj2/tests/i32.le_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.le_s0.wat b/tests/proj2/tests/i32.le_s0.wat
new file mode 100644
index 0000000..533908d
--- /dev/null
+++ b/tests/proj2/tests/i32.le_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.le_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.le_s0.wee.wasm b/tests/proj2/tests/i32.le_s0.wee.wasm
new file mode 100644
index 0000000..c269465
--- /dev/null
+++ b/tests/proj2/tests/i32.le_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.le_u0.runs b/tests/proj2/tests/i32.le_u0.runs
new file mode 100644
index 0000000..17808cd
--- /dev/null
+++ b/tests/proj2/tests/i32.le_u0.runs
@@ -0,0 +1,12 @@
+-1 0 = 0
+-3 -4 = 0
+-55 -55 = 1
+50000000 60000000 = 1
+-50000000 -60000000 = 0
+-2147483648 -1 = 1
+-2147483648 -2147483647 = 1
+55 54 = 0
+55 55 = 1
+55 56 = 1
+-56 -55 = 1
+-55 56 = 0
diff --git a/tests/proj2/tests/i32.le_u0.wasm b/tests/proj2/tests/i32.le_u0.wasm
new file mode 100644
index 0000000..46b4597
--- /dev/null
+++ b/tests/proj2/tests/i32.le_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.le_u0.wat b/tests/proj2/tests/i32.le_u0.wat
new file mode 100644
index 0000000..fe9addf
--- /dev/null
+++ b/tests/proj2/tests/i32.le_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.le_u (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.le_u0.wee.wasm b/tests/proj2/tests/i32.le_u0.wee.wasm
new file mode 100644
index 0000000..12c2079
--- /dev/null
+++ b/tests/proj2/tests/i32.le_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load0.runs b/tests/proj2/tests/i32.load0.runs
new file mode 100644
index 0000000..ea38b0e
--- /dev/null
+++ b/tests/proj2/tests/i32.load0.runs
@@ -0,0 +1,6 @@
+0 = 0
+1 = 0
+100 = 0
+1024 = 0
+65530 = 0
+65532 = 0
diff --git a/tests/proj2/tests/i32.load0.wasm b/tests/proj2/tests/i32.load0.wasm
new file mode 100644
index 0000000..3e76665
--- /dev/null
+++ b/tests/proj2/tests/i32.load0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load0.wat b/tests/proj2/tests/i32.load0.wat
new file mode 100644
index 0000000..23d8b8c
--- /dev/null
+++ b/tests/proj2/tests/i32.load0.wat
@@ -0,0 +1,6 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (i32.load offset=0 (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load0.wee.wasm b/tests/proj2/tests/i32.load0.wee.wasm
new file mode 100644
index 0000000..0eaed96
--- /dev/null
+++ b/tests/proj2/tests/i32.load0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load1.runs b/tests/proj2/tests/i32.load1.runs
new file mode 100644
index 0000000..8643400
--- /dev/null
+++ b/tests/proj2/tests/i32.load1.runs
@@ -0,0 +1,7 @@
+0 = 0
+1 = 0
+100 = 0
+1024 = 0
+65500 = 0
+65530 = !trap
+65532 = !trap
diff --git a/tests/proj2/tests/i32.load1.wasm b/tests/proj2/tests/i32.load1.wasm
new file mode 100644
index 0000000..f360bc6
--- /dev/null
+++ b/tests/proj2/tests/i32.load1.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load1.wat b/tests/proj2/tests/i32.load1.wat
new file mode 100644
index 0000000..3137264
--- /dev/null
+++ b/tests/proj2/tests/i32.load1.wat
@@ -0,0 +1,6 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (i32.load offset=32 (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load1.wee.wasm b/tests/proj2/tests/i32.load1.wee.wasm
new file mode 100644
index 0000000..fe8d156
--- /dev/null
+++ b/tests/proj2/tests/i32.load1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load16_s0.runs b/tests/proj2/tests/i32.load16_s0.runs
new file mode 100644
index 0000000..bfcdacd
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_s0.runs
@@ -0,0 +1,13 @@
+1100 = 0
+1101 = 0
+1102 = 0
+1103 = 30720
+1104 = -26248
+1105 = 12441
+1106 = 12592
+1107 = 49
+1108 = 0
+1109 = 0
+1110 = 0
+1111 = 0
+1112 = 0
diff --git a/tests/proj2/tests/i32.load16_s0.wasm b/tests/proj2/tests/i32.load16_s0.wasm
new file mode 100644
index 0000000..931e190
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load16_s0.wat b/tests/proj2/tests/i32.load16_s0.wat
new file mode 100644
index 0000000..b6229d1
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_s0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 1104) "x\9901")
+ (func (export "main") (param i32) (result i32)
+ (i32.load16_s (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load16_s0.wee.wasm b/tests/proj2/tests/i32.load16_s0.wee.wasm
new file mode 100644
index 0000000..686dfef
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load16_u0.runs b/tests/proj2/tests/i32.load16_u0.runs
new file mode 100644
index 0000000..0a9993c
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u0.runs
@@ -0,0 +1,13 @@
+1000 = 0
+1001 = 0
+1002 = 0
+1003 = 30720
+1004 = 39288
+1005 = 12441
+1006 = 12592
+1007 = 49
+1008 = 0
+1009 = 0
+1010 = 0
+1011 = 0
+1012 = 0
diff --git a/tests/proj2/tests/i32.load16_u0.wasm b/tests/proj2/tests/i32.load16_u0.wasm
new file mode 100644
index 0000000..7690cc7
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load16_u0.wat b/tests/proj2/tests/i32.load16_u0.wat
new file mode 100644
index 0000000..7eba8e2
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 1004) "x\9901")
+ (func (export "main") (param i32) (result i32)
+ (i32.load16_u (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load16_u0.wee.wasm b/tests/proj2/tests/i32.load16_u0.wee.wasm
new file mode 100644
index 0000000..10b3052
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load16_u1.runs b/tests/proj2/tests/i32.load16_u1.runs
new file mode 100644
index 0000000..26374d0
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u1.runs
@@ -0,0 +1,13 @@
+500 = 0
+501 = 0
+502 = 0
+503 = 30720
+504 = 39288
+505 = 12441
+506 = 12592
+507 = 49
+508 = 0
+509 = 0
+55 = 0
+511 = 0
+512 = 0
diff --git a/tests/proj2/tests/i32.load16_u1.wasm b/tests/proj2/tests/i32.load16_u1.wasm
new file mode 100644
index 0000000..2d0b46e
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u1.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load16_u1.wat b/tests/proj2/tests/i32.load16_u1.wat
new file mode 100644
index 0000000..6112295
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u1.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 1004) "x\9901")
+ (func (export "main") (param i32) (result i32)
+ (i32.load16_u offset=500 (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load16_u1.wee.wasm b/tests/proj2/tests/i32.load16_u1.wee.wasm
new file mode 100644
index 0000000..f5140af
--- /dev/null
+++ b/tests/proj2/tests/i32.load16_u1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load2.runs b/tests/proj2/tests/i32.load2.runs
new file mode 100644
index 0000000..59f95d0
--- /dev/null
+++ b/tests/proj2/tests/i32.load2.runs
@@ -0,0 +1,11 @@
+0 = 0
+1 = 0
+100 = 0
+1024 = 0
+65500 = 0
+65530 = 0
+65532 = 0
+100000 = 0
+131072 = !trap
+131040 = !trap
+131036 = 0
diff --git a/tests/proj2/tests/i32.load2.wasm b/tests/proj2/tests/i32.load2.wasm
new file mode 100644
index 0000000..57a2231
--- /dev/null
+++ b/tests/proj2/tests/i32.load2.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load2.wat b/tests/proj2/tests/i32.load2.wat
new file mode 100644
index 0000000..90f3c1e
--- /dev/null
+++ b/tests/proj2/tests/i32.load2.wat
@@ -0,0 +1,6 @@
+(module
+ (memory 2)
+ (func (export "main") (param i32) (result i32)
+ (i32.load offset=32 (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load2.wee.wasm b/tests/proj2/tests/i32.load2.wee.wasm
new file mode 100644
index 0000000..bfe1c18
--- /dev/null
+++ b/tests/proj2/tests/i32.load2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load3.runs b/tests/proj2/tests/i32.load3.runs
new file mode 100644
index 0000000..61f2e00
--- /dev/null
+++ b/tests/proj2/tests/i32.load3.runs
@@ -0,0 +1,3 @@
+0 = 0
+60 = !trap
+56 = 0
diff --git a/tests/proj2/tests/i32.load3.wasm b/tests/proj2/tests/i32.load3.wasm
new file mode 100644
index 0000000..098ceb1
--- /dev/null
+++ b/tests/proj2/tests/i32.load3.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load3.wat b/tests/proj2/tests/i32.load3.wat
new file mode 100644
index 0000000..6de5fe3
--- /dev/null
+++ b/tests/proj2/tests/i32.load3.wat
@@ -0,0 +1,6 @@
+(module
+ (memory 10)
+ (func (export "main") (param i32) (result i32)
+ (i32.load offset=655300 (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load3.wee.wasm b/tests/proj2/tests/i32.load3.wee.wasm
new file mode 100644
index 0000000..e1cd500
--- /dev/null
+++ b/tests/proj2/tests/i32.load3.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load4.runs b/tests/proj2/tests/i32.load4.runs
new file mode 100644
index 0000000..6263e85
--- /dev/null
+++ b/tests/proj2/tests/i32.load4.runs
@@ -0,0 +1,13 @@
+0 = 0
+1 = 2013265920
+2 = 2037907456
+3 = 2054780928
+4 = 2004515192
+5 = 7830137
+6 = 30586
+7 = 119
+8 = 0
+9 = 0
+10 = 0
+11 = 0
+12 = 0
diff --git a/tests/proj2/tests/i32.load4.wasm b/tests/proj2/tests/i32.load4.wasm
new file mode 100644
index 0000000..02f890a
--- /dev/null
+++ b/tests/proj2/tests/i32.load4.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load4.wat b/tests/proj2/tests/i32.load4.wat
new file mode 100644
index 0000000..fc0ad0f
--- /dev/null
+++ b/tests/proj2/tests/i32.load4.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 4) "xyzw")
+ (func (export "main") (param i32) (result i32)
+ (i32.load (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load4.wee.wasm b/tests/proj2/tests/i32.load4.wee.wasm
new file mode 100644
index 0000000..7fc320e
--- /dev/null
+++ b/tests/proj2/tests/i32.load4.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load8_s0.runs b/tests/proj2/tests/i32.load8_s0.runs
new file mode 100644
index 0000000..319a9e5
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_s0.runs
@@ -0,0 +1,13 @@
+400 = 0
+401 = 0
+402 = 0
+403 = 0
+404 = 120
+405 = -103
+406 = 48
+407 = 49
+408 = 0
+409 = 0
+410 = 0
+411 = 0
+412 = 0
diff --git a/tests/proj2/tests/i32.load8_s0.wasm b/tests/proj2/tests/i32.load8_s0.wasm
new file mode 100644
index 0000000..33e1fcd
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load8_s0.wat b/tests/proj2/tests/i32.load8_s0.wat
new file mode 100644
index 0000000..df2fa4a
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_s0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 404) "x\9901")
+ (func (export "main") (param i32) (result i32)
+ (i32.load8_s (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load8_s0.wee.wasm b/tests/proj2/tests/i32.load8_s0.wee.wasm
new file mode 100644
index 0000000..34c7444
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load8_u0.runs b/tests/proj2/tests/i32.load8_u0.runs
new file mode 100644
index 0000000..dcab3c3
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u0.runs
@@ -0,0 +1,13 @@
+500 = 0
+501 = 0
+502 = 0
+503 = 0
+504 = 120
+505 = 121
+506 = 122
+507 = 119
+508 = 0
+509 = 0
+510 = 0
+511 = 0
+512 = 0
diff --git a/tests/proj2/tests/i32.load8_u0.wasm b/tests/proj2/tests/i32.load8_u0.wasm
new file mode 100644
index 0000000..c832368
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load8_u0.wat b/tests/proj2/tests/i32.load8_u0.wat
new file mode 100644
index 0000000..216f918
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 504) "xyzw")
+ (func (export "main") (param i32) (result i32)
+ (i32.load8_u (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load8_u0.wee.wasm b/tests/proj2/tests/i32.load8_u0.wee.wasm
new file mode 100644
index 0000000..302d8e1
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load8_u1.runs b/tests/proj2/tests/i32.load8_u1.runs
new file mode 100644
index 0000000..77abaf2
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u1.runs
@@ -0,0 +1,13 @@
+200 = 0
+201 = 0
+202 = 0
+203 = 0
+204 = 120
+205 = 121
+206 = 122
+207 = 119
+208 = 0
+209 = 0
+210 = 0
+211 = 0
+212 = 0
diff --git a/tests/proj2/tests/i32.load8_u1.wasm b/tests/proj2/tests/i32.load8_u1.wasm
new file mode 100644
index 0000000..fbdb269
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u1.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.load8_u1.wat b/tests/proj2/tests/i32.load8_u1.wat
new file mode 100644
index 0000000..60759d9
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u1.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 504) "xyzw")
+ (func (export "main") (param i32) (result i32)
+ (i32.load8_u offset=300 (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.load8_u1.wee.wasm b/tests/proj2/tests/i32.load8_u1.wee.wasm
new file mode 100644
index 0000000..aa62e25
--- /dev/null
+++ b/tests/proj2/tests/i32.load8_u1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.lt_s0.runs b/tests/proj2/tests/i32.lt_s0.runs
new file mode 100644
index 0000000..2c1aed0
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_s0.runs
@@ -0,0 +1,12 @@
+-1 0 = 1
+-1 -2 = 0
+-55 -55 = 0
+30000000 40000000 = 1
+-30000000 -40000000 = 0
+-2147483648 -1 = 1
+-2147483648 -2147483647 = 1
+55 54 = 0
+55 55 = 0
+55 56 = 1
+-56 -55 = 1
+-55 56 = 1
diff --git a/tests/proj2/tests/i32.lt_s0.wasm b/tests/proj2/tests/i32.lt_s0.wasm
new file mode 100644
index 0000000..b785865
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.lt_s0.wat b/tests/proj2/tests/i32.lt_s0.wat
new file mode 100644
index 0000000..c89d521
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.lt_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.lt_s0.wee.wasm b/tests/proj2/tests/i32.lt_s0.wee.wasm
new file mode 100644
index 0000000..3dac5d4
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.lt_u0.runs b/tests/proj2/tests/i32.lt_u0.runs
new file mode 100644
index 0000000..12d002b
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_u0.runs
@@ -0,0 +1,12 @@
+-1 0 = 0
+-1 -2 = 0
+-55 -55 = 0
+30000000 40000000 = 1
+-30000000 -40000000 = 0
+-2147483648 -1 = 1
+-2147483648 -2147483647 = 1
+55 54 = 0
+55 55 = 0
+55 56 = 1
+-56 -55 = 1
+-55 56 = 0
diff --git a/tests/proj2/tests/i32.lt_u0.wasm b/tests/proj2/tests/i32.lt_u0.wasm
new file mode 100644
index 0000000..3bbe9e9
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.lt_u0.wat b/tests/proj2/tests/i32.lt_u0.wat
new file mode 100644
index 0000000..8586101
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.lt_u (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.lt_u0.wee.wasm b/tests/proj2/tests/i32.lt_u0.wee.wasm
new file mode 100644
index 0000000..0d83759
--- /dev/null
+++ b/tests/proj2/tests/i32.lt_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.mul0.runs b/tests/proj2/tests/i32.mul0.runs
new file mode 100644
index 0000000..b0374bc
--- /dev/null
+++ b/tests/proj2/tests/i32.mul0.runs
@@ -0,0 +1,9 @@
+8 9 = 72
+33 44 = 1452
+111 222 = 24642
+2222 3333 = 7405926
+111111111 666666666 = 1332460582
+-2147483648 -2147483648 = 0
+-2129587951 -2093796557 = 909101411
+2000000000 1 = 2000000000
+2000000000 3 = 1705032704
diff --git a/tests/proj2/tests/i32.mul0.wasm b/tests/proj2/tests/i32.mul0.wasm
new file mode 100644
index 0000000..ac058f7
--- /dev/null
+++ b/tests/proj2/tests/i32.mul0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.mul0.wat b/tests/proj2/tests/i32.mul0.wat
new file mode 100644
index 0000000..950ccf9
--- /dev/null
+++ b/tests/proj2/tests/i32.mul0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.mul (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.mul0.wee.wasm b/tests/proj2/tests/i32.mul0.wee.wasm
new file mode 100644
index 0000000..e43be6e
--- /dev/null
+++ b/tests/proj2/tests/i32.mul0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ne0.runs b/tests/proj2/tests/i32.ne0.runs
new file mode 100644
index 0000000..2d9e7fe
--- /dev/null
+++ b/tests/proj2/tests/i32.ne0.runs
@@ -0,0 +1,5 @@
+0 0 = 0
+1 0 = 1
+0 1 = 1
+5555 5555 = 0
+-87239487 -8723487 = 1
diff --git a/tests/proj2/tests/i32.ne0.wasm b/tests/proj2/tests/i32.ne0.wasm
new file mode 100644
index 0000000..e53b5f7
--- /dev/null
+++ b/tests/proj2/tests/i32.ne0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.ne0.wat b/tests/proj2/tests/i32.ne0.wat
new file mode 100644
index 0000000..cefe4f1
--- /dev/null
+++ b/tests/proj2/tests/i32.ne0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.ne (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.ne0.wee.wasm b/tests/proj2/tests/i32.ne0.wee.wasm
new file mode 100644
index 0000000..578fc5b
--- /dev/null
+++ b/tests/proj2/tests/i32.ne0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.or0.runs b/tests/proj2/tests/i32.or0.runs
new file mode 100644
index 0000000..94753f6
--- /dev/null
+++ b/tests/proj2/tests/i32.or0.runs
@@ -0,0 +1,4 @@
+876234 982134 = 1048318
+897234 0 = 897234
+89273498 -1 = -1
+-555 -2147483648 = -555
diff --git a/tests/proj2/tests/i32.or0.wasm b/tests/proj2/tests/i32.or0.wasm
new file mode 100644
index 0000000..c1f46c7
--- /dev/null
+++ b/tests/proj2/tests/i32.or0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.or0.wat b/tests/proj2/tests/i32.or0.wat
new file mode 100644
index 0000000..8763eb7
--- /dev/null
+++ b/tests/proj2/tests/i32.or0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.or (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.or0.wee.wasm b/tests/proj2/tests/i32.or0.wee.wasm
new file mode 100644
index 0000000..df51bb9
--- /dev/null
+++ b/tests/proj2/tests/i32.or0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.popcnt0.runs b/tests/proj2/tests/i32.popcnt0.runs
new file mode 100644
index 0000000..10de3e3
--- /dev/null
+++ b/tests/proj2/tests/i32.popcnt0.runs
@@ -0,0 +1,6 @@
+0 = 0
+1 = 1
+2 = 1
+89721348 = 9
+-8934345 = 23
+-2147483648 = 1
diff --git a/tests/proj2/tests/i32.popcnt0.wasm b/tests/proj2/tests/i32.popcnt0.wasm
new file mode 100644
index 0000000..758dffc
--- /dev/null
+++ b/tests/proj2/tests/i32.popcnt0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.popcnt0.wat b/tests/proj2/tests/i32.popcnt0.wat
new file mode 100644
index 0000000..d7017d1
--- /dev/null
+++ b/tests/proj2/tests/i32.popcnt0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.popcnt (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.popcnt0.wee.wasm b/tests/proj2/tests/i32.popcnt0.wee.wasm
new file mode 100644
index 0000000..cf78011
--- /dev/null
+++ b/tests/proj2/tests/i32.popcnt0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rem_s0.runs b/tests/proj2/tests/i32.rem_s0.runs
new file mode 100644
index 0000000..a9c3537
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_s0.runs
@@ -0,0 +1,8 @@
+99 10 = 9
+107 -10 = 7
+-107 -10 = -7
+-107 10 = -7
+1 0 = !trap
+5559823 1 = 0
+-2147483648 -1 = 0
+876345 -1 = 0
diff --git a/tests/proj2/tests/i32.rem_s0.wasm b/tests/proj2/tests/i32.rem_s0.wasm
new file mode 100644
index 0000000..64c2f86
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rem_s0.wat b/tests/proj2/tests/i32.rem_s0.wat
new file mode 100644
index 0000000..e779dd8
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.rem_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.rem_s0.wee.wasm b/tests/proj2/tests/i32.rem_s0.wee.wasm
new file mode 100644
index 0000000..fafce8b
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rem_u0.runs b/tests/proj2/tests/i32.rem_u0.runs
new file mode 100644
index 0000000..d9f3ea6
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_u0.runs
@@ -0,0 +1,5 @@
+13338 10 = 8
+99 -3 = 99
+1 0 = !trap
+555 1 = 0
+-2147483648 -1 = -2147483648
diff --git a/tests/proj2/tests/i32.rem_u0.wasm b/tests/proj2/tests/i32.rem_u0.wasm
new file mode 100644
index 0000000..cb08fe9
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rem_u0.wat b/tests/proj2/tests/i32.rem_u0.wat
new file mode 100644
index 0000000..7b26f03
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.rem_u (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.rem_u0.wee.wasm b/tests/proj2/tests/i32.rem_u0.wee.wasm
new file mode 100644
index 0000000..7a3a50a
--- /dev/null
+++ b/tests/proj2/tests/i32.rem_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rotl0.runs b/tests/proj2/tests/i32.rotl0.runs
new file mode 100644
index 0000000..ac7cbf5
--- /dev/null
+++ b/tests/proj2/tests/i32.rotl0.runs
@@ -0,0 +1,5 @@
+1044480 0 = 1044480
+1044480 32 = 1044480
+8972134 13 = 485277713
+-8972134 13 = -485269522
+-1412628189 36 = -1127214534
diff --git a/tests/proj2/tests/i32.rotl0.wasm b/tests/proj2/tests/i32.rotl0.wasm
new file mode 100644
index 0000000..3dc31fc
--- /dev/null
+++ b/tests/proj2/tests/i32.rotl0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rotl0.wat b/tests/proj2/tests/i32.rotl0.wat
new file mode 100644
index 0000000..aee7a86
--- /dev/null
+++ b/tests/proj2/tests/i32.rotl0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.rotl (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.rotl0.wee.wasm b/tests/proj2/tests/i32.rotl0.wee.wasm
new file mode 100644
index 0000000..5d4bd39
--- /dev/null
+++ b/tests/proj2/tests/i32.rotl0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rotr0.runs b/tests/proj2/tests/i32.rotr0.runs
new file mode 100644
index 0000000..5dd3a4e
--- /dev/null
+++ b/tests/proj2/tests/i32.rotr0.runs
@@ -0,0 +1,5 @@
+1044480 0 = 1044480
+1044480 32 = 1044480
+8972134 13 = 993002567
+-8972134 13 = -992478280
+-1412628189 36 = 985452562
diff --git a/tests/proj2/tests/i32.rotr0.wasm b/tests/proj2/tests/i32.rotr0.wasm
new file mode 100644
index 0000000..aae96a1
--- /dev/null
+++ b/tests/proj2/tests/i32.rotr0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.rotr0.wat b/tests/proj2/tests/i32.rotr0.wat
new file mode 100644
index 0000000..c563af3
--- /dev/null
+++ b/tests/proj2/tests/i32.rotr0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.rotr (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.rotr0.wee.wasm b/tests/proj2/tests/i32.rotr0.wee.wasm
new file mode 100644
index 0000000..4161906
--- /dev/null
+++ b/tests/proj2/tests/i32.rotr0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.shl0.runs b/tests/proj2/tests/i32.shl0.runs
new file mode 100644
index 0000000..449f471
--- /dev/null
+++ b/tests/proj2/tests/i32.shl0.runs
@@ -0,0 +1,5 @@
+1044480 0 = 1044480
+1044480 32 = 1044480
+8972134 23 = -1291845632
+-1 31 = -2147483648
+1044480 36 = 16711680
diff --git a/tests/proj2/tests/i32.shl0.wasm b/tests/proj2/tests/i32.shl0.wasm
new file mode 100644
index 0000000..dcc34a4
--- /dev/null
+++ b/tests/proj2/tests/i32.shl0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.shl0.wat b/tests/proj2/tests/i32.shl0.wat
new file mode 100644
index 0000000..0fee16f
--- /dev/null
+++ b/tests/proj2/tests/i32.shl0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.shl (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.shl0.wee.wasm b/tests/proj2/tests/i32.shl0.wee.wasm
new file mode 100644
index 0000000..fcc234a
--- /dev/null
+++ b/tests/proj2/tests/i32.shl0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.shr_s0.runs b/tests/proj2/tests/i32.shr_s0.runs
new file mode 100644
index 0000000..eb74900
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_s0.runs
@@ -0,0 +1,7 @@
+1044480 0 = 1044480
+1044480 32 = 1044480
+8972134 13 = 1095
+-8972134 13 = -1096
+268435455 27 = 1
+-256 4 = -16
+1044480 36 = 65280
diff --git a/tests/proj2/tests/i32.shr_s0.wasm b/tests/proj2/tests/i32.shr_s0.wasm
new file mode 100644
index 0000000..7717511
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.shr_s0.wat b/tests/proj2/tests/i32.shr_s0.wat
new file mode 100644
index 0000000..e3d9d75
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.shr_s (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.shr_s0.wee.wasm b/tests/proj2/tests/i32.shr_s0.wee.wasm
new file mode 100644
index 0000000..69fc69e
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.shr_u0.runs b/tests/proj2/tests/i32.shr_u0.runs
new file mode 100644
index 0000000..cd50052
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_u0.runs
@@ -0,0 +1,6 @@
+1044480 0 = 1044480
+1044480 32 = 1044480
+8972134 13 = 1095
+-8972134 13 = 523192
+-1 31 = 1
+1044480 36 = 65280
diff --git a/tests/proj2/tests/i32.shr_u0.wasm b/tests/proj2/tests/i32.shr_u0.wasm
new file mode 100644
index 0000000..273fcc0
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.shr_u0.wat b/tests/proj2/tests/i32.shr_u0.wat
new file mode 100644
index 0000000..3609d05
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.shr_u (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.shr_u0.wee.wasm b/tests/proj2/tests/i32.shr_u0.wee.wasm
new file mode 100644
index 0000000..a560fbd
--- /dev/null
+++ b/tests/proj2/tests/i32.shr_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store0.runs b/tests/proj2/tests/i32.store0.runs
new file mode 100644
index 0000000..eb9aada
--- /dev/null
+++ b/tests/proj2/tests/i32.store0.runs
@@ -0,0 +1,10 @@
+0 = 0
+996 = 0
+997 = 1426063360
+998 = 1146421248
+999 = 860116224
+1000 = 573785173
+1001 = 2241348
+1002 = 8755
+1003 = 34
+1004 = 0
diff --git a/tests/proj2/tests/i32.store0.wasm b/tests/proj2/tests/i32.store0.wasm
new file mode 100644
index 0000000..8579aba
--- /dev/null
+++ b/tests/proj2/tests/i32.store0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store0.wat b/tests/proj2/tests/i32.store0.wat
new file mode 100644
index 0000000..0596153
--- /dev/null
+++ b/tests/proj2/tests/i32.store0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (i32.store (i32.const 1000) (i32.const 0x22334455))
+ (i32.load (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.store0.wee.wasm b/tests/proj2/tests/i32.store0.wee.wasm
new file mode 100644
index 0000000..9a0206e
--- /dev/null
+++ b/tests/proj2/tests/i32.store0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store1.runs b/tests/proj2/tests/i32.store1.runs
new file mode 100644
index 0000000..107460d
--- /dev/null
+++ b/tests/proj2/tests/i32.store1.runs
@@ -0,0 +1,10 @@
+496 = 0
+497 = 34
+498 = 8755
+499 = 2241348
+500 = 573785173
+501 = 860116224
+502 = 1146421248
+503 = 1426063360
+504 = 0
+505 = 0
diff --git a/tests/proj2/tests/i32.store1.wasm b/tests/proj2/tests/i32.store1.wasm
new file mode 100644
index 0000000..c590d88
--- /dev/null
+++ b/tests/proj2/tests/i32.store1.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store1.wat b/tests/proj2/tests/i32.store1.wat
new file mode 100644
index 0000000..74bb665
--- /dev/null
+++ b/tests/proj2/tests/i32.store1.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (i32.store (local.get 0) (i32.const 0x22334455))
+ (i32.load (i32.const 500))
+ )
+)
diff --git a/tests/proj2/tests/i32.store1.wee.wasm b/tests/proj2/tests/i32.store1.wee.wasm
new file mode 100644
index 0000000..ccb06d8
--- /dev/null
+++ b/tests/proj2/tests/i32.store1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store16_0.runs b/tests/proj2/tests/i32.store16_0.runs
new file mode 100644
index 0000000..5c30cf5
--- /dev/null
+++ b/tests/proj2/tests/i32.store16_0.runs
@@ -0,0 +1,10 @@
+0 = 0
+996 = 0
+997 = 1426063360
+998 = 1146421248
+999 = 4478208
+1000 = 17493
+1001 = 68
+1002 = 0
+1003 = 0
+1004 = 0
diff --git a/tests/proj2/tests/i32.store16_0.wasm b/tests/proj2/tests/i32.store16_0.wasm
new file mode 100644
index 0000000..15d8f76
--- /dev/null
+++ b/tests/proj2/tests/i32.store16_0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store16_0.wat b/tests/proj2/tests/i32.store16_0.wat
new file mode 100644
index 0000000..95519fd
--- /dev/null
+++ b/tests/proj2/tests/i32.store16_0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (i32.store16 (i32.const 1000) (i32.const 0x22334455))
+ (i32.load (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.store16_0.wee.wasm b/tests/proj2/tests/i32.store16_0.wee.wasm
new file mode 100644
index 0000000..291c0af
--- /dev/null
+++ b/tests/proj2/tests/i32.store16_0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store8_0.runs b/tests/proj2/tests/i32.store8_0.runs
new file mode 100644
index 0000000..2ab9847
--- /dev/null
+++ b/tests/proj2/tests/i32.store8_0.runs
@@ -0,0 +1,10 @@
+0 = 0
+996 = 0
+997 = 1426063360
+998 = 5570560
+999 = 21760
+1000 = 85
+1001 = 0
+1002 = 0
+1003 = 0
+1004 = 0
diff --git a/tests/proj2/tests/i32.store8_0.wasm b/tests/proj2/tests/i32.store8_0.wasm
new file mode 100644
index 0000000..225bc26
--- /dev/null
+++ b/tests/proj2/tests/i32.store8_0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.store8_0.wat b/tests/proj2/tests/i32.store8_0.wat
new file mode 100644
index 0000000..649338d
--- /dev/null
+++ b/tests/proj2/tests/i32.store8_0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (i32.store8 (i32.const 1000) (i32.const 0x22334455))
+ (i32.load (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.store8_0.wee.wasm b/tests/proj2/tests/i32.store8_0.wee.wasm
new file mode 100644
index 0000000..e6b688e
--- /dev/null
+++ b/tests/proj2/tests/i32.store8_0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.sub0.runs b/tests/proj2/tests/i32.sub0.runs
new file mode 100644
index 0000000..dd17d1b
--- /dev/null
+++ b/tests/proj2/tests/i32.sub0.runs
@@ -0,0 +1,8 @@
+8 9 = -1
+33 44 = -11
+111 222 = -111
+2222 3333 = -1111
+111111111 666666666 = -555555555
+-2147483648 -2147483648 = 0
+-2129587951 -2093796557 = -35791394
+2000000000 1 = 1999999999
diff --git a/tests/proj2/tests/i32.sub0.wasm b/tests/proj2/tests/i32.sub0.wasm
new file mode 100644
index 0000000..60d2e71
--- /dev/null
+++ b/tests/proj2/tests/i32.sub0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.sub0.wat b/tests/proj2/tests/i32.sub0.wat
new file mode 100644
index 0000000..0a6782a
--- /dev/null
+++ b/tests/proj2/tests/i32.sub0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.sub (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.sub0.wee.wasm b/tests/proj2/tests/i32.sub0.wee.wasm
new file mode 100644
index 0000000..579d572
--- /dev/null
+++ b/tests/proj2/tests/i32.sub0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.trunc_f64_s0.runs b/tests/proj2/tests/i32.trunc_f64_s0.runs
new file mode 100644
index 0000000..bc9401f
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_s0.runs
@@ -0,0 +1,8 @@
+0d = 0
+0.9d = 0
+-0.9d = 0
+1d = 1
+-87234d = -87234
+-2147483648d = -2147483648
+-3000000000d = !trap
+3000000000d = !trap
diff --git a/tests/proj2/tests/i32.trunc_f64_s0.wasm b/tests/proj2/tests/i32.trunc_f64_s0.wasm
new file mode 100644
index 0000000..672b69c
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_s0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.trunc_f64_s0.wat b/tests/proj2/tests/i32.trunc_f64_s0.wat
new file mode 100644
index 0000000..c70234b
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_s0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64) (result i32)
+ (i32.trunc_f64_s (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.trunc_f64_s0.wee.wasm b/tests/proj2/tests/i32.trunc_f64_s0.wee.wasm
new file mode 100644
index 0000000..fa6f6ba
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_s0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.trunc_f64_u0.runs b/tests/proj2/tests/i32.trunc_f64_u0.runs
new file mode 100644
index 0000000..13759f2
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_u0.runs
@@ -0,0 +1,7 @@
+0d = 0
+1d = 1
+0.9d = 0
+-0.9d = 0
+-87234d = !trap
+-2147483648d = !trap
+3000000000d = -1294967296
diff --git a/tests/proj2/tests/i32.trunc_f64_u0.wasm b/tests/proj2/tests/i32.trunc_f64_u0.wasm
new file mode 100644
index 0000000..5e161df
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_u0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.trunc_f64_u0.wat b/tests/proj2/tests/i32.trunc_f64_u0.wat
new file mode 100644
index 0000000..54f39b4
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_u0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param f64) (result i32)
+ (i32.trunc_f64_u (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/i32.trunc_f64_u0.wee.wasm b/tests/proj2/tests/i32.trunc_f64_u0.wee.wasm
new file mode 100644
index 0000000..242b7bb
--- /dev/null
+++ b/tests/proj2/tests/i32.trunc_f64_u0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.xor0.runs b/tests/proj2/tests/i32.xor0.runs
new file mode 100644
index 0000000..d0a1f1a
--- /dev/null
+++ b/tests/proj2/tests/i32.xor0.runs
@@ -0,0 +1,4 @@
+876234 982134 = 238268
+897234 0 = 897234
+89273498 -1 = -89273499
+-555 -2147483648 = 2147483093
diff --git a/tests/proj2/tests/i32.xor0.wasm b/tests/proj2/tests/i32.xor0.wasm
new file mode 100644
index 0000000..3a0d000
--- /dev/null
+++ b/tests/proj2/tests/i32.xor0.wasm
Binary files differ
diff --git a/tests/proj2/tests/i32.xor0.wat b/tests/proj2/tests/i32.xor0.wat
new file mode 100644
index 0000000..a982151
--- /dev/null
+++ b/tests/proj2/tests/i32.xor0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.xor (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/i32.xor0.wee.wasm b/tests/proj2/tests/i32.xor0.wee.wasm
new file mode 100644
index 0000000..9e015ae
--- /dev/null
+++ b/tests/proj2/tests/i32.xor0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob0.runs b/tests/proj2/tests/load_oob0.runs
new file mode 100644
index 0000000..de1a1e0
--- /dev/null
+++ b/tests/proj2/tests/load_oob0.runs
@@ -0,0 +1,12 @@
+65531 = 1144201728
+65532 = 1430532898
+65533 = !trap
+65534 = !trap
+65535 = !trap
+65536 = !trap
+100000 = !trap
+1000000 = !trap
+10000000 = !trap
+100000000 = !trap
+1000000000 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/load_oob0.wasm b/tests/proj2/tests/load_oob0.wasm
new file mode 100644
index 0000000..52c4268
--- /dev/null
+++ b/tests/proj2/tests/load_oob0.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob0.wat b/tests/proj2/tests/load_oob0.wat
new file mode 100644
index 0000000..08e9555
--- /dev/null
+++ b/tests/proj2/tests/load_oob0.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 65532) "\22\33\44\55")
+ (func (export "main") (param i32) (result i32)
+ (i32.load (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/load_oob0.wee.wasm b/tests/proj2/tests/load_oob0.wee.wasm
new file mode 100644
index 0000000..2f26796
--- /dev/null
+++ b/tests/proj2/tests/load_oob0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob1.runs b/tests/proj2/tests/load_oob1.runs
new file mode 100644
index 0000000..a594e28
--- /dev/null
+++ b/tests/proj2/tests/load_oob1.runs
@@ -0,0 +1,16 @@
+65531 = 0
+65532 = 0
+65533 = 0
+65534 = 0
+131066 = 857866240
+131067 = 1144201728
+131068 = 1430532898
+131069 = !trap
+131070 = !trap
+131071 = !trap
+131072 = !trap
+1000000 = !trap
+10000000 = !trap
+100000000 = !trap
+1000000000 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/load_oob1.wasm b/tests/proj2/tests/load_oob1.wasm
new file mode 100644
index 0000000..add5875
--- /dev/null
+++ b/tests/proj2/tests/load_oob1.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob1.wat b/tests/proj2/tests/load_oob1.wat
new file mode 100644
index 0000000..1317e30
--- /dev/null
+++ b/tests/proj2/tests/load_oob1.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 2)
+ (data (i32.const 131068) "\22\33\44\55")
+ (func (export "main") (param i32) (result i32)
+ (i32.load (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/load_oob1.wee.wasm b/tests/proj2/tests/load_oob1.wee.wasm
new file mode 100644
index 0000000..818df89
--- /dev/null
+++ b/tests/proj2/tests/load_oob1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob2.runs b/tests/proj2/tests/load_oob2.runs
new file mode 100644
index 0000000..23c54a5
--- /dev/null
+++ b/tests/proj2/tests/load_oob2.runs
@@ -0,0 +1,12 @@
+65531 = 0
+65532 = 34
+65533 = 51
+65534 = 68
+65535 = 85
+65536 = !trap
+100000 = !trap
+1000000 = !trap
+10000000 = !trap
+100000000 = !trap
+1000000000 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/load_oob2.wasm b/tests/proj2/tests/load_oob2.wasm
new file mode 100644
index 0000000..02f28c9
--- /dev/null
+++ b/tests/proj2/tests/load_oob2.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob2.wat b/tests/proj2/tests/load_oob2.wat
new file mode 100644
index 0000000..c00e6c0
--- /dev/null
+++ b/tests/proj2/tests/load_oob2.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 1)
+ (data (i32.const 65532) "\22\33\44\55")
+ (func (export "main") (param i32) (result i32)
+ (i32.load8_u (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/load_oob2.wee.wasm b/tests/proj2/tests/load_oob2.wee.wasm
new file mode 100644
index 0000000..c33c69a
--- /dev/null
+++ b/tests/proj2/tests/load_oob2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob3.runs b/tests/proj2/tests/load_oob3.runs
new file mode 100644
index 0000000..de1a1e0
--- /dev/null
+++ b/tests/proj2/tests/load_oob3.runs
@@ -0,0 +1,12 @@
+65531 = 1144201728
+65532 = 1430532898
+65533 = !trap
+65534 = !trap
+65535 = !trap
+65536 = !trap
+100000 = !trap
+1000000 = !trap
+10000000 = !trap
+100000000 = !trap
+1000000000 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/load_oob3.wasm b/tests/proj2/tests/load_oob3.wasm
new file mode 100644
index 0000000..b68d6d0
--- /dev/null
+++ b/tests/proj2/tests/load_oob3.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob3.wat b/tests/proj2/tests/load_oob3.wat
new file mode 100644
index 0000000..782c62c
--- /dev/null
+++ b/tests/proj2/tests/load_oob3.wat
@@ -0,0 +1,7 @@
+(module
+ (memory 2)
+ (data (i32.const 131068) "\22\33\44\55")
+ (func (export "main") (param i32) (result i32)
+ (i32.load offset=65536 (local.get 0))
+ )
+)
diff --git a/tests/proj2/tests/load_oob3.wee.wasm b/tests/proj2/tests/load_oob3.wee.wasm
new file mode 100644
index 0000000..21edfed
--- /dev/null
+++ b/tests/proj2/tests/load_oob3.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob5.runs b/tests/proj2/tests/load_oob5.runs
new file mode 100644
index 0000000..b57668e
--- /dev/null
+++ b/tests/proj2/tests/load_oob5.runs
@@ -0,0 +1,12 @@
+0 = 145
+1 = 145
+1000 = 145
+65528 = 145
+65529 = !trap
+65530 = !trap
+65531 = !trap
+65532 = !trap
+65533 = !trap
+65534 = !trap
+65535 = !trap
+65536 = !trap
diff --git a/tests/proj2/tests/load_oob5.wasm b/tests/proj2/tests/load_oob5.wasm
new file mode 100644
index 0000000..fca4f9b
--- /dev/null
+++ b/tests/proj2/tests/load_oob5.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob5.wat b/tests/proj2/tests/load_oob5.wat
new file mode 100644
index 0000000..0f38d58
--- /dev/null
+++ b/tests/proj2/tests/load_oob5.wat
@@ -0,0 +1,8 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (f64.load (local.get 0))
+ (drop)
+ (i32.const 145)
+ )
+)
diff --git a/tests/proj2/tests/load_oob5.wee.wasm b/tests/proj2/tests/load_oob5.wee.wasm
new file mode 100644
index 0000000..3ced6de
--- /dev/null
+++ b/tests/proj2/tests/load_oob5.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob6.runs b/tests/proj2/tests/load_oob6.runs
new file mode 100644
index 0000000..6b5514e
--- /dev/null
+++ b/tests/proj2/tests/load_oob6.runs
@@ -0,0 +1,12 @@
+0 = 143
+1 = 143
+1000 = 143
+5528 = 143
+5529 = !trap
+5530 = !trap
+5531 = !trap
+5532 = !trap
+5533 = !trap
+5534 = !trap
+5535 = !trap
+5536 = !trap
diff --git a/tests/proj2/tests/load_oob6.wasm b/tests/proj2/tests/load_oob6.wasm
new file mode 100644
index 0000000..3deb2c9
--- /dev/null
+++ b/tests/proj2/tests/load_oob6.wasm
Binary files differ
diff --git a/tests/proj2/tests/load_oob6.wat b/tests/proj2/tests/load_oob6.wat
new file mode 100644
index 0000000..1b9435a
--- /dev/null
+++ b/tests/proj2/tests/load_oob6.wat
@@ -0,0 +1,8 @@
+(module
+ (memory 1)
+ (func (export "main") (param i32) (result i32)
+ (f64.load offset=60000 (local.get 0))
+ (drop)
+ (i32.const 143)
+ )
+)
diff --git a/tests/proj2/tests/load_oob6.wee.wasm b/tests/proj2/tests/load_oob6.wee.wasm
new file mode 100644
index 0000000..af3ab64
--- /dev/null
+++ b/tests/proj2/tests/load_oob6.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/mul0.runs b/tests/proj2/tests/mul0.runs
new file mode 100644
index 0000000..b0374bc
--- /dev/null
+++ b/tests/proj2/tests/mul0.runs
@@ -0,0 +1,9 @@
+8 9 = 72
+33 44 = 1452
+111 222 = 24642
+2222 3333 = 7405926
+111111111 666666666 = 1332460582
+-2147483648 -2147483648 = 0
+-2129587951 -2093796557 = 909101411
+2000000000 1 = 2000000000
+2000000000 3 = 1705032704
diff --git a/tests/proj2/tests/mul0.wasm b/tests/proj2/tests/mul0.wasm
new file mode 100644
index 0000000..ac058f7
--- /dev/null
+++ b/tests/proj2/tests/mul0.wasm
Binary files differ
diff --git a/tests/proj2/tests/mul0.wat b/tests/proj2/tests/mul0.wat
new file mode 100644
index 0000000..950ccf9
--- /dev/null
+++ b/tests/proj2/tests/mul0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.mul (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/mul0.wee.wasm b/tests/proj2/tests/mul0.wee.wasm
new file mode 100644
index 0000000..e43be6e
--- /dev/null
+++ b/tests/proj2/tests/mul0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/rec.runs b/tests/proj2/tests/rec.runs
new file mode 100644
index 0000000..e4b0cf4
--- /dev/null
+++ b/tests/proj2/tests/rec.runs
@@ -0,0 +1 @@
+0 = 20
diff --git a/tests/proj2/tests/rec.wasm b/tests/proj2/tests/rec.wasm
new file mode 100644
index 0000000..961f36a
--- /dev/null
+++ b/tests/proj2/tests/rec.wasm
Binary files differ
diff --git a/tests/proj2/tests/rec.wat b/tests/proj2/tests/rec.wat
new file mode 100644
index 0000000..b6c0abe
--- /dev/null
+++ b/tests/proj2/tests/rec.wat
@@ -0,0 +1,11 @@
+(module
+ (global $g (mut i32) (i32.const 20))
+ (func $ref (export "main") (param i32) (result i32)
+ (global.get $g)
+ (br_if 0 (i32.le_s (local.get 0) (i32.const 0)))
+ (i32.const 1)
+ (i32.add)
+ (global.set $g)
+ (call $ref (i32.sub (local.get 0) (i32.const 1)))
+ )
+)
diff --git a/tests/proj2/tests/rec.wee.wasm b/tests/proj2/tests/rec.wee.wasm
new file mode 100644
index 0000000..116a9f9
--- /dev/null
+++ b/tests/proj2/tests/rec.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/return0.expect b/tests/proj2/tests/return0.expect
new file mode 100644
index 0000000..98d9bcb
--- /dev/null
+++ b/tests/proj2/tests/return0.expect
@@ -0,0 +1 @@
+17
diff --git a/tests/proj2/tests/return0.wasm b/tests/proj2/tests/return0.wasm
new file mode 100644
index 0000000..22a9a60
--- /dev/null
+++ b/tests/proj2/tests/return0.wasm
Binary files differ
diff --git a/tests/proj2/tests/return0.wat b/tests/proj2/tests/return0.wat
new file mode 100644
index 0000000..796dfd6
--- /dev/null
+++ b/tests/proj2/tests/return0.wat
@@ -0,0 +1,6 @@
+(module
+ (func (export "main") (result i32)
+ i32.const 17
+ return
+ )
+)
diff --git a/tests/proj2/tests/return0.wee.wasm b/tests/proj2/tests/return0.wee.wasm
new file mode 100644
index 0000000..66cbcb7
--- /dev/null
+++ b/tests/proj2/tests/return0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/return1.expect b/tests/proj2/tests/return1.expect
new file mode 100644
index 0000000..b6a7d89
--- /dev/null
+++ b/tests/proj2/tests/return1.expect
@@ -0,0 +1 @@
+16
diff --git a/tests/proj2/tests/return1.wasm b/tests/proj2/tests/return1.wasm
new file mode 100644
index 0000000..5bf6a32
--- /dev/null
+++ b/tests/proj2/tests/return1.wasm
Binary files differ
diff --git a/tests/proj2/tests/return1.wat b/tests/proj2/tests/return1.wat
new file mode 100644
index 0000000..4a6c696
--- /dev/null
+++ b/tests/proj2/tests/return1.wat
@@ -0,0 +1,7 @@
+(module
+ (func (export "main") (result i32)
+ i32.const 33
+ i32.const 16
+ return
+ )
+)
diff --git a/tests/proj2/tests/return1.wee.wasm b/tests/proj2/tests/return1.wee.wasm
new file mode 100644
index 0000000..100a386
--- /dev/null
+++ b/tests/proj2/tests/return1.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/return2.expect b/tests/proj2/tests/return2.expect
new file mode 100644
index 0000000..60d3b2f
--- /dev/null
+++ b/tests/proj2/tests/return2.expect
@@ -0,0 +1 @@
+15
diff --git a/tests/proj2/tests/return2.wasm b/tests/proj2/tests/return2.wasm
new file mode 100644
index 0000000..8a678b3
--- /dev/null
+++ b/tests/proj2/tests/return2.wasm
Binary files differ
diff --git a/tests/proj2/tests/return2.wat b/tests/proj2/tests/return2.wat
new file mode 100644
index 0000000..12dbcdb
--- /dev/null
+++ b/tests/proj2/tests/return2.wat
@@ -0,0 +1,16 @@
+(module
+ (func (export "main") (result i32)
+ i32.const 31
+ i32.const 32
+ i32.const 33
+ i32.const 34
+ i32.const 35
+ i32.const 36
+ i32.const 37
+ i32.const 38
+ i32.const 39
+ i32.const 39
+ i32.const 15
+ return
+ )
+)
diff --git a/tests/proj2/tests/return2.wee.wasm b/tests/proj2/tests/return2.wee.wasm
new file mode 100644
index 0000000..db836c2
--- /dev/null
+++ b/tests/proj2/tests/return2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/start0.expect b/tests/proj2/tests/start0.expect
new file mode 100644
index 0000000..7273c0f
--- /dev/null
+++ b/tests/proj2/tests/start0.expect
@@ -0,0 +1 @@
+25
diff --git a/tests/proj2/tests/start0.wasm b/tests/proj2/tests/start0.wasm
new file mode 100644
index 0000000..e599fdf
--- /dev/null
+++ b/tests/proj2/tests/start0.wasm
Binary files differ
diff --git a/tests/proj2/tests/start0.wat b/tests/proj2/tests/start0.wat
new file mode 100644
index 0000000..a498865
--- /dev/null
+++ b/tests/proj2/tests/start0.wat
@@ -0,0 +1,8 @@
+(module
+ (global $g (mut i32) (i32.const 20))
+ (func $start (global.set $g (i32.const 25)))
+ (start $start)
+ (func (export "main") (result i32)
+ (global.get $g)
+ )
+) \ No newline at end of file
diff --git a/tests/proj2/tests/start0.wee.wasm b/tests/proj2/tests/start0.wee.wasm
new file mode 100644
index 0000000..f98c676
--- /dev/null
+++ b/tests/proj2/tests/start0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/store_oob0.runs b/tests/proj2/tests/store_oob0.runs
new file mode 100644
index 0000000..572928c
--- /dev/null
+++ b/tests/proj2/tests/store_oob0.runs
@@ -0,0 +1,12 @@
+65531 = 12
+65532 = 12
+65533 = !trap
+65534 = !trap
+65535 = !trap
+65536 = !trap
+100000 = !trap
+1000000 = !trap
+10000000 = !trap
+100000000 = !trap
+1000000000 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/store_oob0.wasm b/tests/proj2/tests/store_oob0.wasm
new file mode 100644
index 0000000..1fa722a
--- /dev/null
+++ b/tests/proj2/tests/store_oob0.wasm
Binary files differ
diff --git a/tests/proj2/tests/store_oob0.wat b/tests/proj2/tests/store_oob0.wat
new file mode 100644
index 0000000..a16bdf7
--- /dev/null
+++ b/tests/proj2/tests/store_oob0.wat
@@ -0,0 +1,8 @@
+(module
+ (memory 1)
+ (data (i32.const 65532) "\22\33\44\55")
+ (func (export "main") (param i32) (result i32)
+ (i32.store (local.get 0) (i32.const 3))
+ (i32.const 12)
+ )
+)
diff --git a/tests/proj2/tests/store_oob0.wee.wasm b/tests/proj2/tests/store_oob0.wee.wasm
new file mode 100644
index 0000000..676005b
--- /dev/null
+++ b/tests/proj2/tests/store_oob0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/store_oob2.runs b/tests/proj2/tests/store_oob2.runs
new file mode 100644
index 0000000..0461704
--- /dev/null
+++ b/tests/proj2/tests/store_oob2.runs
@@ -0,0 +1,12 @@
+65531 = 77
+65532 = 77
+65533 = 77
+65534 = 77
+65535 = 77
+65536 = !trap
+100000 = !trap
+1000000 = !trap
+10000000 = !trap
+100000000 = !trap
+1000000000 = !trap
+-1 = !trap
diff --git a/tests/proj2/tests/store_oob2.wasm b/tests/proj2/tests/store_oob2.wasm
new file mode 100644
index 0000000..cc9678a
--- /dev/null
+++ b/tests/proj2/tests/store_oob2.wasm
Binary files differ
diff --git a/tests/proj2/tests/store_oob2.wat b/tests/proj2/tests/store_oob2.wat
new file mode 100644
index 0000000..e841c59
--- /dev/null
+++ b/tests/proj2/tests/store_oob2.wat
@@ -0,0 +1,8 @@
+(module
+ (memory 1)
+ (data (i32.const 65532) "\22\33\44\55")
+ (func (export "main") (param i32) (result i32)
+ (i32.store8 (local.get 0) (i32.const 44))
+ (i32.const 77)
+ )
+)
diff --git a/tests/proj2/tests/store_oob2.wee.wasm b/tests/proj2/tests/store_oob2.wee.wasm
new file mode 100644
index 0000000..45c7b03
--- /dev/null
+++ b/tests/proj2/tests/store_oob2.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/sub0.runs b/tests/proj2/tests/sub0.runs
new file mode 100644
index 0000000..dd17d1b
--- /dev/null
+++ b/tests/proj2/tests/sub0.runs
@@ -0,0 +1,8 @@
+8 9 = -1
+33 44 = -11
+111 222 = -111
+2222 3333 = -1111
+111111111 666666666 = -555555555
+-2147483648 -2147483648 = 0
+-2129587951 -2093796557 = -35791394
+2000000000 1 = 1999999999
diff --git a/tests/proj2/tests/sub0.wasm b/tests/proj2/tests/sub0.wasm
new file mode 100644
index 0000000..60d2e71
--- /dev/null
+++ b/tests/proj2/tests/sub0.wasm
Binary files differ
diff --git a/tests/proj2/tests/sub0.wat b/tests/proj2/tests/sub0.wat
new file mode 100644
index 0000000..0a6782a
--- /dev/null
+++ b/tests/proj2/tests/sub0.wat
@@ -0,0 +1,5 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.sub (local.get 0) (local.get 1))
+ )
+)
diff --git a/tests/proj2/tests/sub0.wee.wasm b/tests/proj2/tests/sub0.wee.wasm
new file mode 100644
index 0000000..579d572
--- /dev/null
+++ b/tests/proj2/tests/sub0.wee.wasm
Binary files differ
diff --git a/tests/proj2/tests/vobj0.runs b/tests/proj2/tests/vobj0.runs
new file mode 100644
index 0000000..307483b
--- /dev/null
+++ b/tests/proj2/tests/vobj0.runs
@@ -0,0 +1,5 @@
+0 = 11
+1 = 12
+2 = 33
+3 = 44
+4 = -55555
diff --git a/tests/proj2/tests/vobj0.wasm b/tests/proj2/tests/vobj0.wasm
new file mode 100644
index 0000000..4e23ccb
--- /dev/null
+++ b/tests/proj2/tests/vobj0.wasm
Binary files differ
diff --git a/tests/proj2/tests/vobj0.wat b/tests/proj2/tests/vobj0.wat
new file mode 100644
index 0000000..d4dd1af
--- /dev/null
+++ b/tests/proj2/tests/vobj0.wat
@@ -0,0 +1,15 @@
+(module
+ (type (;0;) (func (param i32) (result i32)))
+ (func (;0;) (type 0) (param i32) (result i32)
+ i32.const 65536
+ local.get 0
+ i32.const 4
+ i32.mul
+ i32.const 8
+ i32.add
+ i32.add
+ i32.load
+ i32.load offset=4)
+ (memory (;0;) 3 3)
+ (export "main" (func 0))
+ (data (;0;) (i32.const 65536) "\13\00\00\00\05\00\00\00\1c\00\01\00$\00\01\00,\00\01\004\00\01\00<\00\01\00\00\00\00\00\0b\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00!\00\00\00\00\00\00\00,\00\00\00\00\00\00\00\fd&\ff\ff"))
diff --git a/tests/proj2/tests/vobj0.wee.wasm b/tests/proj2/tests/vobj0.wee.wasm
new file mode 100644
index 0000000..cb05182
--- /dev/null
+++ b/tests/proj2/tests/vobj0.wee.wasm
Binary files differ
diff --git a/tests/proj3/grade.sh b/tests/proj3/grade.sh
new file mode 100755
index 0000000..d720ffb
--- /dev/null
+++ b/tests/proj3/grade.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+if [ $# = 0 ]; then
+ WEERUN='../../weerun'
+else
+ WEERUN=$1
+ shift
+fi
+
+T=${OUT:=/tmp/$USER/cs17670/$STUDENT/proj2-test/}
+mkdir -p $T
+
+
+if [ ! -x "$WEERUN" ]; then
+ printf "##+weerun\n"
+ printf "##-fail, weerun not found: %s\n" $WEERUN
+ exit 1
+fi
+
+if [ $# = 0 ]; then
+ TESTS=$(ls tests/*.wee.wasm)
+else
+ TESTS=$@
+fi
+
+# substitute for the "timeout" command on MacOS
+function xtimeout {
+ timeout=$1
+ shift
+ command=("$@")
+ (
+ "${command[@]}" &
+ runnerpid=$!
+ trap -- '' SIGTERM
+ ( # killer job
+ sleep $timeout
+ if ps -p $runnerpid > /dev/null; then
+ echo "Timed out, killing"
+ kill -SIGKILL $runnerpid 2>/dev/null
+ fi
+ ) &
+ killerpid=$!
+ wait $runnerpid
+ kill -SIGKILL $killerpid
+ )
+}
+
+function run_one() {
+ echo $WEERUN $f $ARGS
+ xtimeout 5s $WEERUN $f $ARGS > $OUT 2>$ERR
+ # ignore case
+ diff --strip-trailing-cr -i $EXP $OUT > $DIFF
+ OK=$?
+ if [ ! -s $DIFF ]; then
+ # remove empty diffs
+ rm $DIFF
+ else
+ cat $DIFF
+ fi
+
+ if [ $OK = 0 ]; then
+ return 0
+ else
+ echo diff $EXP $OUT
+ printf "##-fail: $ARGS\n"
+ return 1
+ fi
+
+}
+
+for f in $TESTS; do
+ # replace slashes with _
+ t=${f//\//_}
+ # replace .wasm with .runs
+ runs=${f/%.wee.wasm/.runs}
+
+ printf "##+%s\n" $t
+
+ OUT=$T/$t.out
+ ERR=$T/$t.err
+ EXP=$T/$t.expect
+ DIFF=$T/$t.diff
+
+ if [ -f $runs ]; then
+ # do multiple runs for this test
+ ok=1
+ while IFS= read -r line
+ do
+ ARGS=$(echo $line | cut -d= -f1)
+ EXPECT=$(echo $line | cut -d= -f2)
+ echo $EXPECT > $EXP
+
+ run_one
+
+ if [ $? != 0 ]; then
+ ok=0
+ break;
+ fi
+ done < $runs
+ if [ $ok = 1 ]; then
+ printf "##-ok\n"
+ fi
+ else
+ # do one run
+ e=${f/%.wee.wasm/.expect}
+ args=${f/%.wee.wasm/.args}
+ cp $e $EXP
+
+ if [ -f $args ]; then
+ ARGS=$(cat $args)
+ else
+ ARGS=""
+ fi
+
+ run_one
+
+ if [ $? = 0 ]; then
+ printf "##-ok\n"
+ fi
+ fi
+done
diff --git a/tests/proj3/tests/array_get0.runs b/tests/proj3/tests/array_get0.runs
new file mode 100644
index 0000000..8e9739c
--- /dev/null
+++ b/tests/proj3/tests/array_get0.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = !trap
+2 = !trap
+3 = !trap
+4 = 4
+5 = 4
+12 = 4
diff --git a/tests/proj3/tests/array_get0.wasm b/tests/proj3/tests/array_get0.wasm
new file mode 100644
index 0000000..ce491b6
--- /dev/null
+++ b/tests/proj3/tests/array_get0.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_get0.wat b/tests/proj3/tests/array_get0.wat
new file mode 100644
index 0000000..4d5f395
--- /dev/null
+++ b/tests/proj3/tests/array_get0.wat
@@ -0,0 +1,26 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func $alloc (param i32) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (loop $l
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (local.get 0)))
+ (local.set 0 (i32.sub (local.get 0) (i32.const 1)))
+ (br_if $l (i32.ge_s (local.get 0) (i32.const 0)))
+ )
+ (local.get $obj)
+ )
+
+ (func $get (param externref i32) (result i32)
+ (call $u (call $g (local.get 0) (call $b (local.get 1))))
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (call $get (call $alloc (local.get 0)) (i32.const 4))
+ )
+)
diff --git a/tests/proj3/tests/array_get0.wee.wasm b/tests/proj3/tests/array_get0.wee.wasm
new file mode 100644
index 0000000..69454ec
--- /dev/null
+++ b/tests/proj3/tests/array_get0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sparse0.runs b/tests/proj3/tests/array_sparse0.runs
new file mode 100644
index 0000000..009157f
--- /dev/null
+++ b/tests/proj3/tests/array_sparse0.runs
@@ -0,0 +1,9 @@
+0 = !trap
+4 = 4
+5 = !trap
+100004 = 4
+200004 = 4
+1000004 = 4
+10000004 = 4
+100000004 = 4
+100000009 = !trap
diff --git a/tests/proj3/tests/array_sparse0.wasm b/tests/proj3/tests/array_sparse0.wasm
new file mode 100644
index 0000000..bb18b5b
--- /dev/null
+++ b/tests/proj3/tests/array_sparse0.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sparse0.wat b/tests/proj3/tests/array_sparse0.wat
new file mode 100644
index 0000000..233453e
--- /dev/null
+++ b/tests/proj3/tests/array_sparse0.wat
@@ -0,0 +1,26 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func $alloc (param i32) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (loop $l
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (local.get 0)))
+ (local.set 0 (i32.sub (local.get 0) (i32.const 100000)))
+ (br_if $l (i32.ge_s (local.get 0) (i32.const 0)))
+ )
+ (local.get $obj)
+ )
+
+ (func $get (param externref i32) (result i32)
+ (call $u (call $g (local.get 0) (call $b (local.get 1))))
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (call $get (call $alloc (local.get 0)) (i32.const 4))
+ )
+)
diff --git a/tests/proj3/tests/array_sparse0.wee.wasm b/tests/proj3/tests/array_sparse0.wee.wasm
new file mode 100644
index 0000000..bdb4e7e
--- /dev/null
+++ b/tests/proj3/tests/array_sparse0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sparse1.runs b/tests/proj3/tests/array_sparse1.runs
new file mode 100644
index 0000000..b317a60
--- /dev/null
+++ b/tests/proj3/tests/array_sparse1.runs
@@ -0,0 +1,4 @@
+0 = !trap
+1 = 4763899
+500 = 4763899
+2000 = 4763899
diff --git a/tests/proj3/tests/array_sparse1.wasm b/tests/proj3/tests/array_sparse1.wasm
new file mode 100644
index 0000000..7a34517
--- /dev/null
+++ b/tests/proj3/tests/array_sparse1.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sparse1.wat b/tests/proj3/tests/array_sparse1.wat
new file mode 100644
index 0000000..7b17cb5
--- /dev/null
+++ b/tests/proj3/tests/array_sparse1.wat
@@ -0,0 +1,28 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func $alloc (param i32) (result externref)
+ (local $obj externref)
+ (local $key externref)
+ (local.set $obj (call $n))
+ (loop $l
+ (local.set $key (call $b (i32.mul (local.get 0) (i32.const 4763899))))
+ (call $s (local.get $obj) (local.get $key) (local.get $key))
+ (local.set 0 (i32.sub (local.get 0) (i32.const 1)))
+ (br_if $l (i32.ge_s (local.get 0) (i32.const 0)))
+ )
+ (local.get $obj)
+ )
+
+ (func $get (param externref i32) (result i32)
+ (call $u (call $g (local.get 0) (call $b (local.get 1))))
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (call $get (call $alloc (local.get 0)) (i32.const 4763899))
+ )
+)
diff --git a/tests/proj3/tests/array_sparse1.wee.wasm b/tests/proj3/tests/array_sparse1.wee.wasm
new file mode 100644
index 0000000..2a521e4
--- /dev/null
+++ b/tests/proj3/tests/array_sparse1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sum0.runs b/tests/proj3/tests/array_sum0.runs
new file mode 100644
index 0000000..c7b8734
--- /dev/null
+++ b/tests/proj3/tests/array_sum0.runs
@@ -0,0 +1,8 @@
+0 = 0
+1 = 1
+2 = 3
+3 = 6
+4 = 10
+5 = 15
+25 = 325
+55 = 1540
diff --git a/tests/proj3/tests/array_sum0.wasm b/tests/proj3/tests/array_sum0.wasm
new file mode 100644
index 0000000..3c5d426
--- /dev/null
+++ b/tests/proj3/tests/array_sum0.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sum0.wat b/tests/proj3/tests/array_sum0.wat
new file mode 100644
index 0000000..fb3759f
--- /dev/null
+++ b/tests/proj3/tests/array_sum0.wat
@@ -0,0 +1,32 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func $alloc (param i32) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (loop $l
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (local.get 0)))
+ (local.set 0 (i32.sub (local.get 0) (i32.const 1)))
+ (br_if $l (i32.ge_s (local.get 0) (i32.const 0)))
+ )
+ (local.get $obj)
+ )
+
+ (func $sum (param externref i32) (result i32)
+ (local $s i32)
+ (loop $l
+ (local.set $s (i32.add (local.get $s) (call $u (call $g (local.get 0) (call $b (local.get 1))))))
+ (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
+ (br_if $l (i32.ge_s (local.get 1) (i32.const 0)))
+ )
+ (local.get $s)
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (call $sum (call $alloc (local.get 0)) (local.get 0))
+ )
+)
diff --git a/tests/proj3/tests/array_sum0.wee.wasm b/tests/proj3/tests/array_sum0.wee.wasm
new file mode 100644
index 0000000..93bdc7f
--- /dev/null
+++ b/tests/proj3/tests/array_sum0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sum1.runs b/tests/proj3/tests/array_sum1.runs
new file mode 100644
index 0000000..87cba9b
--- /dev/null
+++ b/tests/proj3/tests/array_sum1.runs
@@ -0,0 +1,8 @@
+0 = 11
+1 = 23
+2 = 36
+3 = 50
+4 = 65
+5 = 81
+25 = 611
+55 = 2156
diff --git a/tests/proj3/tests/array_sum1.wasm b/tests/proj3/tests/array_sum1.wasm
new file mode 100644
index 0000000..0d1f815
--- /dev/null
+++ b/tests/proj3/tests/array_sum1.wasm
Binary files differ
diff --git a/tests/proj3/tests/array_sum1.wat b/tests/proj3/tests/array_sum1.wat
new file mode 100644
index 0000000..41885a0
--- /dev/null
+++ b/tests/proj3/tests/array_sum1.wat
@@ -0,0 +1,32 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func $alloc (param i32) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (loop $l
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (i32.add (local.get 0) (i32.const 11))))
+ (local.set 0 (i32.sub (local.get 0) (i32.const 1)))
+ (br_if $l (i32.ge_s (local.get 0) (i32.const 0)))
+ )
+ (local.get $obj)
+ )
+
+ (func $sum (param externref i32) (result i32)
+ (local $s i32)
+ (loop $l
+ (local.set $s (i32.add (local.get $s) (call $u (call $g (local.get 0) (call $b (local.get 1))))))
+ (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
+ (br_if $l (i32.ge_s (local.get 1) (i32.const 0)))
+ )
+ (local.get $s)
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (call $sum (call $alloc (local.get 0)) (local.get 0))
+ )
+)
diff --git a/tests/proj3/tests/array_sum1.wee.wasm b/tests/proj3/tests/array_sum1.wee.wasm
new file mode 100644
index 0000000..df55408
--- /dev/null
+++ b/tests/proj3/tests/array_sum1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br0.expect b/tests/proj3/tests/br0.expect
new file mode 100644
index 0000000..920a139
--- /dev/null
+++ b/tests/proj3/tests/br0.expect
@@ -0,0 +1 @@
+43
diff --git a/tests/proj3/tests/br0.wasm b/tests/proj3/tests/br0.wasm
new file mode 100644
index 0000000..c71f1fb
--- /dev/null
+++ b/tests/proj3/tests/br0.wasm
Binary files differ
diff --git a/tests/proj3/tests/br0.wat b/tests/proj3/tests/br0.wat
new file mode 100644
index 0000000..d4607f2
--- /dev/null
+++ b/tests/proj3/tests/br0.wat
@@ -0,0 +1,8 @@
+(module
+ (func (export "main") (result i32)
+ (block
+ (br 0)
+ )
+ (i32.const 43)
+ )
+)
diff --git a/tests/proj3/tests/br0.wee.wasm b/tests/proj3/tests/br0.wee.wasm
new file mode 100644
index 0000000..83ec9f9
--- /dev/null
+++ b/tests/proj3/tests/br0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br1.expect b/tests/proj3/tests/br1.expect
new file mode 100644
index 0000000..abac1ea
--- /dev/null
+++ b/tests/proj3/tests/br1.expect
@@ -0,0 +1 @@
+47
diff --git a/tests/proj3/tests/br1.wasm b/tests/proj3/tests/br1.wasm
new file mode 100644
index 0000000..bb64ae0
--- /dev/null
+++ b/tests/proj3/tests/br1.wasm
Binary files differ
diff --git a/tests/proj3/tests/br1.wat b/tests/proj3/tests/br1.wat
new file mode 100644
index 0000000..0e6e1f6
--- /dev/null
+++ b/tests/proj3/tests/br1.wat
@@ -0,0 +1,6 @@
+(module
+ (func (export "main") (result i32)
+ (i32.const 47)
+ (br 0)
+ )
+)
diff --git a/tests/proj3/tests/br1.wee.wasm b/tests/proj3/tests/br1.wee.wasm
new file mode 100644
index 0000000..75de416
--- /dev/null
+++ b/tests/proj3/tests/br1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br2.expect b/tests/proj3/tests/br2.expect
new file mode 100644
index 0000000..95f9650
--- /dev/null
+++ b/tests/proj3/tests/br2.expect
@@ -0,0 +1 @@
+49
diff --git a/tests/proj3/tests/br2.wasm b/tests/proj3/tests/br2.wasm
new file mode 100644
index 0000000..49568d1
--- /dev/null
+++ b/tests/proj3/tests/br2.wasm
Binary files differ
diff --git a/tests/proj3/tests/br2.wat b/tests/proj3/tests/br2.wat
new file mode 100644
index 0000000..05c1ad8
--- /dev/null
+++ b/tests/proj3/tests/br2.wat
@@ -0,0 +1,9 @@
+(module
+ (func (export "main") (result i32)
+ (block
+ (i32.const 49)
+ (br 1)
+ drop)
+ (i32.const 67)
+ )
+)
diff --git a/tests/proj3/tests/br2.wee.wasm b/tests/proj3/tests/br2.wee.wasm
new file mode 100644
index 0000000..cd769c4
--- /dev/null
+++ b/tests/proj3/tests/br2.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br3.expect b/tests/proj3/tests/br3.expect
new file mode 100644
index 0000000..59343b0
--- /dev/null
+++ b/tests/proj3/tests/br3.expect
@@ -0,0 +1 @@
+53
diff --git a/tests/proj3/tests/br3.wasm b/tests/proj3/tests/br3.wasm
new file mode 100644
index 0000000..22be754
--- /dev/null
+++ b/tests/proj3/tests/br3.wasm
Binary files differ
diff --git a/tests/proj3/tests/br3.wat b/tests/proj3/tests/br3.wat
new file mode 100644
index 0000000..b5872ab
--- /dev/null
+++ b/tests/proj3/tests/br3.wat
@@ -0,0 +1,11 @@
+(module
+ (func (export "main") (result i32)
+ (block
+ (block
+ (i32.const 53)
+ (br 2)
+ drop)
+ )
+ (i32.const 67)
+ )
+)
diff --git a/tests/proj3/tests/br3.wee.wasm b/tests/proj3/tests/br3.wee.wasm
new file mode 100644
index 0000000..17ab547
--- /dev/null
+++ b/tests/proj3/tests/br3.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_if0.runs b/tests/proj3/tests/br_if0.runs
new file mode 100644
index 0000000..cf65396
--- /dev/null
+++ b/tests/proj3/tests/br_if0.runs
@@ -0,0 +1,3 @@
+0 = 57
+1 = 46
+87234 = 46
diff --git a/tests/proj3/tests/br_if0.wasm b/tests/proj3/tests/br_if0.wasm
new file mode 100644
index 0000000..4e6e06a
--- /dev/null
+++ b/tests/proj3/tests/br_if0.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_if0.wat b/tests/proj3/tests/br_if0.wat
new file mode 100644
index 0000000..a07f636
--- /dev/null
+++ b/tests/proj3/tests/br_if0.wat
@@ -0,0 +1,8 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (i32.const 46)
+ (br_if 0 (local.get 0))
+ (drop)
+ (i32.const 57)
+ )
+) \ No newline at end of file
diff --git a/tests/proj3/tests/br_if0.wee.wasm b/tests/proj3/tests/br_if0.wee.wasm
new file mode 100644
index 0000000..552356f
--- /dev/null
+++ b/tests/proj3/tests/br_if0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_if1.runs b/tests/proj3/tests/br_if1.runs
new file mode 100644
index 0000000..a47419c
--- /dev/null
+++ b/tests/proj3/tests/br_if1.runs
@@ -0,0 +1,7 @@
+0 0 = 66
+1 0 = 44
+0 1 = 55
+-1 0 = 44
+0 -1 = 55
+98237 55 = 44
+0 982345 = 55
diff --git a/tests/proj3/tests/br_if1.wasm b/tests/proj3/tests/br_if1.wasm
new file mode 100644
index 0000000..e1df9fa
--- /dev/null
+++ b/tests/proj3/tests/br_if1.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_if1.wat b/tests/proj3/tests/br_if1.wat
new file mode 100644
index 0000000..82d9c07
--- /dev/null
+++ b/tests/proj3/tests/br_if1.wat
@@ -0,0 +1,11 @@
+(module
+ (func (export "main") (param i32 i32) (result i32)
+ (i32.const 44)
+ (br_if 0 (local.get 0))
+ (drop)
+ (i32.const 55)
+ (br_if 0 (local.get 1))
+ (drop)
+ (i32.const 66)
+ )
+) \ No newline at end of file
diff --git a/tests/proj3/tests/br_if1.wee.wasm b/tests/proj3/tests/br_if1.wee.wasm
new file mode 100644
index 0000000..5db77d6
--- /dev/null
+++ b/tests/proj3/tests/br_if1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_if2.runs b/tests/proj3/tests/br_if2.runs
new file mode 100644
index 0000000..581af19
--- /dev/null
+++ b/tests/proj3/tests/br_if2.runs
@@ -0,0 +1,8 @@
+0 0 0 = 44
+1 0 0 = 11
+0 1 0 = 22
+0 0 1 = 33
+1 0 0 = 11
+1 1 0 = 11
+1 1 1 = 11
+0 1 1 = 22
diff --git a/tests/proj3/tests/br_if2.wasm b/tests/proj3/tests/br_if2.wasm
new file mode 100644
index 0000000..08e61b5
--- /dev/null
+++ b/tests/proj3/tests/br_if2.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_if2.wat b/tests/proj3/tests/br_if2.wat
new file mode 100644
index 0000000..bd2d810
--- /dev/null
+++ b/tests/proj3/tests/br_if2.wat
@@ -0,0 +1,16 @@
+(module
+ (func (export "main") (param i32 i32 i32) (result i32)
+ (block
+ (i32.const 11)
+ (br_if 1 (local.get 0))
+ (drop)
+ (i32.const 22)
+ (br_if 1 (local.get 1))
+ (drop)
+ (i32.const 33)
+ (br_if 1 (local.get 2))
+ (drop)
+ )
+ (i32.const 44)
+ )
+)
diff --git a/tests/proj3/tests/br_if2.wee.wasm b/tests/proj3/tests/br_if2.wee.wasm
new file mode 100644
index 0000000..db48ae7
--- /dev/null
+++ b/tests/proj3/tests/br_if2.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_table4.runs b/tests/proj3/tests/br_table4.runs
new file mode 100644
index 0000000..9c5bf64
--- /dev/null
+++ b/tests/proj3/tests/br_table4.runs
@@ -0,0 +1,24 @@
+0 = 45
+1 = 46
+2 = 47
+3 = 48
+4 = 49
+5 = 56
+6 = 56
+7 = 49
+8 = 48
+9 = 47
+10 = 46
+11 = 45
+12 = 45
+13 = 45
+14 = 46
+15 = 46
+16 = 47
+17 = 47
+18 = 47
+19 = 47
+20 = 47
+21 = 47
+22 = 47
+23 = 47
diff --git a/tests/proj3/tests/br_table4.wasm b/tests/proj3/tests/br_table4.wasm
new file mode 100644
index 0000000..5ed1ddf
--- /dev/null
+++ b/tests/proj3/tests/br_table4.wasm
Binary files differ
diff --git a/tests/proj3/tests/br_table4.wat b/tests/proj3/tests/br_table4.wat
new file mode 100644
index 0000000..6b1d0b0
--- /dev/null
+++ b/tests/proj3/tests/br_table4.wat
@@ -0,0 +1,19 @@
+(module
+ (func (export "main") (param i32) (result i32)
+ (block
+ (block
+ (block
+ (block
+ (block
+ (block
+ (br_table 0 1 2 3 4 5 5 4 3 2 1 0 0 0 1 1 2 2 (local.get 0)
+ ) (return (i32.const 44))
+ ) (return (i32.const 45))
+ ) (return (i32.const 46))
+ ) (return (i32.const 47))
+ ) (return (i32.const 48))
+ ) (return (i32.const 49))
+ )
+ (i32.const 56)
+ )
+)
diff --git a/tests/proj3/tests/br_table4.wee.wasm b/tests/proj3/tests/br_table4.wee.wasm
new file mode 100644
index 0000000..3357ef9
--- /dev/null
+++ b/tests/proj3/tests/br_table4.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/build.sh b/tests/proj3/tests/build.sh
new file mode 100755
index 0000000..a319aba
--- /dev/null
+++ b/tests/proj3/tests/build.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ]; do
+ DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+ SOURCE="$(readlink "$SOURCE")"
+ [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
+done
+DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+
+PROJ2=$(cd $DIR/.. && pwd)
+WEEIFY=$PROJ2/weeify
+
+WAT2WASM=$(which wat2wasm)
+
+if [[ ! -x $WAT2WASM ]]; then
+ echo Error: wat2asm not found in PATH
+ exit 1
+fi
+
+if [[ ! -x $WEEIFY ]]; then
+ echo Error: weeify not found $DIR
+ exit 1
+fi
+
+if [ $# = 0 ]; then
+ FILES="*.wat"
+else
+ FILES="$@"
+fi
+
+for f in $FILES; do
+ wat2wasm $f
+ $WEEIFY -o ${f/%.wat/.wee.wasm} ${f/%.wat/.wasm}
+done
diff --git a/tests/proj3/tests/call_indirect0.runs b/tests/proj3/tests/call_indirect0.runs
new file mode 100644
index 0000000..9b03289
--- /dev/null
+++ b/tests/proj3/tests/call_indirect0.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = !trap
+2 = !trap
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj3/tests/call_indirect0.wasm b/tests/proj3/tests/call_indirect0.wasm
new file mode 100644
index 0000000..e0383b1
--- /dev/null
+++ b/tests/proj3/tests/call_indirect0.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect0.wat b/tests/proj3/tests/call_indirect0.wat
new file mode 100644
index 0000000..5a08ddc
--- /dev/null
+++ b/tests/proj3/tests/call_indirect0.wat
@@ -0,0 +1,10 @@
+(module
+ (table 5 funcref)
+ (type $v_r (func (result externref)))
+
+ (func (export "main") (param i32) (result i32)
+ (call_indirect (type $v_r) (local.get 0))
+ (drop)
+ (i32.const 0)
+ )
+)
diff --git a/tests/proj3/tests/call_indirect0.wee.wasm b/tests/proj3/tests/call_indirect0.wee.wasm
new file mode 100644
index 0000000..f3ba3a1
--- /dev/null
+++ b/tests/proj3/tests/call_indirect0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect1.runs b/tests/proj3/tests/call_indirect1.runs
new file mode 100644
index 0000000..9b03289
--- /dev/null
+++ b/tests/proj3/tests/call_indirect1.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = !trap
+2 = !trap
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj3/tests/call_indirect1.wasm b/tests/proj3/tests/call_indirect1.wasm
new file mode 100644
index 0000000..449648d
--- /dev/null
+++ b/tests/proj3/tests/call_indirect1.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect1.wat b/tests/proj3/tests/call_indirect1.wat
new file mode 100644
index 0000000..3e51c10
--- /dev/null
+++ b/tests/proj3/tests/call_indirect1.wat
@@ -0,0 +1,9 @@
+(module
+ (table funcref (elem $main))
+ (type $v_r (func (result externref)))
+ (func $main (export "main") (param i32) (result i32)
+ (call_indirect (type $v_r) (local.get 0))
+ (drop)
+ (i32.const 1)
+ )
+)
diff --git a/tests/proj3/tests/call_indirect1.wee.wasm b/tests/proj3/tests/call_indirect1.wee.wasm
new file mode 100644
index 0000000..cc7732e
--- /dev/null
+++ b/tests/proj3/tests/call_indirect1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect2.runs b/tests/proj3/tests/call_indirect2.runs
new file mode 100644
index 0000000..62141a7
--- /dev/null
+++ b/tests/proj3/tests/call_indirect2.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = 1888
+2 = !trap
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj3/tests/call_indirect2.wasm b/tests/proj3/tests/call_indirect2.wasm
new file mode 100644
index 0000000..e4abade
--- /dev/null
+++ b/tests/proj3/tests/call_indirect2.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect2.wat b/tests/proj3/tests/call_indirect2.wat
new file mode 100644
index 0000000..e71c07f
--- /dev/null
+++ b/tests/proj3/tests/call_indirect2.wat
@@ -0,0 +1,13 @@
+(module
+ (table funcref (elem $main $empty))
+ (type $v_r (func (result externref)))
+ (func $main (export "main") (param i32) (result i32)
+ (call_indirect (type $v_r) (local.get 0))
+ (drop)
+ (i32.const 1888)
+ )
+ (func $empty (result externref)
+ (local $foo externref)
+ (local.get $foo)
+ )
+)
diff --git a/tests/proj3/tests/call_indirect2.wee.wasm b/tests/proj3/tests/call_indirect2.wee.wasm
new file mode 100644
index 0000000..3e13fcc
--- /dev/null
+++ b/tests/proj3/tests/call_indirect2.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect3.runs b/tests/proj3/tests/call_indirect3.runs
new file mode 100644
index 0000000..6c63a70
--- /dev/null
+++ b/tests/proj3/tests/call_indirect3.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = -1877
+2 = -1877
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj3/tests/call_indirect3.wasm b/tests/proj3/tests/call_indirect3.wasm
new file mode 100644
index 0000000..54a094e
--- /dev/null
+++ b/tests/proj3/tests/call_indirect3.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect3.wat b/tests/proj3/tests/call_indirect3.wat
new file mode 100644
index 0000000..6af5aba
--- /dev/null
+++ b/tests/proj3/tests/call_indirect3.wat
@@ -0,0 +1,14 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+
+ (table funcref (elem $main $empty $n))
+ (type $v_r (func (result externref)))
+ (func $main (export "main") (param i32) (result i32)
+ (call_indirect (type $v_r) (local.get 0))
+ (drop)
+ (i32.const -1877)
+ )
+ (func $empty (result externref)
+ (call $n)
+ )
+)
diff --git a/tests/proj3/tests/call_indirect3.wee.wasm b/tests/proj3/tests/call_indirect3.wee.wasm
new file mode 100644
index 0000000..0f5eb8e
--- /dev/null
+++ b/tests/proj3/tests/call_indirect3.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect4.runs b/tests/proj3/tests/call_indirect4.runs
new file mode 100644
index 0000000..9b03289
--- /dev/null
+++ b/tests/proj3/tests/call_indirect4.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = !trap
+2 = !trap
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj3/tests/call_indirect4.wasm b/tests/proj3/tests/call_indirect4.wasm
new file mode 100644
index 0000000..dcaf3cb
--- /dev/null
+++ b/tests/proj3/tests/call_indirect4.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect4.wat b/tests/proj3/tests/call_indirect4.wat
new file mode 100644
index 0000000..32eea34
--- /dev/null
+++ b/tests/proj3/tests/call_indirect4.wat
@@ -0,0 +1,15 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+
+ (table funcref (elem $main $empty))
+ (type $v_r (func (result externref)))
+
+ (func $main (export "main") (param i32) (result i32)
+ (call_indirect (type $v_r) (local.get 0))
+ (drop)
+ (i32.const -1866)
+ )
+ (func $empty (param externref) (result externref)
+ (call $n)
+ )
+)
diff --git a/tests/proj3/tests/call_indirect4.wee.wasm b/tests/proj3/tests/call_indirect4.wee.wasm
new file mode 100644
index 0000000..8062ec8
--- /dev/null
+++ b/tests/proj3/tests/call_indirect4.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect5.runs b/tests/proj3/tests/call_indirect5.runs
new file mode 100644
index 0000000..828a780
--- /dev/null
+++ b/tests/proj3/tests/call_indirect5.runs
@@ -0,0 +1,7 @@
+0 = !trap
+1 = -1865
+2 = !trap
+4 = !trap
+5 = !trap
+6 = !trap
+-1 = !trap
diff --git a/tests/proj3/tests/call_indirect5.wasm b/tests/proj3/tests/call_indirect5.wasm
new file mode 100644
index 0000000..db51d44
--- /dev/null
+++ b/tests/proj3/tests/call_indirect5.wasm
Binary files differ
diff --git a/tests/proj3/tests/call_indirect5.wat b/tests/proj3/tests/call_indirect5.wat
new file mode 100644
index 0000000..85d6510
--- /dev/null
+++ b/tests/proj3/tests/call_indirect5.wat
@@ -0,0 +1,15 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+
+ (table funcref (elem $main $empty))
+ (type $v_r (func (param externref) (result externref)))
+
+ (func $main (export "main") (param i32) (result i32)
+ (call_indirect (type $v_r) (call $n) (local.get 0))
+ (drop)
+ (i32.const -1865)
+ )
+ (func $empty (param externref) (result externref)
+ (call $n)
+ )
+)
diff --git a/tests/proj3/tests/call_indirect5.wee.wasm b/tests/proj3/tests/call_indirect5.wee.wasm
new file mode 100644
index 0000000..5d7f07d
--- /dev/null
+++ b/tests/proj3/tests/call_indirect5.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/ec_puti0.expect b/tests/proj3/tests/ec_puti0.expect
new file mode 100644
index 0000000..209cee3
--- /dev/null
+++ b/tests/proj3/tests/ec_puti0.expect
@@ -0,0 +1 @@
+4647
diff --git a/tests/proj3/tests/ec_puti0.wasm b/tests/proj3/tests/ec_puti0.wasm
new file mode 100644
index 0000000..8c67c22
--- /dev/null
+++ b/tests/proj3/tests/ec_puti0.wasm
Binary files differ
diff --git a/tests/proj3/tests/ec_puti0.wat b/tests/proj3/tests/ec_puti0.wat
new file mode 100644
index 0000000..a42fc37
--- /dev/null
+++ b/tests/proj3/tests/ec_puti0.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "puti" (func $puti (param i32)))
+ (func (export "main") (result i32)
+ (call $puti (i32.const 46))
+ (i32.const 47)
+ )
+)
diff --git a/tests/proj3/tests/ec_puti0.wee.wasm b/tests/proj3/tests/ec_puti0.wee.wasm
new file mode 100644
index 0000000..8b87e4b
--- /dev/null
+++ b/tests/proj3/tests/ec_puti0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/ec_puti1.expect b/tests/proj3/tests/ec_puti1.expect
new file mode 100644
index 0000000..f45c7ba
--- /dev/null
+++ b/tests/proj3/tests/ec_puti1.expect
@@ -0,0 +1 @@
+46931111666
diff --git a/tests/proj3/tests/ec_puti1.wasm b/tests/proj3/tests/ec_puti1.wasm
new file mode 100644
index 0000000..ec0001d
--- /dev/null
+++ b/tests/proj3/tests/ec_puti1.wasm
Binary files differ
diff --git a/tests/proj3/tests/ec_puti1.wat b/tests/proj3/tests/ec_puti1.wat
new file mode 100644
index 0000000..a9288c2
--- /dev/null
+++ b/tests/proj3/tests/ec_puti1.wat
@@ -0,0 +1,9 @@
+(module
+ (import "weewasm" "puti" (func $puti (param i32)))
+ (func (export "main") (result i32)
+ (call $puti (i32.const 46))
+ (call $puti (i32.const 93))
+ (call $puti (i32.const 1111))
+ (i32.const 666)
+ )
+)
diff --git a/tests/proj3/tests/ec_puti1.wee.wasm b/tests/proj3/tests/ec_puti1.wee.wasm
new file mode 100644
index 0000000..84cbec1
--- /dev/null
+++ b/tests/proj3/tests/ec_puti1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/eq_null0.expect b/tests/proj3/tests/eq_null0.expect
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/proj3/tests/eq_null0.expect
@@ -0,0 +1 @@
+0
diff --git a/tests/proj3/tests/eq_null0.wasm b/tests/proj3/tests/eq_null0.wasm
new file mode 100644
index 0000000..68ee98d
--- /dev/null
+++ b/tests/proj3/tests/eq_null0.wasm
Binary files differ
diff --git a/tests/proj3/tests/eq_null0.wat b/tests/proj3/tests/eq_null0.wat
new file mode 100644
index 0000000..7bc33c9
--- /dev/null
+++ b/tests/proj3/tests/eq_null0.wat
@@ -0,0 +1,9 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func (export "main") (result i32)
+ (local $null externref)
+ (call $eq (local.get $null) (call $n))
+ )
+)
diff --git a/tests/proj3/tests/eq_null0.wee.wasm b/tests/proj3/tests/eq_null0.wee.wasm
new file mode 100644
index 0000000..62ce3f2
--- /dev/null
+++ b/tests/proj3/tests/eq_null0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/eq_null1.expect b/tests/proj3/tests/eq_null1.expect
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/proj3/tests/eq_null1.expect
@@ -0,0 +1 @@
+0
diff --git a/tests/proj3/tests/eq_null1.wasm b/tests/proj3/tests/eq_null1.wasm
new file mode 100644
index 0000000..1f23dd2
--- /dev/null
+++ b/tests/proj3/tests/eq_null1.wasm
Binary files differ
diff --git a/tests/proj3/tests/eq_null1.wat b/tests/proj3/tests/eq_null1.wat
new file mode 100644
index 0000000..8c6b162
--- /dev/null
+++ b/tests/proj3/tests/eq_null1.wat
@@ -0,0 +1,8 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func (export "main") (result i32)
+ (call $eq (call $n) (call $n))
+ )
+)
diff --git a/tests/proj3/tests/eq_null1.wee.wasm b/tests/proj3/tests/eq_null1.wee.wasm
new file mode 100644
index 0000000..e5e6683
--- /dev/null
+++ b/tests/proj3/tests/eq_null1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/eqn.expect b/tests/proj3/tests/eqn.expect
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/tests/proj3/tests/eqn.expect
@@ -0,0 +1 @@
+9
diff --git a/tests/proj3/tests/eqn.wasm b/tests/proj3/tests/eqn.wasm
new file mode 100644
index 0000000..a24fd58
--- /dev/null
+++ b/tests/proj3/tests/eqn.wasm
Binary files differ
diff --git a/tests/proj3/tests/eqn.wat b/tests/proj3/tests/eqn.wat
new file mode 100644
index 0000000..8bc199f
--- /dev/null
+++ b/tests/proj3/tests/eqn.wat
@@ -0,0 +1,28 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func $equal (param externref externref i32) (result i32)
+ (local.get 2)
+ (br_if 0 (call $eq (local.get 0) (local.get 1)))
+ (drop)
+ (i32.const 0)
+ )
+
+ (func (export "main") (result i32)
+ (local $o1 externref)
+ (local $o2 externref)
+ (local $o3 externref)
+ (local.set $o2 (call $n))
+ (local.set $o3 (call $n))
+ (i32.or
+ (i32.or
+ (i32.or
+ (call $equal (local.get 0) (local.get 0) (i32.const 1))
+ (call $equal (local.get 0) (local.get 1) (i32.const 2)))
+ (i32.or
+ (call $equal (local.get 0) (local.get 2) (i32.const 4))
+ (call $equal (local.get 1) (local.get 1) (i32.const 8))))
+ (call $equal (local.get 1) (local.get 2) (i32.const 16)))
+ )
+)
diff --git a/tests/proj3/tests/eqn.wee.wasm b/tests/proj3/tests/eqn.wee.wasm
new file mode 100644
index 0000000..db4a331
--- /dev/null
+++ b/tests/proj3/tests/eqn.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/eqn2.expect b/tests/proj3/tests/eqn2.expect
new file mode 100644
index 0000000..7273c0f
--- /dev/null
+++ b/tests/proj3/tests/eqn2.expect
@@ -0,0 +1 @@
+25
diff --git a/tests/proj3/tests/eqn2.wasm b/tests/proj3/tests/eqn2.wasm
new file mode 100644
index 0000000..83ed0e7
--- /dev/null
+++ b/tests/proj3/tests/eqn2.wasm
Binary files differ
diff --git a/tests/proj3/tests/eqn2.wat b/tests/proj3/tests/eqn2.wat
new file mode 100644
index 0000000..9bb02ab
--- /dev/null
+++ b/tests/proj3/tests/eqn2.wat
@@ -0,0 +1,28 @@
+(module
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+
+ (func $equal (param externref externref i32) (result i32)
+ (local.get 2)
+ (br_if 0 (call $eq (local.get 0) (local.get 1)))
+ (drop)
+ (i32.const 0)
+ )
+
+ (func (export "main") (result i32)
+ (local $o1 externref)
+ (local $o2 externref)
+ (local $o3 externref)
+ (local.set $o2 (call $b (i32.const 44)))
+ (local.set $o3 (call $b (i32.const 44)))
+ (i32.or
+ (i32.or
+ (i32.or
+ (call $equal (local.get 0) (local.get 0) (i32.const 1))
+ (call $equal (local.get 0) (local.get 1) (i32.const 2)))
+ (i32.or
+ (call $equal (local.get 0) (local.get 2) (i32.const 4))
+ (call $equal (local.get 1) (local.get 1) (i32.const 8))))
+ (call $equal (local.get 1) (local.get 2) (i32.const 16)))
+ )
+)
diff --git a/tests/proj3/tests/eqn2.wee.wasm b/tests/proj3/tests/eqn2.wee.wasm
new file mode 100644
index 0000000..37cb551
--- /dev/null
+++ b/tests/proj3/tests/eqn2.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/eqn3.expect b/tests/proj3/tests/eqn3.expect
new file mode 100644
index 0000000..7273c0f
--- /dev/null
+++ b/tests/proj3/tests/eqn3.expect
@@ -0,0 +1 @@
+25
diff --git a/tests/proj3/tests/eqn3.wasm b/tests/proj3/tests/eqn3.wasm
new file mode 100644
index 0000000..f48ca5a
--- /dev/null
+++ b/tests/proj3/tests/eqn3.wasm
Binary files differ
diff --git a/tests/proj3/tests/eqn3.wat b/tests/proj3/tests/eqn3.wat
new file mode 100644
index 0000000..5cab459
--- /dev/null
+++ b/tests/proj3/tests/eqn3.wat
@@ -0,0 +1,28 @@
+(module
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+
+ (func $equal (param externref externref i32) (result i32)
+ (local.get 2)
+ (br_if 0 (call $eq (local.get 0) (local.get 1)))
+ (drop)
+ (i32.const 0)
+ )
+
+ (func (export "main") (result i32)
+ (local $o1 externref)
+ (local $o2 externref)
+ (local $o3 externref)
+ (local.set $o2 (call $b (f64.const -44.55)))
+ (local.set $o3 (call $b (f64.const -44.55)))
+ (i32.or
+ (i32.or
+ (i32.or
+ (call $equal (local.get 0) (local.get 0) (i32.const 1))
+ (call $equal (local.get 0) (local.get 1) (i32.const 2)))
+ (i32.or
+ (call $equal (local.get 0) (local.get 2) (i32.const 4))
+ (call $equal (local.get 1) (local.get 1) (i32.const 8))))
+ (call $equal (local.get 1) (local.get 2) (i32.const 16)))
+ )
+)
diff --git a/tests/proj3/tests/eqn3.wee.wasm b/tests/proj3/tests/eqn3.wee.wasm
new file mode 100644
index 0000000..5c3cda8
--- /dev/null
+++ b/tests/proj3/tests/eqn3.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64.add0_d.runs b/tests/proj3/tests/f64.add0_d.runs
new file mode 100644
index 0000000..51f77e8
--- /dev/null
+++ b/tests/proj3/tests/f64.add0_d.runs
@@ -0,0 +1,3 @@
+0d 1d = 1.000000
+0.25d -1.75d = -1.500000
+489728.83423d -782374.47d = -292645.635770
diff --git a/tests/proj3/tests/f64.add0_d.wasm b/tests/proj3/tests/f64.add0_d.wasm
new file mode 100644
index 0000000..64225ec
--- /dev/null
+++ b/tests/proj3/tests/f64.add0_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64.add0_d.wat b/tests/proj3/tests/f64.add0_d.wat
new file mode 100644
index 0000000..39ccc28
--- /dev/null
+++ b/tests/proj3/tests/f64.add0_d.wat
@@ -0,0 +1,8 @@
+(module
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+
+ (func (export "main") (param f64 f64) (result f64)
+ (f64.add (call $u (call $b (local.get 0))) (call $u (call $b (local.get 1))))
+ )
+)
diff --git a/tests/proj3/tests/f64.add0_d.wee.wasm b/tests/proj3/tests/f64.add0_d.wee.wasm
new file mode 100644
index 0000000..c86930b
--- /dev/null
+++ b/tests/proj3/tests/f64.add0_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64.add1_d.runs b/tests/proj3/tests/f64.add1_d.runs
new file mode 100644
index 0000000..51f77e8
--- /dev/null
+++ b/tests/proj3/tests/f64.add1_d.runs
@@ -0,0 +1,3 @@
+0d 1d = 1.000000
+0.25d -1.75d = -1.500000
+489728.83423d -782374.47d = -292645.635770
diff --git a/tests/proj3/tests/f64.add1_d.wasm b/tests/proj3/tests/f64.add1_d.wasm
new file mode 100644
index 0000000..005a91b
--- /dev/null
+++ b/tests/proj3/tests/f64.add1_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64.add1_d.wat b/tests/proj3/tests/f64.add1_d.wat
new file mode 100644
index 0000000..b067e33
--- /dev/null
+++ b/tests/proj3/tests/f64.add1_d.wat
@@ -0,0 +1,8 @@
+(module
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+
+ (func (export "main") (param f64 f64) (result f64)
+ (f64.add (call $u (call $b (local.get 0))) (local.get 1))
+ )
+)
diff --git a/tests/proj3/tests/f64.add1_d.wee.wasm b/tests/proj3/tests/f64.add1_d.wee.wasm
new file mode 100644
index 0000000..9f3a1c0
--- /dev/null
+++ b/tests/proj3/tests/f64.add1_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_box_unbox0_d.runs b/tests/proj3/tests/f64_box_unbox0_d.runs
new file mode 100644
index 0000000..0110ba6
--- /dev/null
+++ b/tests/proj3/tests/f64_box_unbox0_d.runs
@@ -0,0 +1,2 @@
+0.000000d = 0.000000
+-44.25d = -44.250000
diff --git a/tests/proj3/tests/f64_box_unbox0_d.wasm b/tests/proj3/tests/f64_box_unbox0_d.wasm
new file mode 100644
index 0000000..3ce66a5
--- /dev/null
+++ b/tests/proj3/tests/f64_box_unbox0_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_box_unbox0_d.wat b/tests/proj3/tests/f64_box_unbox0_d.wat
new file mode 100644
index 0000000..c9b1f60
--- /dev/null
+++ b/tests/proj3/tests/f64_box_unbox0_d.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (func (export "main") (param f64) (result f64)
+ (call $u (call $b (local.get 0)))
+ )
+)
diff --git a/tests/proj3/tests/f64_box_unbox0_d.wee.wasm b/tests/proj3/tests/f64_box_unbox0_d.wee.wasm
new file mode 100644
index 0000000..f6a93f2
--- /dev/null
+++ b/tests/proj3/tests/f64_box_unbox0_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_key0_d.runs b/tests/proj3/tests/f64_key0_d.runs
new file mode 100644
index 0000000..9dcb868
--- /dev/null
+++ b/tests/proj3/tests/f64_key0_d.runs
@@ -0,0 +1,3 @@
+0d = 100.000000
+1.25d = 101.250000
+-99d = 1.000000
diff --git a/tests/proj3/tests/f64_key0_d.wasm b/tests/proj3/tests/f64_key0_d.wasm
new file mode 100644
index 0000000..b0574ff
--- /dev/null
+++ b/tests/proj3/tests/f64_key0_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_key0_d.wat b/tests/proj3/tests/f64_key0_d.wat
new file mode 100644
index 0000000..05192c2
--- /dev/null
+++ b/tests/proj3/tests/f64_key0_d.wat
@@ -0,0 +1,16 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+
+ (func (export "main") (param f64) (result f64)
+ (local $obj externref)
+ (local $k externref)
+ (local.set $obj (call $n))
+ (local.set $k (call $b (local.get 0)))
+ (call $s (local.get $obj) (local.get $k) (call $b (f64.add (local.get 0) (f64.const 100))))
+ (call $u (call $g (local.get $obj) (local.get $k)))
+ )
+)
diff --git a/tests/proj3/tests/f64_key0_d.wee.wasm b/tests/proj3/tests/f64_key0_d.wee.wasm
new file mode 100644
index 0000000..ba641c6
--- /dev/null
+++ b/tests/proj3/tests/f64_key0_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_key1_d.runs b/tests/proj3/tests/f64_key1_d.runs
new file mode 100644
index 0000000..9dcb868
--- /dev/null
+++ b/tests/proj3/tests/f64_key1_d.runs
@@ -0,0 +1,3 @@
+0d = 100.000000
+1.25d = 101.250000
+-99d = 1.000000
diff --git a/tests/proj3/tests/f64_key1_d.wasm b/tests/proj3/tests/f64_key1_d.wasm
new file mode 100644
index 0000000..de9deb9
--- /dev/null
+++ b/tests/proj3/tests/f64_key1_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_key1_d.wat b/tests/proj3/tests/f64_key1_d.wat
new file mode 100644
index 0000000..8be55f3
--- /dev/null
+++ b/tests/proj3/tests/f64_key1_d.wat
@@ -0,0 +1,14 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+
+ (func (export "main") (param f64) (result f64)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100))))
+ (call $u (call $g (local.get $obj) (call $b (local.get 0))))
+ )
+)
diff --git a/tests/proj3/tests/f64_key1_d.wee.wasm b/tests/proj3/tests/f64_key1_d.wee.wasm
new file mode 100644
index 0000000..87adf92
--- /dev/null
+++ b/tests/proj3/tests/f64_key1_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_key2_d.runs b/tests/proj3/tests/f64_key2_d.runs
new file mode 100644
index 0000000..c5d28c1
--- /dev/null
+++ b/tests/proj3/tests/f64_key2_d.runs
@@ -0,0 +1,3 @@
+0d = !trap
+1.25d = !trap
+-99d = !trap
diff --git a/tests/proj3/tests/f64_key2_d.wasm b/tests/proj3/tests/f64_key2_d.wasm
new file mode 100644
index 0000000..037e14f
--- /dev/null
+++ b/tests/proj3/tests/f64_key2_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/f64_key2_d.wat b/tests/proj3/tests/f64_key2_d.wat
new file mode 100644
index 0000000..106c2fb
--- /dev/null
+++ b/tests/proj3/tests/f64_key2_d.wat
@@ -0,0 +1,15 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+
+ (func (export "main") (param f64) (result f64)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100))))
+ (call $u (call $g (local.get $obj) (call $bi (i32.trunc_f64_s (local.get 0)))))
+ )
+)
diff --git a/tests/proj3/tests/f64_key2_d.wee.wasm b/tests/proj3/tests/f64_key2_d.wee.wasm
new file mode 100644
index 0000000..0abd217
--- /dev/null
+++ b/tests/proj3/tests/f64_key2_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/fib.runs b/tests/proj3/tests/fib.runs
new file mode 100644
index 0000000..fba1687
--- /dev/null
+++ b/tests/proj3/tests/fib.runs
@@ -0,0 +1,9 @@
+0 = 1
+1 = 1
+2 = 2
+3 = 3
+4 = 5
+5 = 8
+6 = 13
+7 = 21
+8 = 34
diff --git a/tests/proj3/tests/fib.wasm b/tests/proj3/tests/fib.wasm
new file mode 100644
index 0000000..e329719
--- /dev/null
+++ b/tests/proj3/tests/fib.wasm
Binary files differ
diff --git a/tests/proj3/tests/fib.wat b/tests/proj3/tests/fib.wat
new file mode 100644
index 0000000..920f2e5
--- /dev/null
+++ b/tests/proj3/tests/fib.wat
@@ -0,0 +1,29 @@
+(module
+ (export "main" (func $fib))
+ (func $fib (param $n i32) (result i32)
+ (block
+ (br_if 0 (i32.ge_s
+ (local.get $n)
+ (i32.const 2)
+ ))
+ (return
+ (i32.const 1)
+ ))
+ (return
+ (i32.add
+ (call $fib
+ (i32.sub
+ (local.get $n)
+ (i32.const 2)
+ )
+ )
+ (call $fib
+ (i32.sub
+ (local.get $n)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+) \ No newline at end of file
diff --git a/tests/proj3/tests/fib.wee.wasm b/tests/proj3/tests/fib.wee.wasm
new file mode 100644
index 0000000..23afd9e
--- /dev/null
+++ b/tests/proj3/tests/fib.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/i32_box_unbox0.runs b/tests/proj3/tests/i32_box_unbox0.runs
new file mode 100644
index 0000000..cff4f69
--- /dev/null
+++ b/tests/proj3/tests/i32_box_unbox0.runs
@@ -0,0 +1,2 @@
+0 = 0
+457 = 457
diff --git a/tests/proj3/tests/i32_box_unbox0.wasm b/tests/proj3/tests/i32_box_unbox0.wasm
new file mode 100644
index 0000000..50bbb27
--- /dev/null
+++ b/tests/proj3/tests/i32_box_unbox0.wasm
Binary files differ
diff --git a/tests/proj3/tests/i32_box_unbox0.wat b/tests/proj3/tests/i32_box_unbox0.wat
new file mode 100644
index 0000000..04ac19f
--- /dev/null
+++ b/tests/proj3/tests/i32_box_unbox0.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (func (export "main") (param i32) (result i32)
+ (call $u (call $b (local.get 0)))
+ )
+)
diff --git a/tests/proj3/tests/i32_box_unbox0.wee.wasm b/tests/proj3/tests/i32_box_unbox0.wee.wasm
new file mode 100644
index 0000000..0c92d6e
--- /dev/null
+++ b/tests/proj3/tests/i32_box_unbox0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/junk0_d.runs b/tests/proj3/tests/junk0_d.runs
new file mode 100644
index 0000000..cc8adb6
--- /dev/null
+++ b/tests/proj3/tests/junk0_d.runs
@@ -0,0 +1,3 @@
+0 = !trap
+0.5d = 100.500000
+125.5d = 100.500000
diff --git a/tests/proj3/tests/junk0_d.wasm b/tests/proj3/tests/junk0_d.wasm
new file mode 100644
index 0000000..45b5831
--- /dev/null
+++ b/tests/proj3/tests/junk0_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/junk0_d.wat b/tests/proj3/tests/junk0_d.wat
new file mode 100644
index 0000000..fe0e25a
--- /dev/null
+++ b/tests/proj3/tests/junk0_d.wat
@@ -0,0 +1,19 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+
+ (func (export "main") (param f64) (result f64)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (loop $l
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100))))
+ (local.set 0 (f64.sub (local.get 0) (f64.const 1.25)))
+ (br_if $l (f64.ge (local.get 0) (f64.const 0)))
+ )
+ (call $u (call $g (local.get $obj) (call $b (f64.const 0.5))))
+ )
+)
diff --git a/tests/proj3/tests/junk0_d.wee.wasm b/tests/proj3/tests/junk0_d.wee.wasm
new file mode 100644
index 0000000..f8bea66
--- /dev/null
+++ b/tests/proj3/tests/junk0_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/junk1_d.runs b/tests/proj3/tests/junk1_d.runs
new file mode 100644
index 0000000..cc8adb6
--- /dev/null
+++ b/tests/proj3/tests/junk1_d.runs
@@ -0,0 +1,3 @@
+0 = !trap
+0.5d = 100.500000
+125.5d = 100.500000
diff --git a/tests/proj3/tests/junk1_d.wasm b/tests/proj3/tests/junk1_d.wasm
new file mode 100644
index 0000000..27dfe06
--- /dev/null
+++ b/tests/proj3/tests/junk1_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/junk1_d.wat b/tests/proj3/tests/junk1_d.wat
new file mode 100644
index 0000000..5ece7b6
--- /dev/null
+++ b/tests/proj3/tests/junk1_d.wat
@@ -0,0 +1,20 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+
+ (func (export "main") (param f64) (result f64)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (loop $l
+ (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100))))
+ (call $s (local.get $obj) (call $bi (i32.trunc_f64_s (local.get 0))) (call $b (local.get 0)))
+ (local.set 0 (f64.sub (local.get 0) (f64.const 1.25)))
+ (br_if $l (f64.ge (local.get 0) (f64.const 0)))
+ )
+ (call $u (call $g (local.get $obj) (call $b (f64.const 0.5))))
+ )
+)
diff --git a/tests/proj3/tests/junk1_d.wee.wasm b/tests/proj3/tests/junk1_d.wee.wasm
new file mode 100644
index 0000000..9f85f5a
--- /dev/null
+++ b/tests/proj3/tests/junk1_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/list0.runs b/tests/proj3/tests/list0.runs
new file mode 100644
index 0000000..eab8be5
--- /dev/null
+++ b/tests/proj3/tests/list0.runs
@@ -0,0 +1,4 @@
+0 = 44
+1 = 55
+2 = -77
+3 = !trap
diff --git a/tests/proj3/tests/list0.wasm b/tests/proj3/tests/list0.wasm
new file mode 100644
index 0000000..4818b49
--- /dev/null
+++ b/tests/proj3/tests/list0.wasm
Binary files differ
diff --git a/tests/proj3/tests/list0.wat b/tests/proj3/tests/list0.wat
new file mode 100644
index 0000000..be2af6c
--- /dev/null
+++ b/tests/proj3/tests/list0.wat
@@ -0,0 +1,44 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func $cons (param i32 externref) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (call $s (local.get $obj) (call $b (i32.const 0)) (call $b (local.get 0)))
+ (call $s (local.get $obj) (call $b (i32.const 1)) (local.get 1))
+ (local.get $obj)
+ )
+
+ (func $cdr (param externref) (result i32)
+ (call $u (call $g (local.get 0) (call $b (i32.const 0))))
+ )
+
+ (func $car (param externref) (result externref)
+ (call $g (local.get 0) (call $b (i32.const 1)))
+ )
+
+ (func $get (param externref i32) (result i32)
+ (block $b
+ (loop $l
+ (br_if $b (i32.eqz (local.get 1)))
+ (local.set 0 (call $car (local.get 0)))
+ (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
+ (br $l)
+ )
+ )
+ (call $cdr (local.get 0))
+ )
+
+
+ (func (export "main") (param i32) (result i32)
+ (local $null externref)
+ (call $get (call $cons (i32.const 44)
+ (call $cons (i32.const 55)
+ (call $cons (i32.const -77) (local.get $null))))
+ (local.get 0))
+ )
+)
diff --git a/tests/proj3/tests/list0.wee.wasm b/tests/proj3/tests/list0.wee.wasm
new file mode 100644
index 0000000..357a1e0
--- /dev/null
+++ b/tests/proj3/tests/list0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/list1.runs b/tests/proj3/tests/list1.runs
new file mode 100644
index 0000000..cf1cbb0
--- /dev/null
+++ b/tests/proj3/tests/list1.runs
@@ -0,0 +1,7 @@
+1 0 = 33
+1 1 = !trap
+5 4 = 165
+5 5 = !trap
+199 165 = 5478
+245 165 = 5478
+9999 10000 = !trap
diff --git a/tests/proj3/tests/list1.wasm b/tests/proj3/tests/list1.wasm
new file mode 100644
index 0000000..17c7b2d
--- /dev/null
+++ b/tests/proj3/tests/list1.wasm
Binary files differ
diff --git a/tests/proj3/tests/list1.wat b/tests/proj3/tests/list1.wat
new file mode 100644
index 0000000..476d712
--- /dev/null
+++ b/tests/proj3/tests/list1.wat
@@ -0,0 +1,55 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func $cons (param i32 externref) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (call $s (local.get $obj) (call $b (i32.const 0)) (call $b (local.get 0)))
+ (call $s (local.get $obj) (call $b (i32.const 1)) (local.get 1))
+ (local.get $obj)
+ )
+
+ (func $cdr (param externref) (result i32)
+ (call $u (call $g (local.get 0) (call $b (i32.const 0))))
+ )
+
+ (func $car (param externref) (result externref)
+ (call $g (local.get 0) (call $b (i32.const 1)))
+ )
+
+ (func $get (param externref i32) (result i32)
+ (block $b
+ (loop $l
+ (br_if $b (i32.eqz (local.get 1)))
+ (local.set 0 (call $car (local.get 0)))
+ (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
+ (br $l)
+ )
+ )
+ (call $cdr (local.get 0))
+ )
+
+ (func $alloc (param i32) (result externref)
+ (local $r externref)
+ (block $b
+ (loop $l
+ (br_if $b (i32.eqz (local.get 0)))
+ (local.set $r (call $cons (i32.mul (local.get 0) (i32.const 33)) (local.get $r)))
+ (local.set 0 (i32.sub (local.get 0) (i32.const 1)))
+ (br $l)
+ )
+ )
+ (local.get $r)
+ )
+
+ (func (export "main") (param i32 i32) (result i32)
+ (local $null externref)
+ (local $r externref)
+ (local.set $r (call $alloc (local.get 0)))
+ (call $get (local.get $r) (local.get 1))
+ )
+)
diff --git a/tests/proj3/tests/list1.wee.wasm b/tests/proj3/tests/list1.wee.wasm
new file mode 100644
index 0000000..a1d1c38
--- /dev/null
+++ b/tests/proj3/tests/list1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.eq0.expect b/tests/proj3/tests/obj.eq0.expect
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/proj3/tests/obj.eq0.expect
@@ -0,0 +1 @@
+1
diff --git a/tests/proj3/tests/obj.eq0.wasm b/tests/proj3/tests/obj.eq0.wasm
new file mode 100644
index 0000000..bdf1b40
--- /dev/null
+++ b/tests/proj3/tests/obj.eq0.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.eq0.wat b/tests/proj3/tests/obj.eq0.wat
new file mode 100644
index 0000000..e5c5a61
--- /dev/null
+++ b/tests/proj3/tests/obj.eq0.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "obj.eq" (func $f (param externref externref) (result i32)))
+ (func (export "main") (result i32)
+ (local $f externref)
+ (call $f (local.get $f) (local.get $f))
+ )
+)
diff --git a/tests/proj3/tests/obj.eq0.wee.wasm b/tests/proj3/tests/obj.eq0.wee.wasm
new file mode 100644
index 0000000..a70df87
--- /dev/null
+++ b/tests/proj3/tests/obj.eq0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.eq1.runs b/tests/proj3/tests/obj.eq1.runs
new file mode 100644
index 0000000..e8c6945
--- /dev/null
+++ b/tests/proj3/tests/obj.eq1.runs
@@ -0,0 +1,2 @@
+0 = 0
+-44 = 1
diff --git a/tests/proj3/tests/obj.eq1.wasm b/tests/proj3/tests/obj.eq1.wasm
new file mode 100644
index 0000000..bb7e4ce
--- /dev/null
+++ b/tests/proj3/tests/obj.eq1.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.eq1.wat b/tests/proj3/tests/obj.eq1.wat
new file mode 100644
index 0000000..d364007
--- /dev/null
+++ b/tests/proj3/tests/obj.eq1.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "obj.eq" (func $f (param externref externref) (result i32)))
+ (func (export "main") (param i32) (result i32)
+ (call $f (call $b (i32.const -44)) (call $b (local.get 0)))
+ )
+)
diff --git a/tests/proj3/tests/obj.eq1.wee.wasm b/tests/proj3/tests/obj.eq1.wee.wasm
new file mode 100644
index 0000000..6d43e9e
--- /dev/null
+++ b/tests/proj3/tests/obj.eq1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.eq2.runs b/tests/proj3/tests/obj.eq2.runs
new file mode 100644
index 0000000..218d9ac
--- /dev/null
+++ b/tests/proj3/tests/obj.eq2.runs
@@ -0,0 +1,3 @@
+0d = 0
+-44d = 0
+-49.25d = 1
diff --git a/tests/proj3/tests/obj.eq2.wasm b/tests/proj3/tests/obj.eq2.wasm
new file mode 100644
index 0000000..cc6511d
--- /dev/null
+++ b/tests/proj3/tests/obj.eq2.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.eq2.wat b/tests/proj3/tests/obj.eq2.wat
new file mode 100644
index 0000000..c0a931d
--- /dev/null
+++ b/tests/proj3/tests/obj.eq2.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "obj.eq" (func $f (param externref externref) (result i32)))
+ (func (export "main") (param f64) (result i32)
+ (call $f (call $b (f64.const -49.25)) (call $b (local.get 0)))
+ )
+)
diff --git a/tests/proj3/tests/obj.eq2.wee.wasm b/tests/proj3/tests/obj.eq2.wee.wasm
new file mode 100644
index 0000000..9f964dc
--- /dev/null
+++ b/tests/proj3/tests/obj.eq2.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.get0.expect b/tests/proj3/tests/obj.get0.expect
new file mode 100644
index 0000000..1189174
--- /dev/null
+++ b/tests/proj3/tests/obj.get0.expect
@@ -0,0 +1 @@
+!trap
diff --git a/tests/proj3/tests/obj.get0.wasm b/tests/proj3/tests/obj.get0.wasm
new file mode 100644
index 0000000..5398ef9
--- /dev/null
+++ b/tests/proj3/tests/obj.get0.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.get0.wat b/tests/proj3/tests/obj.get0.wat
new file mode 100644
index 0000000..5ce1ec8
--- /dev/null
+++ b/tests/proj3/tests/obj.get0.wat
@@ -0,0 +1,8 @@
+(module
+ (import "weewasm" "obj.get" (func $f (param externref externref) (result externref)))
+ (func (export "main") (result i32)
+ (local $f externref)
+ (drop (call $f (local.get $f) (local.get $f)))
+ (i32.const 47)
+ )
+)
diff --git a/tests/proj3/tests/obj.get0.wee.wasm b/tests/proj3/tests/obj.get0.wee.wasm
new file mode 100644
index 0000000..3c07f8c
--- /dev/null
+++ b/tests/proj3/tests/obj.get0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.get1.expect b/tests/proj3/tests/obj.get1.expect
new file mode 100644
index 0000000..1189174
--- /dev/null
+++ b/tests/proj3/tests/obj.get1.expect
@@ -0,0 +1 @@
+!trap
diff --git a/tests/proj3/tests/obj.get1.wasm b/tests/proj3/tests/obj.get1.wasm
new file mode 100644
index 0000000..a172efc
--- /dev/null
+++ b/tests/proj3/tests/obj.get1.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.get1.wat b/tests/proj3/tests/obj.get1.wat
new file mode 100644
index 0000000..85e9278
--- /dev/null
+++ b/tests/proj3/tests/obj.get1.wat
@@ -0,0 +1,8 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (func (export "main") (result externref)
+ (local $f externref)
+ (call $g (call $n) (local.get $f))
+ )
+)
diff --git a/tests/proj3/tests/obj.get1.wee.wasm b/tests/proj3/tests/obj.get1.wee.wasm
new file mode 100644
index 0000000..beb29be
--- /dev/null
+++ b/tests/proj3/tests/obj.get1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset0.runs b/tests/proj3/tests/obj.getset0.runs
new file mode 100644
index 0000000..05f1f37
--- /dev/null
+++ b/tests/proj3/tests/obj.getset0.runs
@@ -0,0 +1,2 @@
+33 = 33
+-98234 = -98234
diff --git a/tests/proj3/tests/obj.getset0.wasm b/tests/proj3/tests/obj.getset0.wasm
new file mode 100644
index 0000000..2d1b3ae
--- /dev/null
+++ b/tests/proj3/tests/obj.getset0.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset0.wat b/tests/proj3/tests/obj.getset0.wat
new file mode 100644
index 0000000..caf8ba2
--- /dev/null
+++ b/tests/proj3/tests/obj.getset0.wat
@@ -0,0 +1,15 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (func (export "main") (param i32) (result i32)
+ (local $f externref)
+ (local $g externref)
+ (local.set $f (call $n))
+ (local.set $g (call $n))
+ (call $s (local.get $f) (local.get $g) (call $b (local.get 0)))
+ (call $u (call $g (local.get $f) (local.get $g)))
+ )
+)
diff --git a/tests/proj3/tests/obj.getset0.wee.wasm b/tests/proj3/tests/obj.getset0.wee.wasm
new file mode 100644
index 0000000..82397da
--- /dev/null
+++ b/tests/proj3/tests/obj.getset0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset1.runs b/tests/proj3/tests/obj.getset1.runs
new file mode 100644
index 0000000..8ecf4b6
--- /dev/null
+++ b/tests/proj3/tests/obj.getset1.runs
@@ -0,0 +1,2 @@
+3344 = 3344
+-9823477 = -9823477
diff --git a/tests/proj3/tests/obj.getset1.wasm b/tests/proj3/tests/obj.getset1.wasm
new file mode 100644
index 0000000..cf9756d
--- /dev/null
+++ b/tests/proj3/tests/obj.getset1.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset1.wat b/tests/proj3/tests/obj.getset1.wat
new file mode 100644
index 0000000..1fa9a7f
--- /dev/null
+++ b/tests/proj3/tests/obj.getset1.wat
@@ -0,0 +1,13 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (func (export "main") (param i32) (result i32)
+ (local $f externref)
+ (local.set $f (call $n))
+ (call $s (local.get $f) (call $b (i32.const 9999)) (call $b (local.get 0)))
+ (call $u (call $g (local.get $f) (call $b (i32.const 9999))))
+ )
+)
diff --git a/tests/proj3/tests/obj.getset1.wee.wasm b/tests/proj3/tests/obj.getset1.wee.wasm
new file mode 100644
index 0000000..a05b7c9
--- /dev/null
+++ b/tests/proj3/tests/obj.getset1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset2.expect b/tests/proj3/tests/obj.getset2.expect
new file mode 100644
index 0000000..1189174
--- /dev/null
+++ b/tests/proj3/tests/obj.getset2.expect
@@ -0,0 +1 @@
+!trap
diff --git a/tests/proj3/tests/obj.getset2.wasm b/tests/proj3/tests/obj.getset2.wasm
new file mode 100644
index 0000000..b02155e
--- /dev/null
+++ b/tests/proj3/tests/obj.getset2.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset2.wat b/tests/proj3/tests/obj.getset2.wat
new file mode 100644
index 0000000..b588472
--- /dev/null
+++ b/tests/proj3/tests/obj.getset2.wat
@@ -0,0 +1,16 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (func (export "main") (result i32)
+ (local $f externref)
+ (local $g externref)
+ (local.set $f (call $n))
+ (local.set $g (call $n))
+ (call $s (local.get $g) (call $b (i32.const 222)) (call $b (i32.const 111)))
+ (call $s (local.get $f) (local.get $g) (call $b (i32.const 1234)))
+ (call $u (call $g (local.get $f) (call $n)))
+ )
+)
diff --git a/tests/proj3/tests/obj.getset2.wee.wasm b/tests/proj3/tests/obj.getset2.wee.wasm
new file mode 100644
index 0000000..5676f41
--- /dev/null
+++ b/tests/proj3/tests/obj.getset2.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset3_d.runs b/tests/proj3/tests/obj.getset3_d.runs
new file mode 100644
index 0000000..9ed9cb5
--- /dev/null
+++ b/tests/proj3/tests/obj.getset3_d.runs
@@ -0,0 +1,2 @@
+0d = 0.000000
+-99.25d = -99.250000
diff --git a/tests/proj3/tests/obj.getset3_d.wasm b/tests/proj3/tests/obj.getset3_d.wasm
new file mode 100644
index 0000000..bd3b0e7
--- /dev/null
+++ b/tests/proj3/tests/obj.getset3_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset3_d.wat b/tests/proj3/tests/obj.getset3_d.wat
new file mode 100644
index 0000000..29cdfec
--- /dev/null
+++ b/tests/proj3/tests/obj.getset3_d.wat
@@ -0,0 +1,15 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (func (export "main") (param f64) (result f64)
+ (local $f externref)
+ (local $g externref)
+ (local.set $f (call $n))
+ (local.set $g (call $n))
+ (call $s (local.get $f) (local.get $g) (call $b (local.get 0)))
+ (call $u (call $g (local.get $f) (local.get $g)))
+ )
+)
diff --git a/tests/proj3/tests/obj.getset3_d.wee.wasm b/tests/proj3/tests/obj.getset3_d.wee.wasm
new file mode 100644
index 0000000..eaa960e
--- /dev/null
+++ b/tests/proj3/tests/obj.getset3_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset4_d.runs b/tests/proj3/tests/obj.getset4_d.runs
new file mode 100644
index 0000000..29cbb58
--- /dev/null
+++ b/tests/proj3/tests/obj.getset4_d.runs
@@ -0,0 +1,3 @@
+0d = 0.000000
+-9.25d = -9.250000
+33.999d = 33.999000
diff --git a/tests/proj3/tests/obj.getset4_d.wasm b/tests/proj3/tests/obj.getset4_d.wasm
new file mode 100644
index 0000000..0fbd798
--- /dev/null
+++ b/tests/proj3/tests/obj.getset4_d.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset4_d.wat b/tests/proj3/tests/obj.getset4_d.wat
new file mode 100644
index 0000000..42d3cd5
--- /dev/null
+++ b/tests/proj3/tests/obj.getset4_d.wat
@@ -0,0 +1,15 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "f64.unbox" (func $u (param externref) (result f64)))
+ (func (export "main") (param f64) (result f64)
+ (local $f externref)
+ (local $g externref)
+ (local.set $f (call $n))
+ (local.set $g (call $b (f64.add (local.get 0) (f64.const 3.44))))
+ (call $s (local.get $f) (local.get $g) (call $b (local.get 0)))
+ (call $u (call $g (local.get $f) (local.get $g)))
+ )
+)
diff --git a/tests/proj3/tests/obj.getset4_d.wee.wasm b/tests/proj3/tests/obj.getset4_d.wee.wasm
new file mode 100644
index 0000000..4ad85c8
--- /dev/null
+++ b/tests/proj3/tests/obj.getset4_d.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset5.runs b/tests/proj3/tests/obj.getset5.runs
new file mode 100644
index 0000000..0a09d96
--- /dev/null
+++ b/tests/proj3/tests/obj.getset5.runs
@@ -0,0 +1,3 @@
+0d 0 = !trap
+33d 33 = !trap
+-77.77d 66 = !trap
diff --git a/tests/proj3/tests/obj.getset5.wasm b/tests/proj3/tests/obj.getset5.wasm
new file mode 100644
index 0000000..de45410
--- /dev/null
+++ b/tests/proj3/tests/obj.getset5.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset5.wat b/tests/proj3/tests/obj.getset5.wat
new file mode 100644
index 0000000..2c53307
--- /dev/null
+++ b/tests/proj3/tests/obj.getset5.wat
@@ -0,0 +1,14 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (func (export "main") (param f64 i32) (result i32)
+ (local $f externref)
+ (local.set $f (call $n))
+ (call $s (local.get $f) (call $b (local.get 0)) (call $bi (local.get 1)))
+ (call $u (call $g (local.get $f) (call $bi (local.get 1))))
+ )
+)
diff --git a/tests/proj3/tests/obj.getset5.wee.wasm b/tests/proj3/tests/obj.getset5.wee.wasm
new file mode 100644
index 0000000..cf8c336
--- /dev/null
+++ b/tests/proj3/tests/obj.getset5.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset6.runs b/tests/proj3/tests/obj.getset6.runs
new file mode 100644
index 0000000..1fc3983
--- /dev/null
+++ b/tests/proj3/tests/obj.getset6.runs
@@ -0,0 +1,4 @@
+0d 0 = 0
+33d 33 = 33
+-44667788d -44667788 = -44667788
+-77.77d 66 = !trap
diff --git a/tests/proj3/tests/obj.getset6.wasm b/tests/proj3/tests/obj.getset6.wasm
new file mode 100644
index 0000000..052675c
--- /dev/null
+++ b/tests/proj3/tests/obj.getset6.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.getset6.wat b/tests/proj3/tests/obj.getset6.wat
new file mode 100644
index 0000000..9519cae
--- /dev/null
+++ b/tests/proj3/tests/obj.getset6.wat
@@ -0,0 +1,14 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (func (export "main") (param f64 i32) (result i32)
+ (local $f externref)
+ (local.set $f (call $n))
+ (call $s (local.get $f) (call $b (local.get 0)) (call $bi (local.get 1)))
+ (call $u (call $g (local.get $f) (call $b (f64.convert_i32_s (local.get 1)))))
+ )
+)
diff --git a/tests/proj3/tests/obj.getset6.wee.wasm b/tests/proj3/tests/obj.getset6.wee.wasm
new file mode 100644
index 0000000..a01127b
--- /dev/null
+++ b/tests/proj3/tests/obj.getset6.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.inflate0.expect b/tests/proj3/tests/obj.inflate0.expect
new file mode 100644
index 0000000..bb95160
--- /dev/null
+++ b/tests/proj3/tests/obj.inflate0.expect
@@ -0,0 +1 @@
+33
diff --git a/tests/proj3/tests/obj.inflate0.wasm b/tests/proj3/tests/obj.inflate0.wasm
new file mode 100644
index 0000000..bd1a300
--- /dev/null
+++ b/tests/proj3/tests/obj.inflate0.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.inflate0.wat b/tests/proj3/tests/obj.inflate0.wat
new file mode 100644
index 0000000..fa354ef
--- /dev/null
+++ b/tests/proj3/tests/obj.inflate0.wat
@@ -0,0 +1,18 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+
+ (func (export "main") (result i32)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (call $s (local.get $obj) (call $b (i32.const 0)) (local.get $obj))
+ (call $s (local.get $obj) (call $b (i32.const 1)) (local.get $obj))
+ (call $s (local.get $obj) (call $b (i32.const 2)) (local.get $obj))
+ (call $s (local.get $obj) (call $b (i32.const 3)) (local.get $obj))
+ (call $s (local.get $obj) (call $b (i32.const 4)) (local.get $obj))
+ (call $s (local.get $obj) (call $b (i32.const 5)) (local.get $obj))
+ (i32.const 33)
+ )
+)
diff --git a/tests/proj3/tests/obj.inflate0.wee.wasm b/tests/proj3/tests/obj.inflate0.wee.wasm
new file mode 100644
index 0000000..9c1ed47
--- /dev/null
+++ b/tests/proj3/tests/obj.inflate0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.new0.expect b/tests/proj3/tests/obj.new0.expect
new file mode 100644
index 0000000..c739b42
--- /dev/null
+++ b/tests/proj3/tests/obj.new0.expect
@@ -0,0 +1 @@
+44
diff --git a/tests/proj3/tests/obj.new0.wasm b/tests/proj3/tests/obj.new0.wasm
new file mode 100644
index 0000000..0daa52a
--- /dev/null
+++ b/tests/proj3/tests/obj.new0.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.new0.wat b/tests/proj3/tests/obj.new0.wat
new file mode 100644
index 0000000..10f05d7
--- /dev/null
+++ b/tests/proj3/tests/obj.new0.wat
@@ -0,0 +1,7 @@
+(module
+ (import "weewasm" "obj.new" (func $f (result externref)))
+ (func (export "main") (result i32)
+ (drop (call $f))
+ (i32.const 44)
+ )
+)
diff --git a/tests/proj3/tests/obj.new0.wee.wasm b/tests/proj3/tests/obj.new0.wee.wasm
new file mode 100644
index 0000000..9dbdfd1
--- /dev/null
+++ b/tests/proj3/tests/obj.new0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.set1.expect b/tests/proj3/tests/obj.set1.expect
new file mode 100644
index 0000000..1189174
--- /dev/null
+++ b/tests/proj3/tests/obj.set1.expect
@@ -0,0 +1 @@
+!trap
diff --git a/tests/proj3/tests/obj.set1.wasm b/tests/proj3/tests/obj.set1.wasm
new file mode 100644
index 0000000..93a2e46
--- /dev/null
+++ b/tests/proj3/tests/obj.set1.wasm
Binary files differ
diff --git a/tests/proj3/tests/obj.set1.wat b/tests/proj3/tests/obj.set1.wat
new file mode 100644
index 0000000..7fd1cee
--- /dev/null
+++ b/tests/proj3/tests/obj.set1.wat
@@ -0,0 +1,9 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (func (export "main") (result i32)
+ (local $f externref)
+ (call $s (call $n) (local.get $f) (local.get $f))
+ (i32.const 55)
+ )
+)
diff --git a/tests/proj3/tests/obj.set1.wee.wasm b/tests/proj3/tests/obj.set1.wee.wasm
new file mode 100644
index 0000000..e492417
--- /dev/null
+++ b/tests/proj3/tests/obj.set1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/pick0.runs b/tests/proj3/tests/pick0.runs
new file mode 100644
index 0000000..e9dc6ab
--- /dev/null
+++ b/tests/proj3/tests/pick0.runs
@@ -0,0 +1,4 @@
+0 = 1
+1 = 0
+2 = 0
+3 = 0
diff --git a/tests/proj3/tests/pick0.wasm b/tests/proj3/tests/pick0.wasm
new file mode 100644
index 0000000..496ea33
--- /dev/null
+++ b/tests/proj3/tests/pick0.wasm
Binary files differ
diff --git a/tests/proj3/tests/pick0.wat b/tests/proj3/tests/pick0.wat
new file mode 100644
index 0000000..2415f0d
--- /dev/null
+++ b/tests/proj3/tests/pick0.wat
@@ -0,0 +1,27 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func $get (param externref externref externref i32) (result externref)
+ (local.get 0)
+ (br_if 0 (i32.eq (local.get 3) (i32.const 0)))
+ (drop)
+
+ (local.get 1)
+ (br_if 0 (i32.eq (local.get 3) (i32.const 1)))
+ (drop)
+
+ (local.get 2)
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (local $a externref)
+ (local $b externref)
+ (local $c externref)
+ (local.set $a (call $n))
+ (local.set $b (call $n))
+ (local.set $c (call $n))
+
+ (call $eq (call $get (local.get $a) (local.get $b) (local.get $c) (local.get 0)) (local.get $a))
+ )
+) \ No newline at end of file
diff --git a/tests/proj3/tests/pick0.wee.wasm b/tests/proj3/tests/pick0.wee.wasm
new file mode 100644
index 0000000..61453b9
--- /dev/null
+++ b/tests/proj3/tests/pick0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/rec.runs b/tests/proj3/tests/rec.runs
new file mode 100644
index 0000000..e4b0cf4
--- /dev/null
+++ b/tests/proj3/tests/rec.runs
@@ -0,0 +1 @@
+0 = 20
diff --git a/tests/proj3/tests/rec.wasm b/tests/proj3/tests/rec.wasm
new file mode 100644
index 0000000..961f36a
--- /dev/null
+++ b/tests/proj3/tests/rec.wasm
Binary files differ
diff --git a/tests/proj3/tests/rec.wat b/tests/proj3/tests/rec.wat
new file mode 100644
index 0000000..b6c0abe
--- /dev/null
+++ b/tests/proj3/tests/rec.wat
@@ -0,0 +1,11 @@
+(module
+ (global $g (mut i32) (i32.const 20))
+ (func $ref (export "main") (param i32) (result i32)
+ (global.get $g)
+ (br_if 0 (i32.le_s (local.get 0) (i32.const 0)))
+ (i32.const 1)
+ (i32.add)
+ (global.set $g)
+ (call $ref (i32.sub (local.get 0) (i32.const 1)))
+ )
+)
diff --git a/tests/proj3/tests/rec.wee.wasm b/tests/proj3/tests/rec.wee.wasm
new file mode 100644
index 0000000..116a9f9
--- /dev/null
+++ b/tests/proj3/tests/rec.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/swap0.expect b/tests/proj3/tests/swap0.expect
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/proj3/tests/swap0.expect
@@ -0,0 +1 @@
+1
diff --git a/tests/proj3/tests/swap0.wasm b/tests/proj3/tests/swap0.wasm
new file mode 100644
index 0000000..a3bd7e6
--- /dev/null
+++ b/tests/proj3/tests/swap0.wasm
Binary files differ
diff --git a/tests/proj3/tests/swap0.wat b/tests/proj3/tests/swap0.wat
new file mode 100644
index 0000000..0886f2f
--- /dev/null
+++ b/tests/proj3/tests/swap0.wat
@@ -0,0 +1,17 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func $swap (param externref externref) (result externref)
+ (local.get 1)
+ )
+
+ (func (export "main") (result i32)
+ (local $a externref)
+ (local $b externref)
+ (local.set $a (call $n))
+ (local.set $b (call $n))
+
+ (call $eq (call $swap (local.get $a) (local.get $b)) (local.get $b))
+ )
+) \ No newline at end of file
diff --git a/tests/proj3/tests/swap0.wee.wasm b/tests/proj3/tests/swap0.wee.wasm
new file mode 100644
index 0000000..ef8ee8d
--- /dev/null
+++ b/tests/proj3/tests/swap0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/swap1.expect b/tests/proj3/tests/swap1.expect
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/proj3/tests/swap1.expect
@@ -0,0 +1 @@
+0
diff --git a/tests/proj3/tests/swap1.wasm b/tests/proj3/tests/swap1.wasm
new file mode 100644
index 0000000..a2bd1cc
--- /dev/null
+++ b/tests/proj3/tests/swap1.wasm
Binary files differ
diff --git a/tests/proj3/tests/swap1.wat b/tests/proj3/tests/swap1.wat
new file mode 100644
index 0000000..dd6aabc
--- /dev/null
+++ b/tests/proj3/tests/swap1.wat
@@ -0,0 +1,17 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func $swap (param externref externref) (result externref)
+ (local.get 1)
+ )
+
+ (func (export "main") (result i32)
+ (local $a externref)
+ (local $b externref)
+ (local.set $a (call $n))
+ (local.set $b (call $n))
+
+ (call $eq (call $swap (local.get $b) (local.get $a)) (local.get $b))
+ )
+) \ No newline at end of file
diff --git a/tests/proj3/tests/swap1.wee.wasm b/tests/proj3/tests/swap1.wee.wasm
new file mode 100644
index 0000000..eb34a08
--- /dev/null
+++ b/tests/proj3/tests/swap1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/tree0.runs b/tests/proj3/tests/tree0.runs
new file mode 100644
index 0000000..e6d97be
--- /dev/null
+++ b/tests/proj3/tests/tree0.runs
@@ -0,0 +1,6 @@
+0 = 1
+1 = 1
+2 = 2
+5 = 5
+10 = 10
+15 = 15
diff --git a/tests/proj3/tests/tree0.wasm b/tests/proj3/tests/tree0.wasm
new file mode 100644
index 0000000..cbd9421
--- /dev/null
+++ b/tests/proj3/tests/tree0.wasm
Binary files differ
diff --git a/tests/proj3/tests/tree0.wat b/tests/proj3/tests/tree0.wat
new file mode 100644
index 0000000..d57f3e9
--- /dev/null
+++ b/tests/proj3/tests/tree0.wat
@@ -0,0 +1,67 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "i32.unbox" (func $u (param externref) (result i32)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func $array_get (param externref i32) (result externref)
+ (call $g (local.get 0) (call $b (local.get 1)))
+ )
+
+ (func $array_set (param externref i32 externref)
+ (call $s (local.get 0) (call $b (local.get 1)) (local.get 2))
+ )
+
+ (func $left_key (param externref) (result externref)
+ (call $array_get (local.get 0) (i32.const 11)))
+
+ (func $right_key (param externref) (result externref)
+ (call $array_get (local.get 0) (i32.const 22)))
+
+ (func $keys (result externref)
+ (local $r externref)
+ (local.set $r (call $n))
+ (call $array_set (local.get $r) (i32.const 11) (call $n))
+ (call $array_set (local.get $r) (i32.const 22) (call $n))
+ (local.get $r)
+ )
+
+ (func $isnull (param externref) (result i32)
+ (local $n externref)
+ (call $eq (local.get $n) (local.get 0)))
+
+ (func $alloc (param externref i32) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (block $l
+ (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
+ (br_if $l (i32.le_s (local.get 1) (i32.const 0)))
+ (call $s (local.get $obj) (call $left_key (local.get 0)) (call $alloc (local.get 0) (local.get 1)))
+ (call $s (local.get $obj) (call $right_key (local.get 0)) (call $alloc (local.get 0) (local.get 1)))
+ )
+ (local.get $obj)
+ )
+
+ (func $height (param externref externref) (result i32)
+ (local $h i32)
+ (block $b
+ (loop $l
+ (br_if $b (call $isnull (local.get 1)))
+ (local.set $h (i32.add (local.get $h) (i32.const 1)))
+ (local.set 1 (call $g (local.get 1) (call $left_key (local.get 0))))
+ (br 0)
+ )
+ )
+ (local.get $h)
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (local $k externref)
+ (local $t externref)
+ (local.set $k (call $keys))
+ (local.set $t (call $alloc (local.get $k) (local.get 0)))
+ (call $height (local.get $k) (local.get $t))
+ )
+)
diff --git a/tests/proj3/tests/tree0.wee.wasm b/tests/proj3/tests/tree0.wee.wasm
new file mode 100644
index 0000000..88cb0c2
--- /dev/null
+++ b/tests/proj3/tests/tree0.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/tree1.runs b/tests/proj3/tests/tree1.runs
new file mode 100644
index 0000000..e6d97be
--- /dev/null
+++ b/tests/proj3/tests/tree1.runs
@@ -0,0 +1,6 @@
+0 = 1
+1 = 1
+2 = 2
+5 = 5
+10 = 10
+15 = 15
diff --git a/tests/proj3/tests/tree1.wasm b/tests/proj3/tests/tree1.wasm
new file mode 100644
index 0000000..8509d92
--- /dev/null
+++ b/tests/proj3/tests/tree1.wasm
Binary files differ
diff --git a/tests/proj3/tests/tree1.wat b/tests/proj3/tests/tree1.wat
new file mode 100644
index 0000000..b7f087c
--- /dev/null
+++ b/tests/proj3/tests/tree1.wat
@@ -0,0 +1,58 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func $left_key (result externref)
+ (call $b (f64.const 3.25)))
+
+ (func $right_key (result externref)
+ (call $b (f64.const -6.5)))
+
+ (func $keys (result externref)
+ (local $r externref)
+ (local.set $r (call $n))
+ (call $s (local.get $r) (call $left_key) (call $n))
+ (call $s (local.get $r) (call $right_key) (call $n))
+ (local.get $r)
+ )
+
+ (func $isnull (param externref) (result i32)
+ (local $n externref)
+ (call $eq (local.get $n) (local.get 0)))
+
+ (func $alloc (param externref i32) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (block $l
+ (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
+ (br_if $l (i32.le_s (local.get 1) (i32.const 0)))
+ (call $s (local.get $obj) (call $left_key) (call $alloc (local.get 0) (local.get 1)))
+ (call $s (local.get $obj) (call $right_key) (call $alloc (local.get 0) (local.get 1)))
+ )
+ (local.get $obj)
+ )
+
+ (func $height (param externref externref) (result i32)
+ (local $h i32)
+ (block $b
+ (loop $l
+ (br_if $b (call $isnull (local.get 1)))
+ (local.set $h (i32.add (local.get $h) (i32.const 1)))
+ (local.set 1 (call $g (local.get 1) (call $left_key)))
+ (br 0)
+ )
+ )
+ (local.get $h)
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (local $k externref)
+ (local $t externref)
+ (local.set $k (call $keys))
+ (local.set $t (call $alloc (local.get $k) (local.get 0)))
+ (call $height (local.get $k) (local.get $t))
+ )
+)
diff --git a/tests/proj3/tests/tree1.wee.wasm b/tests/proj3/tests/tree1.wee.wasm
new file mode 100644
index 0000000..4a8968c
--- /dev/null
+++ b/tests/proj3/tests/tree1.wee.wasm
Binary files differ
diff --git a/tests/proj3/tests/tree2.runs b/tests/proj3/tests/tree2.runs
new file mode 100644
index 0000000..e6d97be
--- /dev/null
+++ b/tests/proj3/tests/tree2.runs
@@ -0,0 +1,6 @@
+0 = 1
+1 = 1
+2 = 2
+5 = 5
+10 = 10
+15 = 15
diff --git a/tests/proj3/tests/tree2.wasm b/tests/proj3/tests/tree2.wasm
new file mode 100644
index 0000000..57aab2e
--- /dev/null
+++ b/tests/proj3/tests/tree2.wasm
Binary files differ
diff --git a/tests/proj3/tests/tree2.wat b/tests/proj3/tests/tree2.wat
new file mode 100644
index 0000000..dc16e27
--- /dev/null
+++ b/tests/proj3/tests/tree2.wat
@@ -0,0 +1,58 @@
+(module
+ (import "weewasm" "obj.new" (func $n (result externref)))
+ (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref)))
+ (import "weewasm" "obj.get" (func $g (param externref externref) (result externref)))
+ (import "weewasm" "obj.set" (func $s (param externref externref externref)))
+ (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32)))
+
+ (func $left_key (result externref)
+ (call $b (i32.const 77665544)))
+
+ (func $right_key (result externref)
+ (call $b (i32.const -99887766)))
+
+ (func $keys (result externref)
+ (local $r externref)
+ (local.set $r (call $n))
+ (call $s (local.get $r) (call $left_key) (call $n))
+ (call $s (local.get $r) (call $right_key) (call $n))
+ (local.get $r)
+ )
+
+ (func $isnull (param externref) (result i32)
+ (local $n externref)
+ (call $eq (local.get $n) (local.get 0)))
+
+ (func $alloc (param externref i32) (result externref)
+ (local $obj externref)
+ (local.set $obj (call $n))
+ (block $l
+ (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
+ (br_if $l (i32.le_s (local.get 1) (i32.const 0)))
+ (call $s (local.get $obj) (call $left_key) (call $alloc (local.get 0) (local.get 1)))
+ (call $s (local.get $obj) (call $right_key) (call $alloc (local.get 0) (local.get 1)))
+ )
+ (local.get $obj)
+ )
+
+ (func $height (param externref externref) (result i32)
+ (local $h i32)
+ (block $b
+ (loop $l
+ (br_if $b (call $isnull (local.get 1)))
+ (local.set $h (i32.add (local.get $h) (i32.const 1)))
+ (local.set 1 (call $g (local.get 1) (call $left_key)))
+ (br 0)
+ )
+ )
+ (local.get $h)
+ )
+
+ (func (export "main") (param i32) (result i32)
+ (local $k externref)
+ (local $t externref)
+ (local.set $k (call $keys))
+ (local.set $t (call $alloc (local.get $k) (local.get 0)))
+ (call $height (local.get $k) (local.get $t))
+ )
+)
diff --git a/tests/proj3/tests/tree2.wee.wasm b/tests/proj3/tests/tree2.wee.wasm
new file mode 100644
index 0000000..d9d7c57
--- /dev/null
+++ b/tests/proj3/tests/tree2.wee.wasm
Binary files differ
diff --git a/vm.h b/vm.h
new file mode 100644
index 0000000..3db064b
--- /dev/null
+++ b/vm.h
@@ -0,0 +1,20 @@
+#pragma once
+#include <stdint.h>
+
+typedef struct {
+ uint8_t *ip;
+} VM;
+
+typedef struct {
+} Chunk;
+
+typedef enum {
+ INTERPRET_OK,
+ INTERPRET_COMPILE_ERROR,
+ INTERPRET_RUNTIME_ERROR
+} InterpretResult;
+
+void initVM();
+void freeVM();
+InterpretResult interpret(Chunk* chunk);
+
diff --git a/weeify b/weeify
new file mode 100755
index 0000000..c8021a3
--- /dev/null
+++ b/weeify
Binary files differ
diff --git a/weeify.c b/weeify.c
new file mode 100644
index 0000000..adf3b66
--- /dev/null
+++ b/weeify.c
@@ -0,0 +1,647 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <stddef.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "common.h"
+#include "vm.h"
+#include "test.h"
+#include "weewasm.h"
+#include "illegal.h"
+
+int weeify(int out_fd, const byte* start, const byte* end);
+
+// Parse arguments and {weeify()} a single file.
+int main(int argc, char* argv[]) {
+ const char* in_path = NULL;
+ const char* out_path = NULL;
+
+ // parse arguments
+ for (int i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (strcmp(arg, "-trace") == 0) {
+ g_trace = 1;
+ continue;
+ }
+ if (strcmp(arg, "-o") == 0 && i < (argc - 1)) {
+ out_path = argv[++i];
+ continue;
+ }
+ if (in_path != NULL) {
+ out_path = NULL;
+ break;
+ }
+ in_path = arg;
+ }
+
+ // check both {in_path} and {out_path} are specified
+ if (in_path == NULL || out_path == NULL) {
+ printf("Usage: weeify [-trace] -o <out_file> <in_file>\n");
+ return 1;
+ }
+
+ // load input file and create output file
+ {
+ byte* start = NULL;
+ byte* end = NULL;
+ ssize_t r = load_file(in_path, &start, &end);
+ if (r < 0) {
+ ERR("failed to load: %s\n", in_path);
+ return 2;
+ }
+ TRACE("loaded %s: %ld bytes\n", in_path, r);
+
+ int out_fd = open(out_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (out_fd < 0) {
+ ERR("failed to create: %s\n", out_path);
+ return 3;
+ }
+ weeify(out_fd, start, end);
+ close(out_fd);
+ unload_file(&start, &end);
+ return 0;
+ }
+}
+
+// emits a single byte
+void emit1(int out_fd, byte val) {
+ write(out_fd, &val, 1);
+}
+
+// emits an unsigned LEB, not padded
+void emit_u32leb(int out_fd, uint32_t val) {
+ off_t cur = lseek(out_fd, 0, SEEK_CUR);
+ TRACE(" cur=0x%llx: emit_u32leb = %u\n", (long long)cur, val);
+ do {
+ uint32_t next = val >> 7;
+ uint32_t v = val & 0x7F;
+ if (next != 0) v |= 0x80;
+ emit1(out_fd, v);
+ val = next;
+ } while (val != 0);
+}
+
+// emits an unsigned LEB, padded to 4 bytes
+void emit_u32leb4(int out_fd, uint32_t val) {
+ off_t cur = lseek(out_fd, 0, SEEK_CUR);
+ TRACE(" cur=0x%llx: emit_u32leb4 = %u\n", (long long)cur, val);
+ byte buf[4];
+ buf[0] = 0x80 | (val & 0x7F);
+ buf[1] = 0x80 | ((val >> 7) & 0x7F);
+ buf[2] = 0x80 | ((val >> 14) & 0x7F);
+ buf[3] = ((val >> 21) & 0x7F);
+ write(out_fd, buf, 4);
+}
+
+// emits an unsigned LEB, padded to 5 bytes
+void emit_u32leb5(int out_fd, uint32_t val) {
+ off_t cur = lseek(out_fd, 0, SEEK_CUR);
+ TRACE(" cur=0x%llx: emit_u32leb5 = %u\n", (long long)cur, val);
+ byte buf[5];
+ buf[0] = 0x80 | (val & 0x7F);
+ buf[1] = 0x80 | ((val >> 7) & 0x7F);
+ buf[2] = 0x80 | ((val >> 14) & 0x7F);
+ buf[3] = 0x80 | ((val >> 21) & 0x7F);
+ buf[4] = ((val >> 28) & 0x7F);
+ write(out_fd, buf, 5);
+}
+
+// emits the bytes from {start ... buf->ptr}
+void emit_from(int out_fd, const byte* start, buffer_t* buf) {
+ off_t cur = lseek(out_fd, 0, SEEK_CUR);
+ TRACE(" cur=0x%llx: emit_from: %d bytes\n", (long long)cur, (int)(buf->ptr - start));
+ write(out_fd, start, (buf->ptr - start));
+}
+
+off_t emit_reserved_length(int out_fd) {
+ off_t before = lseek(out_fd, 0, SEEK_CUR);
+ TRACE(" cur=0x%llx: reserve 5 byte LEB for length\n", (long long)before);
+ emit_u32leb5(out_fd, 0);
+ return before;
+}
+
+void emit_patched_length(int out_fd, off_t before) {
+ off_t cur = lseek(out_fd, 0, SEEK_CUR);
+ off_t diff = cur - before - 5;
+ TRACE(" cur=0x%llx: patch 5 byte LEB for length @ 0x%llx = %lld\n", (long long)cur, (long long)before, (long long)diff);
+ lseek(out_fd, before, SEEK_SET);
+ emit_u32leb5(out_fd, diff);
+ lseek(out_fd, cur, SEEK_SET);
+}
+
+// Returns the string name of a section code.
+const char* section_name(byte code) {
+ switch (code) {
+ case WASM_SECT_TYPE: return "type";
+ case WASM_SECT_IMPORT: return "import";
+ case WASM_SECT_FUNCTION: return "function";
+ case WASM_SECT_TABLE: return "table";
+ case WASM_SECT_MEMORY: return "memory";
+ case WASM_SECT_GLOBAL: return "global";
+ case WASM_SECT_EXPORT: return "export";
+ case WASM_SECT_START: return "start";
+ case WASM_SECT_ELEMENT: return "element";
+ case WASM_SECT_CODE: return "code";
+ case WASM_SECT_DATA: return "data";
+ case 0: return "custom";
+ default:
+ return "unknown";
+ }
+}
+
+#define WASM_TYPE_I32 -1
+#define WASM_TYPE_I64 -2
+#define WASM_TYPE_F32 -3
+#define WASM_TYPE_F64 -4
+#define WASM_TYPE_V128 -5
+#define WASM_TYPE_EXTERNREF -17
+#define WASM_TYPE_FUNCREF -16
+
+// Returns the string name of a type code.
+const char* type_name(uint32_t code) {
+ switch (code) {
+ case WASM_TYPE_I32: return "i32";
+ case WASM_TYPE_I64: return "<!illegal i64>";
+ case WASM_TYPE_F32: return "<!illegal f32>";
+ case WASM_TYPE_F64: return "f64";
+ case WASM_TYPE_V128: return "<!illegal v128>";
+ case WASM_TYPE_EXTERNREF: return "externref";
+ case WASM_TYPE_FUNCREF: return "funcref";
+ default: return "<!unknown type>";
+ }
+}
+
+int transform_code_section(int out_fd, buffer_t* buf);
+int transform_body(int out_fd, buffer_t* buf);
+
+// Transforms the wasm file in {start ... end} and outputs the bytes to {out_fd}.
+int weeify(int out_fd, const byte* start, const byte* end) {
+ buffer_t onstack_buf = {
+ start,
+ start,
+ end
+ };
+ buffer_t* buf = &onstack_buf;
+ ssize_t len = 0;
+
+ //==== Check magic word =============================================
+ uint32_t magic = decode_u32(buf->ptr, buf->end, &len);
+ TRACE("read_magic = 0x%08x\n", magic);
+ if (len != 4 || magic != WASM_MAGIC) {
+ ERR("invalid magic word, expected %x\n", WASM_MAGIC);
+ return -1;
+ }
+ buf->ptr += 4;
+
+ //==== Check Wasm Version ===========================================
+ uint32_t version = decode_u32(buf->ptr, buf->end, &len);
+ TRACE("read_version = 0x%08x\n", version);
+ if (len != 4 || version != WASM_VERSION) {
+ ERR("invalid Wasm version, expected %x\n", WASM_VERSION);
+ return -2;
+ }
+ buf->ptr += 4;
+
+ TRACE(" copy header\n");
+ emit_from(out_fd, buf->start, buf);
+
+ //==== Read Wasm sections ===========================================
+ while (buf->ptr < buf->end) {
+ const byte* section_start = buf->ptr;
+
+ byte code = read_u8(buf);
+ uint32_t sectlen = read_u32leb(buf);
+ TRACE("read_section_code = 0x%02x (%s), %u bytes\n", code, section_name(code), sectlen);
+ const byte* section_end = buf->ptr + sectlen;
+ if (section_end > end) {
+ ERR("invalid: section length too large");
+ return -4;
+ }
+
+ if (code == WASM_SECT_CODE) {
+ // transform a code section
+ buffer_t code_buf = { // use a sub-buffer to avoid going OOB
+ section_start,
+ buf->ptr,
+ section_end
+ };
+ int result = transform_code_section(out_fd, &code_buf);
+ if (result != 0) return result;
+ } else {
+ // not a code section; copy section verbatim
+ ptrdiff_t diff = (section_end - section_start);
+ TRACE(" copy %td byte section\n", diff);
+ write(out_fd, section_start, diff);
+ }
+
+ buf->ptr = section_end;
+
+ if (section_end == section_start) {
+ ERR("internal error: zero-length section");
+ return -3;
+ }
+ }
+ off_t cur = lseek(out_fd, 0, SEEK_CUR);
+ TRACE("file size = %lld bytes\n", (long long)cur);
+ return 0;
+}
+
+// Transforms a code section, padding branch instructions to be at least 4-byte LEBs.
+int transform_code_section(int out_fd, buffer_t* buf) {
+ emit1(out_fd, WASM_SECT_CODE);
+ off_t before = emit_reserved_length(out_fd);
+
+ uint32_t body_count = read_u32leb(buf);
+ emit_u32leb(out_fd, body_count);
+ for (uint32_t i = 0; i < body_count; i++) {
+ TRACE("transform body #%u\n", i);
+ const byte* body_start = buf->ptr;
+ uint32_t body_len = read_u32leb(buf);
+ buffer_t body_buf = { // use a sub-buffer to avoid going OOB
+ body_start,
+ buf->ptr,
+ buf->ptr + body_len
+ };
+
+ transform_body(out_fd, &body_buf);
+ buf->ptr = body_buf.end;
+ }
+ emit_patched_length(out_fd, before);
+ return 0;
+}
+
+// Support for disassembling/transforming the bytecode
+typedef struct {
+ const char* mnemonic;
+ int immkind;
+ int illegal;
+} opcode_imm_t;
+
+#define IMM_NONE 0
+#define IMM_BLOCKT 1
+#define IMM_LABEL 2
+#define IMM_LABELS 3
+#define IMM_FUNC 4
+#define IMM_SIG_TABLE 5
+#define IMM_LOCAL 6
+#define IMM_GLOBAL 7
+#define IMM_TABLE 8
+#define IMM_MEMARG 9
+#define IMM_I32 10
+#define IMM_F64 11
+#define IMM_MEMORY 12
+#define IMM_TAG 13
+#define IMM_I64 14
+#define IMM_F32 15
+#define IMM_REFNULLT 16
+#define IMM_VALTS 17
+
+opcode_imm_t opcode_imm_table[256] = {
+ [WASM_OP_UNREACHABLE] = {"unreachable" },
+ [WASM_OP_NOP] = {"nop" },
+ [WASM_OP_BLOCK] = {"block", IMM_BLOCKT },
+ [WASM_OP_LOOP] = {"loop", IMM_BLOCKT },
+ [WASM_OP_END] = {"end" },
+ [WASM_OP_BR] = {"br", IMM_LABEL },
+ [WASM_OP_BR_IF] = {"br_if", IMM_LABEL },
+ [WASM_OP_BR_TABLE] = {"br_table", IMM_LABELS },
+ [WASM_OP_RETURN] = {"return" },
+ [WASM_OP_CALL] = {"call", IMM_FUNC },
+ [WASM_OP_CALL_INDIRECT] = {"call_indirect", IMM_SIG_TABLE },
+ [WASM_OP_DROP] = {"drop" },
+ [WASM_OP_SELECT] = {"select" },
+ [WASM_OP_LOCAL_GET] = {"local.get", IMM_LOCAL },
+ [WASM_OP_LOCAL_SET] = {"local.set", IMM_LOCAL },
+ [WASM_OP_LOCAL_TEE] = {"local.tee", IMM_LOCAL },
+ [WASM_OP_GLOBAL_GET] = {"global.get", IMM_GLOBAL },
+ [WASM_OP_GLOBAL_SET] = {"global.set", IMM_GLOBAL },
+ [WASM_OP_TABLE_GET] = {"table.get", IMM_TABLE },
+ [WASM_OP_TABLE_SET] = {"table.set", IMM_TABLE },
+ [WASM_OP_I32_LOAD] = {"i32.load", IMM_MEMARG },
+ [WASM_OP_F64_LOAD] = {"f64.load", IMM_MEMARG },
+ [WASM_OP_I32_LOAD8_S] = {"i32.load8_s", IMM_MEMARG },
+ [WASM_OP_I32_LOAD8_U] = {"i32.load8_u", IMM_MEMARG },
+ [WASM_OP_I32_LOAD16_S] = {"i32.load16_s", IMM_MEMARG },
+ [WASM_OP_I32_LOAD16_U] = {"i32.load16_u", IMM_MEMARG },
+ [WASM_OP_I32_STORE] = {"i32.store", IMM_MEMARG },
+ [WASM_OP_F64_STORE] = {"f64.store", IMM_MEMARG },
+ [WASM_OP_I32_STORE8] = {"i32.store8", IMM_MEMARG },
+ [WASM_OP_I32_STORE16] = {"i32.store16", IMM_MEMARG },
+ [WASM_OP_I32_CONST] = {"i32.const", IMM_I32 },
+ [WASM_OP_F64_CONST] = {"f64.const", IMM_F64 },
+ [WASM_OP_I32_EQZ] = {"i32.eqz" },
+ [WASM_OP_I32_EQ] = {"i32.eq" },
+ [WASM_OP_I32_NE] = {"i32.ne" },
+ [WASM_OP_I32_LT_S] = {"i32.lt_s" },
+ [WASM_OP_I32_LT_U] = {"i32.lt_u" },
+ [WASM_OP_I32_GT_S] = {"i32.gt_s" },
+ [WASM_OP_I32_GT_U] = {"i32.gt_u" },
+ [WASM_OP_I32_LE_S] = {"i32.le_s" },
+ [WASM_OP_I32_LE_U] = {"i32.le_u" },
+ [WASM_OP_I32_GE_S] = {"i32.ge_s" },
+ [WASM_OP_I32_GE_U] = {"i32.ge_u" },
+ [WASM_OP_F64_EQ] = {"f64.eq" },
+ [WASM_OP_F64_NE] = {"f64.ne" },
+ [WASM_OP_F64_LT] = {"f64.lt" },
+ [WASM_OP_F64_GT] = {"f64.gt" },
+ [WASM_OP_F64_LE] = {"f64.le" },
+ [WASM_OP_F64_GE] = {"f64.ge" },
+ [WASM_OP_I32_CLZ] = {"i32.clz" },
+ [WASM_OP_I32_CTZ] = {"i32.ctz" },
+ [WASM_OP_I32_POPCNT] = {"i32.popcnt" },
+ [WASM_OP_I32_ADD] = {"i32.add" },
+ [WASM_OP_I32_SUB] = {"i32.sub" },
+ [WASM_OP_I32_MUL] = {"i32.mul" },
+ [WASM_OP_I32_DIV_S] = {"i32.div_s" },
+ [WASM_OP_I32_DIV_U] = {"i32.div_u" },
+ [WASM_OP_I32_REM_S] = {"i32.rem_s" },
+ [WASM_OP_I32_REM_U] = {"i32.rem_u" },
+ [WASM_OP_I32_AND] = {"i32.and" },
+ [WASM_OP_I32_OR] = {"i32.or" },
+ [WASM_OP_I32_XOR] = {"i32.xor" },
+ [WASM_OP_I32_SHL] = {"i32.shl" },
+ [WASM_OP_I32_SHR_S] = {"i32.shr_s" },
+ [WASM_OP_I32_SHR_U] = {"i32.shr_u" },
+ [WASM_OP_I32_ROTL] = {"i32.rotl" },
+ [WASM_OP_I32_ROTR] = {"i32.rotr" },
+ [WASM_OP_F64_ADD] = {"f64.add" },
+ [WASM_OP_F64_SUB] = {"f64.sub" },
+ [WASM_OP_F64_MUL] = {"f64.mul" },
+ [WASM_OP_F64_DIV] = {"f64.div" },
+ [WASM_OP_I32_TRUNC_F64_S] = {"i32.trunc_f64_s" },
+ [WASM_OP_I32_TRUNC_F64_U] = {"i32.trunc_f64_u" },
+ [WASM_OP_F64_CONVERT_I32_S] = {"f64.convert_i32_s" },
+ [WASM_OP_F64_CONVERT_I32_U] = {"f64.convert_i32_u" },
+ [WASM_OP_F64_CONVERT_I64_S] = {"f64.convert_i64_s" },
+ [WASM_OP_F64_CONVERT_I64_U] = {"f64.convert_i64_u" },
+ [WASM_OP_I32_EXTEND8_S] = {"i32.extend8_s" },
+ [WASM_OP_I32_EXTEND16_S] = {"i32.extend16_s" },
+ // illegal bytecodes
+ [WASM_OP_IF] = {"if", IMM_BLOCKT, -1 },
+ [WASM_OP_ELSE] = {"else", -1 },
+ [WASM_OP_TRY] = {"try", IMM_BLOCKT, -1},
+ [WASM_OP_CATCH] = {"catch", IMM_TAG, -1},
+ [WASM_OP_THROW] = {"throw", IMM_TAG, -1},
+ [WASM_OP_RETHROW] = {"rethrow", IMM_NONE, -1},
+ [WASM_OP_RETURN_CALL] = {"return_call", IMM_FUNC, -1},
+ [WASM_OP_RETURN_CALL_INDIRECT]= {"return_call_indirect", IMM_SIG_TABLE, -1},
+ [WASM_OP_CALL_REF] = {"call_ref", IMM_NONE, -1},
+ [WASM_OP_RETURN_CALL_REF] = {"return_call_ref", IMM_NONE, -1},
+ [WASM_OP_DELEGATE] = {"delegate", IMM_NONE, -1},
+ [WASM_OP_CATCH_ALL] = {"catch_all", IMM_NONE, -1},
+ [WASM_OP_SELECT_T] = {"select", IMM_VALTS, -1},
+ [WASM_OP_I64_LOAD] = {"i64.load", IMM_MEMARG, -1},
+ [WASM_OP_F32_LOAD] = {"f32.load", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD8_S] = {"i64.load8_s", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD8_U] = {"i64.load8_u", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD16_S] = {"i64.load16_s", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD16_U] = {"i64.load16_u", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD32_S] = {"i64.load32_s", IMM_MEMARG, -1},
+ [WASM_OP_I64_LOAD32_U] = {"i64.load32_u", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE] = {"i64.store", IMM_MEMARG, -1},
+ [WASM_OP_F32_STORE] = {"f32.store", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE8] = {"i64.store8", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE16] = {"i64.store16", IMM_MEMARG, -1},
+ [WASM_OP_I64_STORE32] = {"i64.store32", IMM_MEMARG, -1},
+ [WASM_OP_MEMORY_SIZE] = {"memory.size", IMM_MEMORY, -1},
+ [WASM_OP_MEMORY_GROW] = {"memory.grow", IMM_MEMORY, -1},
+ [WASM_OP_I64_CONST] = {"i64.const", IMM_I64, -1},
+ [WASM_OP_F32_CONST] = {"f32.const", IMM_F32, -1},
+ [WASM_OP_I64_EQZ] = {"i64.eqz", IMM_NONE, -1},
+ [WASM_OP_I64_EQ] = {"i64.eq", IMM_NONE, -1},
+ [WASM_OP_I64_NE] = {"i64.ne", IMM_NONE, -1},
+ [WASM_OP_I64_LT_S] = {"i64.lt_s", IMM_NONE, -1},
+ [WASM_OP_I64_LT_U] = {"i64.lt_u", IMM_NONE, -1},
+ [WASM_OP_I64_GT_S] = {"i64.gt_s", IMM_NONE, -1},
+ [WASM_OP_I64_GT_U] = {"i64.gt_u", IMM_NONE, -1},
+ [WASM_OP_I64_LE_S] = {"i64.le_s", IMM_NONE, -1},
+ [WASM_OP_I64_LE_U] = {"i64.le_u", IMM_NONE, -1},
+ [WASM_OP_I64_GE_S] = {"i64.ge_s", IMM_NONE, -1},
+ [WASM_OP_I64_GE_U] = {"i64.ge_u", IMM_NONE, -1},
+ [WASM_OP_F32_EQ] = {"f32.eq", IMM_NONE, -1},
+ [WASM_OP_F32_NE] = {"f32.ne", IMM_NONE, -1},
+ [WASM_OP_F32_LT] = {"f32.lt", IMM_NONE, -1},
+ [WASM_OP_F32_GT] = {"f32.gt", IMM_NONE, -1},
+ [WASM_OP_F32_LE] = {"f32.le", IMM_NONE, -1},
+ [WASM_OP_F32_GE] = {"f32.ge", IMM_NONE, -1},
+ [WASM_OP_I64_CLZ] = {"i64.clz", IMM_NONE, -1},
+ [WASM_OP_I64_CTZ] = {"i64.ctz", IMM_NONE, -1},
+ [WASM_OP_I64_POPCNT] = {"i64.popcnt", IMM_NONE, -1},
+ [WASM_OP_I64_ADD] = {"i64.add", IMM_NONE, -1},
+ [WASM_OP_I64_SUB] = {"i64.sub", IMM_NONE, -1},
+ [WASM_OP_I64_MUL] = {"i64.mul", IMM_NONE, -1},
+ [WASM_OP_I64_DIV_S] = {"i64.div_s", IMM_NONE, -1},
+ [WASM_OP_I64_DIV_U] = {"i64.div_u", IMM_NONE, -1},
+ [WASM_OP_I64_REM_S] = {"i64.rem_s", IMM_NONE, -1},
+ [WASM_OP_I64_REM_U] = {"i64.rem_u", IMM_NONE, -1},
+ [WASM_OP_I64_AND] = {"i64.and", IMM_NONE, -1},
+ [WASM_OP_I64_OR] = {"i64.or", IMM_NONE, -1},
+ [WASM_OP_I64_XOR] = {"i64.xor", IMM_NONE, -1},
+ [WASM_OP_I64_SHL] = {"i64.shl", IMM_NONE, -1},
+ [WASM_OP_I64_SHR_S] = {"i64.shr_s", IMM_NONE, -1},
+ [WASM_OP_I64_SHR_U] = {"i64.shr_u", IMM_NONE, -1},
+ [WASM_OP_I64_ROTL] = {"i64.rotl", IMM_NONE, -1},
+ [WASM_OP_I64_ROTR] = {"i64.rotr", IMM_NONE, -1},
+ [WASM_OP_F32_ABS] = {"f32.abs", IMM_NONE, -1},
+ [WASM_OP_F32_NEG] = {"f32.neg", IMM_NONE, -1},
+ [WASM_OP_F32_CEIL] = {"f32.ceil", IMM_NONE, -1},
+ [WASM_OP_F32_FLOOR] = {"f32.floor", IMM_NONE, -1},
+ [WASM_OP_F32_TRUNC] = {"f32.trunc", IMM_NONE, -1},
+ [WASM_OP_F32_NEAREST] = {"f32.nearest", IMM_NONE, -1},
+ [WASM_OP_F32_SQRT] = {"f32.sqrt", IMM_NONE, -1},
+ [WASM_OP_F32_ADD] = {"f32.add", IMM_NONE, -1},
+ [WASM_OP_F32_SUB] = {"f32.sub", IMM_NONE, -1},
+ [WASM_OP_F32_MUL] = {"f32.mul", IMM_NONE, -1},
+ [WASM_OP_F32_DIV] = {"f32.div", IMM_NONE, -1},
+ [WASM_OP_F32_MIN] = {"f32.min", IMM_NONE, -1},
+ [WASM_OP_F32_MAX] = {"f32.max", IMM_NONE, -1},
+ [WASM_OP_F32_COPYSIGN] = {"f32.copysign", IMM_NONE, -1},
+ [WASM_OP_F64_ABS] = {"f64.abs", IMM_NONE, -1},
+ [WASM_OP_F64_NEG] = {"f64.neg", IMM_NONE, -1},
+ [WASM_OP_F64_CEIL] = {"f64.ceil", IMM_NONE, -1},
+ [WASM_OP_F64_FLOOR] = {"f64.floor", IMM_NONE, -1},
+ [WASM_OP_F64_TRUNC] = {"f64.trunc", IMM_NONE, -1},
+ [WASM_OP_F64_NEAREST] = {"f64.nearest", IMM_NONE, -1},
+ [WASM_OP_F64_SQRT] = {"f64.sqrt", IMM_NONE, -1},
+ [WASM_OP_F64_MIN] = {"f64.min", IMM_NONE, -1},
+ [WASM_OP_F64_MAX] = {"f64.max", IMM_NONE, -1},
+ [WASM_OP_F64_COPYSIGN] = {"f64.copysign", IMM_NONE, -1},
+ [WASM_OP_I32_WRAP_I64] = {"i32.wrap_i64", IMM_NONE, -1},
+ [WASM_OP_I32_TRUNC_F32_S] = {"i32.trunc_f32_s", IMM_NONE, -1},
+ [WASM_OP_I32_TRUNC_F32_U] = {"i32.trunc_f32_u", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND_I32_S] = {"i64.extend_i32_s", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND_I32_U] = {"i64.extend_i32_u", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F32_S] = {"i64.trunc_f32_s", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F32_U] = {"i64.trunc_f32_u", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F64_S] = {"i64.trunc_f64_s", IMM_NONE, -1},
+ [WASM_OP_I64_TRUNC_F64_U] = {"i64.trunc_f64_u", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I32_S] = {"f32.convert_i32_s", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I32_U] = {"f32.convert_i32_u", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I64_S] = {"f32.convert_i64_s", IMM_NONE, -1},
+ [WASM_OP_F32_CONVERT_I64_U] = {"f32.convert_i64_u", IMM_NONE, -1},
+ [WASM_OP_F32_DEMOTE_F64] = {"f32.demote_f64", IMM_NONE, -1},
+ [WASM_OP_F64_PROMOTE_F32] = {"f64.promote_f32", IMM_NONE, -1},
+ [WASM_OP_I32_REINTERPRET_F32] = {"i32.reinterpret_f32", IMM_NONE, -1},
+ [WASM_OP_I64_REINTERPRET_F64] = {"i64.reinterpret_f64", IMM_NONE, -1},
+ [WASM_OP_F32_REINTERPRET_I32] = {"f32.reinterpret_i32", IMM_NONE, -1},
+ [WASM_OP_F64_REINTERPRET_I64] = {"f64.reinterpret_i64", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND8_S] = {"i64.extend8_s", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND16_S] = {"i64.extend16_s", IMM_NONE, -1},
+ [WASM_OP_I64_EXTEND32_S] = {"i64.extend32_s", IMM_NONE, -1},
+ [WASM_OP_REF_NULL] = {"ref.null", IMM_REFNULLT, -1},
+ [WASM_OP_REF_IS_NULL] = {"ref.is_null", IMM_NONE, -1},
+ [WASM_OP_REF_FUNC] = {"ref.func", IMM_FUNC, -1},
+ [WASM_OP_REF_AS_NON_NULL] = {"ref.as_non_null", IMM_NONE, -1},
+ [WASM_OP_BR_ON_NULL] = {"br_on_null", IMM_LABEL, -1},
+ [WASM_OP_REF_EQ] = {"ref.eq", IMM_NONE, -1},
+ [WASM_OP_BR_ON_NON_NULL] = {"br_on_non_null", IMM_LABEL, -1},
+};
+
+int transform_bytecode(int out_fd, buffer_t* buf) {
+ TRACE(" ");
+ const byte* start = buf->ptr;
+
+ byte code = read_u8(buf);
+ opcode_imm_t* entry = &opcode_imm_table[code];
+ if (entry->mnemonic == NULL) {
+ ERR("<!illegal bytecode %02X>", code);
+ return -3;
+ } else if (entry->illegal) {
+ ERR("<!illegal %s>", entry->mnemonic);
+ return -4;
+ } else {
+ TRACE("%s", entry->mnemonic);
+ }
+ switch (entry->immkind) {
+ case IMM_LABEL: {
+ // expand to 4-byte LEB
+ uint32_t imm = read_u32leb(buf);
+ TRACE(" %u", imm);
+ emit1(out_fd, code);
+ emit_u32leb4(out_fd, imm);
+ return 0;
+ }
+ case IMM_LABELS: {
+ // expand to 4-byte LEBs
+ uint32_t count = read_u32leb(buf);
+ TRACE(" %u", count);
+ emit1(out_fd, code);
+ emit_u32leb4(out_fd, count);
+ for (uint32_t i = 0; i <= count && buf->ptr < buf->end; i++) {
+ uint32_t lbl = read_u32leb(buf);
+ emit_u32leb4(out_fd, lbl);
+ TRACE(" %u", lbl);
+ }
+ return 0;
+ }
+ case IMM_FUNC: // fallthru
+ case IMM_LOCAL: // fallthru
+ case IMM_GLOBAL: // fallthru
+ case IMM_MEMORY: // fallthru
+ case IMM_TAG: // fallthru
+ case IMM_REFNULLT:
+ case IMM_TABLE: {
+ uint32_t imm = read_u32leb(buf);
+ TRACE(" %u", imm);
+ break;
+ }
+
+ case IMM_NONE: break;
+ case IMM_BLOCKT: {
+ int32_t imm = read_i32leb(buf);
+ if (imm != -64) {
+ ERR(" <!illegal blocktype %d>", imm);
+ return -5;
+ }
+ break;
+ }
+ case IMM_SIG_TABLE: {
+ uint32_t sig = read_u32leb(buf);
+ TRACE(" %d", sig);
+ uint32_t tbl = read_u32leb(buf);
+ if (tbl != 0) {
+ ERR(" <!illegal table %d>", tbl);\
+ return -2;
+ }
+ break;
+ }
+ case IMM_MEMARG: {
+ byte b = read_u8(buf);
+ uint32_t offset = read_u32leb(buf);
+ TRACE(" %u", offset);
+ break;
+ }
+ case IMM_I32: {
+ int32_t imm = read_i32leb(buf);
+ TRACE(" %d", imm);
+ break;
+ }
+ case IMM_F64: {
+ if (buf->end - buf->ptr >= 8) {
+ uint64_t val = *((uint64_t*)buf->ptr);
+ TRACE(" %016" PRIx64, val);
+ buf->ptr += 8;
+ } else {
+ ERR(" <!invalid f64>");
+ return -6;
+ }
+ break;
+ }
+ case IMM_I64: {
+ ssize_t leblen = 0;
+ if (buf->ptr >= buf->end) break;
+ int64_t imm = decode_i64leb(buf->ptr, buf->end, &leblen);
+ if (leblen <= 0) buf->ptr = buf->end; // force failure
+ else buf->ptr += leblen;
+ TRACE(" %" PRId64 "", imm);
+ break;
+ }
+ case IMM_F32: {
+ for (int i = 0; i < 4; i++) {
+ byte b = read_u8(buf);
+ TRACE(" %02X", b);
+ }
+ break;
+ }
+ case IMM_VALTS: {
+ int32_t tcode = read_i32leb(buf);
+ TRACE(" %s", type_name(tcode));
+ break;
+ }
+ default: break;
+ }
+ TRACE("\n");
+ // emit the bytes as-is
+ emit_from(out_fd, start, buf);
+ return 0;
+}
+
+int transform_body(int out_fd, buffer_t* buf) {
+ off_t before = emit_reserved_length(out_fd);
+
+ const byte* start = buf->ptr;
+ uint32_t cnt = read_u32leb(buf);
+ TRACE(" locals %d\n", cnt);
+ for (uint32_t i = 0; i < cnt; i++) {
+ uint32_t cnt = read_u32leb(buf);
+ TRACE(" %u", cnt);
+ int32_t type = read_i32leb(buf);
+ TRACE(" %s\n", type_name(type));
+ }
+ emit_from(out_fd, start, buf);
+ // disassemble code
+ while (buf->ptr < buf->end) {
+ int result = transform_bytecode(out_fd, buf);
+ if (result != 0) return result;
+ }
+
+ emit_patched_length(out_fd, before);
+ return 0;
+}
diff --git a/weerun.c b/weerun.c
new file mode 100644
index 0000000..32b1ff0
--- /dev/null
+++ b/weerun.c
@@ -0,0 +1,68 @@
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "ir.h"
+#include "weewasm.h"
+
+// Initialize the runtime functions.
+void init_runtime();
+void init_libc_runtime();
+
+// Disassembles? and runs a wasm module.
+wasm_typed_value_t run(const byte* start,
+ const byte* end,
+ uint32_t num_args,
+ wasm_value_t* args);
+
+// Main function.
+// Parses arguments and either runs the tests or runs a file with arguments.
+// -trace: enable tracing to stderr
+// -test: run internal tests
+int main(int argc, char* argv[]) {
+ for (int i = 1; i < argc; i++) {
+ char* arg = argv[i];
+ if (strcmp(arg, "-trace") == 0) {
+ g_trace = 1;
+ continue;
+ }
+ if (strcmp(arg, "-disassemble") == 0) {
+ g_disassemble = 1;
+ continue;
+ }
+
+ byte* start = NULL;
+ byte* end = NULL;
+ ssize_t r = load_file(arg, &start, &end);
+ if (r >= 0) {
+ TRACE("loaded %s: %ld bytes\n", arg, r);
+ int num_args = argc - i - 1;
+ wasm_value_t* args = NULL;
+ if (num_args > 0) {
+ args = (wasm_value_t*)malloc(sizeof(wasm_value_t) * num_args);
+ for (int j = i + 1; j < argc; j++) {
+ int a = j - i - 1;
+ args[a] = parse_wasm_value(argv[j]);
+ TRACE("args[%d] = ", a);
+ // trace_wasm_value(args[a]);
+ TRACE("\n");
+ }
+ }
+ init_runtime();
+ init_libc_runtime();
+ wasm_typed_value_t result = run(start, end, num_args, args);
+ unload_file(&start, &end);
+ print_wasm_value(result);
+ printf("\n");
+ exit(0);
+ return 0;
+ } else {
+ ERR("failed to load: %s\n", arg);
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/weerun.hpp b/weerun.hpp
new file mode 100644
index 0000000..e9f0ed3
--- /dev/null
+++ b/weerun.hpp
@@ -0,0 +1,255 @@
+#pragma once
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+extern "C" {
+#include "common.h"
+#include "ir.h"
+#include "weewasm.h"
+}
+
+#define WASM_TYPE_FUNCTION 0x60
+#define WASM_TYPE_I32 0x7F
+#define WASM_TYPE_I64 0x7E
+#define WASM_TYPE_F64 0x7C
+#define WASM_TYPE_FUNCREF 0x70
+#define WASM_TYPE_EXTERNREF 0x6F
+
+struct wasm_func_decl_t {
+ std::vector<uint8_t> args_;
+ std::vector<uint8_t> ret_;
+};
+
+struct wasm_table_decl_t {
+ uint8_t type_;
+ byte has_max_;
+ uint32_t init_;
+ uint32_t max_;
+};
+
+struct wasm_memory_decl_t {
+ byte has_max_;
+ uint32_t init_;
+ uint32_t max_;
+};
+
+struct wasm_global_decl_t {
+ uint8_t type_;
+ byte is_mut_;
+};
+
+struct wasm_import_decl_t {
+ enum class type { FUNCTION = 0x0, TABLE = 0x1, MEMORY = 0x2, GLOBAL = 0x3 };
+
+ type type_;
+ std::string module_;
+ std::string name_;
+ union {
+ uint32_t funcindex_;
+ wasm_table_decl_t table_;
+ wasm_memory_decl_t memory_;
+ wasm_global_decl_t global_;
+ };
+};
+
+struct wasm_global_t {
+ wasm_global_decl_t type_;
+ union {
+ uint32_t i32;
+ double f64;
+ void* ref;
+ } val_;
+};
+
+struct wasm_export_t {
+ std::string name_;
+ uint32_t type_;
+ uint32_t idx_;
+};
+
+struct wasm_elem_decl_t {
+ int32_t offset_;
+ std::vector<uint32_t> funcidx_;
+};
+
+struct wasm_local_decl_t {
+ uint32_t count_;
+ uint32_t type_;
+};
+
+struct wasm_code_decl_t {
+ uint32_t size_;
+ std::vector<wasm_local_decl_t> locals_;
+ std::vector<byte> code_;
+};
+
+struct wasm_data_decl_t {
+ uint32_t offset_;
+ std::vector<byte> data_;
+};
+
+struct wasm_instance_t;
+
+struct wasm_func_t {
+ wasm_func_decl_t* sig_;
+ uint32_t typeid_;
+ std::vector<wasm_local_decl_t> locals_;
+ std::vector<byte> code_;
+
+ // run imported function in interperter
+ void (*run_)(wasm_instance_t* ins);
+ // run imported function in JIT
+ void* run_jit_;
+};
+
+struct wasm_module_t {
+ wasm_memory_decl_t mem_limits_;
+ wasm_table_decl_t table_;
+ uint32_t num_import_funcs_;
+ uint32_t main_index_;
+ bool have_start_;
+ uint32_t start_index_;
+ std::vector<wasm_func_decl_t> sigs_;
+ std::vector<wasm_func_t> funcs_;
+ std::vector<wasm_global_t> globals_;
+ std::vector<wasm_data_decl_t> datas_;
+ std::vector<wasm_elem_decl_t> elems_;
+
+ wasm_instance_t* create_instance();
+};
+
+const uint32_t wasm_page_size = 65536;
+
+struct wasm_stack_frame_t {
+ buffer_t pc_;
+ wasm_func_t* f_;
+ std::vector<wasm_value_t> locals_;
+};
+
+struct wasm_jit_table_entry_t {
+ int64_t typeidx;
+ uint8_t* addr;
+};
+
+struct wasm_instance_t {
+ wasm_module_t* module_;
+ std::vector<byte> memory_;
+ std::vector<wasm_func_t*> table_;
+ std::vector<wasm_jit_table_entry_t> jit_table_;
+ std::vector<wasm_value_t> globals_;
+ std::vector<wasm_value_t> value_stack_;
+ std::vector<wasm_stack_frame_t> frames_;
+ wasm_stack_frame_t* cur_frame_;
+ uint32_t trapped;
+
+ void run_function(uint32_t funcidx);
+ wasm_value_t run(std::vector<wasm_value_t> args);
+ wasm_value_t run_jit(std::vector<wasm_value_t> args);
+ void run_fn(uint8_t* f,
+ size_t num_args,
+ wasm_value_t* args,
+ uint8_t* arg_types,
+ wasm_value_t* r,
+ int r_type);
+ void trap(uint32_t reason);
+
+ uint32_t read_u32leb();
+ int32_t read_i32leb();
+ double read_double();
+ byte read_byte();
+
+ void push_value(wasm_value_t v);
+ wasm_value_t pop_value();
+ void branch(uint32_t to_off);
+
+ void push_frame(wasm_func_t* f);
+ void pop_frame();
+
+ void ensure_memory(uint32_t offset);
+ void ensure_table(uint32_t offset);
+};
+
+#define WASM_TRAP_REASON_NOTRAP 0
+#define WASM_TRAP_REASON_FUNCEND 1
+#define WASM_TRAP_REASON_SIGFPE 2
+#define WASM_TRAP_REASON_OOB 3
+#define WASM_TRAP_REASON_TYPEERR 4
+#define WASM_TRAP_REASON_UNREACHABLE 5
+#define WASM_TRAP_REASON_NULLFUNCREF 6
+#define WASM_TRAP_REASON_NULLEXTERNREF 7
+#define WASM_TRAP_REASON_BADOBJECT 8
+
+#define WASM_INST_TYPE_NOARG 0
+#define WASM_INST_TYPE_BLOCK 1
+#define WASM_INST_TYPE_I32 2
+#define WASM_INST_TYPE_F64 3
+#define WASM_INST_TYPE_MEMARG 4
+#define WASM_INST_TYPE_BRTABLE 5
+#define WASM_INST_TYPE_I32_I32 6
+#define WASM_INST_TYPE_S32 7
+
+struct wasm_jit_t;
+
+struct wasm_inst_desc_t {
+ byte opcode_;
+ byte type_;
+ const char* name_;
+ void (*run)(wasm_instance_t* ins, byte opcode);
+ void (wasm_jit_t::*emit)();
+};
+
+extern const struct wasm_inst_desc_t g_inst_desc[];
+
+struct wasm_rt_func_t {
+ void (*run_)(wasm_instance_t* ins);
+ void* run_jit_;
+};
+extern std::unordered_map<std::string, wasm_rt_func_t> g_runtime_funcs;
+
+#define WASM_EXTERN_NULL 0
+#define WASM_EXTERN_OBJECT 1
+#define WASM_EXTERN_STRING 2
+#define WASM_EXTERN_BOXI32 3
+#define WASM_EXTERN_BOXF64 4
+
+struct wasm_externref_t {
+ uint32_t type_;
+ // make it not move constructible
+ wasm_externref_t(wasm_externref_t&&) = delete;
+ wasm_externref_t(uint32_t type) : type_(type){};
+};
+
+struct wasm_e_string_t : public wasm_externref_t {
+ std::string str_;
+ wasm_e_string_t(const char* str)
+ : wasm_externref_t(WASM_EXTERN_STRING), str_(str) {}
+};
+
+typedef std::pair<uint32_t, uint64_t> wasm_key_t;
+
+struct wasm_e_object_t : public wasm_externref_t {
+ std::map<wasm_key_t, wasm_externref_t*> map_;
+ wasm_e_object_t() : wasm_externref_t(WASM_EXTERN_OBJECT) {}
+};
+
+struct wasm_e_box_t : public wasm_externref_t {
+ union {
+ int32_t i32_;
+ double f64_;
+ };
+ wasm_e_box_t(uint32_t type) : wasm_externref_t(type) {}
+};
+
+extern wasm_instance_t* active_instance;
+extern uint32_t jit;
diff --git a/weerun_dis.cpp b/weerun_dis.cpp
new file mode 100644
index 0000000..0e930aa
--- /dev/null
+++ b/weerun_dis.cpp
@@ -0,0 +1,314 @@
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "weerun.hpp"
+
+template <typename T>
+T decode(buffer_t* buf);
+
+template <typename T>
+std::vector<T> decode_vector(buffer_t* buf) {
+ std::vector<T> result;
+ uint32_t num_elem = read_u32leb(buf);
+ for (uint32_t i = 0; i < num_elem; i++) {
+ result.push_back(decode<T>(buf));
+ }
+ return result;
+}
+
+template <>
+byte decode<byte>(buffer_t* buf) {
+ return read_u8(buf);
+}
+
+template <>
+uint32_t decode<uint32_t>(buffer_t* buf) {
+ return read_u32leb(buf);
+}
+
+template <>
+std::string decode<std::string>(buffer_t* buf) {
+ uint32_t length = read_u32leb(buf);
+ std::string result(buf->ptr, buf->ptr + length);
+ buf->ptr += length;
+ return result;
+}
+
+template <>
+wasm_func_decl_t decode<wasm_func_decl_t>(buffer_t* buf) {
+ read_u8(buf);
+ wasm_func_decl_t result;
+ result.args_ = decode_vector<uint8_t>(buf);
+ result.ret_ = decode_vector<uint8_t>(buf);
+ return result;
+}
+
+template <>
+wasm_table_decl_t decode<wasm_table_decl_t>(buffer_t* buf) {
+ wasm_table_decl_t result;
+ result.type_ = read_u8(buf);
+ result.has_max_ = read_u8(buf);
+ result.init_ = read_u32leb(buf);
+ if (result.has_max_ != 0) {
+ result.max_ = read_u32leb(buf);
+ }
+ return result;
+}
+
+template <>
+wasm_memory_decl_t decode<wasm_memory_decl_t>(buffer_t* buf) {
+ wasm_memory_decl_t result;
+ result.has_max_ = read_u8(buf);
+ result.init_ = read_u32leb(buf);
+ if (result.has_max_ != 0) {
+ result.max_ = read_u32leb(buf);
+ }
+ return result;
+}
+
+template <>
+wasm_global_decl_t decode<wasm_global_decl_t>(buffer_t* buf) {
+ wasm_global_decl_t result;
+ result.type_ = read_u8(buf);
+ result.is_mut_ = read_u8(buf);
+ return result;
+}
+
+template <>
+wasm_import_decl_t decode<wasm_import_decl_t>(buffer_t* buf) {
+ wasm_import_decl_t result;
+ result.module_ = decode<std::string>(buf);
+ result.name_ = decode<std::string>(buf);
+ result.type_ = (wasm_import_decl_t::type)read_u8(buf);
+ switch (result.type_) {
+ case wasm_import_decl_t::type::FUNCTION:
+ result.funcindex_ = read_u32leb(buf);
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
+template <>
+wasm_global_t decode<wasm_global_t>(buffer_t* buf) {
+ wasm_global_t result;
+ result.type_ = decode<wasm_global_decl_t>(buf);
+ uint32_t opcode = read_u8(buf);
+ switch (opcode) {
+ case WASM_OP_I32_CONST:
+ result.val_.i32 = read_i32leb(buf);
+ break;
+ case WASM_OP_F64_CONST:
+ result.val_.f64 = *(double*)buf->ptr;
+ buf->ptr += sizeof(double);
+ break;
+ }
+ opcode = read_u8(buf);
+ return result;
+}
+
+template <>
+wasm_export_t decode<wasm_export_t>(buffer_t* buf) {
+ wasm_export_t result;
+ result.name_ = decode<std::string>(buf);
+ result.type_ = read_u32leb(buf);
+ result.idx_ = read_u32leb(buf);
+ return result;
+}
+
+template <>
+wasm_elem_decl_t decode<wasm_elem_decl_t>(buffer_t* buf) {
+ wasm_elem_decl_t result;
+ uint32_t tmp = read_u32leb(buf);
+ assert(tmp == 0);
+ tmp = read_u8(buf);
+ assert(tmp == WASM_OP_I32_CONST);
+ result.offset_ = read_i32leb(buf);
+ tmp = read_u8(buf);
+ assert(tmp == WASM_OP_END);
+ result.funcidx_ = decode_vector<uint32_t>(buf);
+ return result;
+}
+
+template <>
+wasm_local_decl_t decode<wasm_local_decl_t>(buffer_t* buf) {
+ wasm_local_decl_t result;
+ result.count_ = read_u32leb(buf);
+ result.type_ = read_u8(buf);
+ return result;
+}
+
+wasm_code_decl_t decode_code_decl(buffer_t* buf, wasm_module_t* module) {
+ wasm_code_decl_t result;
+ result.size_ = read_u32leb(buf);
+ result.locals_ = decode_vector<wasm_local_decl_t>(buf);
+ const byte* code_start = buf->ptr;
+
+ int blocks = 1;
+ // a block's enclosing block
+ std::map<const byte*, const byte*> block_parent;
+
+ // a br's target block when br happens
+ std::map<const byte*, const byte*> br_target;
+
+ // when we reach an OP_END, we can record the current block's end/start
+ // address. for OP_BLOCK we record the end address (OP_END+1). for OP_LOOP we
+ // record the start address (OP_LOOP+1). so when a br instruction wants to
+ // jump to this block, we know where to jump
+ std::map<const byte*, const byte*> block_target;
+
+ const byte* cur_block = code_start;
+ block_parent[cur_block] = cur_block;
+ while (blocks != 0) {
+ uint32_t opcode = read_u8(buf);
+ const wasm_inst_desc_t* desc = &g_inst_desc[opcode];
+ switch (desc->type_) {
+ case WASM_INST_TYPE_NOARG:
+ if (opcode == WASM_OP_END) {
+ blocks--;
+ if (blocks == 0) {
+ // reach the OP_END for the function body
+ block_target[cur_block] = buf->ptr - 1;
+ break;
+ }
+ // An OP_END for an OP_BLOCK/OP_LOOP
+ if (*(cur_block - 2) == WASM_OP_BLOCK) {
+ // br a block will go to the end
+ block_target[cur_block] = buf->ptr;
+ } else {
+ // br a loop will go to the beginning (skip OP_LOOP and blocktype)
+ block_target[cur_block] = cur_block;
+ }
+ cur_block = block_parent[cur_block];
+ }
+ break;
+ case WASM_INST_TYPE_I32:
+ if (opcode == WASM_OP_BR || opcode == WASM_OP_BR_IF) {
+ const byte* ptr = buf->ptr;
+ const byte* block = cur_block;
+ uint32_t depth = read_u32leb(buf);
+ while (depth > 0) {
+ block = block_parent[block];
+ depth--;
+ }
+ br_target[ptr] = block;
+ } else {
+ read_u32leb(buf);
+ }
+ break;
+ case WASM_INST_TYPE_S32:
+ read_i32leb(buf);
+ break;
+ case WASM_INST_TYPE_I32_I32:
+ read_u32leb(buf);
+ read_u32leb(buf);
+ break;
+ case WASM_INST_TYPE_F64:
+ buf->ptr += sizeof(double);
+ break;
+ case WASM_INST_TYPE_MEMARG:
+ read_u32leb(buf);
+ read_u32leb(buf);
+ break;
+ case WASM_INST_TYPE_BLOCK:
+ read_u8(buf);
+ if (opcode == WASM_OP_BLOCK || opcode == WASM_OP_LOOP) {
+ blocks++;
+ // link a block to its enclosing block
+ block_parent[buf->ptr] = cur_block;
+ cur_block = buf->ptr;
+ }
+ break;
+ case WASM_INST_TYPE_BRTABLE: {
+ uint32_t num_cases = read_u32leb(buf);
+ // cases and the default case
+ for (uint32_t i = 0; i <= num_cases; i++) {
+ const byte* ptr = buf->ptr;
+ const byte* block = cur_block;
+ // go through the blocks to find the target block
+ uint32_t depth = read_u32leb(buf);
+ while (depth > 0) {
+ block = block_parent[block];
+ depth--;
+ }
+ br_target[ptr] = block;
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+ result.code_ = std::vector<byte>(code_start, buf->ptr);
+ byte* patch_code = result.code_.data();
+ // resolve all brs and rewrite it to offset
+ for (auto br : br_target) {
+ *(uint32_t*)(patch_code + (br.first - code_start)) =
+ (uint32_t)(block_target[br.second] - code_start);
+ }
+ return result;
+}
+
+wasm_code_decl_t decode_code_decl_jit(buffer_t* buf, wasm_module_t* module) {
+ wasm_code_decl_t result;
+ result.size_ = read_u32leb(buf);
+ const byte* code_end = buf->ptr + result.size_;
+ result.locals_ = decode_vector<wasm_local_decl_t>(buf);
+ result.code_ = std::vector<byte>(buf->ptr, code_end);
+ buf->ptr = code_end;
+ return result;
+}
+
+// turns out that decoding code section needs the module context
+std::vector<wasm_code_decl_t> decode_vector_code_decl(buffer_t* buf,
+ wasm_module_t* module) {
+ std::vector<wasm_code_decl_t> result;
+ uint32_t num_elem = read_u32leb(buf);
+ for (uint32_t i = 0; i < num_elem; i++) {
+ if (jit != 0) {
+ result.push_back(decode_code_decl_jit(buf, module));
+ } else {
+ result.push_back(decode_code_decl(buf, module));
+ }
+ }
+ return result;
+}
+
+template <>
+wasm_data_decl_t decode<wasm_data_decl_t>(buffer_t* buf) {
+ wasm_data_decl_t result;
+ read_u32leb(buf);
+ read_u8(buf);
+ result.offset_ = read_i32leb(buf);
+ read_u8(buf);
+ result.data_ = decode_vector<byte>(buf);
+ return result;
+}
+
+template std::vector<wasm_func_decl_t> decode_vector<wasm_func_decl_t>(
+ buffer_t* buffer);
+template std::vector<wasm_import_decl_t> decode_vector<wasm_import_decl_t>(
+ buffer_t* buffer);
+template std::vector<wasm_table_decl_t> decode_vector<wasm_table_decl_t>(
+ buffer_t* buffer);
+template std::vector<wasm_memory_decl_t> decode_vector<wasm_memory_decl_t>(
+ buffer_t* buffer);
+template std::vector<wasm_global_t> decode_vector<wasm_global_t>(
+ buffer_t* buffer);
+template std::vector<wasm_export_t> decode_vector<wasm_export_t>(
+ buffer_t* buffer);
+template std::vector<wasm_elem_decl_t> decode_vector<wasm_elem_decl_t>(
+ buffer_t* buffer);
+template std::vector<wasm_data_decl_t> decode_vector<wasm_data_decl_t>(
+ buffer_t* buffer);
+template std::vector<uint32_t> decode_vector<uint32_t>(buffer_t* buffer);
diff --git a/weerun_inst.cpp b/weerun_inst.cpp
new file mode 100644
index 0000000..f05997b
--- /dev/null
+++ b/weerun_inst.cpp
@@ -0,0 +1,978 @@
+#include <cmath>
+#include <iostream>
+
+#include "weerun.hpp"
+#include "weerun_jit.hpp"
+
+#define INVALID_INST \
+ { 0, 0, "illegal", nullptr, nullptr }
+
+static void run_unreachable(wasm_instance_t* ins, byte opcode);
+static void run_nop(wasm_instance_t* ins, byte opcode);
+static void run_drop(wasm_instance_t* ins, byte opcode);
+static void run_select(wasm_instance_t* ins, byte opcode);
+static void run_local_get(wasm_instance_t* ins, byte opcode);
+static void run_local_set(wasm_instance_t* ins, byte opcode);
+static void run_local_tee(wasm_instance_t* ins, byte opcode);
+static void run_global_get(wasm_instance_t* ins, byte opcode);
+static void run_global_set(wasm_instance_t* ins, byte opcode);
+
+#if 0
+static void run_tabel_get(wasm_instance_t* ins, byte opcode);
+static void run_tabel_set(wasm_instance_t* ins, byte opcode);
+#endif
+
+static void run_i32_load(wasm_instance_t* ins, byte opcode);
+static void run_f64_load(wasm_instance_t* ins, byte opcode);
+static void run_i32_load8_u(wasm_instance_t* ins, byte opcode);
+static void run_i32_load8_s(wasm_instance_t* ins, byte opcode);
+static void run_i32_load16_u(wasm_instance_t* ins, byte opcode);
+static void run_i32_load16_s(wasm_instance_t* ins, byte opcode);
+static void run_i32_store(wasm_instance_t* ins, byte opcode);
+static void run_f64_store(wasm_instance_t* ins, byte opcode);
+static void run_i32_store8(wasm_instance_t* ins, byte opcode);
+static void run_i32_store16(wasm_instance_t* ins, byte opcode);
+static void run_i32_const(wasm_instance_t* ins, byte opcode);
+static void run_f64_const(wasm_instance_t* ins, byte opcode);
+static void run_i32_numeric(wasm_instance_t* ins, byte opcode);
+static void run_f64_compare(wasm_instance_t* ins, byte opcode);
+static void run_f64_compute(wasm_instance_t* ins, byte opcode);
+static void run_f64_convert(wasm_instance_t* ins, byte opcode);
+static void run_call(wasm_instance_t* ins, byte opcode);
+static void run_call_indirect(wasm_instance_t* ins, byte opcode);
+static void run_return(wasm_instance_t* ins, byte opcode);
+static void run_block(wasm_instance_t* ins, byte opcode);
+static void run_end(wasm_instance_t* ins, byte opcode);
+static void run_br(wasm_instance_t* ins, byte opcode);
+static void run_br_table(wasm_instance_t* ins, byte opcode);
+
+const struct wasm_inst_desc_t g_inst_desc[] = {
+ {WASM_OP_UNREACHABLE, WASM_INST_TYPE_NOARG, "unreachable", run_unreachable,
+ &wasm_jit_t::emit_unreachable},
+ {WASM_OP_NOP, WASM_INST_TYPE_NOARG, "nop", run_nop, &wasm_jit_t::emit_nop},
+ {WASM_OP_BLOCK, WASM_INST_TYPE_BLOCK, "block", run_block,
+ &wasm_jit_t::emit_block},
+ {WASM_OP_LOOP, WASM_INST_TYPE_BLOCK, "loop", run_block,
+ &wasm_jit_t::emit_block},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_END, WASM_INST_TYPE_NOARG, "end", run_end, &wasm_jit_t::emit_end},
+ {WASM_OP_BR, WASM_INST_TYPE_I32, "br", run_br, &wasm_jit_t::emit_br},
+ {WASM_OP_BR_IF, WASM_INST_TYPE_I32, "br_if", run_br,
+ &wasm_jit_t::emit_br_if},
+ {WASM_OP_BR_TABLE, WASM_INST_TYPE_BRTABLE, "br_tale", run_br_table,
+ &wasm_jit_t::emit_br_table},
+ {WASM_OP_RETURN, WASM_INST_TYPE_NOARG, "return", run_return,
+ &wasm_jit_t::emit_return},
+ {WASM_OP_CALL, WASM_INST_TYPE_I32, "call", run_call,
+ &wasm_jit_t::emit_call},
+ {WASM_OP_CALL_INDIRECT, WASM_INST_TYPE_I32_I32, "call_indirect",
+ run_call_indirect, &wasm_jit_t::emit_call_indirect},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_DROP, WASM_INST_TYPE_NOARG, "drop", run_drop,
+ &wasm_jit_t::emit_drop},
+ {WASM_OP_SELECT, WASM_INST_TYPE_NOARG, "select", run_select,
+ &wasm_jit_t::emit_select},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_LOCAL_GET, WASM_INST_TYPE_I32, "local.get", run_local_get,
+ &wasm_jit_t::emit_local_get},
+ {WASM_OP_LOCAL_SET, WASM_INST_TYPE_I32, "local.set", run_local_set,
+ &wasm_jit_t::emit_local_set},
+ {WASM_OP_LOCAL_TEE, WASM_INST_TYPE_I32, "local.tee", run_local_tee,
+ &wasm_jit_t::emit_local_tee},
+ {WASM_OP_GLOBAL_GET, WASM_INST_TYPE_I32, "global.get", run_global_get,
+ &wasm_jit_t::emit_global_get},
+ {WASM_OP_GLOBAL_SET, WASM_INST_TYPE_I32, "global.set", run_global_set,
+ &wasm_jit_t::emit_global_set},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_I32_LOAD, WASM_INST_TYPE_MEMARG, "i32.load", run_i32_load,
+ &wasm_jit_t::emit_i32_load},
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_F64_LOAD, WASM_INST_TYPE_MEMARG, "f64.load", run_f64_load,
+ &wasm_jit_t::emit_f64_load},
+ {WASM_OP_I32_LOAD8_S, WASM_INST_TYPE_MEMARG, "i32.load8_s", run_i32_load8_s,
+ &wasm_jit_t::emit_i32_load},
+ {WASM_OP_I32_LOAD8_U, WASM_INST_TYPE_MEMARG, "i32.load8_u", run_i32_load8_u,
+ &wasm_jit_t::emit_i32_load},
+ {WASM_OP_I32_LOAD16_S, WASM_INST_TYPE_MEMARG, "i32.load16_s",
+ run_i32_load16_s, &wasm_jit_t::emit_i32_load},
+ {WASM_OP_I32_LOAD16_U, WASM_INST_TYPE_MEMARG, "i32.load16_u",
+ run_i32_load16_u, &wasm_jit_t::emit_i32_load},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_I32_STORE, WASM_INST_TYPE_MEMARG, "i32.store", run_i32_store,
+ &wasm_jit_t::emit_i32_store},
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_F64_STORE, WASM_INST_TYPE_MEMARG, "f64.store", run_f64_store,
+ &wasm_jit_t::emit_f64_store},
+ {WASM_OP_I32_STORE8, WASM_INST_TYPE_MEMARG, "i32.store8", run_i32_store8,
+ &wasm_jit_t::emit_i32_store},
+ {WASM_OP_I32_STORE16, WASM_INST_TYPE_MEMARG, "i32.store16", run_i32_store16,
+ &wasm_jit_t::emit_i32_store},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_I32_CONST, WASM_INST_TYPE_S32, "i32.const", run_i32_const,
+ &wasm_jit_t::emit_i32_const},
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_F64_CONST, WASM_INST_TYPE_F64, "f64.const", run_f64_const,
+ &wasm_jit_t::emit_f64_const},
+ {WASM_OP_I32_EQZ, WASM_INST_TYPE_NOARG, "i32.eqz", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_EQ, WASM_INST_TYPE_NOARG, "i32.eq", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_NE, WASM_INST_TYPE_NOARG, "i32.ne", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_LT_S, WASM_INST_TYPE_NOARG, "i32.lt_s", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_LT_U, WASM_INST_TYPE_NOARG, "i32.lt_u", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_GT_S, WASM_INST_TYPE_NOARG, "i32.gt_s", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_GT_U, WASM_INST_TYPE_NOARG, "i32.gt_u", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_LE_S, WASM_INST_TYPE_NOARG, "i32.le_s", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_LE_U, WASM_INST_TYPE_NOARG, "i32.le_u", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_GE_S, WASM_INST_TYPE_NOARG, "i32.ge_s", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_GE_U, WASM_INST_TYPE_NOARG, "i32.ge_u", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_F64_EQ, WASM_INST_TYPE_NOARG, "f64.eq", run_f64_compare,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_NE, WASM_INST_TYPE_NOARG, "f64.ne", run_f64_compare,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_LT, WASM_INST_TYPE_NOARG, "f64.lt", run_f64_compare,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_GT, WASM_INST_TYPE_NOARG, "f64.gt", run_f64_compare,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_LE, WASM_INST_TYPE_NOARG, "f64.le", run_f64_compare,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_GE, WASM_INST_TYPE_NOARG, "f64.ge", run_f64_compare,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_I32_CLZ, WASM_INST_TYPE_NOARG, "i32.clz", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_CTZ, WASM_INST_TYPE_NOARG, "i32.ctz", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_POPCNT, WASM_INST_TYPE_NOARG, "i32.popcnt", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_ADD, WASM_INST_TYPE_NOARG, "i32.add", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_SUB, WASM_INST_TYPE_NOARG, "i32.sub", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_MUL, WASM_INST_TYPE_NOARG, "i32.mul", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_DIV_S, WASM_INST_TYPE_NOARG, "i32.div_s", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_DIV_U, WASM_INST_TYPE_NOARG, "i32.div_u", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_REM_S, WASM_INST_TYPE_NOARG, "i32.rem_s", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_REM_U, WASM_INST_TYPE_NOARG, "i32.rem_u", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_AND, WASM_INST_TYPE_NOARG, "i32.and", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_OR, WASM_INST_TYPE_NOARG, "i32.or", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_XOR, WASM_INST_TYPE_NOARG, "i32.xor", run_i32_numeric,
+ &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_SHL, WASM_INST_TYPE_NOARG, "i32.shl", run_i32_numeric,
+ &wasm_jit_t::emit_i32_shift},
+ {WASM_OP_I32_SHR_S, WASM_INST_TYPE_NOARG, "i32.shr_s", run_i32_numeric,
+ &wasm_jit_t::emit_i32_shift},
+ {WASM_OP_I32_SHR_U, WASM_INST_TYPE_NOARG, "i32.shr_u", run_i32_numeric,
+ &wasm_jit_t::emit_i32_shift},
+ {WASM_OP_I32_ROTL, WASM_INST_TYPE_NOARG, "i32.rotl", run_i32_numeric,
+ &wasm_jit_t::emit_i32_shift},
+ {WASM_OP_I32_ROTR, WASM_INST_TYPE_NOARG, "i32.rotr", run_i32_numeric,
+ &wasm_jit_t::emit_i32_shift},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_F64_ADD, WASM_INST_TYPE_NOARG, "f64.add", run_f64_compute,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_SUB, WASM_INST_TYPE_NOARG, "f64.sub", run_f64_compute,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_MUL, WASM_INST_TYPE_NOARG, "f64.mul", run_f64_compute,
+ &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_DIV, WASM_INST_TYPE_NOARG, "f64.div", run_f64_compute,
+ &wasm_jit_t::emit_f64_compute},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_I32_TRUNC_F64_S, WASM_INST_TYPE_NOARG, "i32.trunc_f64_s",
+ run_i32_numeric, &wasm_jit_t::emit_i32_convert},
+ {WASM_OP_I32_TRUNC_F64_U, WASM_INST_TYPE_NOARG, "i32.trunc_f64_u",
+ run_i32_numeric, &wasm_jit_t::emit_i32_convert},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_F64_CONVERT_I32_S, WASM_INST_TYPE_NOARG, "f64.convert_i32_s",
+ run_f64_convert, &wasm_jit_t::emit_f64_compute},
+ {WASM_OP_F64_CONVERT_I32_U, WASM_INST_TYPE_NOARG, "f64.convert_i32_u",
+ run_f64_convert, &wasm_jit_t::emit_f64_compute},
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ INVALID_INST,
+ {WASM_OP_I32_EXTEND8_S, WASM_INST_TYPE_NOARG, "i32.extend8_s",
+ run_i32_numeric, &wasm_jit_t::emit_i32_numeric},
+ {WASM_OP_I32_EXTEND16_S, WASM_INST_TYPE_NOARG, "i32.extend16_s",
+ run_i32_numeric, &wasm_jit_t::emit_i32_numeric},
+};
+
+static bool is_zero(wasm_value_t v, uint8_t type) {
+ switch (type) {
+ case WASM_TYPE_I32:
+ return v.val.i32 == 0;
+ case WASM_TYPE_F64:
+ return v.val.f64 == 0;
+ default:
+ break;
+ }
+ return v.val.ref == nullptr;
+}
+
+// fancy ops
+static inline uint32_t i32_clz(uint32_t x) {
+ uint32_t zeros = 0;
+ for (int i = 31; i >= 0; i--) {
+ if ((x & (1 << i)) == 0) {
+ zeros++;
+ } else {
+ break;
+ }
+ }
+ return zeros;
+}
+
+static inline uint32_t i32_ctz(uint32_t x) {
+ uint32_t zeros = 0;
+ for (int i = 0; i < 32; i++) {
+ if ((x & (1 << i)) == 0) {
+ zeros++;
+ } else {
+ break;
+ }
+ }
+ return zeros;
+}
+
+static inline uint32_t i32_popcnt(uint32_t x) {
+ uint32_t ones = 0;
+ for (int i = 31; i >= 0; i--) {
+ if ((x & (1 << i)) != 0) {
+ ones++;
+ }
+ }
+ return ones;
+}
+
+static inline uint32_t i32_rotl(uint32_t x, uint32_t n) {
+ return (x << n) | (x >> (32 - n));
+}
+
+static inline uint32_t i32_rotr(uint32_t x, uint32_t n) {
+ return (x >> n) | (x << (32 - n));
+}
+
+static inline std::pair<bool, int32_t> i32_div_s(int32_t a, int32_t b) {
+ if (b == 0) {
+ return {false, 0};
+ }
+ if (a == (int32_t)0x80000000 && b == (int32_t)0xffffffff) {
+ return {false, 0};
+ }
+ return {true, a / b};
+}
+
+static inline std::pair<bool, int32_t> i32_rem_s(int32_t a, int32_t b) {
+ if (b == 0) {
+ return {false, 0};
+ }
+ if (a == (int32_t)0x80000000 && b == (int32_t)0xffffffff) {
+ return {true, 0};
+ }
+ return {true, a % b};
+}
+
+static inline std::pair<bool, uint32_t> i32_div_u(uint32_t a, uint32_t b) {
+ if (b == 0) {
+ return {false, 0};
+ }
+ return {true, a / b};
+}
+
+static inline std::pair<bool, uint32_t> i32_rem_u(uint32_t a, uint32_t b) {
+ if (b == 0) {
+ return {false, 0};
+ }
+ return {true, a % b};
+}
+
+static inline std::pair<bool, int32_t> i32_trunc_f64_s(double x) {
+ int type = std::fpclassify(x);
+ if (type == FP_NAN || type == FP_INFINITE) {
+ return {false, 0};
+ }
+ if (x <= -2147483649.0 || x >= 2147483648.0) {
+ return {false, 0};
+ }
+ return {true, x};
+}
+
+static inline std::pair<bool, uint32_t> i32_trunc_f64_u(double x) {
+ int type = std::fpclassify(x);
+ if (type == FP_NAN || type == FP_INFINITE) {
+ return {false, 0};
+ }
+ if (x <= -1.0 || x >= 4294967296.0) {
+ return {false, 0};
+ }
+ return {true, x};
+}
+
+template <typename T>
+static inline bool check_access(wasm_instance_t* ins,
+ uint32_t offset,
+ uint32_t addend) {
+ uint32_t size = ins->memory_.size();
+ return offset <= size && addend <= size &&
+ offset + addend + sizeof(T) <= size;
+}
+
+static void run_unreachable(wasm_instance_t* ins, byte opcode) {
+ ins->trap(WASM_OP_UNREACHABLE);
+}
+
+static void run_nop(wasm_instance_t* ins, byte opcode) {}
+
+static void run_drop(wasm_instance_t* ins, byte opcode) {
+ ins->pop_value();
+}
+
+static void run_select(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t c = ins->pop_value();
+ wasm_value_t b = ins->pop_value();
+ wasm_value_t a = ins->pop_value();
+ if (is_zero(c, WASM_TYPE_I32) == false) {
+ ins->push_value(a);
+ } else {
+ ins->push_value(b);
+ }
+}
+
+static void run_local_get(wasm_instance_t* ins, byte opcode) {
+ uint32_t idx = ins->read_u32leb();
+ ins->push_value(ins->cur_frame_->locals_[idx]);
+}
+
+static void run_local_set(wasm_instance_t* ins, byte opcode) {
+ uint32_t idx = ins->read_u32leb();
+ ins->cur_frame_->locals_[idx] = ins->pop_value();
+}
+
+static void run_local_tee(wasm_instance_t* ins, byte opcode) {
+ uint32_t idx = ins->read_u32leb();
+ wasm_value_t v = ins->value_stack_.back();
+ ins->cur_frame_->locals_[idx] = v;
+}
+
+static void run_global_get(wasm_instance_t* ins, byte opcode) {
+ uint32_t idx = ins->read_u32leb();
+ ins->push_value(ins->globals_[idx]);
+}
+
+static void run_global_set(wasm_instance_t* ins, byte opcode) {
+ uint32_t idx = ins->read_u32leb();
+ ins->globals_[idx] = ins->pop_value();
+}
+
+#if 0
+static void run_tabel_get(wasm_instance_t* ins, byte opcode) {
+ uint32_t idx = ins->read_u32leb();
+ wasm_value_t v;
+ v.val.ref = (void*)ins->table_[idx];
+ ins->push_value(v);
+}
+
+static void run_tabel_set(wasm_instance_t* ins, byte opcode) {
+ uint32_t idx = ins->read_u32leb();
+ ins->table_[idx] = (wasm_func_t*)ins->pop_value().val.ref;
+}
+#endif
+
+static void run_i32_load(wasm_instance_t* ins, byte opcode) {
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<uint32_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ wasm_value_t v;
+ v.val.i32 = *(uint32_t*)(base + (offset + addend));
+ ins->push_value(v);
+}
+
+static void run_f64_load(wasm_instance_t* ins, byte opcode) {
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<double>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ wasm_value_t v;
+ v.val.f64 = *(double*)(base + (offset + addend));
+ ins->push_value(v);
+}
+
+static void run_i32_load8_u(wasm_instance_t* ins, byte opcode) {
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<uint8_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ uint8_t u8 = *(uint8_t*)(base + (offset + addend));
+ wasm_value_t v;
+ v.val.i32 = (uint32_t)u8;
+ ins->push_value(v);
+}
+
+static void run_i32_load8_s(wasm_instance_t* ins, byte opcode) {
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<int8_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ int8_t i8 = *(int8_t*)(base + (offset + addend));
+ wasm_value_t v;
+ v.val.i32 = (uint32_t)(int32_t)i8;
+ ins->push_value(v);
+}
+
+static void run_i32_load16_u(wasm_instance_t* ins, byte opcode) {
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<uint16_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ uint16_t u16 = *(uint16_t*)(base + (offset + addend));
+ wasm_value_t v;
+ v.val.i32 = (uint32_t)u16;
+ ins->push_value(v);
+}
+
+static void run_i32_load16_s(wasm_instance_t* ins, byte opcode) {
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<int16_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ int16_t i16 = *(int16_t*)(base + (offset + addend));
+ wasm_value_t v;
+ v.val.i32 = (uint32_t)(int32_t)i16;
+ ins->push_value(v);
+}
+
+static void run_i32_store(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t v = ins->pop_value();
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<uint32_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ *(uint32_t*)(base + (offset + addend)) = v.val.i32;
+}
+
+static void run_f64_store(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t v = ins->pop_value();
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<double>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ *(double*)(base + (offset + addend)) = v.val.f64;
+}
+
+static void run_i32_store8(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t v = ins->pop_value();
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<uint8_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ *(uint8_t*)(base + (offset + addend)) = (uint8_t)v.val.i32;
+}
+
+static void run_i32_store16(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t v = ins->pop_value();
+ uint32_t addend = ins->pop_value().val.i32;
+ ins->read_u32leb();
+ uint32_t offset = ins->read_u32leb();
+ if (check_access<uint16_t>(ins, offset, addend) == false) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ byte* base = ins->memory_.data();
+ *(uint16_t*)(base + (offset + addend)) = (uint16_t)v.val.i32;
+}
+
+static void run_i32_const(wasm_instance_t* ins, byte opcode) {
+ uint32_t x = ins->read_i32leb();
+ wasm_value_t v;
+ v.val.i32 = x;
+ ins->push_value(v);
+}
+
+static void run_f64_const(wasm_instance_t* ins, byte opcode) {
+ double x = ins->read_double();
+ wasm_value_t v;
+ v.val.f64 = x;
+ ins->push_value(v);
+}
+
+static void run_i32_numeric(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t a;
+ wasm_value_t b;
+ wasm_value_t result;
+
+ b = ins->pop_value();
+ switch (opcode) {
+ case WASM_OP_I32_EQZ:
+ result.val.i32 = (b.val.i32 == 0);
+ break;
+ case WASM_OP_I32_EQ:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 == b.val.i32);
+ break;
+ case WASM_OP_I32_NE:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 != b.val.i32);
+ break;
+ case WASM_OP_I32_LT_S:
+ a = ins->pop_value();
+ result.val.i32 = ((int32_t)a.val.i32 < (int32_t)b.val.i32);
+ break;
+ case WASM_OP_I32_LT_U:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 < b.val.i32);
+ break;
+ case WASM_OP_I32_GT_S:
+ a = ins->pop_value();
+ result.val.i32 = ((int32_t)a.val.i32 > (int32_t)b.val.i32);
+ break;
+ case WASM_OP_I32_GT_U:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 > b.val.i32);
+ break;
+ case WASM_OP_I32_LE_S:
+ a = ins->pop_value();
+ result.val.i32 = ((int32_t)a.val.i32 <= (int32_t)b.val.i32);
+ break;
+ case WASM_OP_I32_LE_U:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 <= b.val.i32);
+ break;
+ case WASM_OP_I32_GE_S:
+ a = ins->pop_value();
+ result.val.i32 = ((int32_t)a.val.i32 >= (int32_t)b.val.i32);
+ break;
+ case WASM_OP_I32_GE_U:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 >= b.val.i32);
+ break;
+ case WASM_OP_I32_CLZ:
+ result.val.i32 = i32_clz(b.val.i32);
+ break;
+ case WASM_OP_I32_CTZ:
+ result.val.i32 = i32_ctz(b.val.i32);
+ break;
+ case WASM_OP_I32_POPCNT:
+ result.val.i32 = i32_popcnt(b.val.i32);
+ break;
+ case WASM_OP_I32_ADD:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 + b.val.i32);
+ break;
+ case WASM_OP_I32_SUB:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 - b.val.i32);
+ break;
+ case WASM_OP_I32_MUL:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 * b.val.i32);
+ break;
+ case WASM_OP_I32_DIV_S: {
+ a = ins->pop_value();
+ auto r = i32_div_s((int32_t)a.val.i32, (int32_t)b.val.i32);
+ if (r.first == false) {
+ ins->trap(WASM_TRAP_REASON_SIGFPE);
+ return;
+ }
+ result.val.i32 = r.second;
+ break;
+ }
+ case WASM_OP_I32_DIV_U: {
+ a = ins->pop_value();
+ auto r = i32_div_u((int32_t)a.val.i32, (int32_t)b.val.i32);
+ if (r.first == false) {
+ ins->trap(WASM_TRAP_REASON_SIGFPE);
+ return;
+ }
+ result.val.i32 = r.second;
+ break;
+ }
+ case WASM_OP_I32_REM_S: {
+ a = ins->pop_value();
+ auto r = i32_rem_s((int32_t)a.val.i32, (int32_t)b.val.i32);
+ if (r.first == false) {
+ ins->trap(WASM_TRAP_REASON_SIGFPE);
+ return;
+ }
+ result.val.i32 = r.second;
+ break;
+ }
+ case WASM_OP_I32_REM_U: {
+ a = ins->pop_value();
+ auto r = i32_rem_u((int32_t)a.val.i32, (int32_t)b.val.i32);
+ if (r.first == false) {
+ ins->trap(WASM_TRAP_REASON_SIGFPE);
+ return;
+ }
+ result.val.i32 = r.second;
+ break;
+ }
+ case WASM_OP_I32_AND:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 & b.val.i32);
+ break;
+ case WASM_OP_I32_OR:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 | b.val.i32);
+ break;
+ case WASM_OP_I32_XOR:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 ^ b.val.i32);
+ break;
+ case WASM_OP_I32_SHL:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 << b.val.i32);
+ break;
+ case WASM_OP_I32_SHR_S:
+ a = ins->pop_value();
+ result.val.i32 = ((int32_t)a.val.i32 >> b.val.i32);
+ break;
+ case WASM_OP_I32_SHR_U:
+ a = ins->pop_value();
+ result.val.i32 = (a.val.i32 >> b.val.i32);
+ break;
+ case WASM_OP_I32_ROTL:
+ a = ins->pop_value();
+ result.val.i32 = i32_rotl(a.val.i32, b.val.i32);
+ break;
+ case WASM_OP_I32_ROTR:
+ a = ins->pop_value();
+ result.val.i32 = i32_rotr(a.val.i32, b.val.i32);
+ break;
+ case WASM_OP_I32_TRUNC_F64_S: {
+ auto r = i32_trunc_f64_s(b.val.f64);
+ if (r.first == false) {
+ ins->trap(WASM_TRAP_REASON_SIGFPE);
+ return;
+ }
+ result.val.i32 = r.second;
+ break;
+ }
+ case WASM_OP_I32_TRUNC_F64_U: {
+ auto r = i32_trunc_f64_u(b.val.f64);
+ if (r.first == false) {
+ ins->trap(WASM_TRAP_REASON_SIGFPE);
+ return;
+ }
+ result.val.i32 = r.second;
+ break;
+ }
+ case WASM_OP_I32_EXTEND8_S:
+ result.val.i32 = (int32_t)(int8_t)b.val.i32;
+ break;
+ case WASM_OP_I32_EXTEND16_S:
+ result.val.i32 = (int32_t)(int16_t)b.val.i32;
+ break;
+ }
+ ins->push_value(result);
+}
+
+static void run_f64_compare(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t a;
+ wasm_value_t b;
+ wasm_value_t result;
+
+ b = ins->pop_value();
+ a = ins->pop_value();
+ switch (opcode) {
+ case WASM_OP_F64_LT:
+ result.val.i32 = (a.val.f64 < b.val.f64);
+ break;
+ case WASM_OP_F64_GT:
+ result.val.i32 = (a.val.f64 > b.val.f64);
+ break;
+ case WASM_OP_F64_LE:
+ result.val.i32 = (a.val.f64 <= b.val.f64);
+ break;
+ case WASM_OP_F64_GE:
+ result.val.i32 = (a.val.f64 >= b.val.f64);
+ break;
+ case WASM_OP_F64_EQ:
+ result.val.i32 = (a.val.f64 == b.val.f64);
+ break;
+ case WASM_OP_F64_NE:
+ result.val.i32 = (a.val.f64 != b.val.f64);
+ break;
+ }
+ ins->push_value(result);
+}
+
+static void run_f64_compute(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t a;
+ wasm_value_t b;
+ wasm_value_t result;
+
+ b = ins->pop_value();
+ a = ins->pop_value();
+ switch (opcode) {
+ case WASM_OP_F64_ADD:
+ result.val.f64 = (a.val.f64 + b.val.f64);
+ break;
+ case WASM_OP_F64_SUB:
+ result.val.f64 = (a.val.f64 - b.val.f64);
+ break;
+ case WASM_OP_F64_MUL:
+ result.val.f64 = (a.val.f64 * b.val.f64);
+ break;
+ case WASM_OP_F64_DIV:
+ result.val.f64 = (a.val.f64 / b.val.f64);
+ break;
+ }
+ ins->push_value(result);
+}
+
+static void run_f64_convert(wasm_instance_t* ins, byte opcode) {
+ wasm_value_t b;
+ wasm_value_t result;
+
+ b = ins->pop_value();
+ switch (opcode) {
+ case WASM_OP_F64_CONVERT_I32_S:
+ result.val.f64 = (int32_t)b.val.i32;
+ break;
+ case WASM_OP_F64_CONVERT_I32_U:
+ result.val.f64 = b.val.i32;
+ break;
+ }
+ ins->push_value(result);
+}
+
+static void run_call(wasm_instance_t* ins, byte opcode) {
+ uint32_t funcidx = ins->read_u32leb();
+ ins->push_frame(&ins->module_->funcs_[funcidx]);
+}
+
+bool is_same_type(wasm_func_decl_t* s, wasm_func_decl_t* t) {
+ if (s->args_.size() != t->args_.size()) {
+ return false;
+ }
+ if (memcmp(s->args_.data(), t->args_.data(), s->args_.size()) != 0) {
+ return false;
+ }
+ if (s->ret_.size() != t->ret_.size()) {
+ return false;
+ }
+ if (memcmp(s->ret_.data(), t->ret_.data(), s->ret_.size()) != 0) {
+ return false;
+ }
+ return true;
+}
+
+static void run_call_indirect(wasm_instance_t* ins, byte opcode) {
+ ins->read_u32leb();
+ uint32_t typeidx = ins->read_u32leb();
+ wasm_value_t v = ins->pop_value();
+ if (v.val.i32 >= ins->table_.size() ||
+ typeidx >= ins->module_->sigs_.size()) {
+ ins->trap(WASM_TRAP_REASON_OOB);
+ return;
+ }
+ wasm_func_t* f = ins->table_[v.val.i32];
+ if (f == nullptr) {
+ ins->trap(WASM_TRAP_REASON_NULLFUNCREF);
+ return;
+ }
+ if (is_same_type(&ins->module_->sigs_[typeidx], f->sig_) == false) {
+ ins->trap(WASM_TRAP_REASON_TYPEERR);
+ return;
+ }
+ ins->push_frame(ins->table_[v.val.i32]);
+}
+
+static void run_return(wasm_instance_t* ins, byte opcode) {
+ ins->pop_frame();
+ if (ins->frames_.empty()) {
+ ins->trap(WASM_TRAP_REASON_FUNCEND);
+ }
+}
+
+static void run_block(wasm_instance_t* ins, byte opcode) {
+ // read the blocktype byte and go
+ ins->read_byte();
+}
+
+static void run_end(wasm_instance_t* ins, byte opcode) {
+ // only the OP_END for the outermost function matters
+ if (ins->cur_frame_->pc_.ptr == ins->cur_frame_->pc_.end) {
+ ins->pop_frame();
+ if (ins->frames_.empty()) {
+ ins->trap(WASM_TRAP_REASON_FUNCEND);
+ }
+ }
+}
+
+static void run_br(wasm_instance_t* ins, byte opcode) {
+ if (opcode == WASM_OP_BR_IF) {
+ wasm_value_t v = ins->pop_value();
+ if (is_zero(v, WASM_TYPE_I32) == true) {
+ ins->cur_frame_->pc_.ptr += sizeof(uint32_t);
+ return;
+ }
+ }
+ uint32_t to_off = *(uint32_t*)(ins->cur_frame_->pc_.ptr);
+ ins->branch(to_off);
+}
+
+static void run_br_table(wasm_instance_t* ins, byte opcode) {
+ uint32_t num_cases = ins->read_u32leb();
+ uint32_t* cases = (uint32_t*)(ins->cur_frame_->pc_.ptr);
+ wasm_value_t v = ins->pop_value();
+ uint32_t to_off;
+ uint32_t index = std::min(v.val.i32, num_cases);
+ to_off = cases[index];
+ ins->branch(to_off);
+}
diff --git a/weerun_jit.cpp b/weerun_jit.cpp
new file mode 100644
index 0000000..ece5b4f
--- /dev/null
+++ b/weerun_jit.cpp
@@ -0,0 +1,1726 @@
+#include <array>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "weerun_jit.hpp"
+
+#define JIT_V(type, i) \
+ (wasm_jit_val_t) { wasm_jit_type_t::type, (i) }
+
+#define JIT_V_INVALID JIT_V(INVALID, 0)
+#define JIT_V_CALLER JIT_V(CALLER_DATA, 0)
+#define JIT_V_INTER JIT_V(INTERMEDIATE, 0)
+#define JIT_V_LOCAL(i) JIT_V(LOCAL_VAL, (int32_t)(i))
+#define JIT_V_STACK(i) JIT_V(STACK_VAL, (int32_t)(i))
+#define JIT_V_GLOBAL_BASE JIT_V(GLOBAL_BASE, 0)
+#define JIT_V_MEMORY_BASE JIT_V(MEMORY_BASE, 0)
+#define JIT_V_MEMORY_SIZE JIT_V(MEMORY_SIZE, 0)
+
+const static int32_t sysv_args[] = {reg::rdi, reg::rsi, reg::rdx,
+ reg::rcx, reg::r8, reg::r9};
+
+inline Xbyak::Reg64 wasm_jit_t::to_xbyak_r64(int32_t index) {
+ const static Xbyak::Reg64 xbyak_regs[] = {rax, rdx, rcx, rdi, rsi, r8, r9,
+ r10, r11, rbx, r12, r13, r14, r15};
+ return xbyak_regs[index];
+}
+
+inline Xbyak::Reg32 wasm_jit_t::to_xbyak_r32(int32_t index) {
+ const static Xbyak::Reg32 xbyak_regs[] = {eax, edx, ecx, edi, esi,
+ r8d, r9d, r10d, r11d, ebx,
+ r12d, r13d, r14d, r15d};
+ return xbyak_regs[index];
+}
+
+inline Xbyak::Reg16 wasm_jit_t::to_xbyak_r16(int32_t index) {
+ const static Xbyak::Reg16 xbyak_regs[] = {
+ ax, dx, cx, di, si, r8w, r9w, r10w, r11w, bx, r12w, r13w, r14w, r15w};
+ return xbyak_regs[index];
+}
+
+inline Xbyak::Reg8 wasm_jit_t::to_xbyak_r8(int32_t index) {
+ const static Xbyak::Reg8 xbyak_regs[] = {
+ al, dl, cl, dil, sil, r8b, r9b, r10b, r11b, bl, r12b, r13b, r14b, r15b};
+ return xbyak_regs[index];
+}
+
+inline Xbyak::Xmm wasm_jit_t::to_xbyak_xmm(int32_t index) {
+ const static Xbyak::Xmm xbyak_regs[] = {
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15};
+ return xbyak_regs[index - reg::xmm0];
+}
+
+// stack layout:
+// return address (-1)
+// RBP --> saved rbp (0)
+// space for rbx,r12-r15 (1, +5)
+// locals (6, +num_locals)
+// wasm stack (6+num_locals, +max_stack)
+// RSP -->
+
+// function layout
+// F1:
+// prologue (changed from nop after jitting body)
+// body (first generated)
+// F1E:
+// epilogue (last generated)
+
+// loop layout
+// OP_LOOP
+// F1L1:
+// OP_WHATEVER
+// OP_BR -> L_1 (jmp to F1L1T0)
+// OP_WHATEVER
+// OP_BR -> L_1 (jmp to F1L2T1)
+// OP_END
+// (jmp to F1L1E)
+// F1L1T0:
+// (restore context and jmp to F1L1)
+// F1L2T1:
+// (restore context and jmp to F1L1)
+// F1L1E:
+// OP_WHATEVER
+
+// block layout
+// OP_BLOCK
+// OP_WHATEVER
+// OP_BR -> B_2 (F1B2 not generated, jmp to F1L2T0)
+// OP_WHATEVER
+// OP_BR -> B_2 (F1B2 not generated, jmp to F1L2T1)
+// OP_END
+// (jmp to F1L2E)
+// F1L2T0:
+// (restore context and jmp to F1L2E)
+// F1L2T1:
+// (restore context and jmp to F1L2E)
+// F1L2E:
+// OP_WHATEVER
+
+// br_table layout
+// OP_BR_TABLE
+// jmp [table_base + table_index*8]
+// .c1:
+// jmp F1L1T1
+// .c2
+// jmp F1L2T1
+// .c3
+// jmp F1L1T1
+
+// table content: .c1, .c2, .c3
+
+void wasm_jit_ctx_t::init(wasm_jit_t* jit, wasm_func_t* f) {
+ reg_ = {JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID,
+ JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID,
+ JIT_V_INVALID, JIT_V_CALLER, JIT_V_CALLER, JIT_V_CALLER,
+ JIT_V_CALLER, JIT_V_CALLER, JIT_V_INVALID, JIT_V_INVALID,
+ JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID,
+ JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID,
+ JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID,
+ JIT_V_INVALID, JIT_V_INVALID};
+ int num_args = f->sig_->args_.size();
+ int num_locals = jit->local_types_.size();
+ stack_valid_.resize(num_locals + 6, false);
+ stack_loc_.clear();
+ local_loc_.resize(num_locals);
+ int num_r64 = 0;
+ int num_f64 = 0;
+ int num_stack_r64 = 0;
+ int num_stack_f64 = 0;
+ for (uint8_t arg : f->sig_->args_) {
+ if (arg != WASM_TYPE_F64) {
+ if (num_r64 < 6) {
+ num_r64++;
+ } else {
+ num_stack_r64++;
+ }
+ } else {
+ if (num_f64 < 8) {
+ num_f64++;
+ } else {
+ num_stack_f64++;
+ }
+ }
+ }
+ int stack_arg_index = num_stack_r64 + num_stack_f64 + 1;
+ for (int i = num_args - 1; i >= 0; i--) {
+ uint8_t arg = f->sig_->args_[i];
+ if (arg != WASM_TYPE_F64) {
+ if (num_stack_r64 > 0) {
+ local_loc_[i] = {reg::on_stack, i + 6};
+ jit->mov(jit->rax, jit->qword[jit->rbp + (stack_arg_index * 0x8)]);
+ jit->rbp_save_r(i + 6, reg::rax);
+ stack_arg_index--;
+ num_stack_r64--;
+ local_loc_[i] = {reg::on_stack, i + 6};
+ } else {
+ num_r64--;
+ local_loc_[i] = {reg::in_reg, sysv_args[num_r64]};
+ reg_[sysv_args[num_r64]] = JIT_V_LOCAL(i);
+ }
+ } else {
+ if (num_stack_f64 > 0) {
+ local_loc_[i] = {reg::on_stack, i + 6};
+ jit->mov(jit->rax, jit->qword[jit->rbp + (stack_arg_index * 0x8)]);
+ jit->rbp_save_r(i + 6, reg::rax);
+ stack_arg_index--;
+ num_stack_f64--;
+ local_loc_[i] = {reg::on_stack, i + 6};
+ } else {
+ num_f64--;
+ local_loc_[i] = {reg::in_reg, reg::xmm0 + num_f64};
+ reg_[reg::xmm0 + num_f64] = JIT_V_LOCAL(i);
+ }
+ }
+ }
+ bool r10_clear = false;
+ bool xmm8_clear = false;
+ for (int i = num_args; i < num_locals; i++) {
+ local_loc_[i] = {reg::on_stack, i + 6};
+ if (jit->local_types_[i] != WASM_TYPE_F64) {
+ if (r10_clear == false) {
+ jit->xor_(jit->r10, jit->r10);
+ r10_clear = true;
+ }
+ jit->rbp_save_r(i + 6, reg::r10);
+ } else {
+ if (xmm8_clear == false) {
+ jit->xorpd(jit->xmm8, jit->xmm8);
+ xmm8_clear = true;
+ }
+ jit->rbp_save_r(i + 6, reg::xmm8);
+ }
+ }
+ std::memset(reg_age_.data(), 0, 30 * sizeof(uint32_t));
+ age_ = 0;
+}
+
+const static size_t memory_off = 0x0;
+const static size_t global_off = 0x8;
+const static size_t table_off = 0x10;
+const static size_t memory_size_off = 0x18;
+const static size_t table_size_off = 0x20;
+const static size_t trap_off = 0x28;
+const static size_t f64_const_off = 0x30;
+
+void trap() {
+ std::cout << "!trap" << std::endl;
+ std::exit(-1);
+}
+
+wasm_jit_t::wasm_jit_t(uint64_t code_size)
+ : CodeGenerator(code_size), enable_check_(true) {
+ size_t pos = getSize();
+ endbr64();
+ push(rbp);
+ mov(rbp, rsp);
+ push(rbx);
+ push(r12);
+ push(r13);
+ push(r14);
+ push(r15);
+ sub(rsp, 0x12345678);
+ max_prologue_size_ = getSize() - pos;
+ reset();
+}
+
+typedef void (*run_void_t)(uint8_t* f,
+ uint64_t* reg,
+ uint64_t* stack,
+ size_t num_stack);
+typedef uint64_t (*run_rax_t)(uint8_t* f,
+ uint64_t* reg,
+ uint64_t* stack,
+ size_t num_stack);
+typedef double (*run_xmm_t)(uint8_t* f,
+ uint64_t* reg,
+ uint64_t* stack,
+ size_t num_stack);
+
+// r_type 0:void 1:rax 2:xmm0
+void wasm_jit_t::run_fn(uint32_t index, wasm_value_t* args, wasm_value_t* r) {
+ wasm_func_decl_t* sig = mod_->funcs_[index].sig_;
+ size_t num_args = sig->args_.size();
+ uint8_t* arg_types = sig->args_.data();
+ std::vector<uint64_t> stack;
+ std::array<uint64_t, 14> reg; // 6 r + 6 xmm
+ size_t num_r64 = 0;
+ size_t num_f64 = 0;
+ for (size_t i = 0; i < num_args; i++) {
+ if (arg_types[i] != WASM_TYPE_F64) {
+ if (num_r64 < 6) {
+ reg[num_r64] = args[i].val.i64;
+ num_r64++;
+ } else {
+ stack.push_back(args[i].val.i64);
+ }
+ } else {
+ if (num_f64 < 8) {
+ reg[6 + num_f64] = args[i].val.i64;
+ num_f64++;
+ } else {
+ stack.push_back(args[i].val.i64);
+ }
+ }
+ }
+ uint8_t* f = f_addr_[index];
+ if (sig->ret_.empty() == true) {
+ run_void_t run_void = (run_void_t)run_fn_;
+ run_void(f, reg.data(), stack.data(), stack.size());
+ } else if (sig->ret_[0] != WASM_TYPE_F64) {
+ run_rax_t run_rax = (run_rax_t)run_fn_;
+ r->val.i64 = run_rax(f, reg.data(), stack.data(), stack.size());
+ } else {
+ run_xmm_t run_xmm = (run_xmm_t)run_fn_;
+ r->val.f64 = run_xmm(f, reg.data(), stack.data(), stack.size());
+ }
+}
+
+void wasm_jit_t::compile_instance(wasm_instance_t* ins) {
+ ins_ = ins;
+ mod_ = ins->module_;
+ f_addr_.resize(mod_->funcs_.size());
+
+ dq((uint64_t)ins->memory_.data());
+ dq((uint64_t)ins->globals_.data());
+ dq((uint64_t)ins->jit_table_.data());
+ dq((uint64_t)ins->memory_.size());
+ dq((uint64_t)ins->jit_table_.size());
+ dq((uint64_t)trap);
+
+ // f64 consts needed by i32.trunc, copied from GDB...
+ dq(0x7fffffffffffffff);
+ dq(0x0000000000000000);
+ dq(0x7fefffffffffffff);
+ dq(0x41e0000000000000);
+ dq(0xc1e0000000200000);
+ dq(0x41f0000000000000);
+ dq(0xbff0000000000000);
+
+ L("trap");
+ push(rax);
+ emit_mov_r_rip(reg::rax, trap_off);
+ xchg(qword[rsp], rax); // push address of trap() and preserve rax
+ ret(); // jump to trap()
+
+ emit_runtime_functions();
+ int num_funcs = mod_->funcs_.size();
+ for (int i = mod_->num_import_funcs_; i < num_funcs; i++) {
+ compile_function(i);
+ }
+
+ // fill jit table
+ for (wasm_elem_decl_t& elem : mod_->elems_) {
+ wasm_jit_table_entry_t* p = &ins_->jit_table_[elem.offset_];
+ for (uint32_t funcidx : elem.funcidx_) {
+ *p = {mod_->funcs_[funcidx].typeid_, f_addr_[funcidx]};
+ p++;
+ }
+ }
+}
+
+void wasm_jit_t::emit_runtime_functions() {
+ align(8);
+ size_t num_rt = mod_->num_import_funcs_;
+ for (size_t i = 0; i < num_rt; i++) {
+ wasm_func_t* f = &mod_->funcs_[i];
+ f_addr_[i] = (uint8_t*)f->run_jit_;
+
+ size_t offset = getSize();
+ dq((uint64_t)f->run_jit_);
+ L("F" + std::to_string(i));
+ emit_lea_r_rip(reg::r10, offset);
+ jmp(qword[r10]);
+ }
+ align(16);
+
+ // rdi: f
+ // rsi: reg
+ // rdx: stack
+ // rcx: num_stack
+ run_fn_ = const_cast<uint8_t*>(getCurr());
+ inLocalLabel();
+ endbr64();
+ push(rbp);
+ mov(rbp, rsp);
+ test(rcx, 0x1);
+ je(".no_padding");
+ sub(rsp, 0x8);
+ L(".no_padding");
+ lea(r8, qword[rdx + rcx * 8]);
+ L(".push_stack");
+ test(rcx, rcx);
+ je(".no_stack");
+ sub(r8, 0x8);
+ mov(rax, qword[r8]);
+ push(rax);
+ dec(rcx);
+ jmp(".push_stack");
+ L(".no_stack");
+ mov(r10, rdi);
+ mov(rax, rsi);
+ mov(rdi, qword[rax]);
+ mov(rsi, qword[rax + 0x8]);
+ mov(rdx, qword[rax + 0x10]);
+ mov(rcx, qword[rax + 0x18]);
+ mov(r8, qword[rax + 0x20]);
+ mov(r9, qword[rax + 0x28]);
+ movsd(xmm0, qword[rax + 0x30]);
+ movsd(xmm1, qword[rax + 0x38]);
+ movsd(xmm2, qword[rax + 0x40]);
+ movsd(xmm3, qword[rax + 0x48]);
+ movsd(xmm4, qword[rax + 0x50]);
+ movsd(xmm5, qword[rax + 0x58]);
+ movsd(xmm6, qword[rax + 0x60]);
+ movsd(xmm7, qword[rax + 0x68]);
+ call(r10);
+ leave();
+ ret();
+ outLocalLabel();
+}
+
+void wasm_jit_t::compile_function(uint32_t index) {
+ f_ = &mod_->funcs_[index];
+ funcidx_ = index;
+ int num_f_locals = 0;
+ local_types_.clear();
+ for (uint8_t t : f_->sig_->args_) {
+ local_types_.push_back(t);
+ }
+ for (wasm_local_decl_t decl : f_->locals_) {
+ for (int i = 0; i < (int)decl.count_; i++) {
+ local_types_.push_back(decl.type_);
+ }
+ num_f_locals += decl.count_;
+ }
+ num_locals_ = f_->sig_->args_.size() + num_f_locals;
+
+ rsp_sub_ = ((num_locals_ + 6) - 1) * 0x8;
+ if (rsp_sub_ % 16 == 8) {
+ rsp_sub_ += 8;
+ }
+ used_callee_ = {0, 0, 0, 0, 0};
+
+ buf_.start = buf_.ptr = f_->code_.data();
+ buf_.end = buf_.start + f_->code_.size();
+ next_bi_ = 0;
+ stop_ = 0;
+
+ // save space for prologue
+ size_t start_off = getSize();
+ nop(max_prologue_size_, false);
+ size_t body_off = getSize();
+ uint8_t* body_pos = const_cast<uint8_t*>(getCurr());
+
+ // generate function body
+ ctx_.init(this, f_);
+ block_stack_.push_back({0, next_bi_++});
+ while (stop_ != 1) {
+ opcode_ = read_u8(&buf_);
+ const wasm_inst_desc_t* desc = &g_inst_desc[opcode_];
+ if (desc->emit == nullptr) {
+ __asm__("int3");
+ }
+ (this->*desc->emit)();
+ }
+ block_stack_.clear();
+ size_t end_off = getSize();
+ L("F" + std::to_string(funcidx_) + "E");
+
+ // generate prologue
+ setSize(start_off);
+ endbr64();
+ push(rbp);
+ mov(rbp, rsp);
+ for (int32_t i = 0; i < 5; i++) {
+ if (used_callee_[i] != 0) {
+ push(to_xbyak_r64(reg::rbx + i));
+ rsp_sub_ -= 0x8;
+ }
+ }
+ sub(rsp, rsp_sub_);
+ size_t prologue_size = getSize() - start_off;
+ size_t gap_size = max_prologue_size_ - prologue_size;
+ for (size_t i = 0; i < prologue_size; i++) {
+ body_pos--;
+ *body_pos = *(body_pos - gap_size);
+ }
+ f_addr_[funcidx_] = body_pos;
+ setSize(start_off);
+ nop(gap_size);
+ setSize(body_off - prologue_size);
+ L("F" + std::to_string(funcidx_));
+
+ // generate epilogue
+ setSize(end_off);
+ add(rsp, rsp_sub_);
+ for (int32_t i = 4; i >= 0; i--) {
+ if (used_callee_[i] != 0) {
+ pop(to_xbyak_r64(reg::rbx + i));
+ }
+ }
+ pop(rbp);
+ ret();
+}
+
+int32_t wasm_jit_t::alloc_r(wasm_jit_val_t usage, uint8_t type) {
+ int32_t start, end;
+ if (type != WASM_TYPE_F64) {
+ start = reg::rax;
+ end = reg::xmm0;
+ } else {
+ start = reg::xmm0;
+ end = reg::num_r;
+ }
+ uint32_t min_age = UINT32_MAX;
+ int32_t min_r = start;
+ for (int32_t r = start; r < end; r++) {
+ if (ctx_.reg_[r].type == wasm_jit_type_t::INVALID) {
+ acquire_r(r, usage);
+ return r;
+ }
+ if (ctx_.reg_age_[r] < min_age) {
+ min_age = ctx_.reg_age_[r];
+ min_r = r;
+ }
+ }
+ acquire_r(min_r, usage);
+ return min_r;
+}
+
+void wasm_jit_t::acquire_r(int32_t index, wasm_jit_val_t usage) {
+ wasm_jit_val_t old_usage = ctx_.reg_[index];
+ int32_t s;
+ switch (old_usage.type) {
+ case wasm_jit_type_t::CALLER_DATA:
+ used_callee_[index - reg::rbx] = 1;
+ break;
+ case wasm_jit_type_t::LOCAL_VAL:
+ s = old_usage.index + 6;
+ rbp_save_r(s, index);
+ ctx_.local_loc_[old_usage.index] = {reg::on_stack, s};
+ break;
+ case wasm_jit_type_t::STACK_VAL:
+ s = alloc_stk();
+ rbp_save_r(s, index);
+ ctx_.stack_loc_[old_usage.index] = {reg::on_stack, s};
+ break;
+ default:
+ break;
+ }
+ ctx_.reg_[index] = usage;
+ ctx_.reg_age_[index] = ctx_.age_++;
+}
+
+void wasm_jit_t::use_r(int32_t index, wasm_jit_val_t usage) {
+ ctx_.reg_[index] = usage;
+ ctx_.reg_age_[index] = ctx_.age_++;
+}
+
+void wasm_jit_t::release_r(int32_t index) {
+ ctx_.reg_[index] = JIT_V_INVALID;
+}
+
+int32_t wasm_jit_t::alloc_stk() {
+ int stack_size = ctx_.stack_valid_.size();
+ for (int i = (int)(num_locals_ + 6); i < stack_size; i++) {
+ if (ctx_.stack_valid_[i] == false) {
+ ctx_.stack_valid_[i] = true;
+ return i;
+ }
+ }
+ // grow stack
+ ctx_.stack_valid_.push_back(false);
+ // new stack_size is stack_size +1
+ // and we need sub rsp, 8*(stack_size-1) (rbp is saved)
+ uint32_t new_rsp_sub = 8 * ((stack_size + 1) - 1);
+ if (new_rsp_sub % 16 == 8) {
+ new_rsp_sub += 8;
+ }
+ rsp_sub_ = std::max(rsp_sub_, new_rsp_sub);
+ return stack_size;
+}
+
+void wasm_jit_t::release_stk(int32_t index) {
+ ctx_.stack_valid_[index] = false;
+}
+
+void wasm_jit_t::acquire_stk(int32_t index) {
+ ctx_.stack_valid_[index] = true;
+}
+
+wasm_jit_loc_t wasm_jit_t::peek_wasm_stk(uint32_t depth) {
+ return ctx_.stack_loc_[ctx_.stack_loc_.size() - depth - 1];
+}
+
+wasm_jit_loc_t wasm_jit_t::pop_wasm_stk() {
+ wasm_jit_loc_t result = ctx_.stack_loc_.back();
+ ctx_.stack_loc_.pop_back();
+ return result;
+}
+
+void wasm_jit_t::rbp_load_r(int32_t index, int32_t r, uint8_t type) {
+ if (type != WASM_TYPE_F64) {
+ if (type != WASM_TYPE_I32) {
+ mov(to_xbyak_r64(r), qword[rbp - (index * 8)]);
+ } else {
+ mov(to_xbyak_r32(r), dword[rbp - (index * 8)]);
+ }
+ } else {
+ movsd(to_xbyak_xmm(r), qword[rbp - (index * 8)]);
+ }
+ release_stk(index);
+}
+
+void wasm_jit_t::rbp_save_r(int32_t index, int32_t r) {
+ if (r < reg::xmm0) {
+ mov(qword[rbp - (index * 8)], to_xbyak_r64(r));
+ } else {
+ movsd(qword[rbp - (index * 8)], to_xbyak_xmm(r));
+ }
+ acquire_stk(index);
+}
+
+int32_t wasm_jit_t::pop_r(uint8_t type) {
+ wasm_jit_loc_t loc = pop_wasm_stk();
+ if (loc.type == reg::in_reg) {
+ use_r(loc.index, JIT_V_INTER);
+ return loc.index;
+ }
+ int32_t r = alloc_r(JIT_V_INTER, type);
+ rbp_load_r(loc.index, r, type);
+ return r;
+}
+
+void wasm_jit_t::pop_r(int32_t index, uint8_t type) {
+ wasm_jit_loc_t loc = peek_wasm_stk(0);
+ if (loc.type == reg::in_reg && loc.index == index) {
+ pop_wasm_stk();
+ use_r(loc.index, JIT_V_INTER);
+ return;
+ }
+ acquire_r(index, JIT_V_INTER);
+ // target may be moved
+ loc = pop_wasm_stk();
+ if (loc.type == reg::in_reg) {
+ if (type != WASM_TYPE_F64) {
+ if (type != WASM_TYPE_I32) {
+ mov(to_xbyak_r64(index), to_xbyak_r64(loc.index));
+ } else {
+ mov(to_xbyak_r32(index), to_xbyak_r32(loc.index));
+ }
+ } else {
+ movsd(to_xbyak_xmm(index), to_xbyak_xmm(loc.index));
+ }
+ release_r(loc.index);
+ return;
+ }
+ rbp_load_r(loc.index, index, type);
+}
+
+int32_t wasm_jit_t::pop_binop_r32_r32(oo_op_t binop) {
+ wasm_jit_loc_t a_loc = peek_wasm_stk(1);
+ int32_t a;
+ if (a_loc.type == reg::on_stack) {
+ // move a to register and check b's location
+ a = alloc_r(JIT_V_INTER, WASM_TYPE_I32);
+ rbp_load_r(a_loc.index, a, WASM_TYPE_I32);
+ } else {
+ // no register allocation needed
+ a = a_loc.index;
+ use_r(a, JIT_V_INTER);
+ }
+ wasm_jit_loc_t b_loc = pop_wasm_stk();
+ pop_wasm_stk();
+ if (b_loc.type == reg::in_reg) {
+ // ra = op(ra, rb)
+ (this->*binop)(to_xbyak_r32(a), to_xbyak_r32(b_loc.index));
+ release_r(b_loc.index);
+ } else {
+ // ra = op(ra, mb)
+ (this->*binop)(to_xbyak_r32(a), dword[rbp - (b_loc.index * 8)]);
+ release_stk(b_loc.index);
+ }
+ return a;
+}
+
+int32_t wasm_jit_t::pop_binop_xmm_xmm(xo_op_t binop) {
+ wasm_jit_loc_t a_loc = peek_wasm_stk(1);
+ int32_t a;
+ if (a_loc.type == reg::on_stack) {
+ // move a to register and check b's location
+ a = alloc_r(JIT_V_INTER, WASM_TYPE_F64);
+ rbp_load_r(a_loc.index, a, WASM_TYPE_F64);
+ } else {
+ // no register allocation needed
+ a = a_loc.index;
+ use_r(a, JIT_V_INTER);
+ }
+ wasm_jit_loc_t b_loc = pop_wasm_stk();
+ pop_wasm_stk();
+ if (b_loc.type == reg::in_reg) {
+ // ra = op(ra, rb)
+ (this->*binop)(to_xbyak_xmm(a), to_xbyak_xmm(b_loc.index));
+ release_r(b_loc.index);
+ } else {
+ // ra = op(ra, mb)
+ (this->*binop)(to_xbyak_xmm(a), dword[rbp - (b_loc.index * 8)]);
+ release_stk(b_loc.index);
+ }
+ return a;
+}
+
+void wasm_jit_t::push_r(int32_t index) {
+ ctx_.stack_loc_.push_back({reg::in_reg, index});
+ ctx_.reg_[index] = JIT_V_STACK(ctx_.stack_loc_.size() - 1);
+}
+
+int32_t wasm_jit_t::alloc_special(wasm_jit_type_t t, size_t off) {
+ for (int32_t i = 0; i < reg::num_r; i++) {
+ if (ctx_.reg_[i].type == t) {
+ return i;
+ }
+ }
+ int32_t r = alloc_r({t, 0}, WASM_TYPE_I64);
+ emit_mov_r_rip(r, off);
+ return r;
+}
+
+int32_t wasm_jit_t::alloc_global_base() {
+ return alloc_special(wasm_jit_type_t::GLOBAL_BASE, global_off);
+}
+
+int32_t wasm_jit_t::alloc_memory_base() {
+ return alloc_special(wasm_jit_type_t::MEMORY_BASE, memory_off);
+}
+
+int32_t wasm_jit_t::alloc_memory_size() {
+ return alloc_special(wasm_jit_type_t::MEMORY_SIZE, memory_size_off);
+}
+
+void wasm_jit_t::emit_lea_r_rip(int32_t r, size_t dest_offset) {
+ size_t pos = getSize();
+ lea(to_xbyak_r64(r), ptr[rip - 0x12345678]);
+ size_t src_offset = getSize();
+ setSize(pos);
+ lea(to_xbyak_r64(r), ptr[rip - (int32_t)(src_offset - dest_offset)]);
+ if (getSize() != src_offset) {
+ throw std::runtime_error("Generated wrong rip addressing LEA");
+ }
+}
+
+void wasm_jit_t::emit_mov_r_rip(int32_t r, size_t dest_offset) {
+ size_t pos = getSize();
+ mov(to_xbyak_r64(r), ptr[rip - 0x12345678]);
+ size_t src_offset = getSize();
+ setSize(pos);
+ mov(to_xbyak_r64(r), ptr[rip - (int32_t)(src_offset - dest_offset)]);
+ if (getSize() != src_offset) {
+ throw std::runtime_error("Generated wrong rip addressing MOV");
+ }
+}
+
+void wasm_jit_t::emit_unreachable() {
+ ud2();
+}
+
+void wasm_jit_t::emit_nop() {}
+
+void wasm_jit_t::emit_drop() {
+ wasm_jit_loc_t loc = pop_wasm_stk();
+ if (loc.type == reg::in_reg) {
+ release_r(loc.index);
+ } else {
+ release_stk(loc.index);
+ }
+}
+
+void wasm_jit_t::emit_select() {
+ int32_t c = pop_r(WASM_TYPE_I32);
+ int32_t b = pop_r(WASM_TYPE_I32);
+ int32_t a = pop_r(WASM_TYPE_I32);
+ test(to_xbyak_r32(c), to_xbyak_r32(c));
+ mov(to_xbyak_r32(c), to_xbyak_r32(b));
+ cmovne(to_xbyak_r32(c), to_xbyak_r32(a));
+ release_r(a);
+ release_r(b);
+ push_r(c);
+}
+
+void wasm_jit_t::emit_local_get() {
+ uint32_t idx = read_u32leb(&buf_);
+ uint8_t type = local_types_[idx];
+ wasm_jit_loc_t* local_loc = &ctx_.local_loc_[idx];
+ if (local_loc->type == reg::in_reg) {
+ // r -> (m, r)
+ rbp_save_r(idx + 6, local_loc->index);
+ push_r(local_loc->index);
+ *local_loc = {reg::on_stack, (int32_t)idx + 6};
+ return;
+ }
+ // m -> (m, r)
+ int32_t r = alloc_r(JIT_V_INTER, type);
+ rbp_load_r(local_loc->index, r, type);
+ push_r(r);
+}
+
+void wasm_jit_t::emit_local_set() {
+ uint32_t idx = read_u32leb(&buf_);
+ uint8_t type = local_types_[idx];
+ wasm_jit_loc_t* local_loc = &ctx_.local_loc_[idx];
+ wasm_jit_loc_t stack_loc = pop_wasm_stk();
+ if (local_loc->type == reg::in_reg) {
+ if (stack_loc.type == reg::in_reg) {
+ // r -> r
+ use_r(stack_loc.index, JIT_V_LOCAL(idx));
+ release_r(local_loc->index);
+ local_loc->index = stack_loc.index;
+ } else {
+ // m -> r
+ rbp_load_r(stack_loc.index, local_loc->index, type);
+ }
+ return;
+ }
+ if (stack_loc.type == reg::in_reg) {
+ // r -> m
+ rbp_save_r(local_loc->index, stack_loc.index);
+ release_r(stack_loc.index);
+ } else {
+ // m -> m, move local to r
+ int32_t r = alloc_r(JIT_V_LOCAL(idx), type);
+ rbp_load_r(stack_loc.index, r, type);
+ *local_loc = {reg::on_stack, r};
+ }
+}
+
+void wasm_jit_t::emit_local_tee() {
+ uint32_t idx = read_u32leb(&buf_);
+ uint8_t type = local_types_[idx];
+ wasm_jit_loc_t* local_loc = &ctx_.local_loc_[idx];
+ wasm_jit_loc_t stack_loc = peek_wasm_stk(0);
+ if (local_loc->type == reg::in_reg) {
+ if (stack_loc.type == reg::in_reg) {
+ // r -> r
+ if (type != WASM_TYPE_F64) {
+ mov(to_xbyak_r64(local_loc->index), to_xbyak_r64(stack_loc.index));
+ } else {
+ mov(to_xbyak_xmm(local_loc->index), to_xbyak_xmm(stack_loc.index));
+ }
+ } else {
+ // m -> r, need to remark stack as valid
+ rbp_load_r(stack_loc.index, local_loc->index, type);
+ acquire_stk(stack_loc.index);
+ }
+ return;
+ }
+ if (stack_loc.type == reg::in_reg) {
+ // r -> m
+ rbp_save_r(local_loc->index, stack_loc.index);
+ } else {
+ // m -> m, move local to r, and need to remark stack as valid
+ int32_t r = alloc_r(JIT_V_LOCAL(idx), type);
+ rbp_load_r(stack_loc.index, r, type);
+ acquire_stk(stack_loc.index);
+ *local_loc = {reg::on_stack, r};
+ }
+}
+
+// globals are always in memory
+void wasm_jit_t::emit_global_get() {
+ uint32_t idx = read_u32leb(&buf_);
+ uint8_t type = mod_->globals_[idx].type_.type_;
+ int32_t r = alloc_global_base();
+ if (type != WASM_TYPE_F64) {
+ if (type != WASM_TYPE_I32) {
+ mov(to_xbyak_r64(r), qword[to_xbyak_r64(r) + (idx * 8)]);
+ push_r(r);
+ } else {
+ mov(to_xbyak_r32(r), dword[to_xbyak_r64(r) + (idx * 8)]);
+ push_r(r);
+ }
+ } else {
+ int32_t s = alloc_r(JIT_V_INTER, WASM_TYPE_F64);
+ movsd(to_xbyak_xmm(s), qword[to_xbyak_r64(r) + (idx * 8)]);
+ push_r(s);
+ release_r(r);
+ }
+}
+
+void wasm_jit_t::emit_global_set() {
+ uint32_t idx = read_u32leb(&buf_);
+ uint8_t type = mod_->globals_[idx].type_.type_;
+ int32_t r = alloc_global_base();
+ // load global base must happen before here or stack loc will change
+ wasm_jit_loc_t stack_loc = pop_wasm_stk();
+ int32_t s;
+ if (stack_loc.type == reg::in_reg) {
+ // r -> m
+ s = stack_loc.index;
+ } else {
+ // m -> m
+ s = alloc_r(JIT_V_INTER, type);
+ rbp_load_r(stack_loc.index, s, type);
+ }
+ if (type != WASM_TYPE_F64) {
+ if (type != WASM_TYPE_I32) {
+ mov(qword[to_xbyak_r64(r) + (idx * 8)], to_xbyak_r64(s));
+ } else {
+ mov(dword[to_xbyak_r64(r) + (idx * 8)], to_xbyak_r32(s));
+ }
+ } else {
+ movsd(qword[to_xbyak_r64(r) + (idx * 8)], to_xbyak_xmm(s));
+ }
+ release_r(s);
+}
+
+void wasm_jit_t::emit_i32_load() {
+ read_u32leb(&buf_);
+ uint32_t addend = read_u32leb(&buf_);
+ uint32_t v_size = 4;
+ switch (opcode_) {
+ case WASM_OP_I32_LOAD16_S:
+ case WASM_OP_I32_LOAD16_U:
+ v_size = 2;
+ break;
+ case WASM_OP_I32_LOAD8_S:
+ case WASM_OP_I32_LOAD8_U:
+ v_size = 1;
+ break;
+ default:
+ break;
+ }
+ int32_t offset = pop_r(WASM_TYPE_I32);
+ int32_t m = alloc_memory_base();
+ Xbyak::RegExp e;
+ if (enable_check_ == true) {
+ int32_t mem_size = alloc_memory_size();
+ inLocalLabel();
+ cmp(to_xbyak_r32(mem_size), addend);
+ jae(".L0");
+ call("trap");
+ L(".L0");
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L1");
+ call("trap");
+ L(".L1");
+ add(to_xbyak_r32(offset), addend);
+ push(to_xbyak_r64(offset));
+ add(to_xbyak_r32(offset), v_size);
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L2");
+ call("trap");
+ L(".L2");
+ outLocalLabel();
+ pop(to_xbyak_r64(offset));
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset);
+ } else {
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend;
+ }
+ switch (opcode_) {
+ case WASM_OP_I32_LOAD16_S:
+ movsx(to_xbyak_r32(offset), word[e]);
+ break;
+ case WASM_OP_I32_LOAD16_U:
+ mov(to_xbyak_r16(offset), word[e]);
+ and_(to_xbyak_r32(offset), 0xFFFF);
+ break;
+ case WASM_OP_I32_LOAD8_S:
+ movsx(to_xbyak_r32(offset), byte[e]);
+ break;
+ case WASM_OP_I32_LOAD8_U:
+ mov(to_xbyak_r8(offset), byte[e]);
+ and_(to_xbyak_r32(offset), 0xFF);
+ break;
+ default:
+ mov(to_xbyak_r32(offset), dword[e]);
+ break;
+ }
+ push_r(offset);
+}
+
+void wasm_jit_t::emit_f64_load() {
+ read_u32leb(&buf_);
+ uint32_t addend = read_u32leb(&buf_);
+ int32_t xmm = alloc_r(JIT_V_INTER, WASM_TYPE_F64);
+ int32_t offset = pop_r(WASM_TYPE_I32);
+ int32_t m = alloc_memory_base();
+ Xbyak::RegExp e;
+ if (enable_check_ == true) {
+ int32_t mem_size = alloc_memory_size();
+ inLocalLabel();
+ cmp(to_xbyak_r32(mem_size), addend);
+ jae(".L0");
+ call("trap");
+ L(".L0");
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L1");
+ call("trap");
+ L(".L1");
+ add(to_xbyak_r32(offset), addend);
+ push(to_xbyak_r64(offset));
+ add(to_xbyak_r32(offset), sizeof(double));
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L2");
+ call("trap");
+ L(".L2");
+ outLocalLabel();
+ pop(to_xbyak_r64(offset));
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset);
+ } else {
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend;
+ }
+ movsd(to_xbyak_xmm(xmm), qword[e]);
+ push_r(xmm);
+ release_r(offset);
+}
+
+void wasm_jit_t::emit_i32_store() {
+ read_u32leb(&buf_);
+ uint32_t addend = read_u32leb(&buf_);
+ uint32_t v_size = 4;
+ switch (opcode_) {
+ case WASM_OP_I32_STORE16:
+ v_size = 2;
+ break;
+ case WASM_OP_I32_STORE8:
+ v_size = 1;
+ break;
+ default:
+ break;
+ }
+ int32_t v = pop_r(WASM_TYPE_I32);
+ int32_t offset = pop_r(WASM_TYPE_I32);
+ int32_t m = alloc_memory_base();
+ Xbyak::RegExp e;
+ int32_t mem_size;
+ if (enable_check_ == true) {
+ mem_size = alloc_memory_size();
+ inLocalLabel();
+ cmp(to_xbyak_r32(mem_size), addend);
+ jae(".L0");
+ call("trap");
+ L(".L0");
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L1");
+ call("trap");
+ L(".L1");
+ add(to_xbyak_r32(offset), addend);
+ push(to_xbyak_r64(offset));
+ add(to_xbyak_r32(offset), v_size);
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L2");
+ call("trap");
+ L(".L2");
+ outLocalLabel();
+ pop(to_xbyak_r64(offset));
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset);
+ } else {
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend;
+ }
+ switch (opcode_) {
+ case WASM_OP_I32_STORE16:
+ mov(word[e], to_xbyak_r16(v));
+ break;
+ case WASM_OP_I32_STORE8:
+ mov(byte[e], to_xbyak_r8(v));
+ break;
+ default:
+ mov(dword[e], to_xbyak_r32(v));
+ break;
+ }
+ release_r(offset);
+ release_r(v);
+}
+
+void wasm_jit_t::emit_f64_store() {
+ read_u32leb(&buf_);
+ uint32_t addend = read_u32leb(&buf_);
+ int32_t v = pop_r(WASM_TYPE_F64);
+ int32_t offset = pop_r(WASM_TYPE_I32);
+ int32_t m = alloc_memory_base();
+ Xbyak::RegExp e;
+ int32_t mem_size;
+ if (enable_check_ == true) {
+ mem_size = alloc_memory_size();
+ inLocalLabel();
+ cmp(to_xbyak_r32(mem_size), addend);
+ jae(".L0");
+ call("trap");
+ L(".L0");
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L1");
+ call("trap");
+ L(".L1");
+ add(to_xbyak_r32(offset), addend);
+ push(to_xbyak_r64(offset));
+ add(to_xbyak_r32(offset), sizeof(double));
+ cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset));
+ jae(".L2");
+ call("trap");
+ L(".L2");
+ outLocalLabel();
+ pop(to_xbyak_r64(offset));
+ movsxd(to_xbyak_r64(offset), to_xbyak_r32(offset));
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset);
+ } else {
+ e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend;
+ }
+ movsd(qword[e], to_xbyak_xmm(v));
+ release_r(offset);
+ release_r(v);
+}
+
+void wasm_jit_t::emit_i32_numeric() {
+ static o_op_t setcc[] = {&wasm_jit_t::sete, &wasm_jit_t::setne,
+ &wasm_jit_t::setl, &wasm_jit_t::setb,
+ &wasm_jit_t::setg, &wasm_jit_t::seta,
+ &wasm_jit_t::setle, &wasm_jit_t::setbe,
+ &wasm_jit_t::setge, &wasm_jit_t::setae};
+ static oo_op_t numeric[] = {
+ &wasm_jit_t::add, &wasm_jit_t::sub, nullptr, nullptr,
+ nullptr, nullptr, nullptr, &wasm_jit_t::and_,
+ &wasm_jit_t::or_, &wasm_jit_t::xor_};
+ int32_t b;
+ int32_t a;
+ switch (opcode_) {
+ case WASM_OP_I32_EQZ:
+ b = pop_r(WASM_TYPE_I32);
+ test(to_xbyak_r32(b), to_xbyak_r32(b));
+ sete(to_xbyak_r8(b));
+ movsx(to_xbyak_r32(b), to_xbyak_r8(b));
+ push_r(b);
+ break;
+ case WASM_OP_I32_EQ:
+ case WASM_OP_I32_NE:
+ case WASM_OP_I32_LT_S:
+ case WASM_OP_I32_LT_U:
+ case WASM_OP_I32_GT_S:
+ case WASM_OP_I32_GT_U:
+ case WASM_OP_I32_LE_S:
+ case WASM_OP_I32_LE_U:
+ case WASM_OP_I32_GE_S:
+ case WASM_OP_I32_GE_U:
+ a = pop_binop_r32_r32(static_cast<oo_op_t>(&wasm_jit_t::cmp));
+ (this->*setcc[opcode_ - WASM_OP_I32_EQ])(to_xbyak_r8(a));
+ movsx(to_xbyak_r32(a), to_xbyak_r8(a));
+ push_r(a);
+ break;
+ case WASM_OP_I32_CLZ:
+ // https://stackoverflow.com/questions/9353973/implementation-of-builtin-clz
+ inLocalLabel();
+ b = pop_r(WASM_TYPE_I32);
+ test(to_xbyak_r32(b), to_xbyak_r32(b));
+ je(".clz_zero");
+ bsr(to_xbyak_r32(b), to_xbyak_r32(b));
+ xor_(to_xbyak_r32(b), 31);
+ jmp(".clz_done");
+ L(".clz_zero");
+ mov(to_xbyak_r32(b), 32);
+ L(".clz_done");
+ push_r(b);
+ outLocalLabel();
+ break;
+ case WASM_OP_I32_CTZ:
+ inLocalLabel();
+ b = pop_r(WASM_TYPE_I32);
+ test(to_xbyak_r32(b), to_xbyak_r32(b));
+ je(".ctz_zero");
+ bsf(to_xbyak_r32(b), to_xbyak_r32(b));
+ jmp(".ctz_done");
+ L(".ctz_zero");
+ mov(to_xbyak_r32(b), 32);
+ L(".ctz_done");
+ push_r(b);
+ outLocalLabel();
+ push_r(b);
+ break;
+ case WASM_OP_I32_POPCNT:
+ b = pop_r(WASM_TYPE_I32);
+ popcnt(to_xbyak_r32(b), to_xbyak_r32(b));
+ push_r(b);
+ break;
+ case WASM_OP_I32_ADD:
+ case WASM_OP_I32_SUB:
+ case WASM_OP_I32_AND:
+ case WASM_OP_I32_OR:
+ case WASM_OP_I32_XOR:
+ a = pop_binop_r32_r32(numeric[opcode_ - WASM_OP_I32_ADD]);
+ push_r(a);
+ break;
+ case WASM_OP_I32_MUL:
+ pop_r(reg::rdx, WASM_TYPE_I32);
+ pop_r(reg::rax, WASM_TYPE_I32);
+ imul(edx);
+ release_r(reg::rdx);
+ push_r(reg::rax);
+ break;
+ case WASM_OP_I32_DIV_S:
+ acquire_r(reg::rdx, JIT_V_INTER);
+ b = pop_r(WASM_TYPE_I32);
+ pop_r(reg::rax, WASM_TYPE_I32);
+ if (enable_check_ == true) {
+ // see i32_div_s() at weerun_inst.cpp:372
+ inLocalLabel();
+ test(to_xbyak_r32(b), to_xbyak_r32(b));
+ jne(".L0");
+ call("trap");
+ L(".L0");
+ cmp(eax, 0x80000000);
+ jne(".L1");
+ cmp(to_xbyak_r32(b), 0xffffffff);
+ jne(".L1");
+ call("trap");
+ L(".L1");
+ outLocalLabel();
+ }
+ cdq();
+ idiv(to_xbyak_r32(b));
+ release_r(b);
+ release_r(reg::rdx);
+ push_r(reg::rax);
+ break;
+ case WASM_OP_I32_DIV_U:
+ acquire_r(reg::rdx, JIT_V_INTER);
+ b = pop_r(WASM_TYPE_I32);
+ pop_r(reg::rax, WASM_TYPE_I32);
+ if (enable_check_ == true) {
+ // see i32_div_s() at weerun_inst.cpp:372
+ inLocalLabel();
+ test(to_xbyak_r32(b), to_xbyak_r32(b));
+ jne(".L0");
+ call("trap");
+ L(".L0");
+ outLocalLabel();
+ }
+ xor_(rdx, rdx);
+ div(to_xbyak_r32(b));
+ release_r(b);
+ release_r(reg::rdx);
+ push_r(reg::rax);
+ break;
+ case WASM_OP_I32_REM_S:
+ inLocalLabel();
+ acquire_r(reg::rdx, JIT_V_INTER);
+ b = pop_r(WASM_TYPE_I32);
+ pop_r(reg::rax, WASM_TYPE_I32);
+ if (enable_check_ == true) {
+ // see i32_div_s() at weerun_inst.cpp:372
+ test(to_xbyak_r32(b), to_xbyak_r32(b));
+ jne(".L0");
+ call("trap");
+ L(".L0");
+ cmp(eax, 0x80000000);
+ jne(".L1");
+ cmp(to_xbyak_r32(b), 0xffffffff);
+ jne(".L1");
+ xor_(rdx, rdx);
+ jmp(".L2");
+ }
+ L(".L1");
+ cdq();
+ idiv(to_xbyak_r32(b));
+ L(".L2");
+ release_r(b);
+ release_r(reg::rax);
+ push_r(reg::rdx);
+ outLocalLabel();
+ break;
+ case WASM_OP_I32_REM_U:
+ acquire_r(reg::rdx, JIT_V_INTER);
+ b = pop_r(WASM_TYPE_I32);
+ pop_r(reg::rax, WASM_TYPE_I32);
+ if (enable_check_ == true) {
+ // see i32_div_s() at weerun_inst.cpp:372
+ inLocalLabel();
+ test(to_xbyak_r64(b), to_xbyak_r64(b));
+ jne(".L0");
+ call("trap");
+ L(".L0");
+ outLocalLabel();
+ }
+ xor_(rdx, rdx);
+ div(to_xbyak_r32(b));
+ release_r(b);
+ release_r(reg::rax);
+ push_r(reg::rdx);
+ break;
+ case WASM_OP_I32_EXTEND16_S:
+ b = pop_r(WASM_TYPE_I32);
+ movsx(to_xbyak_r32(b), to_xbyak_r16(b));
+ push_r(b);
+ break;
+ case WASM_OP_I32_EXTEND8_S:
+ b = pop_r(WASM_TYPE_I32);
+ movsx(to_xbyak_r32(b), to_xbyak_r8(b));
+ push_r(b);
+ break;
+ default:
+ throw std::runtime_error("Opcode not implemented");
+ }
+}
+
+void wasm_jit_t::emit_i32_shift() {
+ static or8_op_t shift[] = {&wasm_jit_t::shl, &wasm_jit_t::sar,
+ &wasm_jit_t::shr, &wasm_jit_t::rol,
+ &wasm_jit_t::ror};
+ pop_r(reg::rcx, WASM_TYPE_I32);
+ and_(ecx, 0x1F);
+ int32_t a = pop_r(WASM_TYPE_I32);
+ (this->*shift[opcode_ - WASM_OP_I32_SHL])(to_xbyak_r32(a), cl);
+ push_r(a);
+ release_r(reg::rcx);
+}
+
+void wasm_jit_t::emit_i32_const() {
+ uint32_t x = read_i32leb(&buf_);
+ int32_t r = alloc_r(JIT_V_INTER, WASM_TYPE_I32);
+ mov(to_xbyak_r32(r), x);
+ push_r(r);
+}
+
+void wasm_jit_t::emit_call_internal(wasm_func_decl_t* sig,
+ int is_direct,
+ int index) {
+ int num_r64 = 0;
+ int num_f64 = 0;
+ int num_stack_r64 = 0;
+ int num_stack_f64 = 0;
+ int num_args = sig->args_.size();
+ int32_t arg_size = 0;
+ for (uint8_t arg : sig->args_) {
+ if (arg != WASM_TYPE_F64) {
+ if (num_r64 < 6) {
+ num_r64++;
+ } else {
+ num_stack_r64++;
+ }
+ } else {
+ if (num_f64 < 8) {
+ num_f64++;
+ } else {
+ num_stack_f64++;
+ }
+ }
+ }
+ for (int32_t r = reg::rax; r < reg::rbx; r++) {
+ acquire_r(r, JIT_V_INVALID);
+ }
+ for (int32_t r = reg::xmm0; r < reg::num_r; r++) {
+ acquire_r(r, JIT_V_INVALID);
+ }
+ if (is_direct != 1) {
+ pop_r(reg::r10, WASM_TYPE_I32);
+ if (enable_check_ == true) {
+ // check function type
+ inLocalLabel();
+ emit_mov_r_rip(reg::rax, table_size_off);
+ cmp(r10, rax);
+ jb(".L0");
+ call("trap");
+ L(".L0");
+ shl(r10, 1);
+ emit_mov_r_rip(reg::rax, table_off);
+ mov(r11, qword[rax + r10 * 8]);
+ cmp(r11, index);
+ je(".L1");
+ call("trap");
+ L(".L1");
+ outLocalLabel();
+ } else {
+ shl(r10, 1);
+ }
+ }
+ arg_size = num_stack_f64 + num_stack_r64;
+ if (arg_size % 2 == 1) {
+ sub(rsp, 0x8);
+ arg_size++;
+ }
+ for (int i = num_args - 1; i >= 0; i--) {
+ if (sig->args_[i] != WASM_TYPE_F64) {
+ if (num_stack_r64 > 0) {
+ wasm_jit_loc_t loc = pop_wasm_stk();
+ if (loc.type == reg::in_reg) {
+ push(to_xbyak_r64(loc.index));
+ release_r(loc.index);
+ } else {
+ rbp_load_r(loc.index, reg::rax, WASM_TYPE_I64);
+ push(to_xbyak_r64(reg::rax));
+ }
+ num_stack_r64--;
+ } else {
+ num_r64--;
+ pop_r(sysv_args[num_r64], WASM_TYPE_I64);
+ }
+ } else {
+ if (num_stack_f64 > 0) {
+ wasm_jit_loc_t loc = pop_wasm_stk();
+ if (loc.type == reg::in_reg) {
+ sub(rsp, 0x8);
+ movsd(qword[rsp], to_xbyak_xmm(loc.index));
+ release_r(loc.index);
+ } else {
+ rbp_load_r(loc.index, reg::rax, WASM_TYPE_I64);
+ push(to_xbyak_r64(reg::rax));
+ }
+ num_stack_f64--;
+ } else {
+ num_f64--;
+ pop_r(reg::xmm0 + num_f64, WASM_TYPE_F64);
+ }
+ }
+ }
+ if (is_direct == 1) {
+ std::string f_label = "F" + std::to_string(index);
+ call(f_label);
+ } else {
+ emit_mov_r_rip(reg::rax, table_off);
+ call(qword[rax + r10 * 8 + 8]);
+ }
+ if (arg_size != 0) {
+ add(rsp, arg_size * 8);
+ }
+ if (sig->ret_.empty() == false) {
+ if (sig->ret_[0] != WASM_TYPE_F64) {
+ push_r(reg::rax);
+ } else {
+ push_r(reg::xmm0);
+ }
+ }
+}
+
+void wasm_jit_t::emit_call() {
+ uint32_t funcidx = read_u32leb(&buf_);
+ wasm_func_t* f = &mod_->funcs_[funcidx];
+ emit_call_internal(f->sig_, 1, funcidx);
+}
+
+void wasm_jit_t::emit_call_indirect() {
+ read_u32leb(&buf_);
+ uint32_t typeidx = read_u32leb(&buf_);
+ emit_call_internal(&mod_->sigs_[typeidx], 0, typeidx);
+}
+
+void wasm_jit_t::emit_pop_result() {
+ if (f_->sig_->ret_.empty() == false) {
+ if (f_->sig_->ret_[0] != WASM_TYPE_F64) {
+ pop_r(reg::rax, f_->sig_->ret_[0]);
+ } else {
+ pop_r(reg::xmm0, f_->sig_->ret_[0]);
+ }
+ }
+}
+
+void wasm_jit_t::emit_return() {
+ emit_pop_result();
+ jmp("F" + std::to_string(funcidx_) + "E", T_NEAR);
+}
+
+void wasm_jit_t::emit_block() {
+ read_u8(&buf_);
+ if (opcode_ == WASM_OP_LOOP) {
+ block_stack_.push_back({1, next_bi_, ctx_});
+ L("F" + std::to_string(funcidx_) + "L" + std::to_string(next_bi_++));
+ } else {
+ block_stack_.push_back({0, next_bi_});
+ next_bi_++;
+ }
+}
+
+void wasm_jit_t::emit_end() {
+ block_t* b = &block_stack_.back();
+ wasm_jit_ctx_t saved_ctx = ctx_;
+ std::string label("F" + std::to_string(funcidx_) + "L" +
+ std::to_string(b->index));
+ std::string end_label(label + "E");
+ int num_brs = b->br_ctxs.size();
+ if (num_brs > 0) {
+ jmp(end_label, T_NEAR);
+ for (int i = 0; i < num_brs; i++) {
+ L(label + "T" + std::to_string(i));
+ if (b->loop == 0) {
+ restore_state(&b->br_ctxs[i], &ctx_);
+ // let last one fall through
+ if (i < num_brs - 1) {
+ jmp(end_label, T_NEAR);
+ }
+ } else {
+ restore_state(&b->br_ctxs[i], &b->saved_ctx);
+ jmp(label, T_NEAR);
+ }
+ ctx_ = saved_ctx;
+ }
+ }
+ L(end_label);
+ block_stack_.pop_back();
+ if (block_stack_.empty() == true) {
+ emit_pop_result();
+ stop_ = 1;
+ return;
+ }
+}
+
+void wasm_jit_t::emit_br() {
+ uint32_t depth = read_u32leb(&buf_);
+ block_t* b = (&block_stack_.back()) - depth;
+ uint32_t t = b->br_ctxs.size();
+ jmp("F" + std::to_string(funcidx_) + "L" + std::to_string(b->index) + "T" +
+ std::to_string(t),
+ T_NEAR);
+ b->br_ctxs.push_back(ctx_);
+}
+
+void wasm_jit_t::emit_br_if() {
+ uint32_t depth = read_u32leb(&buf_);
+ block_t* b = (&block_stack_.back()) - depth;
+ uint32_t t = b->br_ctxs.size();
+ int32_t r = pop_r(WASM_TYPE_I32);
+ test(to_xbyak_r32(r), to_xbyak_r32(r));
+ jne("F" + std::to_string(funcidx_) + "L" + std::to_string(b->index) + "T" +
+ std::to_string(t),
+ T_NEAR);
+ b->br_ctxs.push_back(ctx_);
+}
+
+void wasm_jit_t::restore_state(wasm_jit_ctx_t* from, wasm_jit_ctx_t* to) {
+ wasm_jit_ctx_t tmp_to = *to; // to may be curent context
+ ctx_ = *from;
+ int num_wasm_local = ctx_.local_loc_.size();
+ int num_wasm_stack = ctx_.stack_loc_.size();
+ int num_wasm_stack_dst = tmp_to.stack_loc_.size();
+ if (num_wasm_stack < num_wasm_stack_dst) {
+ throw std::runtime_error("jmp dst have more stack variables");
+ }
+ acquire_r(reg::rax, JIT_V_INVALID); // use rax for m -> m
+ // save all stack variables
+ if (num_wasm_stack_dst != 0) {
+ sub(rsp, num_wasm_stack_dst * 0x8);
+ }
+ for (int i = 0; i < num_wasm_stack_dst; i++) {
+ wasm_jit_loc_t loc = ctx_.stack_loc_[i];
+ if (loc.type == reg::in_reg) {
+ if (loc.index < reg::xmm0) {
+ // r -> m
+ mov(qword[rsp + (i * 0x8)], to_xbyak_r64(loc.index));
+ } else {
+ // xmm -> m
+ movsd(qword[rsp + (i * 0x8)], to_xbyak_xmm(loc.index));
+ }
+ } else {
+ // m -> m
+ rbp_load_r(loc.index, reg::rax, WASM_TYPE_I64);
+ mov(qword[rsp + (i * 0x8)], rax);
+ }
+ }
+ // save all local variables, local variables have fixed stack pos
+ for (int i = 0; i < num_wasm_local; i++) {
+ wasm_jit_loc_t loc = ctx_.local_loc_[i];
+ if (loc.type == reg::in_reg) {
+ rbp_save_r(i + 6, loc.index);
+ }
+ }
+ // restore stack variables
+ for (int i = 0; i < num_wasm_stack_dst; i++) {
+ wasm_jit_loc_t loc = tmp_to.stack_loc_[i];
+ if (loc.type == reg::in_reg) {
+ if (loc.index < reg::xmm0) {
+ // r -> m
+ mov(to_xbyak_r64(loc.index), qword[rsp + (i * 0x8)]);
+ } else {
+ // xmm -> m
+ movsd(to_xbyak_xmm(loc.index), qword[rsp + (i * 0x8)]);
+ }
+ } else {
+ // m -> m
+ mov(rax, qword[rsp + (i * 0x8)]);
+ rbp_save_r(loc.index, reg::rax);
+ }
+ }
+ if (num_wasm_stack_dst != 0) {
+ add(rsp, num_wasm_stack_dst * 0x8);
+ }
+ // restore local variables
+ for (int i = 0; i < num_wasm_local; i++) {
+ wasm_jit_loc_t loc = tmp_to.local_loc_[i];
+ if (loc.type == reg::in_reg) {
+ rbp_load_r(i + 6, loc.index, local_types_[i]);
+ }
+ }
+ // restore special register values
+ for (int i = 0; i < reg::num_r; i++) {
+ switch (tmp_to.reg_[i].type) {
+ case wasm_jit_type_t::GLOBAL_BASE:
+ emit_mov_r_rip(i, global_off);
+ break;
+ case wasm_jit_type_t::MEMORY_BASE:
+ emit_mov_r_rip(i, memory_off);
+ break;
+ case wasm_jit_type_t::MEMORY_SIZE:
+ emit_mov_r_rip(i, memory_size_off);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+// reimplement code generated by GDB, I don't know how it works...
+void wasm_jit_t::emit_i32_convert() {
+ inLocalLabel();
+ int32_t x0i = pop_r(WASM_TYPE_F64);
+ int32_t x1i = alloc_r(JIT_V_INTER, WASM_TYPE_F64);
+ Xbyak::Xmm x0 = to_xbyak_xmm(x0i);
+ Xbyak::Xmm x1 = to_xbyak_xmm(x1i);
+ int32_t r = alloc_r(JIT_V_INTER, WASM_TYPE_I64);
+ movapd(x1, x0);
+ emit_lea_r_rip(r, f64_const_off);
+ andpd(x1, xword[to_xbyak_r64(r)]);
+ ucomisd(x1, qword[to_xbyak_r64(r) + 0x10]);
+ ja(".trap");
+ ucomisd(x1, x1);
+ jp(".trap");
+ movsd(x1, qword[to_xbyak_r64(r) +
+ (opcode_ == WASM_OP_I32_TRUNC_F64_S ? 0x20 : 0x30)]);
+ comisd(x1, x0);
+ jae(".trap");
+ comisd(x0, qword[to_xbyak_r64(r) +
+ (opcode_ == WASM_OP_I32_TRUNC_F64_S ? 0x18 : 0x28)]);
+ jae(".trap");
+ if (opcode_ == WASM_OP_I32_TRUNC_F64_S) {
+ cvttsd2si(to_xbyak_r32(r), x0);
+ } else {
+ cvttsd2si(to_xbyak_r64(r), x0);
+ }
+ jmp(".safe");
+ L(".trap");
+ call("trap");
+ L(".safe");
+ push_r(r);
+ release_r(x0i);
+ release_r(x1i);
+ outLocalLabel();
+}
+
+void wasm_jit_t::emit_f64_const() {
+ uint64_t x = *(uint64_t*)(buf_.ptr);
+ buf_.ptr += sizeof(uint64_t);
+ int32_t s = alloc_r(JIT_V_INTER, WASM_TYPE_I64);
+ int32_t r = alloc_r(JIT_V_INTER, WASM_TYPE_F64);
+ mov(to_xbyak_r64(s), x);
+ push(to_xbyak_r64(s));
+ movsd(to_xbyak_xmm(r), qword[rsp]);
+ add(rsp, 0x8);
+ release_r(s);
+ push_r(r);
+}
+
+void wasm_jit_t::emit_f64_compute() {
+ static o_op_t setcc[] = {&wasm_jit_t::sete, &wasm_jit_t::setne,
+ &wasm_jit_t::setb, &wasm_jit_t::seta,
+ &wasm_jit_t::setbe, &wasm_jit_t::setae};
+ static xo_op_t fnumeric[] = {&wasm_jit_t::addsd, &wasm_jit_t::subsd,
+ &wasm_jit_t::mulsd, &wasm_jit_t::divsd};
+ int32_t b;
+ int32_t a;
+ int32_t r;
+ switch (opcode_) {
+ case WASM_OP_F64_EQ:
+ case WASM_OP_F64_NE:
+ case WASM_OP_F64_LT:
+ case WASM_OP_F64_GT:
+ case WASM_OP_F64_LE:
+ case WASM_OP_F64_GE:
+ b = pop_r(WASM_TYPE_F64);
+ a = pop_r(WASM_TYPE_F64);
+ r = alloc_r(JIT_V_INTER, WASM_TYPE_I64);
+ comisd(to_xbyak_xmm(a), to_xbyak_xmm(b));
+ (this->*setcc[opcode_ - WASM_OP_F64_EQ])(to_xbyak_r8(r));
+ movsx(to_xbyak_r32(r), to_xbyak_r8(r));
+ release_r(b);
+ release_r(a);
+ push_r(r);
+ break;
+ case WASM_OP_F64_ADD:
+ case WASM_OP_F64_SUB:
+ case WASM_OP_F64_MUL:
+ case WASM_OP_F64_DIV:
+ a = pop_binop_xmm_xmm(fnumeric[opcode_ - WASM_OP_F64_ADD]);
+ push_r(a);
+ break;
+ case WASM_OP_F64_CONVERT_I32_S:
+ b = pop_r(WASM_TYPE_I32);
+ r = alloc_r(JIT_V_INTER, WASM_TYPE_F64);
+ cvtsi2sd(to_xbyak_xmm(r), to_xbyak_r32(b));
+ push_r(r);
+ release_r(b);
+ break;
+ case WASM_OP_F64_CONVERT_I32_U:
+ b = pop_r(WASM_TYPE_I64);
+ r = alloc_r(JIT_V_INTER, WASM_TYPE_F64);
+ mov(to_xbyak_r64(b), to_xbyak_r64(b));
+ cvtsi2sd(to_xbyak_xmm(r), to_xbyak_r64(b));
+ push_r(r);
+ release_r(b);
+ break;
+ }
+}
+
+void wasm_jit_t::emit_br_table() {
+ uint32_t num_cases = read_u32leb(&buf_);
+ std::map<uint32_t, size_t> dst_offsets; // depth -> offset
+ std::vector<uint32_t> table_offsets; // table element -> offset
+ inLocalLabel();
+ int32_t a = pop_r(WASM_TYPE_I32);
+ int32_t b = alloc_r(JIT_V_INTER, WASM_TYPE_I64);
+ mov(to_xbyak_r32(b), num_cases);
+ cmp(to_xbyak_r32(a), to_xbyak_r32(b));
+ // use default case as the last one
+ cmovae(to_xbyak_r32(a), to_xbyak_r32(b));
+ size_t lea_pos = getSize();
+ lea(to_xbyak_r64(b), qword[rip + 0x12345678]);
+ size_t start_offset = getSize();
+ movsxd(to_xbyak_r64(a), dword[to_xbyak_r64(b) + to_xbyak_r64(a) * 4]);
+ add(to_xbyak_r64(a), to_xbyak_r64(b));
+ db(0x3e); // disable endbr64
+ jmp(to_xbyak_r32(a));
+ align(4);
+ size_t end_offset = getSize();
+ setSize(lea_pos);
+ lea(to_xbyak_r64(b), qword[rip + (int)(end_offset - start_offset)]);
+ if (getSize() != start_offset) {
+ throw std::runtime_error("Generated wrong rip addressing LEA");
+ }
+ // alloc space for offsets
+ table_offsets.resize(num_cases + 1);
+ setSize(end_offset + 4 * (num_cases + 1));
+ // also takes care of default case
+ for (uint32_t i = 0; i <= num_cases; i++) {
+ uint32_t depth = read_u32leb(&buf_);
+ auto result = dst_offsets.find(depth);
+ if (result == dst_offsets.end()) {
+ dst_offsets[depth] = getSize();
+ table_offsets[i] = getSize();
+ block_t* b = (&block_stack_.back()) - depth;
+ uint32_t t = b->br_ctxs.size();
+ std::string jmp_label = "F" + std::to_string(funcidx_) + "L" +
+ std::to_string(b->index) + "T" +
+ std::to_string(t);
+ jmp(jmp_label);
+ b->br_ctxs.push_back(ctx_);
+ } else {
+ table_offsets[i] = result->second;
+ }
+ }
+ size_t inst_end_offset = getSize();
+ setSize(end_offset);
+ for (uint32_t i = 0; i <= num_cases; i++) {
+ dd((uint32_t)(table_offsets[i] - end_offset));
+ }
+ setSize(inst_end_offset);
+ release_r(a);
+ release_r(b);
+ outLocalLabel();
+}
diff --git a/weerun_jit.hpp b/weerun_jit.hpp
new file mode 100644
index 0000000..509f02c
--- /dev/null
+++ b/weerun_jit.hpp
@@ -0,0 +1,216 @@
+#pragma once
+
+#include <array>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "weerun.hpp"
+
+#include <xbyak/xbyak.h>
+#include <xbyak/xbyak_bin2hex.h>
+
+namespace reg {
+enum reg {
+ rax = 0,
+ rdx = 1,
+ rcx = 2,
+ rdi = 3,
+ rsi = 4,
+ r8 = 5,
+ r9 = 6,
+ r10 = 7,
+ r11 = 8,
+ // callee-saved:
+ rbx = 9,
+ r12 = 10,
+ r13 = 11,
+ r14 = 12,
+ r15 = 13,
+
+ xmm0 = 14,
+ xmm1 = 15,
+ xmm2 = 16,
+ xmm3 = 17,
+ xmm4 = 18,
+ xmm5 = 19,
+ xmm6 = 20,
+ xmm7 = 21,
+ xmm8 = 22,
+ xmm9 = 23,
+ xmm10 = 24,
+ xmm11 = 25,
+ xmm12 = 26,
+ xmm13 = 27,
+ xmm14 = 28,
+ xmm15 = 29,
+
+ num_r = 30
+};
+
+const int32_t in_reg = 0;
+const int32_t on_stack = 1;
+} // namespace reg
+
+struct wasm_jit_loc_t {
+ int32_t type; // 0:in register, 1:on stack
+ int32_t index; // register index or [rbp-8*index]
+
+ bool operator==(const wasm_jit_loc_t& rhs) {
+ return type == rhs.type && index == rhs.index;
+ }
+};
+
+enum class wasm_jit_type_t : int32_t {
+ INVALID,
+ CALLER_DATA,
+ INTERMEDIATE,
+ LOCAL_VAL, // index = local variable index
+ STACK_VAL, // index = stack index
+ GLOBAL_BASE,
+ MEMORY_BASE,
+ MEMORY_SIZE,
+};
+
+struct wasm_jit_val_t {
+ wasm_jit_type_t type;
+ int32_t index;
+
+ bool operator==(const wasm_jit_val_t& rhs) {
+ return type == rhs.type && index == rhs.index;
+ }
+ bool operator!=(const wasm_jit_val_t& rhs) {
+ return type != rhs.type || index != rhs.index;
+ }
+};
+
+struct wasm_jit_ctx_t {
+ std::array<wasm_jit_val_t, 30> reg_; // reg content
+ std::array<uint32_t, 30> reg_age_; // reg content
+ uint32_t age_;
+ std::vector<uint8_t> stack_valid_; // stack valid?
+
+ std::vector<wasm_jit_loc_t> stack_loc_; // location of wasm stack values
+ std::vector<wasm_jit_loc_t> local_loc_; // location of wasm local values
+
+ void init(wasm_jit_t* jit, wasm_func_t* f);
+};
+
+struct wasm_jit_t : public Xbyak::CodeGenerator {
+ wasm_module_t* mod_;
+ wasm_instance_t* ins_;
+ int max_prologue_size_;
+ bool enable_check_;
+ std::vector<uint8_t*> f_addr_;
+ uint8_t* run_fn_; // call helper function
+
+ // current function info
+ wasm_func_t* f_;
+ uint32_t funcidx_;
+ uint32_t num_locals_;
+ std::vector<uint8_t> local_types_;
+ uint32_t rsp_sub_;
+ std::array<uint8_t, 5> used_callee_;
+
+ // decoder info
+ uint32_t opcode_;
+ buffer_t buf_;
+ uint32_t next_bi_;
+ uint32_t stop_;
+
+ // register allocation context
+ wasm_jit_ctx_t ctx_;
+
+ // branch info
+ struct block_t {
+ uint32_t loop;
+ uint32_t index;
+ wasm_jit_ctx_t saved_ctx; // for loop, we need to save context early
+ std::vector<wasm_jit_ctx_t> br_ctxs; // brs' cpntext
+ };
+ std::vector<block_t> block_stack_;
+
+ wasm_jit_t(uint64_t code_size);
+
+ void compile_instance(wasm_instance_t* ins);
+ void emit_runtime_functions();
+ void compile_function(uint32_t index);
+ void run_fn(uint32_t index, wasm_value_t* args, wasm_value_t* r);
+
+ Xbyak::Reg64 to_xbyak_r64(int32_t index);
+ Xbyak::Reg32 to_xbyak_r32(int32_t index);
+ Xbyak::Reg16 to_xbyak_r16(int32_t index);
+ Xbyak::Reg8 to_xbyak_r8(int32_t index);
+ Xbyak::Xmm to_xbyak_xmm(int32_t index);
+
+ int32_t alloc_r(wasm_jit_val_t usage, uint8_t type);
+ void acquire_r(int32_t index, wasm_jit_val_t usage);
+ void use_r(int32_t index, wasm_jit_val_t usage);
+ void release_r(int32_t index); // mark a register as invalid
+
+ int32_t alloc_stk();
+ void release_stk(int32_t index);
+ void acquire_stk(int32_t index);
+
+ inline wasm_jit_loc_t peek_wasm_stk(uint32_t depth);
+ inline wasm_jit_loc_t pop_wasm_stk();
+
+ int32_t pop_r(uint8_t type); // pop to a 32bit register
+ void pop_r(int32_t index, uint8_t type); // pop to the given 32bit register
+ void push_r(int32_t index); // push a register
+
+ void restore_state(wasm_jit_ctx_t* from, wasm_jit_ctx_t* to);
+
+ typedef void (CodeGenerator::*oo_op_t)(const Xbyak::Operand&,
+ const Xbyak::Operand&);
+ typedef void (CodeGenerator::*or8_op_t)(const Xbyak::Operand&,
+ const Xbyak::Reg8&);
+ typedef void (CodeGenerator::*o_op_t)(const Xbyak::Operand&);
+ typedef void (CodeGenerator::*xo_op_t)(const Xbyak::Xmm&,
+ const Xbyak::Operand&);
+
+ int32_t pop_binop_r32_r32(oo_op_t binop);
+ int32_t pop_binop_xmm_xmm(xo_op_t binop);
+
+ void rbp_load_r(int32_t index, int32_t r, uint8_t type);
+ void rbp_save_r(int32_t index, int32_t r);
+
+ int32_t alloc_special(wasm_jit_type_t t,
+ size_t off); // load global base to a register
+ int32_t alloc_global_base(); // load global base to a register
+ int32_t alloc_memory_base(); // load memory base to a register
+ int32_t alloc_memory_size(); // load memory size to a register
+
+ void emit_lea_r_rip(int32_t r, size_t dest_offset);
+ void emit_mov_r_rip(int32_t r, size_t dest_offset);
+ void emit_call_internal(wasm_func_decl_t* sig, int is_direct, int index);
+ void emit_pop_result();
+
+ void emit_unreachable();
+ void emit_nop();
+ void emit_drop();
+ void emit_select();
+ void emit_local_get();
+ void emit_local_set();
+ void emit_local_tee();
+ void emit_global_get();
+ void emit_global_set();
+ void emit_i32_load();
+ void emit_f64_load();
+ void emit_i32_store();
+ void emit_f64_store();
+ void emit_i32_const();
+ void emit_f64_const();
+ void emit_i32_numeric();
+ void emit_i32_shift();
+ void emit_i32_convert();
+ void emit_f64_compute();
+ void emit_call();
+ void emit_call_indirect();
+ void emit_return();
+ void emit_block();
+ void emit_end();
+ void emit_br();
+ void emit_br_if();
+ void emit_br_table();
+};
diff --git a/weerun_parse.cpp b/weerun_parse.cpp
new file mode 100644
index 0000000..2e2a5df
--- /dev/null
+++ b/weerun_parse.cpp
@@ -0,0 +1,394 @@
+#include <algorithm>
+#include <csignal>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+
+#include "weerun.hpp"
+#include "weerun_jit.hpp"
+
+template <typename T>
+T decode(buffer_t* buf);
+
+template <typename T>
+std::vector<T> decode_vector(buffer_t* buf);
+
+void parse_custom_section(wasm_module_t* module, buffer_t* buf);
+void parse_type_section(wasm_module_t* module, buffer_t* buf);
+void parse_import_section(wasm_module_t* module, buffer_t* buf);
+void parse_function_section(wasm_module_t* module, buffer_t* buf);
+void parse_table_section(wasm_module_t* module, buffer_t* buf);
+void parse_memory_section(wasm_module_t* module, buffer_t* buf);
+void parse_global_section(wasm_module_t* module, buffer_t* buf);
+void parse_export_section(wasm_module_t* module, buffer_t* buf);
+void parse_start_section(wasm_module_t* module, buffer_t* buf);
+void parse_element_section(wasm_module_t* module, buffer_t* buf);
+void parse_code_section(wasm_module_t* module, buffer_t* buf);
+void parse_data_section(wasm_module_t* module, buffer_t* buf);
+
+extern "C" wasm_module_t* parse(buffer_t* buf) {
+ buf->ptr += 8; // magic and version
+ wasm_module_t* module = new wasm_module_t();
+ module->num_import_funcs_ = 0;
+ module->have_start_ = false;
+ while (buf->ptr != buf->end) {
+ byte type = read_u8(buf);
+ switch (type) {
+ case 0:
+ parse_custom_section(module, buf);
+ break;
+ case WASM_SECT_TYPE:
+ parse_type_section(module, buf);
+ break;
+ case WASM_SECT_IMPORT:
+ parse_import_section(module, buf);
+ break;
+ case WASM_SECT_FUNCTION:
+ parse_function_section(module, buf);
+ break;
+ case WASM_SECT_TABLE:
+ parse_table_section(module, buf);
+ break;
+ case WASM_SECT_MEMORY:
+ parse_memory_section(module, buf);
+ break;
+ case WASM_SECT_GLOBAL:
+ parse_global_section(module, buf);
+ break;
+ case WASM_SECT_EXPORT:
+ parse_export_section(module, buf);
+ break;
+ case WASM_SECT_START:
+ parse_start_section(module, buf);
+ break;
+ case WASM_SECT_ELEMENT:
+ parse_element_section(module, buf);
+ break;
+ case WASM_SECT_CODE:
+ parse_code_section(module, buf);
+ break;
+ case WASM_SECT_DATA:
+ parse_data_section(module, buf);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ return module;
+}
+
+wasm_instance_t* active_instance;
+uint32_t jit = 1;
+
+extern "C" wasm_typed_value_t run(const byte* start,
+ const byte* end,
+ uint32_t num_args,
+ wasm_value_t* args) {
+ buffer_t onstack_buf = {start, start, end};
+ wasm_module_t* module = parse(&onstack_buf);
+ wasm_instance_t* instance = module->create_instance();
+ wasm_value_t result;
+ if (jit != 0) {
+ result =
+ instance->run_jit(std::vector<wasm_value_t>(args, args + num_args));
+ } else {
+ result = instance->run(std::vector<wasm_value_t>(args, args + num_args));
+ }
+ wasm_typed_value_t tr = {module->funcs_[module->main_index_].sig_->ret_[0],
+ result};
+ delete instance;
+ delete module;
+ return tr;
+}
+
+void parse_custom_section(wasm_module_t* module, buffer_t* buf) {
+ (void)module;
+ uint32_t size = read_u32leb(buf);
+ const byte* section_end = buf->ptr + size;
+ std::string name = decode<std::string>(buf);
+ buf->ptr = section_end;
+ return;
+}
+
+void parse_type_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ module->sigs_ = decode_vector<wasm_func_decl_t>(buf);
+}
+
+void parse_import_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ std::vector<wasm_import_decl_t> imports =
+ decode_vector<wasm_import_decl_t>(buf);
+ // create imported functions
+ for (wasm_import_decl_t& imp : imports) {
+ switch (imp.type_) {
+ case wasm_import_decl_t::type::FUNCTION: {
+ std::string name = imp.module_ + "." + imp.name_;
+ auto result = g_runtime_funcs.find(name);
+ if (result == g_runtime_funcs.end()) {
+ std::cout << "error: " << name << " cannot be imported";
+ throw std::runtime_error(name + " not found");
+ }
+ wasm_func_t f;
+ f.sig_ = &module->sigs_[imp.funcindex_];
+ f.typeid_ = imp.funcindex_;
+ f.run_ = result->second.run_;
+ f.run_jit_ = result->second.run_jit_;
+ module->funcs_.push_back(f);
+ module->num_import_funcs_++;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+void parse_function_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ std::vector<uint32_t> funcidxs = decode_vector<uint32_t>(buf);
+ // create function objects
+ for (uint32_t func : funcidxs) {
+ wasm_func_t f;
+ f.sig_ = &module->sigs_[func];
+ f.typeid_ = func;
+ f.run_ = nullptr;
+ module->funcs_.push_back(f);
+ }
+}
+
+void parse_table_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ std::vector<wasm_table_decl_t> tables = decode_vector<wasm_table_decl_t>(buf);
+ module->table_ = tables[0];
+}
+
+void parse_memory_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ std::vector<wasm_memory_decl_t> memories =
+ decode_vector<wasm_memory_decl_t>(buf);
+ module->mem_limits_ = memories[0];
+}
+
+void parse_global_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ module->globals_ = decode_vector<wasm_global_t>(buf);
+}
+
+void parse_export_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ std::vector<wasm_export_t> exps = decode_vector<wasm_export_t>(buf);
+ // we assume that the module only exports a main function
+ module->main_index_ = exps[0].idx_;
+}
+
+void parse_start_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ module->have_start_ = true;
+ module->start_index_ = read_u32leb(buf);
+}
+
+void parse_element_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ module->elems_ = decode_vector<wasm_elem_decl_t>(buf);
+}
+
+std::vector<wasm_code_decl_t> decode_vector_code_decl(buffer_t* buf,
+ wasm_module_t* module);
+
+void parse_code_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ std::vector<wasm_code_decl_t> codes = decode_vector_code_decl(buf, module);
+ // start from the first non-imported functions
+ uint32_t funcidx = module->num_import_funcs_;
+ for (wasm_code_decl_t& code : codes) {
+ module->funcs_[funcidx].locals_ = code.locals_;
+ module->funcs_[funcidx].code_ = code.code_;
+ funcidx++;
+ }
+}
+
+void parse_data_section(wasm_module_t* module, buffer_t* buf) {
+ read_u32leb(buf);
+ module->datas_ = decode_vector<wasm_data_decl_t>(buf);
+}
+
+wasm_instance_t* wasm_module_t::create_instance() {
+ wasm_instance_t* instance = new wasm_instance_t();
+ instance->module_ = this;
+
+ // initialize memory using data
+ instance->memory_.resize(mem_limits_.init_ * wasm_page_size, 0);
+ for (wasm_data_decl_t& data : datas_) {
+ byte* mem = instance->memory_.data();
+ std::memcpy(mem + data.offset_, data.data_.data(), data.data_.size());
+ }
+
+ // initialize global variables
+ instance->globals_.resize(globals_.size());
+ for (uint32_t i = 0; i < globals_.size(); i++) {
+ switch (globals_[i].type_.type_) {
+ case WASM_TYPE_I32:
+ instance->globals_[i].val.i32 = globals_[i].val_.i32;
+ break;
+ case WASM_TYPE_F64:
+ instance->globals_[i].val.f64 = globals_[i].val_.f64;
+ break;
+ default:
+ instance->globals_[i].val.ref = globals_[i].val_.ref;
+ break;
+ }
+ }
+
+ // initialize table
+ instance->table_.resize(table_.init_, nullptr);
+ for (wasm_elem_decl_t& elem : elems_) {
+ instance->ensure_table(elem.offset_ + elem.funcidx_.size());
+ wasm_func_t** p = &instance->table_[elem.offset_];
+ for (uint32_t funcidx : elem.funcidx_) {
+ *p = &funcs_[funcidx];
+ p++;
+ }
+ }
+ instance->jit_table_.resize(instance->table_.size(), {-1, nullptr});
+ return instance;
+}
+
+void wasm_instance_t::push_value(wasm_value_t v) {
+ value_stack_.push_back(v);
+}
+
+wasm_value_t wasm_instance_t::pop_value() {
+ wasm_value_t result = value_stack_.back();
+ value_stack_.pop_back();
+ return result;
+}
+
+void wasm_instance_t::branch(uint32_t to_off) {
+ cur_frame_->pc_.ptr = cur_frame_->pc_.start + to_off;
+}
+
+void wasm_instance_t::push_frame(wasm_func_t* f) {
+ if (f->run_ != nullptr) {
+ // runtime functions
+ f->run_(this);
+ return;
+ }
+
+ // create a frame for function f
+ wasm_stack_frame_t frame;
+ frame.f_ = f;
+
+ // locals contains arguments and f's own locals
+ uint32_t num_args = f->sig_->args_.size();
+ frame.locals_.resize(num_args);
+ // move argument from stack
+ for (int i = num_args - 1; i >= 0; i--) {
+ frame.locals_[i] = pop_value();
+ }
+ // initialize locals
+ for (wasm_local_decl_t& local : f->locals_) {
+ wasm_value_t v;
+ switch (local.type_) {
+ case WASM_TYPE_I32:
+ v.val.i32 = 0;
+ break;
+ case WASM_TYPE_F64:
+ v.val.f64 = 0;
+ break;
+ case WASM_TYPE_EXTERNREF:
+ v.val.ref = nullptr;
+ }
+ for (uint32_t i = 0; i < local.count_; i++) {
+ frame.locals_.push_back(v);
+ }
+ }
+
+ // set pc to the start of function bytecode
+ frame.pc_.start = frame.pc_.ptr = f->code_.data();
+ frame.pc_.end = frame.pc_.start + f->code_.size();
+ frames_.push_back(frame);
+
+ // update current frame
+ cur_frame_ = &frames_.back();
+}
+
+void wasm_instance_t::pop_frame() {
+ // pop the from when a funtcion reaches the end
+ frames_.pop_back();
+ cur_frame_ = &frames_.back();
+}
+
+wasm_value_t wasm_instance_t::run(std::vector<wasm_value_t> args) {
+ if (module_->have_start_ == true) {
+ run_function(module_->start_index_);
+ }
+ // create the frame for main()
+ for (wasm_value_t& v : args) {
+ value_stack_.push_back(v);
+ }
+ active_instance = this;
+ run_function(module_->main_index_);
+ // return the value on stack;
+ return value_stack_.back();
+}
+
+wasm_value_t wasm_instance_t::run_jit(std::vector<wasm_value_t> args) {
+ wasm_jit_t jit(1 << 20); // 1M code size
+ jit.compile_instance(this);
+
+ active_instance = this;
+ if (module_->have_start_ == true) {
+ jit.run_fn(module_->start_index_, nullptr, nullptr);
+ }
+ wasm_value_t r;
+ jit.run_fn(module_->main_index_, args.data(), &r);
+ return r;
+}
+
+void wasm_instance_t::run_function(uint32_t funcidx) {
+ trapped = WASM_TRAP_REASON_NOTRAP;
+ push_frame(&module_->funcs_[funcidx]);
+
+ // start interpretation
+ while (trapped == WASM_TRAP_REASON_NOTRAP) {
+ byte opcode = read_u8(&cur_frame_->pc_);
+ const wasm_inst_desc_t* desc = &g_inst_desc[opcode];
+ desc->run(this, opcode);
+ }
+
+ if (trapped != WASM_TRAP_REASON_FUNCEND) {
+ std::cout << "!trap" << std::endl;
+ std::exit(0);
+ }
+}
+
+void wasm_instance_t::trap(uint32_t reason) {
+ trapped = reason;
+}
+
+uint32_t wasm_instance_t::read_u32leb() {
+ return ::read_u32leb(&cur_frame_->pc_);
+}
+
+int32_t wasm_instance_t::read_i32leb() {
+ return ::read_i32leb(&cur_frame_->pc_);
+}
+
+double wasm_instance_t::read_double() {
+ double result = *(double*)(cur_frame_->pc_.ptr);
+ cur_frame_->pc_.ptr += sizeof(double);
+ return result;
+}
+
+byte wasm_instance_t::read_byte() {
+ byte result = *(byte*)(cur_frame_->pc_.ptr);
+ cur_frame_->pc_.ptr += sizeof(byte);
+ return result;
+}
+
+void wasm_instance_t::ensure_table(uint32_t offset) {
+ if (table_.size() < offset) {
+ table_.resize(offset, nullptr);
+ }
+}
diff --git a/weerun_runtime.cpp b/weerun_runtime.cpp
new file mode 100644
index 0000000..e499670
--- /dev/null
+++ b/weerun_runtime.cpp
@@ -0,0 +1,300 @@
+#include <cmath>
+#include <cstdio>
+#include <ctime>
+#include <iostream>
+#include <map>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "weerun.hpp"
+
+void trap();
+
+std::unordered_map<std::string, wasm_rt_func_t> g_runtime_funcs;
+
+static void weewasm_puti(wasm_instance_t* ins) {
+ wasm_value_t v = ins->pop_value();
+ std::printf("%d", (int32_t)v.val.i32);
+}
+
+static void weewasm_putd(wasm_instance_t* ins) {
+ wasm_value_t v = ins->pop_value();
+ std::printf("%f", v.val.f64);
+}
+
+static void weewasm_puts(wasm_instance_t* ins) {
+ wasm_value_t size = ins->pop_value();
+ wasm_value_t start = ins->pop_value();
+ const byte* base = ins->memory_.data() + start.val.i32;
+ std::cout << std::string(base, base + size.val.i32);
+}
+
+static void weewasm_puti_jit(int32_t v) {
+ std::printf("%d", v);
+}
+
+static void weewasm_putd_jit(double v) {
+ std::printf("%f", v);
+}
+
+static void weewasm_puts_jit(uint32_t start, uint32_t size) {
+ const byte* base = active_instance->memory_.data() + start;
+ std::cout << std::string(base, base + size);
+}
+
+static inline wasm_key_t convert_key(wasm_externref_t* ref) {
+ union {
+ uint64_t i64;
+ double f64;
+ void* ptr;
+ } u;
+ if (ref == nullptr) {
+ return {WASM_EXTERN_NULL, 0};
+ }
+ switch (ref->type_) {
+ case WASM_EXTERN_BOXI32:
+ u.i64 = ((wasm_e_box_t*)ref)->i32_;
+ break;
+ case WASM_EXTERN_BOXF64:
+ u.f64 = ((wasm_e_box_t*)ref)->f64_;
+ break;
+ default:
+ u.ptr = (void*)ref;
+ break;
+ }
+ return {ref->type_, u.i64};
+}
+
+static void weewasm_obj_new(wasm_instance_t* ins) {
+ wasm_value_t v;
+ v.val.ref = (void*)(new wasm_e_object_t());
+ ins->push_value(v);
+}
+
+static void weewasm_obj_box_i32(wasm_instance_t* ins) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXI32);
+ wasm_value_t x = ins->pop_value();
+ obj->i32_ = (int32_t)x.val.i32;
+ wasm_value_t v;
+ v.val.ref = (void*)(obj);
+ ins->push_value(v);
+}
+
+static void weewasm_obj_box_f64(wasm_instance_t* ins) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXF64);
+ wasm_value_t x = ins->pop_value();
+ obj->f64_ = x.val.f64;
+ wasm_value_t v;
+ v.val.ref = (void*)(obj);
+ ins->push_value(v);
+}
+
+static void weewasm_obj_get(wasm_instance_t* ins) {
+ wasm_value_t key = ins->pop_value();
+ wasm_value_t o = ins->pop_value();
+ if (key.val.ref == nullptr || o.val.ref == nullptr) {
+ ins->trap(WASM_TRAP_REASON_NULLEXTERNREF);
+ return;
+ }
+ wasm_e_object_t* obj = (wasm_e_object_t*)o.val.ref;
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ wasm_value_t v;
+ auto result = obj->map_.find(convert_key((wasm_externref_t*)key.val.ref));
+ if (result == obj->map_.end()) {
+ v.val.ref = nullptr;
+ } else {
+ v.val.ref = (void*)result->second;
+ }
+ ins->push_value(v);
+ return;
+}
+
+static void weewasm_obj_set(wasm_instance_t* ins) {
+ wasm_value_t value = ins->pop_value();
+ wasm_value_t key = ins->pop_value();
+ wasm_value_t o = ins->pop_value();
+ if (key.val.ref == nullptr || o.val.ref == nullptr) {
+ ins->trap(WASM_TRAP_REASON_NULLEXTERNREF);
+ return;
+ }
+ wasm_e_object_t* obj = (wasm_e_object_t*)o.val.ref;
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ obj->map_[convert_key((wasm_externref_t*)key.val.ref)] =
+ (wasm_externref_t*)value.val.ref;
+ return;
+}
+
+static void weewasm_i32_unbox(wasm_instance_t* ins) {
+ wasm_value_t value = ins->pop_value();
+ wasm_e_box_t* box = (wasm_e_box_t*)value.val.ref;
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXI32) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ wasm_value_t v;
+ v.val.i32 = (uint32_t)box->i32_;
+ ins->push_value(v);
+ return;
+}
+
+static void weewasm_f64_unbox(wasm_instance_t* ins) {
+ wasm_value_t value = ins->pop_value();
+ wasm_e_box_t* box = (wasm_e_box_t*)value.val.ref;
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXF64) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ wasm_value_t v;
+ v.val.f64 = box->f64_;
+ ins->push_value(v);
+ return;
+}
+
+static void weewasm_obj_eq(wasm_instance_t* ins) {
+ wasm_value_t rhs = ins->pop_value();
+ wasm_value_t lhs = ins->pop_value();
+ wasm_value_t v;
+ v.val.i32 = (convert_key((wasm_externref_t*)lhs.val.ref) ==
+ convert_key((wasm_externref_t*)rhs.val.ref))
+ ? 1
+ : 0;
+ ins->push_value(v);
+}
+
+static wasm_e_object_t* weewasm_obj_new_jit() {
+ return new wasm_e_object_t();
+}
+
+static wasm_e_box_t* weewasm_obj_box_i32_jit(int32_t v) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXI32);
+ obj->i32_ = v;
+ return obj;
+}
+
+static wasm_e_box_t* weewasm_obj_box_f64_jit(double v) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXF64);
+ obj->f64_ = v;
+ return obj;
+}
+
+static wasm_externref_t* weewasm_obj_get_jit(wasm_e_object_t* obj,
+ wasm_externref_t* key) {
+ if (key == nullptr || obj == nullptr) {
+ trap();
+ }
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ trap();
+ }
+ auto result = obj->map_.find(convert_key(key));
+ if (result == obj->map_.end()) {
+ return nullptr;
+ }
+ return result->second;
+}
+
+static void weewasm_obj_set_jit(wasm_e_object_t* obj,
+ wasm_externref_t* key,
+ wasm_externref_t* value) {
+ if (key == nullptr || obj == nullptr) {
+ trap();
+ }
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ trap();
+ }
+ obj->map_[convert_key(key)] = value;
+}
+
+static int32_t weewasm_i32_unbox_jit(wasm_e_box_t* box) {
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXI32) {
+ trap();
+ }
+ return box->i32_;
+}
+
+static double weewasm_f64_unbox_jit(wasm_e_box_t* box) {
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXF64) {
+ trap();
+ }
+ return box->f64_;
+}
+
+static uint32_t weewasm_obj_eq_jit(wasm_externref_t* lhs,
+ wasm_externref_t* rhs) {
+ return (convert_key(lhs) == convert_key(rhs)) ? 1 : 0;
+}
+
+extern "C" void init_runtime() {
+ g_runtime_funcs["weewasm.puti"] = {weewasm_puti, (void*)weewasm_puti_jit};
+ g_runtime_funcs["weewasm.putd"] = {weewasm_putd, (void*)weewasm_putd_jit};
+ g_runtime_funcs["weewasm.puts"] = {weewasm_puts, (void*)weewasm_puts_jit};
+ g_runtime_funcs["weewasm.obj.new"] = {weewasm_obj_new,
+ (void*)weewasm_obj_new_jit};
+ g_runtime_funcs["weewasm.obj.box_i32"] = {weewasm_obj_box_i32,
+ (void*)weewasm_obj_box_i32_jit};
+ g_runtime_funcs["weewasm.obj.box_f64"] = {weewasm_obj_box_f64,
+ (void*)weewasm_obj_box_f64_jit};
+ g_runtime_funcs["weewasm.obj.get"] = {weewasm_obj_get,
+ (void*)weewasm_obj_get_jit};
+ g_runtime_funcs["weewasm.obj.set"] = {weewasm_obj_set,
+ (void*)weewasm_obj_set_jit};
+ g_runtime_funcs["weewasm.i32.unbox"] = {weewasm_i32_unbox,
+ (void*)weewasm_i32_unbox_jit};
+ g_runtime_funcs["weewasm.f64.unbox"] = {weewasm_f64_unbox,
+ (void*)weewasm_f64_unbox_jit};
+ g_runtime_funcs["weewasm.obj.eq"] = {weewasm_obj_eq,
+ (void*)weewasm_obj_eq_jit};
+}
+
+static void libc_sin(wasm_instance_t* ins) {
+ wasm_value_t x = ins->pop_value();
+ x.val.f64 = std::sin(x.val.f64);
+ ins->push_value(x);
+}
+
+static void libc_cos(wasm_instance_t* ins) {
+ wasm_value_t x = ins->pop_value();
+ x.val.f64 = std::cos(x.val.f64);
+ ins->push_value(x);
+}
+
+static void libc_rand(wasm_instance_t* ins) {
+ wasm_value_t x;
+ x.val.i32 = std::rand();
+ ins->push_value(x);
+}
+
+static void libc_time(wasm_instance_t* ins) {
+ wasm_value_t x;
+ x.val.i32 = std::time(nullptr);
+ ins->push_value(x);
+}
+
+static void libc_srand(wasm_instance_t* ins) {
+ wasm_value_t x = ins->pop_value();
+ std::srand(x.val.i32);
+}
+
+int32_t libc_time_jit() {
+ return std::time(nullptr);
+}
+
+extern "C" void init_libc_runtime() {
+ static std::vector<wasm_func_decl_t> func_decls;
+ func_decls.push_back({{WASM_TYPE_F64}, {WASM_TYPE_F64}});
+ func_decls.push_back({{}, {WASM_TYPE_I32}});
+ func_decls.push_back({{WASM_TYPE_I32}, {}});
+ g_runtime_funcs["libc.sin"] = {
+ libc_sin, (void*)static_cast<double (*)(double)>(std::sin)};
+ g_runtime_funcs["libc.cos"] = {
+ libc_cos, (void*)static_cast<double (*)(double)>(std::cos)};
+ g_runtime_funcs["libc.rand"] = {libc_rand, (void*)std::rand};
+ g_runtime_funcs["libc.time"] = {libc_time, (void*)libc_time_jit};
+ g_runtime_funcs["libc.srand"] = {libc_srand, (void*)std::srand};
+}
diff --git a/weewasm.h b/weewasm.h
new file mode 100644
index 0000000..c8c2305
--- /dev/null
+++ b/weewasm.h
@@ -0,0 +1,102 @@
+#pragma once
+
+#define WASM_MAGIC 0x6d736100u
+#define WASM_VERSION 1
+
+// Section constants
+#define WASM_SECT_TYPE 1
+#define WASM_SECT_IMPORT 2
+#define WASM_SECT_FUNCTION 3
+#define WASM_SECT_TABLE 4
+#define WASM_SECT_MEMORY 5
+#define WASM_SECT_GLOBAL 6
+#define WASM_SECT_EXPORT 7
+#define WASM_SECT_START 8
+#define WASM_SECT_ELEMENT 9
+#define WASM_SECT_CODE 10
+#define WASM_SECT_DATA 11
+
+// Opcode constants
+#define WASM_OP_UNREACHABLE 0x00 /* "unreachable" */
+#define WASM_OP_NOP 0x01 /* "nop" */
+#define WASM_OP_BLOCK 0x02 /* "block" BLOCKT */
+#define WASM_OP_LOOP 0x03 /* "loop" BLOCKT */
+#define WASM_OP_END 0x0B /* "end" */
+#define WASM_OP_BR 0x0C /* "br" LABEL */
+#define WASM_OP_BR_IF 0x0D /* "br_if" LABEL */
+#define WASM_OP_BR_TABLE 0x0E /* "br_table" LABELS */
+#define WASM_OP_RETURN 0x0F /* "return" */
+#define WASM_OP_CALL 0x10 /* "call" FUNC */
+#define WASM_OP_CALL_INDIRECT 0x11 /* "call_indirect" SIG_TABLE */
+#define WASM_OP_DROP 0x1A /* "drop" */
+#define WASM_OP_SELECT 0x1B /* "select" */
+#define WASM_OP_LOCAL_GET 0x20 /* "local.get" LOCAL */
+#define WASM_OP_LOCAL_SET 0x21 /* "local.set" LOCAL */
+#define WASM_OP_LOCAL_TEE 0x22 /* "local.tee" LOCAL */
+#define WASM_OP_GLOBAL_GET 0x23 /* "global.get" GLOBAL */
+#define WASM_OP_GLOBAL_SET 0x24 /* "global.set" GLOBAL */
+#define WASM_OP_I32_LOAD 0x28 /* "i32.load" MEMARG */
+#define WASM_OP_F64_LOAD 0x2B /* "f64.load" MEMARG */
+#define WASM_OP_I32_LOAD8_S 0x2C /* "i32.load8_s" MEMARG */
+#define WASM_OP_I32_LOAD8_U 0x2D /* "i32.load8_u" MEMARG */
+#define WASM_OP_I32_LOAD16_S 0x2E /* "i32.load16_s" MEMARG */
+#define WASM_OP_I32_LOAD16_U 0x2F /* "i32.load16_u" MEMARG */
+#define WASM_OP_I32_STORE 0x36 /* "i32.store" MEMARG */
+#define WASM_OP_F64_STORE 0x39 /* "f64.store" MEMARG */
+#define WASM_OP_I32_STORE8 0x3A /* "i32.store8" MEMARG */
+#define WASM_OP_I32_STORE16 0x3B /* "i32.store16" MEMARG */
+#define WASM_OP_I32_CONST 0x41 /* "i32.const" I32 */
+#define WASM_OP_F64_CONST 0x44 /* "f64.const" F64 */
+#define WASM_OP_I32_EQZ 0x45 /* "i32.eqz" */
+#define WASM_OP_I32_EQ 0x46 /* "i32.eq" */
+#define WASM_OP_I32_NE 0x47 /* "i32.ne" */
+#define WASM_OP_I32_LT_S 0x48 /* "i32.lt_s" */
+#define WASM_OP_I32_LT_U 0x49 /* "i32.lt_u" */
+#define WASM_OP_I32_GT_S 0x4A /* "i32.gt_s" */
+#define WASM_OP_I32_GT_U 0x4B /* "i32.gt_u" */
+#define WASM_OP_I32_LE_S 0x4C /* "i32.le_s" */
+#define WASM_OP_I32_LE_U 0x4D /* "i32.le_u" */
+#define WASM_OP_I32_GE_S 0x4E /* "i32.ge_s" */
+#define WASM_OP_I32_GE_U 0x4F /* "i32.ge_u" */
+#define WASM_OP_F64_EQ 0x61 /* "f64.eq" */
+#define WASM_OP_F64_NE 0x62 /* "f64.ne" */
+#define WASM_OP_F64_LT 0x63 /* "f64.lt" */
+#define WASM_OP_F64_GT 0x64 /* "f64.gt" */
+#define WASM_OP_F64_LE 0x65 /* "f64.le" */
+#define WASM_OP_F64_GE 0x66 /* "f64.ge" */
+#define WASM_OP_I32_CLZ 0x67 /* "i32.clz" */
+#define WASM_OP_I32_CTZ 0x68 /* "i32.ctz" */
+#define WASM_OP_I32_POPCNT 0x69 /* "i32.popcnt" */
+#define WASM_OP_I32_ADD 0x6A /* "i32.add" */
+#define WASM_OP_I32_SUB 0x6B /* "i32.sub" */
+#define WASM_OP_I32_MUL 0x6C /* "i32.mul" */
+#define WASM_OP_I32_DIV_S 0x6D /* "i32.div_s" */
+#define WASM_OP_I32_DIV_U 0x6E /* "i32.div_u" */
+#define WASM_OP_I32_REM_S 0x6F /* "i32.rem_s" */
+#define WASM_OP_I32_REM_U 0x70 /* "i32.rem_u" */
+#define WASM_OP_I32_AND 0x71 /* "i32.and" */
+#define WASM_OP_I32_OR 0x72 /* "i32.or" */
+#define WASM_OP_I32_XOR 0x73 /* "i32.xor" */
+#define WASM_OP_I32_SHL 0x74 /* "i32.shl" */
+#define WASM_OP_I32_SHR_S 0x75 /* "i32.shr_s" */
+#define WASM_OP_I32_SHR_U 0x76 /* "i32.shr_u" */
+#define WASM_OP_I32_ROTL 0x77 /* "i32.rotl" */
+#define WASM_OP_I32_ROTR 0x78 /* "i32.rotr" */
+#define WASM_OP_F64_ADD 0xA0 /* "f64.add" */
+#define WASM_OP_F64_SUB 0xA1 /* "f64.sub" */
+#define WASM_OP_F64_MUL 0xA2 /* "f64.mul" */
+#define WASM_OP_F64_DIV 0xA3 /* "f64.div" */
+#define WASM_OP_I32_TRUNC_F64_S 0xAA /* "i32.trunc_f64_s" */
+#define WASM_OP_I32_TRUNC_F64_U 0xAB /* "i32.trunc_f64_u" */
+#define WASM_OP_F64_CONVERT_I32_S 0xB7 /* "f64.convert_i32_s" */
+#define WASM_OP_F64_CONVERT_I32_U 0xB8 /* "f64.convert_i32_u" */
+#define WASM_OP_I32_EXTEND8_S 0xC0 /* "i32.extend8_s" */
+#define WASM_OP_I32_EXTEND16_S 0xC1 /* "i32.extend16_s" */
+
+#define WASM_OP_JMP 0xF0 /* "jmp" */
+#define WASM_OP_JMP_IF 0xF1 /* "jmp_if */
+#define WASM_OP_JMP_TABLE 0xF2 /* jmp_table */
+
+#define WEEWASM_INTRINSIC_PUTI 0x01
+#define WEEWASM_INTRINSIC_PUTD 0x02
+#define WEEWASM_INTRINSIC_PUTS 0x03
diff --git a/xbyak/COPYRIGHT b/xbyak/COPYRIGHT
new file mode 100644
index 0000000..55da9ce
--- /dev/null
+++ b/xbyak/COPYRIGHT
@@ -0,0 +1,27 @@
+
+Copyright (c) 2007 MITSUNARI Shigeo
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+Neither the name of the copyright owner nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
new file mode 100644
index 0000000..e080708
--- /dev/null
+++ b/xbyak/xbyak.h
@@ -0,0 +1,2951 @@
+#pragma once
+#ifndef XBYAK_XBYAK_H_
+#define XBYAK_XBYAK_H_
+/*!
+ @file xbyak.h
+ @brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++
+ @author herumi
+ @url https://github.com/herumi/xbyak
+ @note modified new BSD license
+ http://opensource.org/licenses/BSD-3-Clause
+*/
+#if (not +0) && !defined(XBYAK_NO_OP_NAMES) // trick to detect whether 'not' is operator or not
+ #define XBYAK_NO_OP_NAMES
+#endif
+
+#include <stdio.h> // for debug print
+#include <assert.h>
+#include <list>
+#include <string>
+#include <algorithm>
+#ifndef NDEBUG
+#include <iostream>
+#endif
+
+// #define XBYAK_DISABLE_AVX512
+
+#if !defined(XBYAK_USE_MMAP_ALLOCATOR) && !defined(XBYAK_DONT_USE_MMAP_ALLOCATOR)
+ #define XBYAK_USE_MMAP_ALLOCATOR
+#endif
+#if !defined(__GNUC__) || defined(__MINGW32__)
+ #undef XBYAK_USE_MMAP_ALLOCATOR
+#endif
+
+#ifdef __GNUC__
+ #define XBYAK_GNUC_PREREQ(major, minor) ((__GNUC__) * 100 + (__GNUC_MINOR__) >= (major) * 100 + (minor))
+#else
+ #define XBYAK_GNUC_PREREQ(major, minor) 0
+#endif
+
+// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
+#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
+ ((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
+ #include <unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::unordered_set
+ #include <unordered_map>
+ #define XBYAK_STD_UNORDERED_MAP std::unordered_map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap
+
+/*
+ Clang/llvm-gcc and ICC-EDG in 'GCC-mode' always claim to be GCC 4.2, using
+ libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version).
+*/
+#elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__)
+ #include <tr1/unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
+ #include <tr1/unordered_map>
+ #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
+
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600)
+ #include <unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
+ #include <unordered_map>
+ #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
+
+#else
+ #include <set>
+ #define XBYAK_STD_UNORDERED_SET std::set
+ #include <map>
+ #define XBYAK_STD_UNORDERED_MAP std::map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::multimap
+#endif
+#ifdef _WIN32
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+ #include <windows.h>
+ #include <malloc.h>
+ #ifdef _MSC_VER
+ #define XBYAK_TLS __declspec(thread)
+ #else
+ #define XBYAK_TLS __thread
+ #endif
+#elif defined(__GNUC__)
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <stdlib.h>
+ #define XBYAK_TLS __thread
+#endif
+#if defined(__APPLE__) && !defined(XBYAK_DONT_USE_MAP_JIT)
+ #define XBYAK_USE_MAP_JIT
+ #include <sys/sysctl.h>
+ #ifndef MAP_JIT
+ #define MAP_JIT 0x800
+ #endif
+#endif
+#if !defined(_MSC_VER) || (_MSC_VER >= 1600)
+ #include <stdint.h>
+#endif
+
+// MFD_CLOEXEC defined only linux 3.17 or later.
+// Android wraps the memfd_create syscall from API version 30.
+#if !defined(MFD_CLOEXEC) || (defined(__ANDROID__) && __ANDROID_API__ < 30)
+ #undef XBYAK_USE_MEMFD
+#endif
+
+#if defined(_WIN64) || defined(__MINGW64__) || (defined(__CYGWIN__) && defined(__x86_64__))
+ #define XBYAK64_WIN
+#elif defined(__x86_64__)
+ #define XBYAK64_GCC
+#endif
+#if !defined(XBYAK64) && !defined(XBYAK32)
+ #if defined(XBYAK64_GCC) || defined(XBYAK64_WIN)
+ #define XBYAK64
+ #else
+ #define XBYAK32
+ #endif
+#endif
+
+#if (__cplusplus >= 201103) || (defined(_MSC_VER) && _MSC_VER >= 1900)
+ #undef XBYAK_TLS
+ #define XBYAK_TLS thread_local
+ #define XBYAK_VARIADIC_TEMPLATE
+ #define XBYAK_NOEXCEPT noexcept
+#else
+ #define XBYAK_NOEXCEPT throw()
+#endif
+
+// require c++14 or later
+// Visual Studio 2017 version 15.0 or later
+// g++-6 or later
+#if ((__cplusplus >= 201402L) && !(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ <= 5))) || (defined(_MSC_VER) && _MSC_VER >= 1910)
+ #define XBYAK_CONSTEXPR constexpr
+#else
+ #define XBYAK_CONSTEXPR
+#endif
+
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable : 4514) /* remove inline function */
+ #pragma warning(disable : 4786) /* identifier is too long */
+ #pragma warning(disable : 4503) /* name is too long */
+ #pragma warning(disable : 4127) /* constant expresison */
+#endif
+
+// disable -Warray-bounds because it may be a bug of gcc. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104603
+#if defined(__GNUC__) && !defined(__clang__)
+ #define XBYAK_DISABLE_WARNING_ARRAY_BOUNDS
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+
+namespace Xbyak {
+
+enum {
+ DEFAULT_MAX_CODE_SIZE = 4096,
+ VERSION = 0x6670 /* 0xABCD = A.BC(.D) */
+};
+
+#ifndef MIE_INTEGER_TYPE_DEFINED
+#define MIE_INTEGER_TYPE_DEFINED
+// for backward compatibility
+typedef uint64_t uint64;
+typedef int64_t sint64;
+typedef uint32_t uint32;
+typedef uint16_t uint16;
+typedef uint8_t uint8;
+#endif
+
+#ifndef MIE_ALIGN
+ #ifdef _MSC_VER
+ #define MIE_ALIGN(x) __declspec(align(x))
+ #else
+ #define MIE_ALIGN(x) __attribute__((aligned(x)))
+ #endif
+#endif
+#ifndef MIE_PACK // for shufps
+ #define MIE_PACK(x, y, z, w) ((x) * 64 + (y) * 16 + (z) * 4 + (w))
+#endif
+
+enum {
+ ERR_NONE = 0,
+ ERR_BAD_ADDRESSING,
+ ERR_CODE_IS_TOO_BIG,
+ ERR_BAD_SCALE,
+ ERR_ESP_CANT_BE_INDEX,
+ ERR_BAD_COMBINATION,
+ ERR_BAD_SIZE_OF_REGISTER,
+ ERR_IMM_IS_TOO_BIG,
+ ERR_BAD_ALIGN,
+ ERR_LABEL_IS_REDEFINED,
+ ERR_LABEL_IS_TOO_FAR,
+ ERR_LABEL_IS_NOT_FOUND,
+ ERR_CODE_ISNOT_COPYABLE,
+ ERR_BAD_PARAMETER,
+ ERR_CANT_PROTECT,
+ ERR_CANT_USE_64BIT_DISP,
+ ERR_OFFSET_IS_TOO_BIG,
+ ERR_MEM_SIZE_IS_NOT_SPECIFIED,
+ ERR_BAD_MEM_SIZE,
+ ERR_BAD_ST_COMBINATION,
+ ERR_OVER_LOCAL_LABEL, // not used
+ ERR_UNDER_LOCAL_LABEL,
+ ERR_CANT_ALLOC,
+ ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW,
+ ERR_BAD_PROTECT_MODE,
+ ERR_BAD_PNUM,
+ ERR_BAD_TNUM,
+ ERR_BAD_VSIB_ADDRESSING,
+ ERR_CANT_CONVERT,
+ ERR_LABEL_ISNOT_SET_BY_L,
+ ERR_LABEL_IS_ALREADY_SET_BY_L,
+ ERR_BAD_LABEL_STR,
+ ERR_MUNMAP,
+ ERR_OPMASK_IS_ALREADY_SET,
+ ERR_ROUNDING_IS_ALREADY_SET,
+ ERR_K0_IS_INVALID,
+ ERR_EVEX_IS_INVALID,
+ ERR_SAE_IS_INVALID,
+ ERR_ER_IS_INVALID,
+ ERR_INVALID_BROADCAST,
+ ERR_INVALID_OPMASK_WITH_MEMORY,
+ ERR_INVALID_ZERO,
+ ERR_INVALID_RIP_IN_AUTO_GROW,
+ ERR_INVALID_MIB_ADDRESS,
+ ERR_X2APIC_IS_NOT_SUPPORTED,
+ ERR_NOT_SUPPORTED,
+ ERR_SAME_REGS_ARE_INVALID,
+ ERR_INTERNAL // Put it at last.
+};
+
+inline const char *ConvertErrorToString(int err)
+{
+ static const char *errTbl[] = {
+ "none",
+ "bad addressing",
+ "code is too big",
+ "bad scale",
+ "esp can't be index",
+ "bad combination",
+ "bad size of register",
+ "imm is too big",
+ "bad align",
+ "label is redefined",
+ "label is too far",
+ "label is not found",
+ "code is not copyable",
+ "bad parameter",
+ "can't protect",
+ "can't use 64bit disp(use (void*))",
+ "offset is too big",
+ "MEM size is not specified",
+ "bad mem size",
+ "bad st combination",
+ "over local label",
+ "under local label",
+ "can't alloc",
+ "T_SHORT is not supported in AutoGrow",
+ "bad protect mode",
+ "bad pNum",
+ "bad tNum",
+ "bad vsib addressing",
+ "can't convert",
+ "label is not set by L()",
+ "label is already set by L()",
+ "bad label string",
+ "err munmap",
+ "opmask is already set",
+ "rounding is already set",
+ "k0 is invalid",
+ "evex is invalid",
+ "sae(suppress all exceptions) is invalid",
+ "er(embedded rounding) is invalid",
+ "invalid broadcast",
+ "invalid opmask with memory",
+ "invalid zero",
+ "invalid rip in AutoGrow",
+ "invalid mib address",
+ "x2APIC is not supported",
+ "not supported",
+ "same regs are invalid",
+ "internal error"
+ };
+ assert(ERR_INTERNAL + 1 == sizeof(errTbl) / sizeof(*errTbl));
+ return err <= ERR_INTERNAL ? errTbl[err] : "unknown err";
+}
+
+#ifdef XBYAK_NO_EXCEPTION
+namespace local {
+
+inline int& GetErrorRef() {
+ static XBYAK_TLS int err = 0;
+ return err;
+}
+
+inline void SetError(int err) {
+ if (local::GetErrorRef()) return; // keep the first err code
+ local::GetErrorRef() = err;
+}
+
+} // local
+
+inline void ClearError() {
+ local::GetErrorRef() = 0;
+}
+inline int GetError() { return Xbyak::local::GetErrorRef(); }
+
+#define XBYAK_THROW(err) { Xbyak::local::SetError(err); return; }
+#define XBYAK_THROW_RET(err, r) { Xbyak::local::SetError(err); return r; }
+
+#else
+class Error : public std::exception {
+ int err_;
+public:
+ explicit Error(int err) : err_(err)
+ {
+ if (err_ < 0 || err_ > ERR_INTERNAL) {
+ err_ = ERR_INTERNAL;
+ }
+ }
+ operator int() const { return err_; }
+ const char *what() const XBYAK_NOEXCEPT
+ {
+ return ConvertErrorToString(err_);
+ }
+};
+
+// dummy functions
+inline void ClearError() { }
+inline int GetError() { return 0; }
+
+inline const char *ConvertErrorToString(const Error& err)
+{
+ return err.what();
+}
+
+#define XBYAK_THROW(err) { throw Error(err); }
+#define XBYAK_THROW_RET(err, r) { throw Error(err); }
+
+#endif
+
+inline void *AlignedMalloc(size_t size, size_t alignment)
+{
+#ifdef __MINGW32__
+ return __mingw_aligned_malloc(size, alignment);
+#elif defined(_WIN32)
+ return _aligned_malloc(size, alignment);
+#else
+ void *p;
+ int ret = posix_memalign(&p, alignment, size);
+ return (ret == 0) ? p : 0;
+#endif
+}
+
+inline void AlignedFree(void *p)
+{
+#ifdef __MINGW32__
+ __mingw_aligned_free(p);
+#elif defined(_MSC_VER)
+ _aligned_free(p);
+#else
+ free(p);
+#endif
+}
+
+template<class To, class From>
+inline const To CastTo(From p) XBYAK_NOEXCEPT
+{
+ return (const To)(size_t)(p);
+}
+namespace inner {
+
+static const size_t ALIGN_PAGE_SIZE = 4096;
+
+inline bool IsInDisp8(uint32_t x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
+inline bool IsInInt32(uint64_t x) { return ~uint64_t(0x7fffffffu) <= x || x <= 0x7FFFFFFFU; }
+
+inline uint32_t VerifyInInt32(uint64_t x)
+{
+#if defined(XBYAK64) && !defined(__ILP32__)
+ if (!IsInInt32(x)) XBYAK_THROW_RET(ERR_OFFSET_IS_TOO_BIG, 0)
+#endif
+ return static_cast<uint32_t>(x);
+}
+
+enum LabelMode {
+ LasIs, // as is
+ Labs, // absolute
+ LaddTop // (addr + top) for mov(reg, label) with AutoGrow
+};
+
+} // inner
+
+/*
+ custom allocator
+*/
+struct Allocator {
+ explicit Allocator(const std::string& = "") {} // same interface with MmapAllocator
+ virtual uint8_t *alloc(size_t size) { return reinterpret_cast<uint8_t*>(AlignedMalloc(size, inner::ALIGN_PAGE_SIZE)); }
+ virtual void free(uint8_t *p) { AlignedFree(p); }
+ virtual ~Allocator() {}
+ /* override to return false if you call protect() manually */
+ virtual bool useProtect() const { return true; }
+};
+
+#ifdef XBYAK_USE_MMAP_ALLOCATOR
+#ifdef XBYAK_USE_MAP_JIT
+namespace util {
+
+inline int getMacOsVersionPure()
+{
+ char buf[64];
+ size_t size = sizeof(buf);
+ int err = sysctlbyname("kern.osrelease", buf, &size, NULL, 0);
+ if (err != 0) return 0;
+ char *endp;
+ int major = strtol(buf, &endp, 10);
+ if (*endp != '.') return 0;
+ return major;
+}
+
+inline int getMacOsVersion()
+{
+ static const int version = getMacOsVersionPure();
+ return version;
+}
+
+} // util
+#endif
+class MmapAllocator : public Allocator {
+ struct Allocation {
+ size_t size;
+#if defined(XBYAK_USE_MEMFD)
+ // fd_ is only used with XBYAK_USE_MEMFD. We keep the file open
+ // during the lifetime of each allocation in order to support
+ // checkpoint/restore by unprivileged users.
+ int fd;
+#endif
+ };
+ const std::string name_; // only used with XBYAK_USE_MEMFD
+ typedef XBYAK_STD_UNORDERED_MAP<uintptr_t, Allocation> AllocationList;
+ AllocationList allocList_;
+public:
+ explicit MmapAllocator(const std::string& name = "xbyak") : name_(name) {}
+ uint8_t *alloc(size_t size)
+ {
+ const size_t alignedSizeM1 = inner::ALIGN_PAGE_SIZE - 1;
+ size = (size + alignedSizeM1) & ~alignedSizeM1;
+#if defined(MAP_ANONYMOUS)
+ int mode = MAP_PRIVATE | MAP_ANONYMOUS;
+#elif defined(MAP_ANON)
+ int mode = MAP_PRIVATE | MAP_ANON;
+#else
+ #error "not supported"
+#endif
+#if defined(XBYAK_USE_MAP_JIT)
+ const int mojaveVersion = 18;
+ if (util::getMacOsVersion() >= mojaveVersion) mode |= MAP_JIT;
+#endif
+ int fd = -1;
+#if defined(XBYAK_USE_MEMFD)
+ fd = memfd_create(name_.c_str(), MFD_CLOEXEC);
+ if (fd != -1) {
+ mode = MAP_SHARED;
+ if (ftruncate(fd, size) != 0) {
+ close(fd);
+ XBYAK_THROW_RET(ERR_CANT_ALLOC, 0)
+ }
+ }
+#endif
+ void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, mode, fd, 0);
+ if (p == MAP_FAILED) {
+ if (fd != -1) close(fd);
+ XBYAK_THROW_RET(ERR_CANT_ALLOC, 0)
+ }
+ assert(p);
+ Allocation &alloc = allocList_[(uintptr_t)p];
+ alloc.size = size;
+#if defined(XBYAK_USE_MEMFD)
+ alloc.fd = fd;
+#endif
+ return (uint8_t*)p;
+ }
+ void free(uint8_t *p)
+ {
+ if (p == 0) return;
+ AllocationList::iterator i = allocList_.find((uintptr_t)p);
+ if (i == allocList_.end()) XBYAK_THROW(ERR_BAD_PARAMETER)
+ if (munmap((void*)i->first, i->second.size) < 0) XBYAK_THROW(ERR_MUNMAP)
+#if defined(XBYAK_USE_MEMFD)
+ if (i->second.fd != -1) close(i->second.fd);
+#endif
+ allocList_.erase(i);
+ }
+};
+#else
+typedef Allocator MmapAllocator;
+#endif
+
+class Address;
+class Reg;
+
+class Operand {
+ static const uint8_t EXT8BIT = 0x20;
+ unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil
+ unsigned int kind_:10;
+ unsigned int bit_:14;
+protected:
+ unsigned int zero_:1;
+ unsigned int mask_:3;
+ unsigned int rounding_:3;
+ void setIdx(int idx) { idx_ = idx; }
+public:
+ enum Kind {
+ NONE = 0,
+ MEM = 1 << 0,
+ REG = 1 << 1,
+ MMX = 1 << 2,
+ FPU = 1 << 3,
+ XMM = 1 << 4,
+ YMM = 1 << 5,
+ ZMM = 1 << 6,
+ OPMASK = 1 << 7,
+ BNDREG = 1 << 8,
+ TMM = 1 << 9
+ };
+ enum Code {
+#ifdef XBYAK64
+ RAX = 0, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15,
+ R8D = 8, R9D, R10D, R11D, R12D, R13D, R14D, R15D,
+ R8W = 8, R9W, R10W, R11W, R12W, R13W, R14W, R15W,
+ R8B = 8, R9B, R10B, R11B, R12B, R13B, R14B, R15B,
+ SPL = 4, BPL, SIL, DIL,
+#endif
+ EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
+ AX = 0, CX, DX, BX, SP, BP, SI, DI,
+ AL = 0, CL, DL, BL, AH, CH, DH, BH
+ };
+ XBYAK_CONSTEXPR Operand() : idx_(0), kind_(0), bit_(0), zero_(0), mask_(0), rounding_(0) { }
+ XBYAK_CONSTEXPR Operand(int idx, Kind kind, int bit, bool ext8bit = 0)
+ : idx_(static_cast<uint8_t>(idx | (ext8bit ? EXT8BIT : 0)))
+ , kind_(kind)
+ , bit_(bit)
+ , zero_(0), mask_(0), rounding_(0)
+ {
+ assert((bit_ & (bit_ - 1)) == 0); // bit must be power of two
+ }
+ XBYAK_CONSTEXPR Kind getKind() const { return static_cast<Kind>(kind_); }
+ XBYAK_CONSTEXPR int getIdx() const { return idx_ & (EXT8BIT - 1); }
+ XBYAK_CONSTEXPR bool isNone() const { return kind_ == 0; }
+ XBYAK_CONSTEXPR bool isMMX() const { return is(MMX); }
+ XBYAK_CONSTEXPR bool isXMM() const { return is(XMM); }
+ XBYAK_CONSTEXPR bool isYMM() const { return is(YMM); }
+ XBYAK_CONSTEXPR bool isZMM() const { return is(ZMM); }
+ XBYAK_CONSTEXPR bool isTMM() const { return is(TMM); }
+ XBYAK_CONSTEXPR bool isXMEM() const { return is(XMM | MEM); }
+ XBYAK_CONSTEXPR bool isYMEM() const { return is(YMM | MEM); }
+ XBYAK_CONSTEXPR bool isZMEM() const { return is(ZMM | MEM); }
+ XBYAK_CONSTEXPR bool isOPMASK() const { return is(OPMASK); }
+ XBYAK_CONSTEXPR bool isBNDREG() const { return is(BNDREG); }
+ XBYAK_CONSTEXPR bool isREG(int bit = 0) const { return is(REG, bit); }
+ XBYAK_CONSTEXPR bool isMEM(int bit = 0) const { return is(MEM, bit); }
+ XBYAK_CONSTEXPR bool isFPU() const { return is(FPU); }
+ XBYAK_CONSTEXPR bool isExt8bit() const { return (idx_ & EXT8BIT) != 0; }
+ XBYAK_CONSTEXPR bool isExtIdx() const { return (getIdx() & 8) != 0; }
+ XBYAK_CONSTEXPR bool isExtIdx2() const { return (getIdx() & 16) != 0; }
+ XBYAK_CONSTEXPR bool hasEvex() const { return isZMM() || isExtIdx2() || getOpmaskIdx() || getRounding(); }
+ XBYAK_CONSTEXPR bool hasRex() const { return isExt8bit() || isREG(64) || isExtIdx(); }
+ XBYAK_CONSTEXPR bool hasZero() const { return zero_; }
+ XBYAK_CONSTEXPR int getOpmaskIdx() const { return mask_; }
+ XBYAK_CONSTEXPR int getRounding() const { return rounding_; }
+ void setKind(Kind kind)
+ {
+ if ((kind & (XMM|YMM|ZMM|TMM)) == 0) return;
+ kind_ = kind;
+ bit_ = kind == XMM ? 128 : kind == YMM ? 256 : kind == ZMM ? 512 : 8192;
+ }
+ // err if MMX/FPU/OPMASK/BNDREG
+ void setBit(int bit);
+ void setOpmaskIdx(int idx, bool /*ignore_idx0*/ = true)
+ {
+ if (mask_) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET)
+ mask_ = idx;
+ }
+ void setRounding(int idx)
+ {
+ if (rounding_) XBYAK_THROW(ERR_ROUNDING_IS_ALREADY_SET)
+ rounding_ = idx;
+ }
+ void setZero() { zero_ = true; }
+ // ah, ch, dh, bh?
+ bool isHigh8bit() const
+ {
+ if (!isBit(8)) return false;
+ if (isExt8bit()) return false;
+ const int idx = getIdx();
+ return AH <= idx && idx <= BH;
+ }
+ // any bit is accetable if bit == 0
+ XBYAK_CONSTEXPR bool is(int kind, uint32_t bit = 0) const
+ {
+ return (kind == 0 || (kind_ & kind)) && (bit == 0 || (bit_ & bit)); // cf. you can set (8|16)
+ }
+ XBYAK_CONSTEXPR bool isBit(uint32_t bit) const { return (bit_ & bit) != 0; }
+ XBYAK_CONSTEXPR uint32_t getBit() const { return bit_; }
+ const char *toString() const
+ {
+ const int idx = getIdx();
+ if (kind_ == REG) {
+ if (isExt8bit()) {
+ static const char *tbl[4] = { "spl", "bpl", "sil", "dil" };
+ return tbl[idx - 4];
+ }
+ static const char *tbl[4][16] = {
+ { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" },
+ { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" },
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" },
+ { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" },
+ };
+ return tbl[bit_ == 8 ? 0 : bit_ == 16 ? 1 : bit_ == 32 ? 2 : 3][idx];
+ } else if (isOPMASK()) {
+ static const char *tbl[8] = { "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" };
+ return tbl[idx];
+ } else if (isTMM()) {
+ static const char *tbl[8] = {
+ "tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7"
+ };
+ return tbl[idx];
+ } else if (isZMM()) {
+ static const char *tbl[32] = {
+ "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15",
+ "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31"
+ };
+ return tbl[idx];
+ } else if (isYMM()) {
+ static const char *tbl[32] = {
+ "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15",
+ "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31"
+ };
+ return tbl[idx];
+ } else if (isXMM()) {
+ static const char *tbl[32] = {
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
+ "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
+ };
+ return tbl[idx];
+ } else if (isMMX()) {
+ static const char *tbl[8] = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" };
+ return tbl[idx];
+ } else if (isFPU()) {
+ static const char *tbl[8] = { "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7" };
+ return tbl[idx];
+ } else if (isBNDREG()) {
+ static const char *tbl[4] = { "bnd0", "bnd1", "bnd2", "bnd3" };
+ return tbl[idx];
+ }
+ XBYAK_THROW_RET(ERR_INTERNAL, 0);
+ }
+ bool isEqualIfNotInherited(const Operand& rhs) const { return idx_ == rhs.idx_ && kind_ == rhs.kind_ && bit_ == rhs.bit_ && zero_ == rhs.zero_ && mask_ == rhs.mask_ && rounding_ == rhs.rounding_; }
+ bool operator==(const Operand& rhs) const;
+ bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
+ const Address& getAddress() const;
+ const Reg& getReg() const;
+};
+
+inline void Operand::setBit(int bit)
+{
+ if (bit != 8 && bit != 16 && bit != 32 && bit != 64 && bit != 128 && bit != 256 && bit != 512 && bit != 8192) goto ERR;
+ if (isBit(bit)) return;
+ if (is(MEM | OPMASK)) {
+ bit_ = bit;
+ return;
+ }
+ if (is(REG | XMM | YMM | ZMM | TMM)) {
+ int idx = getIdx();
+ // err if converting ah, bh, ch, dh
+ if (isREG(8) && (4 <= idx && idx < 8) && !isExt8bit()) goto ERR;
+ Kind kind = REG;
+ switch (bit) {
+ case 8:
+ if (idx >= 16) goto ERR;
+#ifdef XBYAK32
+ if (idx >= 4) goto ERR;
+#else
+ if (4 <= idx && idx < 8) idx |= EXT8BIT;
+#endif
+ break;
+ case 16:
+ case 32:
+ case 64:
+ if (idx >= 16) goto ERR;
+ break;
+ case 128: kind = XMM; break;
+ case 256: kind = YMM; break;
+ case 512: kind = ZMM; break;
+ case 8192: kind = TMM; break;
+ }
+ idx_ = idx;
+ kind_ = kind;
+ bit_ = bit;
+ if (bit >= 128) return; // keep mask_ and rounding_
+ mask_ = 0;
+ rounding_ = 0;
+ return;
+ }
+ERR:
+ XBYAK_THROW(ERR_CANT_CONVERT)
+}
+
+class Label;
+
+struct Reg8;
+struct Reg16;
+struct Reg32;
+#ifdef XBYAK64
+struct Reg64;
+#endif
+class Reg : public Operand {
+public:
+ XBYAK_CONSTEXPR Reg() { }
+ XBYAK_CONSTEXPR Reg(int idx, Kind kind, int bit = 0, bool ext8bit = false) : Operand(idx, kind, bit, ext8bit) { }
+ // convert to Reg8/Reg16/Reg32/Reg64/XMM/YMM/ZMM
+ Reg changeBit(int bit) const { Reg r(*this); r.setBit(bit); return r; }
+ uint8_t getRexW() const { return isREG(64) ? 8 : 0; }
+ uint8_t getRexR() const { return isExtIdx() ? 4 : 0; }
+ uint8_t getRexX() const { return isExtIdx() ? 2 : 0; }
+ uint8_t getRexB() const { return isExtIdx() ? 1 : 0; }
+ uint8_t getRex(const Reg& base = Reg()) const
+ {
+ uint8_t rex = getRexW() | getRexR() | base.getRexW() | base.getRexB();
+ if (rex || isExt8bit() || base.isExt8bit()) rex |= 0x40;
+ return rex;
+ }
+ Reg8 cvt8() const;
+ Reg16 cvt16() const;
+ Reg32 cvt32() const;
+#ifdef XBYAK64
+ Reg64 cvt64() const;
+#endif
+};
+
+inline const Reg& Operand::getReg() const
+{
+ assert(!isMEM());
+ return static_cast<const Reg&>(*this);
+}
+
+struct Reg8 : public Reg {
+ explicit XBYAK_CONSTEXPR Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { }
+};
+
+struct Reg16 : public Reg {
+ explicit XBYAK_CONSTEXPR Reg16(int idx = 0) : Reg(idx, Operand::REG, 16) { }
+};
+
+struct Mmx : public Reg {
+ explicit XBYAK_CONSTEXPR Mmx(int idx = 0, Kind kind = Operand::MMX, int bit = 64) : Reg(idx, kind, bit) { }
+};
+
+struct EvexModifierRounding {
+ enum {
+ T_RN_SAE = 1,
+ T_RD_SAE = 2,
+ T_RU_SAE = 3,
+ T_RZ_SAE = 4,
+ T_SAE = 5
+ };
+ explicit XBYAK_CONSTEXPR EvexModifierRounding(int rounding) : rounding(rounding) {}
+ int rounding;
+};
+struct EvexModifierZero{ XBYAK_CONSTEXPR EvexModifierZero() {}};
+
+struct Xmm : public Mmx {
+ explicit XBYAK_CONSTEXPR Xmm(int idx = 0, Kind kind = Operand::XMM, int bit = 128) : Mmx(idx, kind, bit) { }
+ XBYAK_CONSTEXPR Xmm(Kind kind, int idx) : Mmx(idx, kind, kind == XMM ? 128 : kind == YMM ? 256 : 512) { }
+ Xmm operator|(const EvexModifierRounding& emr) const { Xmm r(*this); r.setRounding(emr.rounding); return r; }
+ Xmm copyAndSetIdx(int idx) const { Xmm ret(*this); ret.setIdx(idx); return ret; }
+ Xmm copyAndSetKind(Operand::Kind kind) const { Xmm ret(*this); ret.setKind(kind); return ret; }
+};
+
+struct Ymm : public Xmm {
+ explicit XBYAK_CONSTEXPR Ymm(int idx = 0, Kind kind = Operand::YMM, int bit = 256) : Xmm(idx, kind, bit) { }
+ Ymm operator|(const EvexModifierRounding& emr) const { Ymm r(*this); r.setRounding(emr.rounding); return r; }
+};
+
+struct Zmm : public Ymm {
+ explicit XBYAK_CONSTEXPR Zmm(int idx = 0) : Ymm(idx, Operand::ZMM, 512) { }
+ Zmm operator|(const EvexModifierRounding& emr) const { Zmm r(*this); r.setRounding(emr.rounding); return r; }
+};
+
+#ifdef XBYAK64
+struct Tmm : public Reg {
+ explicit XBYAK_CONSTEXPR Tmm(int idx = 0, Kind kind = Operand::TMM, int bit = 8192) : Reg(idx, kind, bit) { }
+};
+#endif
+
+struct Opmask : public Reg {
+ explicit XBYAK_CONSTEXPR Opmask(int idx = 0) : Reg(idx, Operand::OPMASK, 64) {}
+};
+
+struct BoundsReg : public Reg {
+ explicit XBYAK_CONSTEXPR BoundsReg(int idx = 0) : Reg(idx, Operand::BNDREG, 128) {}
+};
+
+template<class T>T operator|(const T& x, const Opmask& k) { T r(x); r.setOpmaskIdx(k.getIdx()); return r; }
+template<class T>T operator|(const T& x, const EvexModifierZero&) { T r(x); r.setZero(); return r; }
+template<class T>T operator|(const T& x, const EvexModifierRounding& emr) { T r(x); r.setRounding(emr.rounding); return r; }
+
+struct Fpu : public Reg {
+ explicit XBYAK_CONSTEXPR Fpu(int idx = 0) : Reg(idx, Operand::FPU, 32) { }
+};
+
+struct Reg32e : public Reg {
+ explicit XBYAK_CONSTEXPR Reg32e(int idx, int bit) : Reg(idx, Operand::REG, bit) {}
+};
+struct Reg32 : public Reg32e {
+ explicit XBYAK_CONSTEXPR Reg32(int idx = 0) : Reg32e(idx, 32) {}
+};
+#ifdef XBYAK64
+struct Reg64 : public Reg32e {
+ explicit XBYAK_CONSTEXPR Reg64(int idx = 0) : Reg32e(idx, 64) {}
+};
+struct RegRip {
+ int64_t disp_;
+ const Label* label_;
+ bool isAddr_;
+ explicit XBYAK_CONSTEXPR RegRip(int64_t disp = 0, const Label* label = 0, bool isAddr = false) : disp_(disp), label_(label), isAddr_(isAddr) {}
+ friend const RegRip operator+(const RegRip& r, int disp) {
+ return RegRip(r.disp_ + disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator-(const RegRip& r, int disp) {
+ return RegRip(r.disp_ - disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator+(const RegRip& r, int64_t disp) {
+ return RegRip(r.disp_ + disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator-(const RegRip& r, int64_t disp) {
+ return RegRip(r.disp_ - disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator+(const RegRip& r, const Label& label) {
+ if (r.label_ || r.isAddr_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegRip());
+ return RegRip(r.disp_, &label);
+ }
+ friend const RegRip operator+(const RegRip& r, const void *addr) {
+ if (r.label_ || r.isAddr_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegRip());
+ return RegRip(r.disp_ + (int64_t)addr, 0, true);
+ }
+};
+#endif
+
+inline Reg8 Reg::cvt8() const
+{
+ Reg r = changeBit(8); return Reg8(r.getIdx(), r.isExt8bit());
+}
+
+inline Reg16 Reg::cvt16() const
+{
+ return Reg16(changeBit(16).getIdx());
+}
+
+inline Reg32 Reg::cvt32() const
+{
+ return Reg32(changeBit(32).getIdx());
+}
+
+#ifdef XBYAK64
+inline Reg64 Reg::cvt64() const
+{
+ return Reg64(changeBit(64).getIdx());
+}
+#endif
+
+#ifndef XBYAK_DISABLE_SEGMENT
+// not derived from Reg
+class Segment {
+ int idx_;
+public:
+ enum {
+ es, cs, ss, ds, fs, gs
+ };
+ explicit XBYAK_CONSTEXPR Segment(int idx) : idx_(idx) { assert(0 <= idx_ && idx_ < 6); }
+ int getIdx() const { return idx_; }
+ const char *toString() const
+ {
+ static const char tbl[][3] = {
+ "es", "cs", "ss", "ds", "fs", "gs"
+ };
+ return tbl[idx_];
+ }
+};
+#endif
+
+class RegExp {
+public:
+#ifdef XBYAK64
+ enum { i32e = 32 | 64 };
+#else
+ enum { i32e = 32 };
+#endif
+ XBYAK_CONSTEXPR RegExp(size_t disp = 0) : scale_(0), disp_(disp) { }
+ XBYAK_CONSTEXPR RegExp(const Reg& r, int scale = 1)
+ : scale_(scale)
+ , disp_(0)
+ {
+ if (!r.isREG(i32e) && !r.is(Reg::XMM|Reg::YMM|Reg::ZMM|Reg::TMM)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
+ if (scale == 0) return;
+ if (scale != 1 && scale != 2 && scale != 4 && scale != 8) XBYAK_THROW(ERR_BAD_SCALE)
+ if (r.getBit() >= 128 || scale != 1) { // xmm/ymm is always index
+ index_ = r;
+ } else {
+ base_ = r;
+ }
+ }
+ bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); }
+ RegExp optimize() const
+ {
+ RegExp exp = *this;
+ // [reg * 2] => [reg + reg]
+ if (index_.isBit(i32e) && !base_.getBit() && scale_ == 2) {
+ exp.base_ = index_;
+ exp.scale_ = 1;
+ }
+ return exp;
+ }
+ bool operator==(const RegExp& rhs) const
+ {
+ return base_ == rhs.base_ && index_ == rhs.index_ && disp_ == rhs.disp_ && scale_ == rhs.scale_;
+ }
+ const Reg& getBase() const { return base_; }
+ const Reg& getIndex() const { return index_; }
+ int getScale() const { return scale_; }
+ size_t getDisp() const { return disp_; }
+ XBYAK_CONSTEXPR void verify() const
+ {
+ if (base_.getBit() >= 128) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
+ if (index_.getBit() && index_.getBit() <= 64) {
+ if (index_.getIdx() == Operand::ESP) XBYAK_THROW(ERR_ESP_CANT_BE_INDEX)
+ if (base_.getBit() && base_.getBit() != index_.getBit()) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
+ }
+ }
+ friend RegExp operator+(const RegExp& a, const RegExp& b);
+ friend RegExp operator-(const RegExp& e, size_t disp);
+ uint8_t getRex() const
+ {
+ uint8_t rex = index_.getRexX() | base_.getRexB();
+ return rex ? uint8_t(rex | 0x40) : 0;
+ }
+private:
+ /*
+ [base_ + index_ * scale_ + disp_]
+ base : Reg32e, index : Reg32e(w/o esp), Xmm, Ymm
+ */
+ Reg base_;
+ Reg index_;
+ int scale_;
+ size_t disp_;
+};
+
+inline RegExp operator+(const RegExp& a, const RegExp& b)
+{
+ if (a.index_.getBit() && b.index_.getBit()) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp())
+ RegExp ret = a;
+ if (!ret.index_.getBit()) { ret.index_ = b.index_; ret.scale_ = b.scale_; }
+ if (b.base_.getBit()) {
+ if (ret.base_.getBit()) {
+ if (ret.index_.getBit()) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp())
+ // base + base => base + index * 1
+ ret.index_ = b.base_;
+ // [reg + esp] => [esp + reg]
+ if (ret.index_.getIdx() == Operand::ESP) std::swap(ret.base_, ret.index_);
+ ret.scale_ = 1;
+ } else {
+ ret.base_ = b.base_;
+ }
+ }
+ ret.disp_ += b.disp_;
+ return ret;
+}
+inline RegExp operator*(const Reg& r, int scale)
+{
+ return RegExp(r, scale);
+}
+inline RegExp operator*(int scale, const Reg& r)
+{
+ return r * scale;
+}
+inline RegExp operator-(const RegExp& e, size_t disp)
+{
+ RegExp ret = e;
+ ret.disp_ -= disp;
+ return ret;
+}
+
+// 2nd parameter for constructor of CodeArray(maxSize, userPtr, alloc)
+void *const AutoGrow = (void*)1; //-V566
+void *const DontSetProtectRWE = (void*)2; //-V566
+
+class CodeArray {
+ enum Type {
+ USER_BUF = 1, // use userPtr(non alignment, non protect)
+ ALLOC_BUF, // use new(alignment, protect)
+ AUTO_GROW // automatically move and grow memory if necessary
+ };
+ CodeArray(const CodeArray& rhs);
+ void operator=(const CodeArray&);
+ bool isAllocType() const { return type_ == ALLOC_BUF || type_ == AUTO_GROW; }
+ struct AddrInfo {
+ size_t codeOffset; // position to write
+ size_t jmpAddr; // value to write
+ int jmpSize; // size of jmpAddr
+ inner::LabelMode mode;
+ AddrInfo(size_t _codeOffset, size_t _jmpAddr, int _jmpSize, inner::LabelMode _mode)
+ : codeOffset(_codeOffset), jmpAddr(_jmpAddr), jmpSize(_jmpSize), mode(_mode) {}
+ uint64_t getVal(const uint8_t *top) const
+ {
+ uint64_t disp = (mode == inner::LaddTop) ? jmpAddr + size_t(top) : (mode == inner::LasIs) ? jmpAddr : jmpAddr - size_t(top);
+ if (jmpSize == 4) disp = inner::VerifyInInt32(disp);
+ return disp;
+ }
+ };
+ typedef std::list<AddrInfo> AddrInfoList;
+ AddrInfoList addrInfoList_;
+ const Type type_;
+#ifdef XBYAK_USE_MMAP_ALLOCATOR
+ MmapAllocator defaultAllocator_;
+#else
+ Allocator defaultAllocator_;
+#endif
+ Allocator *alloc_;
+protected:
+ size_t maxSize_;
+ uint8_t *top_;
+ size_t size_;
+ bool isCalledCalcJmpAddress_;
+
+ bool useProtect() const { return alloc_->useProtect(); }
+ /*
+ allocate new memory and copy old data to the new area
+ */
+ void growMemory()
+ {
+ const size_t newSize = (std::max<size_t>)(DEFAULT_MAX_CODE_SIZE, maxSize_ * 2);
+ uint8_t *newTop = alloc_->alloc(newSize);
+ if (newTop == 0) XBYAK_THROW(ERR_CANT_ALLOC)
+ for (size_t i = 0; i < size_; i++) newTop[i] = top_[i];
+ alloc_->free(top_);
+ top_ = newTop;
+ maxSize_ = newSize;
+ }
+ /*
+ calc jmp address for AutoGrow mode
+ */
+ void calcJmpAddress()
+ {
+ if (isCalledCalcJmpAddress_) return;
+ for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) {
+ uint64_t disp = i->getVal(top_);
+ rewrite(i->codeOffset, disp, i->jmpSize);
+ }
+ isCalledCalcJmpAddress_ = true;
+ }
+public:
+ enum ProtectMode {
+ PROTECT_RW = 0, // read/write
+ PROTECT_RWE = 1, // read/write/exec
+ PROTECT_RE = 2 // read/exec
+ };
+ explicit CodeArray(size_t maxSize, void *userPtr = 0, Allocator *allocator = 0)
+ : type_(userPtr == AutoGrow ? AUTO_GROW : (userPtr == 0 || userPtr == DontSetProtectRWE) ? ALLOC_BUF : USER_BUF)
+ , alloc_(allocator ? allocator : (Allocator*)&defaultAllocator_)
+ , maxSize_(maxSize)
+ , top_(type_ == USER_BUF ? reinterpret_cast<uint8_t*>(userPtr) : alloc_->alloc((std::max<size_t>)(maxSize, 1)))
+ , size_(0)
+ , isCalledCalcJmpAddress_(false)
+ {
+ if (maxSize_ > 0 && top_ == 0) XBYAK_THROW(ERR_CANT_ALLOC)
+ if ((type_ == ALLOC_BUF && userPtr != DontSetProtectRWE && useProtect()) && !setProtectMode(PROTECT_RWE, false)) {
+ alloc_->free(top_);
+ XBYAK_THROW(ERR_CANT_PROTECT)
+ }
+ }
+ virtual ~CodeArray()
+ {
+ if (isAllocType()) {
+ if (useProtect()) setProtectModeRW(false);
+ alloc_->free(top_);
+ }
+ }
+ bool setProtectMode(ProtectMode mode, bool throwException = true)
+ {
+ bool isOK = protect(top_, maxSize_, mode);
+ if (isOK) return true;
+ if (throwException) XBYAK_THROW_RET(ERR_CANT_PROTECT, false)
+ return false;
+ }
+ bool setProtectModeRE(bool throwException = true) { return setProtectMode(PROTECT_RE, throwException); }
+ bool setProtectModeRW(bool throwException = true) { return setProtectMode(PROTECT_RW, throwException); }
+ void resetSize()
+ {
+ size_ = 0;
+ addrInfoList_.clear();
+ isCalledCalcJmpAddress_ = false;
+ }
+ void db(int code)
+ {
+ if (size_ >= maxSize_) {
+ if (type_ == AUTO_GROW) {
+ growMemory();
+ } else {
+ XBYAK_THROW(ERR_CODE_IS_TOO_BIG)
+ }
+ }
+ top_[size_++] = static_cast<uint8_t>(code);
+ }
+ void db(const uint8_t *code, size_t codeSize)
+ {
+ for (size_t i = 0; i < codeSize; i++) db(code[i]);
+ }
+ void db(uint64_t code, size_t codeSize)
+ {
+ if (codeSize > 8) XBYAK_THROW(ERR_BAD_PARAMETER)
+ for (size_t i = 0; i < codeSize; i++) db(static_cast<uint8_t>(code >> (i * 8)));
+ }
+ void dw(uint32_t code) { db(code, 2); }
+ void dd(uint32_t code) { db(code, 4); }
+ void dq(uint64_t code) { db(code, 8); }
+ const uint8_t *getCode() const { return top_; }
+ template<class F>
+ const F getCode() const { return reinterpret_cast<F>(top_); }
+ const uint8_t *getCurr() const { return &top_[size_]; }
+ template<class F>
+ const F getCurr() const { return reinterpret_cast<F>(&top_[size_]); }
+ size_t getSize() const { return size_; }
+ void setSize(size_t size)
+ {
+ if (size > maxSize_) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG)
+ size_ = size;
+ }
+ void dump() const
+ {
+ const uint8_t *p = getCode();
+ size_t bufSize = getSize();
+ size_t remain = bufSize;
+ for (int i = 0; i < 4; i++) {
+ size_t disp = 16;
+ if (remain < 16) {
+ disp = remain;
+ }
+ for (size_t j = 0; j < 16; j++) {
+ if (j < disp) {
+ printf("%02X", p[i * 16 + j]);
+ }
+ }
+ putchar('\n');
+ remain -= disp;
+ if (remain == 0) {
+ break;
+ }
+ }
+ }
+ /*
+ @param offset [in] offset from top
+ @param disp [in] offset from the next of jmp
+ @param size [in] write size(1, 2, 4, 8)
+ */
+ void rewrite(size_t offset, uint64_t disp, size_t size)
+ {
+ assert(offset < maxSize_);
+ if (size != 1 && size != 2 && size != 4 && size != 8) XBYAK_THROW(ERR_BAD_PARAMETER)
+ uint8_t *const data = top_ + offset;
+ for (size_t i = 0; i < size; i++) {
+ data[i] = static_cast<uint8_t>(disp >> (i * 8));
+ }
+ }
+ void save(size_t offset, size_t val, int size, inner::LabelMode mode)
+ {
+ addrInfoList_.push_back(AddrInfo(offset, val, size, mode));
+ }
+ bool isAutoGrow() const { return type_ == AUTO_GROW; }
+ bool isCalledCalcJmpAddress() const { return isCalledCalcJmpAddress_; }
+ /**
+ change exec permission of memory
+ @param addr [in] buffer address
+ @param size [in] buffer size
+ @param protectMode [in] mode(RW/RWE/RE)
+ @return true(success), false(failure)
+ */
+ static inline bool protect(const void *addr, size_t size, int protectMode)
+ {
+#if defined(_WIN32)
+ const DWORD c_rw = PAGE_READWRITE;
+ const DWORD c_rwe = PAGE_EXECUTE_READWRITE;
+ const DWORD c_re = PAGE_EXECUTE_READ;
+ DWORD mode;
+#else
+ const int c_rw = PROT_READ | PROT_WRITE;
+ const int c_rwe = PROT_READ | PROT_WRITE | PROT_EXEC;
+ const int c_re = PROT_READ | PROT_EXEC;
+ int mode;
+#endif
+ switch (protectMode) {
+ case PROTECT_RW: mode = c_rw; break;
+ case PROTECT_RWE: mode = c_rwe; break;
+ case PROTECT_RE: mode = c_re; break;
+ default:
+ return false;
+ }
+#if defined(_WIN32)
+ DWORD oldProtect;
+ return VirtualProtect(const_cast<void*>(addr), size, mode, &oldProtect) != 0;
+#elif defined(__GNUC__)
+ size_t pageSize = sysconf(_SC_PAGESIZE);
+ size_t iaddr = reinterpret_cast<size_t>(addr);
+ size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
+#ifndef NDEBUG
+ if (pageSize != 4096) fprintf(stderr, "large page(%zd) is used. not tested enough.\n", pageSize);
+#endif
+ return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
+#else
+ return true;
+#endif
+ }
+ /**
+ get aligned memory pointer
+ @param addr [in] address
+ @param alignedSize [in] power of two
+ @return aligned addr by alingedSize
+ */
+ static inline uint8_t *getAlignedAddress(uint8_t *addr, size_t alignedSize = 16)
+ {
+ return reinterpret_cast<uint8_t*>((reinterpret_cast<size_t>(addr) + alignedSize - 1) & ~(alignedSize - static_cast<size_t>(1)));
+ }
+};
+
+class Address : public Operand {
+public:
+ enum Mode {
+ M_ModRM,
+ M_64bitDisp,
+ M_rip,
+ M_ripAddr
+ };
+ XBYAK_CONSTEXPR Address(uint32_t sizeBit, bool broadcast, const RegExp& e)
+ : Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), broadcast_(broadcast)
+ {
+ e_.verify();
+ }
+#ifdef XBYAK64
+ explicit XBYAK_CONSTEXPR Address(size_t disp)
+ : Operand(0, MEM, 64), e_(disp), label_(0), mode_(M_64bitDisp), broadcast_(false){ }
+ XBYAK_CONSTEXPR Address(uint32_t sizeBit, bool broadcast, const RegRip& addr)
+ : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), broadcast_(broadcast) { }
+#endif
+ RegExp getRegExp(bool optimize = true) const
+ {
+ return optimize ? e_.optimize() : e_;
+ }
+ Mode getMode() const { return mode_; }
+ bool is32bit() const { return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; }
+ bool isOnlyDisp() const { return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax
+ size_t getDisp() const { return e_.getDisp(); }
+ uint8_t getRex() const
+ {
+ if (mode_ != M_ModRM) return 0;
+ return getRegExp().getRex();
+ }
+ bool is64bitDisp() const { return mode_ == M_64bitDisp; } // for moffset
+ bool isBroadcast() const { return broadcast_; }
+ const Label* getLabel() const { return label_; }
+ bool operator==(const Address& rhs) const
+ {
+ return getBit() == rhs.getBit() && e_ == rhs.e_ && label_ == rhs.label_ && mode_ == rhs.mode_ && broadcast_ == rhs.broadcast_;
+ }
+ bool operator!=(const Address& rhs) const { return !operator==(rhs); }
+ bool isVsib() const { return e_.isVsib(); }
+private:
+ RegExp e_;
+ const Label* label_;
+ Mode mode_;
+ bool broadcast_;
+};
+
+inline const Address& Operand::getAddress() const
+{
+ assert(isMEM());
+ return static_cast<const Address&>(*this);
+}
+
+inline bool Operand::operator==(const Operand& rhs) const
+{
+ if (isMEM() && rhs.isMEM()) return this->getAddress() == rhs.getAddress();
+ return isEqualIfNotInherited(rhs);
+}
+
+class AddressFrame {
+ void operator=(const AddressFrame&);
+ AddressFrame(const AddressFrame&);
+public:
+ const uint32_t bit_;
+ const bool broadcast_;
+ explicit XBYAK_CONSTEXPR AddressFrame(uint32_t bit, bool broadcast = false) : bit_(bit), broadcast_(broadcast) { }
+ Address operator[](const RegExp& e) const
+ {
+ return Address(bit_, broadcast_, e);
+ }
+ Address operator[](const void *disp) const
+ {
+ return Address(bit_, broadcast_, RegExp(reinterpret_cast<size_t>(disp)));
+ }
+#ifdef XBYAK64
+ Address operator[](uint64_t disp) const { return Address(disp); }
+ Address operator[](const RegRip& addr) const { return Address(bit_, broadcast_, addr); }
+#endif
+};
+
+struct JmpLabel {
+ size_t endOfJmp; /* offset from top to the end address of jmp */
+ int jmpSize;
+ inner::LabelMode mode;
+ size_t disp; // disp for [rip + disp]
+ explicit JmpLabel(size_t endOfJmp = 0, int jmpSize = 0, inner::LabelMode mode = inner::LasIs, size_t disp = 0)
+ : endOfJmp(endOfJmp), jmpSize(jmpSize), mode(mode), disp(disp)
+ {
+ }
+};
+
+class LabelManager;
+
+class Label {
+ mutable LabelManager *mgr;
+ mutable int id;
+ friend class LabelManager;
+public:
+ Label() : mgr(0), id(0) {}
+ Label(const Label& rhs);
+ Label& operator=(const Label& rhs);
+ ~Label();
+ void clear() { mgr = 0; id = 0; }
+ int getId() const { return id; }
+ const uint8_t *getAddress() const;
+
+ // backward compatibility
+ static inline std::string toStr(int num)
+ {
+ char buf[16];
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+ _snprintf_s
+#else
+ snprintf
+#endif
+ (buf, sizeof(buf), ".%08x", num);
+ return buf;
+ }
+};
+
+class LabelManager {
+ // for string label
+ struct SlabelVal {
+ size_t offset;
+ SlabelVal(size_t offset) : offset(offset) {}
+ };
+ typedef XBYAK_STD_UNORDERED_MAP<std::string, SlabelVal> SlabelDefList;
+ typedef XBYAK_STD_UNORDERED_MULTIMAP<std::string, const JmpLabel> SlabelUndefList;
+ struct SlabelState {
+ SlabelDefList defList;
+ SlabelUndefList undefList;
+ };
+ typedef std::list<SlabelState> StateList;
+ // for Label class
+ struct ClabelVal {
+ ClabelVal(size_t offset = 0) : offset(offset), refCount(1) {}
+ size_t offset;
+ int refCount;
+ };
+ typedef XBYAK_STD_UNORDERED_MAP<int, ClabelVal> ClabelDefList;
+ typedef XBYAK_STD_UNORDERED_MULTIMAP<int, const JmpLabel> ClabelUndefList;
+ typedef XBYAK_STD_UNORDERED_SET<Label*> LabelPtrList;
+
+ CodeArray *base_;
+ // global : stateList_.front(), local : stateList_.back()
+ StateList stateList_;
+ mutable int labelId_;
+ ClabelDefList clabelDefList_;
+ ClabelUndefList clabelUndefList_;
+ LabelPtrList labelPtrList_;
+
+ int getId(const Label& label) const
+ {
+ if (label.id == 0) label.id = labelId_++;
+ return label.id;
+ }
+ template<class DefList, class UndefList, class T>
+ void define_inner(DefList& defList, UndefList& undefList, const T& labelId, size_t addrOffset)
+ {
+ // add label
+ typename DefList::value_type item(labelId, addrOffset);
+ std::pair<typename DefList::iterator, bool> ret = defList.insert(item);
+ if (!ret.second) XBYAK_THROW(ERR_LABEL_IS_REDEFINED)
+ // search undefined label
+ for (;;) {
+ typename UndefList::iterator itr = undefList.find(labelId);
+ if (itr == undefList.end()) break;
+ const JmpLabel *jmp = &itr->second;
+ const size_t offset = jmp->endOfJmp - jmp->jmpSize;
+ size_t disp;
+ if (jmp->mode == inner::LaddTop) {
+ disp = addrOffset;
+ } else if (jmp->mode == inner::Labs) {
+ disp = size_t(base_->getCurr());
+ } else {
+ disp = addrOffset - jmp->endOfJmp + jmp->disp;
+#ifdef XBYAK64
+ if (jmp->jmpSize <= 4 && !inner::IsInInt32(disp)) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG)
+#endif
+ if (jmp->jmpSize == 1 && !inner::IsInDisp8((uint32_t)disp)) XBYAK_THROW(ERR_LABEL_IS_TOO_FAR)
+ }
+ if (base_->isAutoGrow()) {
+ base_->save(offset, disp, jmp->jmpSize, jmp->mode);
+ } else {
+ base_->rewrite(offset, disp, jmp->jmpSize);
+ }
+ undefList.erase(itr);
+ }
+ }
+ template<class DefList, class T>
+ bool getOffset_inner(const DefList& defList, size_t *offset, const T& label) const
+ {
+ typename DefList::const_iterator i = defList.find(label);
+ if (i == defList.end()) return false;
+ *offset = i->second.offset;
+ return true;
+ }
+ friend class Label;
+ void incRefCount(int id, Label *label)
+ {
+ clabelDefList_[id].refCount++;
+ labelPtrList_.insert(label);
+ }
+ void decRefCount(int id, Label *label)
+ {
+ labelPtrList_.erase(label);
+ ClabelDefList::iterator i = clabelDefList_.find(id);
+ if (i == clabelDefList_.end()) return;
+ if (i->second.refCount == 1) {
+ clabelDefList_.erase(id);
+ } else {
+ --i->second.refCount;
+ }
+ }
+ template<class T>
+ bool hasUndefinedLabel_inner(const T& list) const
+ {
+#ifndef NDEBUG
+ for (typename T::const_iterator i = list.begin(); i != list.end(); ++i) {
+ std::cerr << "undefined label:" << i->first << std::endl;
+ }
+#endif
+ return !list.empty();
+ }
+ // detach all labels linked to LabelManager
+ void resetLabelPtrList()
+ {
+ for (LabelPtrList::iterator i = labelPtrList_.begin(), ie = labelPtrList_.end(); i != ie; ++i) {
+ (*i)->clear();
+ }
+ labelPtrList_.clear();
+ }
+public:
+ LabelManager()
+ {
+ reset();
+ }
+ ~LabelManager()
+ {
+ resetLabelPtrList();
+ }
+ void reset()
+ {
+ base_ = 0;
+ labelId_ = 1;
+ stateList_.clear();
+ stateList_.push_back(SlabelState());
+ stateList_.push_back(SlabelState());
+ clabelDefList_.clear();
+ clabelUndefList_.clear();
+ resetLabelPtrList();
+ }
+ void enterLocal()
+ {
+ stateList_.push_back(SlabelState());
+ }
+ void leaveLocal()
+ {
+ if (stateList_.size() <= 2) XBYAK_THROW(ERR_UNDER_LOCAL_LABEL)
+ if (hasUndefinedLabel_inner(stateList_.back().undefList)) XBYAK_THROW(ERR_LABEL_IS_NOT_FOUND)
+ stateList_.pop_back();
+ }
+ void set(CodeArray *base) { base_ = base; }
+ void defineSlabel(std::string label)
+ {
+ if (label == "@b" || label == "@f") XBYAK_THROW(ERR_BAD_LABEL_STR)
+ if (label == "@@") {
+ SlabelDefList& defList = stateList_.front().defList;
+ SlabelDefList::iterator i = defList.find("@f");
+ if (i != defList.end()) {
+ defList.erase(i);
+ label = "@b";
+ } else {
+ i = defList.find("@b");
+ if (i != defList.end()) {
+ defList.erase(i);
+ }
+ label = "@f";
+ }
+ }
+ SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
+ define_inner(st.defList, st.undefList, label, base_->getSize());
+ }
+ void defineClabel(Label& label)
+ {
+ define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize());
+ label.mgr = this;
+ labelPtrList_.insert(&label);
+ }
+ void assign(Label& dst, const Label& src)
+ {
+ ClabelDefList::const_iterator i = clabelDefList_.find(src.id);
+ if (i == clabelDefList_.end()) XBYAK_THROW(ERR_LABEL_ISNOT_SET_BY_L)
+ define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset);
+ dst.mgr = this;
+ labelPtrList_.insert(&dst);
+ }
+ bool getOffset(size_t *offset, std::string& label) const
+ {
+ const SlabelDefList& defList = stateList_.front().defList;
+ if (label == "@b") {
+ if (defList.find("@f") != defList.end()) {
+ label = "@f";
+ } else if (defList.find("@b") == defList.end()) {
+ XBYAK_THROW_RET(ERR_LABEL_IS_NOT_FOUND, false)
+ }
+ } else if (label == "@f") {
+ if (defList.find("@f") != defList.end()) {
+ label = "@b";
+ }
+ }
+ const SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
+ return getOffset_inner(st.defList, offset, label);
+ }
+ bool getOffset(size_t *offset, const Label& label) const
+ {
+ return getOffset_inner(clabelDefList_, offset, getId(label));
+ }
+ void addUndefinedLabel(const std::string& label, const JmpLabel& jmp)
+ {
+ SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
+ st.undefList.insert(SlabelUndefList::value_type(label, jmp));
+ }
+ void addUndefinedLabel(const Label& label, const JmpLabel& jmp)
+ {
+ clabelUndefList_.insert(ClabelUndefList::value_type(label.id, jmp));
+ }
+ bool hasUndefSlabel() const
+ {
+ for (StateList::const_iterator i = stateList_.begin(), ie = stateList_.end(); i != ie; ++i) {
+ if (hasUndefinedLabel_inner(i->undefList)) return true;
+ }
+ return false;
+ }
+ bool hasUndefClabel() const { return hasUndefinedLabel_inner(clabelUndefList_); }
+ const uint8_t *getCode() const { return base_->getCode(); }
+ bool isReady() const { return !base_->isAutoGrow() || base_->isCalledCalcJmpAddress(); }
+};
+
+inline Label::Label(const Label& rhs)
+{
+ id = rhs.id;
+ mgr = rhs.mgr;
+ if (mgr) mgr->incRefCount(id, this);
+}
+inline Label& Label::operator=(const Label& rhs)
+{
+ if (id) XBYAK_THROW_RET(ERR_LABEL_IS_ALREADY_SET_BY_L, *this)
+ id = rhs.id;
+ mgr = rhs.mgr;
+ if (mgr) mgr->incRefCount(id, this);
+ return *this;
+}
+inline Label::~Label()
+{
+ if (id && mgr) mgr->decRefCount(id, this);
+}
+inline const uint8_t* Label::getAddress() const
+{
+ if (mgr == 0 || !mgr->isReady()) return 0;
+ size_t offset;
+ if (!mgr->getOffset(&offset, *this)) return 0;
+ return mgr->getCode() + offset;
+}
+
+typedef enum {
+ DefaultEncoding,
+ VexEncoding,
+ EvexEncoding
+} PreferredEncoding;
+
+class CodeGenerator : public CodeArray {
+public:
+ enum LabelType {
+ T_SHORT,
+ T_NEAR,
+ T_FAR, // far jump
+ T_AUTO // T_SHORT if possible
+ };
+private:
+ CodeGenerator operator=(const CodeGenerator&); // don't call
+#ifdef XBYAK64
+ enum { i32e = 32 | 64, BIT = 64 };
+ static const uint64_t dummyAddr = uint64_t(0x1122334455667788ull);
+ typedef Reg64 NativeReg;
+#else
+ enum { i32e = 32, BIT = 32 };
+ static const size_t dummyAddr = 0x12345678;
+ typedef Reg32 NativeReg;
+#endif
+ // (XMM, XMM|MEM)
+ static inline bool isXMM_XMMorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isXMM() && (op2.isXMM() || op2.isMEM());
+ }
+ // (MMX, MMX|MEM) or (XMM, XMM|MEM)
+ static inline bool isXMMorMMX_MEM(const Operand& op1, const Operand& op2)
+ {
+ return (op1.isMMX() && (op2.isMMX() || op2.isMEM())) || isXMM_XMMorMEM(op1, op2);
+ }
+ // (XMM, MMX|MEM)
+ static inline bool isXMM_MMXorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isXMM() && (op2.isMMX() || op2.isMEM());
+ }
+ // (MMX, XMM|MEM)
+ static inline bool isMMX_XMMorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isMMX() && (op2.isXMM() || op2.isMEM());
+ }
+ // (XMM, REG32|MEM)
+ static inline bool isXMM_REG32orMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isXMM() && (op2.isREG(i32e) || op2.isMEM());
+ }
+ // (REG32, XMM|MEM)
+ static inline bool isREG32_XMMorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isREG(i32e) && (op2.isXMM() || op2.isMEM());
+ }
+ // (REG32, REG32|MEM)
+ static inline bool isREG32_REG32orMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isREG(i32e) && ((op2.isREG(i32e) && op1.getBit() == op2.getBit()) || op2.isMEM());
+ }
+ static inline bool isValidSSE(const Operand& op1)
+ {
+ // SSE instructions do not support XMM16 - XMM31
+ return !(op1.isXMM() && op1.getIdx() >= 16);
+ }
+ void rex(const Operand& op1, const Operand& op2 = Operand())
+ {
+ uint8_t rex = 0;
+ const Operand *p1 = &op1, *p2 = &op2;
+ if (p1->isMEM()) std::swap(p1, p2);
+ if (p1->isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION)
+ if (p2->isMEM()) {
+ const Address& addr = p2->getAddress();
+ if (BIT == 64 && addr.is32bit()) db(0x67);
+ rex = addr.getRex() | p1->getReg().getRex();
+ } else {
+ // ModRM(reg, base);
+ rex = op2.getReg().getRex(op1.getReg());
+ }
+ // except movsx(16bit, 32/64bit)
+ if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66);
+ if (rex) db(rex);
+ }
+ enum AVXtype {
+ // low 3 bit
+ T_N1 = 1,
+ T_N2 = 2,
+ T_N4 = 3,
+ T_N8 = 4,
+ T_N16 = 5,
+ T_N32 = 6,
+ T_NX_MASK = 7,
+ //
+ T_N_VL = 1 << 3, // N * (1, 2, 4) for VL
+ T_DUP = 1 << 4, // N = (8, 32, 64)
+ T_66 = 1 << 5, // pp = 1
+ T_F3 = 1 << 6, // pp = 2
+ T_F2 = T_66 | T_F3, // pp = 3
+ T_ER_R = 1 << 7, // reg{er}
+ T_0F = 1 << 8,
+ T_0F38 = 1 << 9,
+ T_0F3A = 1 << 10,
+ T_L0 = 1 << 11,
+ T_L1 = 1 << 12,
+ T_W0 = 1 << 13,
+ T_W1 = 1 << 14,
+ T_EW0 = 1 << 15,
+ T_EW1 = 1 << 16,
+ T_YMM = 1 << 17, // support YMM, ZMM
+ T_EVEX = 1 << 18,
+ T_ER_X = 1 << 19, // xmm{er}
+ T_ER_Y = 1 << 20, // ymm{er}
+ T_ER_Z = 1 << 21, // zmm{er}
+ T_SAE_X = 1 << 22, // xmm{sae}
+ T_SAE_Y = 1 << 23, // ymm{sae}
+ T_SAE_Z = 1 << 24, // zmm{sae}
+ T_MUST_EVEX = 1 << 25, // contains T_EVEX
+ T_B32 = 1 << 26, // m32bcst
+ T_B64 = 1 << 27, // m64bcst
+ T_B16 = T_B32 | T_B64, // m16bcst (Be careful)
+ T_M_K = 1 << 28, // mem{k}
+ T_VSIB = 1 << 29,
+ T_MEM_EVEX = 1 << 30, // use evex if mem
+ T_FP16 = 1 << 31, // avx512-fp16
+ T_MAP5 = T_FP16 | T_0F,
+ T_MAP6 = T_FP16 | T_0F38,
+ T_XXX
+ };
+ // T_66 = 1, T_F3 = 2, T_F2 = 3
+ uint32_t getPP(int type) const { return (type >> 5) & 3; }
+ void vex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false)
+ {
+ int w = (type & T_W1) ? 1 : 0;
+ bool is256 = (type & T_L1) ? true : (type & T_L0) ? false : reg.isYMM();
+ bool r = reg.isExtIdx();
+ bool b = base.isExtIdx();
+ int idx = v ? v->getIdx() : 0;
+ if ((idx | reg.getIdx() | base.getIdx()) >= 16) XBYAK_THROW(ERR_BAD_COMBINATION)
+ uint32_t pp = getPP(type);
+ uint32_t vvvv = (((~idx) & 15) << 3) | (is256 ? 4 : 0) | pp;
+ if (!b && !x && !w && (type & T_0F)) {
+ db(0xC5); db((r ? 0 : 0x80) | vvvv);
+ } else {
+ uint32_t mmmm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0;
+ db(0xC4); db((r ? 0 : 0x80) | (x ? 0 : 0x40) | (b ? 0 : 0x20) | mmmm); db((w << 7) | vvvv);
+ }
+ db(code);
+ }
+ void verifySAE(const Reg& r, int type) const
+ {
+ if (((type & T_SAE_X) && r.isXMM()) || ((type & T_SAE_Y) && r.isYMM()) || ((type & T_SAE_Z) && r.isZMM())) return;
+ XBYAK_THROW(ERR_SAE_IS_INVALID)
+ }
+ void verifyER(const Reg& r, int type) const
+ {
+ if ((type & T_ER_R) && r.isREG(32|64)) return;
+ if (((type & T_ER_X) && r.isXMM()) || ((type & T_ER_Y) && r.isYMM()) || ((type & T_ER_Z) && r.isZMM())) return;
+ XBYAK_THROW(ERR_ER_IS_INVALID)
+ }
+ // (a, b, c) contains non zero two or three values then err
+ int verifyDuplicate(int a, int b, int c, int err)
+ {
+ int v = a | b | c;
+ if ((a > 0 && a != v) + (b > 0 && b != v) + (c > 0 && c != v) > 0) XBYAK_THROW_RET(err, 0)
+ return v;
+ }
+ int evex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false, bool b = false, int aaa = 0, uint32_t VL = 0, bool Hi16Vidx = false)
+ {
+ if (!(type & (T_EVEX | T_MUST_EVEX))) XBYAK_THROW_RET(ERR_EVEX_IS_INVALID, 0)
+ int w = (type & T_EW1) ? 1 : 0;
+ uint32_t mmm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0;
+ if (type & T_FP16) mmm |= 4;
+ uint32_t pp = getPP(type);
+ int idx = v ? v->getIdx() : 0;
+ uint32_t vvvv = ~idx;
+
+ bool R = !reg.isExtIdx();
+ bool X = x ? false : !base.isExtIdx2();
+ bool B = !base.isExtIdx();
+ bool Rp = !reg.isExtIdx2();
+ int LL;
+ int rounding = verifyDuplicate(reg.getRounding(), base.getRounding(), v ? v->getRounding() : 0, ERR_ROUNDING_IS_ALREADY_SET);
+ int disp8N = 1;
+ if (rounding) {
+ if (rounding == EvexModifierRounding::T_SAE) {
+ verifySAE(base, type); LL = 0;
+ } else {
+ verifyER(base, type); LL = rounding - 1;
+ }
+ b = true;
+ } else {
+ if (v) VL = (std::max)(VL, v->getBit());
+ VL = (std::max)((std::max)(reg.getBit(), base.getBit()), VL);
+ LL = (VL == 512) ? 2 : (VL == 256) ? 1 : 0;
+ if (b) {
+ disp8N = ((type & T_B16) == T_B16) ? 2 : (type & T_B32) ? 4 : 8;
+ } else if (type & T_DUP) {
+ disp8N = VL == 128 ? 8 : VL == 256 ? 32 : 64;
+ } else {
+ if ((type & (T_NX_MASK | T_N_VL)) == 0) {
+ type |= T_N16 | T_N_VL; // default
+ }
+ int low = type & T_NX_MASK;
+ if (low > 0) {
+ disp8N = 1 << (low - 1);
+ if (type & T_N_VL) disp8N *= (VL == 512 ? 4 : VL == 256 ? 2 : 1);
+ }
+ }
+ }
+ bool Vp = !((v ? v->isExtIdx2() : 0) | Hi16Vidx);
+ bool z = reg.hasZero() || base.hasZero() || (v ? v->hasZero() : false);
+ if (aaa == 0) aaa = verifyDuplicate(base.getOpmaskIdx(), reg.getOpmaskIdx(), (v ? v->getOpmaskIdx() : 0), ERR_OPMASK_IS_ALREADY_SET);
+ if (aaa == 0) z = 0; // clear T_z if mask is not set
+ db(0x62);
+ db((R ? 0x80 : 0) | (X ? 0x40 : 0) | (B ? 0x20 : 0) | (Rp ? 0x10 : 0) | mmm);
+ db((w == 1 ? 0x80 : 0) | ((vvvv & 15) << 3) | 4 | (pp & 3));
+ db((z ? 0x80 : 0) | ((LL & 3) << 5) | (b ? 0x10 : 0) | (Vp ? 8 : 0) | (aaa & 7));
+ db(code);
+ return disp8N;
+ }
+ void setModRM(int mod, int r1, int r2)
+ {
+ db(static_cast<uint8_t>((mod << 6) | ((r1 & 7) << 3) | (r2 & 7)));
+ }
+ void setSIB(const RegExp& e, int reg, int disp8N = 0)
+ {
+ uint64_t disp64 = e.getDisp();
+#if defined(XBYAK64) && !defined(__ILP32__)
+#ifdef XBYAK_OLD_DISP_CHECK
+ // treat 0xffffffff as 0xffffffffffffffff
+ uint64_t high = disp64 >> 32;
+ if (high != 0 && high != 0xFFFFFFFF) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG)
+#else
+ // displacement should be a signed 32-bit value, so also check sign bit
+ uint64_t high = disp64 >> 31;
+ if (high != 0 && high != 0x1FFFFFFFF) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG)
+#endif
+#endif
+ uint32_t disp = static_cast<uint32_t>(disp64);
+ const Reg& base = e.getBase();
+ const Reg& index = e.getIndex();
+ const int baseIdx = base.getIdx();
+ const int baseBit = base.getBit();
+ const int indexBit = index.getBit();
+ enum {
+ mod00 = 0, mod01 = 1, mod10 = 2
+ };
+ int mod = mod10; // disp32
+ if (!baseBit || ((baseIdx & 7) != Operand::EBP && disp == 0)) {
+ mod = mod00;
+ } else {
+ if (disp8N == 0) {
+ if (inner::IsInDisp8(disp)) {
+ mod = mod01;
+ }
+ } else {
+ // disp must be casted to signed
+ uint32_t t = static_cast<uint32_t>(static_cast<int>(disp) / disp8N);
+ if ((disp % disp8N) == 0 && inner::IsInDisp8(t)) {
+ disp = t;
+ mod = mod01;
+ }
+ }
+ }
+ const int newBaseIdx = baseBit ? (baseIdx & 7) : Operand::EBP;
+ /* ModR/M = [2:3:3] = [Mod:reg/code:R/M] */
+ bool hasSIB = indexBit || (baseIdx & 7) == Operand::ESP;
+#ifdef XBYAK64
+ if (!baseBit && !indexBit) hasSIB = true;
+#endif
+ if (hasSIB) {
+ setModRM(mod, reg, Operand::ESP);
+ /* SIB = [2:3:3] = [SS:index:base(=rm)] */
+ const int idx = indexBit ? (index.getIdx() & 7) : Operand::ESP;
+ const int scale = e.getScale();
+ const int SS = (scale == 8) ? 3 : (scale == 4) ? 2 : (scale == 2) ? 1 : 0;
+ setModRM(SS, idx, newBaseIdx);
+ } else {
+ setModRM(mod, reg, newBaseIdx);
+ }
+ if (mod == mod01) {
+ db(disp);
+ } else if (mod == mod10 || (mod == mod00 && !baseBit)) {
+ dd(disp);
+ }
+ }
+ LabelManager labelMgr_;
+ bool isInDisp16(uint32_t x) const { return 0xFFFF8000 <= x || x <= 0x7FFF; }
+ void opModR(const Reg& reg1, const Reg& reg2, int code0, int code1 = NONE, int code2 = NONE)
+ {
+ rex(reg2, reg1);
+ db(code0 | (reg1.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
+ setModRM(3, reg1.getIdx(), reg2.getIdx());
+ }
+ void opModM(const Address& addr, const Reg& reg, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
+ {
+ if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
+ rex(addr, reg);
+ db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
+ opAddr(addr, reg.getIdx(), immSize);
+ }
+ void opLoadSeg(const Address& addr, const Reg& reg, int code0, int code1 = NONE)
+ {
+ if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
+ if (reg.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
+ rex(addr, reg);
+ db(code0); if (code1 != NONE) db(code1);
+ opAddr(addr, reg.getIdx());
+ }
+ void opMIB(const Address& addr, const Reg& reg, int code0, int code1)
+ {
+ if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
+ if (addr.getMode() != Address::M_ModRM) XBYAK_THROW(ERR_INVALID_MIB_ADDRESS)
+ if (BIT == 64 && addr.is32bit()) db(0x67);
+ const RegExp& regExp = addr.getRegExp(false);
+ uint8_t rex = regExp.getRex();
+ if (rex) db(rex);
+ db(code0); db(code1);
+ setSIB(regExp, reg.getIdx());
+ }
+ void makeJmp(uint32_t disp, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref)
+ {
+ const int shortJmpSize = 2;
+ const int longHeaderSize = longPref ? 2 : 1;
+ const int longJmpSize = longHeaderSize + 4;
+ if (type != T_NEAR && inner::IsInDisp8(disp - shortJmpSize)) {
+ db(shortCode); db(disp - shortJmpSize);
+ } else {
+ if (type == T_SHORT) XBYAK_THROW(ERR_LABEL_IS_TOO_FAR)
+ if (longPref) db(longPref);
+ db(longCode); dd(disp - longJmpSize);
+ }
+ }
+ bool isNEAR(LabelType type) const { return type == T_NEAR || (type == T_AUTO && isDefaultJmpNEAR_); }
+ template<class T>
+ void opJmp(T& label, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref)
+ {
+ if (type == T_FAR) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */
+ size_t offset = 0;
+ if (labelMgr_.getOffset(&offset, label)) { /* label exists */
+ makeJmp(inner::VerifyInInt32(offset - size_), type, shortCode, longCode, longPref);
+ } else {
+ int jmpSize = 0;
+ if (isNEAR(type)) {
+ jmpSize = 4;
+ if (longPref) db(longPref);
+ db(longCode); dd(0);
+ } else {
+ jmpSize = 1;
+ db(shortCode); db(0);
+ }
+ JmpLabel jmp(size_, jmpSize, inner::LasIs);
+ labelMgr_.addUndefinedLabel(label, jmp);
+ }
+ }
+ void opJmpAbs(const void *addr, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref = 0)
+ {
+ if (type == T_FAR) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ if (isAutoGrow()) {
+ if (!isNEAR(type)) XBYAK_THROW(ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW)
+ if (size_ + 16 >= maxSize_) growMemory();
+ if (longPref) db(longPref);
+ db(longCode);
+ dd(0);
+ save(size_ - 4, size_t(addr) - size_, 4, inner::Labs);
+ } else {
+ makeJmp(inner::VerifyInInt32(reinterpret_cast<const uint8_t*>(addr) - getCurr()), type, shortCode, longCode, longPref);
+ }
+
+ }
+ void opJmpOp(const Operand& op, LabelType type, int ext)
+ {
+ const int bit = 16|i32e;
+ if (type == T_FAR) {
+ if (!op.isMEM(bit)) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ opR_ModM(op, bit, ext + 1, 0xFF, NONE, NONE, false);
+ } else {
+ opR_ModM(op, bit, ext, 0xFF, NONE, NONE, true);
+ }
+ }
+ // reg is reg field of ModRM
+ // immSize is the size for immediate value
+ // disp8N = 0(normal), disp8N = 1(force disp32), disp8N = {2, 4, 8} ; compressed displacement
+ void opAddr(const Address &addr, int reg, int immSize = 0, int disp8N = 0, bool permitVisb = false)
+ {
+ if (!permitVisb && addr.isVsib()) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING)
+ if (addr.getMode() == Address::M_ModRM) {
+ setSIB(addr.getRegExp(), reg, disp8N);
+ } else if (addr.getMode() == Address::M_rip || addr.getMode() == Address::M_ripAddr) {
+ setModRM(0, reg, 5);
+ if (addr.getLabel()) { // [rip + Label]
+ putL_inner(*addr.getLabel(), true, addr.getDisp() - immSize);
+ } else {
+ size_t disp = addr.getDisp();
+ if (addr.getMode() == Address::M_ripAddr) {
+ if (isAutoGrow()) XBYAK_THROW(ERR_INVALID_RIP_IN_AUTO_GROW)
+ disp -= (size_t)getCurr() + 4 + immSize;
+ }
+ dd(inner::VerifyInInt32(disp));
+ }
+ }
+ }
+ /* preCode is for SSSE3/SSE4 */
+ void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE)
+ {
+ if (isValid && !isValid(reg, op)) XBYAK_THROW(ERR_BAD_COMBINATION)
+ if (!isValidSSE(reg) || !isValidSSE(op)) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ if (pref != NONE) db(pref);
+ if (op.isMEM()) {
+ opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0);
+ } else {
+ opModR(reg.getReg(), op.getReg(), 0x0F, preCode, code);
+ }
+ if (imm8 != NONE) db(imm8);
+ }
+ void opMMX_IMM(const Mmx& mmx, int imm8, int code, int ext)
+ {
+ if (!isValidSSE(mmx)) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ if (mmx.isXMM()) db(0x66);
+ opModR(Reg32(ext), mmx, 0x0F, code);
+ db(imm8);
+ }
+ void opMMX(const Mmx& mmx, const Operand& op, int code, int pref = 0x66, int imm8 = NONE, int preCode = NONE)
+ {
+ opGen(mmx, op, code, mmx.isXMM() ? pref : NONE, isXMMorMMX_MEM, imm8, preCode);
+ }
+ void opMovXMM(const Operand& op1, const Operand& op2, int code, int pref)
+ {
+ if (!isValidSSE(op1) || !isValidSSE(op2)) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ if (pref != NONE) db(pref);
+ if (op1.isXMM() && op2.isMEM()) {
+ opModM(op2.getAddress(), op1.getReg(), 0x0F, code);
+ } else if (op1.isMEM() && op2.isXMM()) {
+ opModM(op1.getAddress(), op2.getReg(), 0x0F, code | 1);
+ } else {
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ }
+ void opExt(const Operand& op, const Mmx& mmx, int code, int imm, bool hasMMX2 = false)
+ {
+ if (!isValidSSE(op) || !isValidSSE(mmx)) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */
+ if (mmx.isXMM()) db(0x66);
+ opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm);
+ } else {
+ opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A);
+ }
+ }
+ void opR_ModM(const Operand& op, int bit, int ext, int code0, int code1 = NONE, int code2 = NONE, bool disableRex = false, int immSize = 0)
+ {
+ int opBit = op.getBit();
+ if (disableRex && opBit == 64) opBit = 32;
+ if (op.isREG(bit)) {
+ opModR(Reg(ext, Operand::REG, opBit), op.getReg().changeBit(opBit), code0, code1, code2);
+ } else if (op.isMEM()) {
+ opModM(op.getAddress(), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize);
+ } else {
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ }
+ void opShift(const Operand& op, int imm, int ext)
+ {
+ verifyMemHasSize(op);
+ opR_ModM(op, 0, ext, (0xC0 | ((imm == 1 ? 1 : 0) << 4)), NONE, NONE, false, (imm != 1) ? 1 : 0);
+ if (imm != 1) db(imm);
+ }
+ void opShift(const Operand& op, const Reg8& _cl, int ext)
+ {
+ if (_cl.getIdx() != Operand::CL) XBYAK_THROW(ERR_BAD_COMBINATION)
+ opR_ModM(op, 0, ext, 0xD2);
+ }
+ void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
+ {
+ if (condR) {
+ opModR(op1.getReg(), op2.getReg(), code0, code1, code2);
+ } else if (condM) {
+ opModM(op2.getAddress(), op1.getReg(), code0, code1, code2, immSize);
+ } else {
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ }
+ void opShxd(const Operand& op, const Reg& reg, uint8_t imm, int code, const Reg8 *_cl = 0)
+ {
+ if (_cl && _cl->getIdx() != Operand::CL) XBYAK_THROW(ERR_BAD_COMBINATION)
+ opModRM(reg, op, (op.isREG(16 | i32e) && op.getBit() == reg.getBit()), op.isMEM() && (reg.isREG(16 | i32e)), 0x0F, code | (_cl ? 1 : 0), NONE, _cl ? 0 : 1);
+ if (!_cl) db(imm);
+ }
+ // (REG, REG|MEM), (MEM, REG)
+ void opRM_RM(const Operand& op1, const Operand& op2, int code)
+ {
+ if (op1.isREG() && op2.isMEM()) {
+ opModM(op2.getAddress(), op1.getReg(), code | 2);
+ } else {
+ opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code);
+ }
+ }
+ // (REG|MEM, IMM)
+ void opRM_I(const Operand& op, uint32_t imm, int code, int ext)
+ {
+ verifyMemHasSize(op);
+ uint32_t immBit = inner::IsInDisp8(imm) ? 8 : isInDisp16(imm) ? 16 : 32;
+ if (op.isBit(8)) immBit = 8;
+ if (op.getBit() < immBit) XBYAK_THROW(ERR_IMM_IS_TOO_BIG)
+ if (op.isBit(32|64) && immBit == 16) immBit = 32; /* don't use MEM16 if 32/64bit mode */
+ if (op.isREG() && op.getIdx() == 0 && (op.getBit() == immBit || (op.isBit(64) && immBit == 32))) { // rax, eax, ax, al
+ rex(op);
+ db(code | 4 | (immBit == 8 ? 0 : 1));
+ } else {
+ int tmp = immBit < (std::min)(op.getBit(), 32U) ? 2 : 0;
+ opR_ModM(op, 0, ext, 0x80 | tmp, NONE, NONE, false, immBit / 8);
+ }
+ db(imm, immBit / 8);
+ }
+ void opIncDec(const Operand& op, int code, int ext)
+ {
+ verifyMemHasSize(op);
+#ifndef XBYAK64
+ if (op.isREG() && !op.isBit(8)) {
+ rex(op); db(code | op.getIdx());
+ return;
+ }
+#endif
+ code = 0xFE;
+ if (op.isREG()) {
+ opModR(Reg(ext, Operand::REG, op.getBit()), op.getReg(), code);
+ } else {
+ opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
+ }
+ }
+ void opPushPop(const Operand& op, int code, int ext, int alt)
+ {
+ int bit = op.getBit();
+ if (bit == 16 || bit == BIT) {
+ if (bit == 16) db(0x66);
+ if (op.isREG()) {
+ if (op.getReg().getIdx() >= 8) db(0x41);
+ db(alt | (op.getIdx() & 7));
+ return;
+ }
+ if (op.isMEM()) {
+ opModM(op.getAddress(), Reg(ext, Operand::REG, 32), code);
+ return;
+ }
+ }
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ void verifyMemHasSize(const Operand& op) const
+ {
+ if (op.isMEM() && op.getBit() == 0) XBYAK_THROW(ERR_MEM_SIZE_IS_NOT_SPECIFIED)
+ }
+ /*
+ mov(r, imm) = db(imm, mov_imm(r, imm))
+ */
+ int mov_imm(const Reg& reg, uint64_t imm)
+ {
+ int bit = reg.getBit();
+ const int idx = reg.getIdx();
+ int code = 0xB0 | ((bit == 8 ? 0 : 1) << 3);
+ if (bit == 64 && (imm & ~uint64_t(0xffffffffu)) == 0) {
+ rex(Reg32(idx));
+ bit = 32;
+ } else {
+ rex(reg);
+ if (bit == 64 && inner::IsInInt32(imm)) {
+ db(0xC7);
+ code = 0xC0;
+ bit = 32;
+ }
+ }
+ db(code | (idx & 7));
+ return bit / 8;
+ }
+ template<class T>
+ void putL_inner(T& label, bool relative = false, size_t disp = 0)
+ {
+ const int jmpSize = relative ? 4 : (int)sizeof(size_t);
+ if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory();
+ size_t offset = 0;
+ if (labelMgr_.getOffset(&offset, label)) {
+ if (relative) {
+ db(inner::VerifyInInt32(offset + disp - size_ - jmpSize), jmpSize);
+ } else if (isAutoGrow()) {
+ db(uint64_t(0), jmpSize);
+ save(size_ - jmpSize, offset, jmpSize, inner::LaddTop);
+ } else {
+ db(size_t(top_) + offset, jmpSize);
+ }
+ return;
+ }
+ db(uint64_t(0), jmpSize);
+ JmpLabel jmp(size_, jmpSize, (relative ? inner::LasIs : isAutoGrow() ? inner::LaddTop : inner::Labs), disp);
+ labelMgr_.addUndefinedLabel(label, jmp);
+ }
+ void opMovxx(const Reg& reg, const Operand& op, uint8_t code)
+ {
+ if (op.isBit(32)) XBYAK_THROW(ERR_BAD_COMBINATION)
+ int w = op.isBit(16);
+ bool cond = reg.isREG() && (reg.getBit() > op.getBit());
+ opModRM(reg, op, cond && op.isREG(), cond && op.isMEM(), 0x0F, code | w);
+ }
+ void opFpuMem(const Address& addr, uint8_t m16, uint8_t m32, uint8_t m64, uint8_t ext, uint8_t m64ext)
+ {
+ if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP)
+ uint8_t code = addr.isBit(16) ? m16 : addr.isBit(32) ? m32 : addr.isBit(64) ? m64 : 0;
+ if (!code) XBYAK_THROW(ERR_BAD_MEM_SIZE)
+ if (m64ext && addr.isBit(64)) ext = m64ext;
+
+ rex(addr, st0);
+ db(code);
+ opAddr(addr, ext);
+ }
+ // use code1 if reg1 == st0
+ // use code2 if reg1 != st0 && reg2 == st0
+ void opFpuFpu(const Fpu& reg1, const Fpu& reg2, uint32_t code1, uint32_t code2)
+ {
+ uint32_t code = reg1.getIdx() == 0 ? code1 : reg2.getIdx() == 0 ? code2 : 0;
+ if (!code) XBYAK_THROW(ERR_BAD_ST_COMBINATION)
+ db(uint8_t(code >> 8));
+ db(uint8_t(code | (reg1.getIdx() | reg2.getIdx())));
+ }
+ void opFpu(const Fpu& reg, uint8_t code1, uint8_t code2)
+ {
+ db(code1); db(code2 | reg.getIdx());
+ }
+ void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE)
+ {
+ if (op2.isMEM()) {
+ const Address& addr = op2.getAddress();
+ const RegExp& regExp = addr.getRegExp();
+ const Reg& base = regExp.getBase();
+ const Reg& index = regExp.getIndex();
+ if (BIT == 64 && addr.is32bit()) db(0x67);
+ int disp8N = 0;
+ bool x = index.isExtIdx();
+ if ((type & (T_MUST_EVEX|T_MEM_EVEX)) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) {
+ int aaa = addr.getOpmaskIdx();
+ if (aaa && !(type & T_M_K)) XBYAK_THROW(ERR_INVALID_OPMASK_WITH_MEMORY)
+ bool b = false;
+ if (addr.isBroadcast()) {
+ if (!(type & (T_B32 | T_B64))) XBYAK_THROW(ERR_INVALID_BROADCAST)
+ b = true;
+ }
+ int VL = regExp.isVsib() ? index.getBit() : 0;
+ disp8N = evex(r, base, p1, type, code, x, b, aaa, VL, index.isExtIdx2());
+ } else {
+ vex(r, base, p1, type, code, x);
+ }
+ opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N, (type & T_VSIB) != 0);
+ } else {
+ const Reg& base = op2.getReg();
+ if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) {
+ evex(r, base, p1, type, code);
+ } else {
+ vex(r, base, p1, type, code);
+ }
+ setModRM(3, r.getIdx(), base.getIdx());
+ }
+ if (imm8 != NONE) db(imm8);
+ }
+ // (r, r, r/m) if isR_R_RM
+ // (r, r/m, r)
+ void opGpr(const Reg32e& r, const Operand& op1, const Operand& op2, int type, uint8_t code, bool isR_R_RM, int imm8 = NONE)
+ {
+ const Operand *p1 = &op1;
+ const Operand *p2 = &op2;
+ if (!isR_R_RM) std::swap(p1, p2);
+ const unsigned int bit = r.getBit();
+ if (p1->getBit() != bit || (p2->isREG() && p2->getBit() != bit)) XBYAK_THROW(ERR_BAD_COMBINATION)
+ type |= (bit == 64) ? T_W1 : T_W0;
+ opVex(r, p1, *p2, type, code, imm8);
+ }
+ void opAVX_X_X_XM(const Xmm& x1, const Operand& op1, const Operand& op2, int type, int code0, int imm8 = NONE)
+ {
+ const Xmm *x2 = static_cast<const Xmm*>(&op1);
+ const Operand *op = &op2;
+ if (op2.isNone()) { // (x1, op1) -> (x1, x1, op1)
+ x2 = &x1;
+ op = &op1;
+ }
+ // (x1, x2, op)
+ if (!((x1.isXMM() && x2->isXMM()) || ((type & T_YMM) && ((x1.isYMM() && x2->isYMM()) || (x1.isZMM() && x2->isZMM()))))) XBYAK_THROW(ERR_BAD_COMBINATION)
+ opVex(x1, x2, *op, type, code0, imm8);
+ }
+ void opAVX_K_X_XM(const Opmask& k, const Xmm& x2, const Operand& op3, int type, int code0, int imm8 = NONE)
+ {
+ if (!op3.isMEM() && (x2.getKind() != op3.getKind())) XBYAK_THROW(ERR_BAD_COMBINATION)
+ opVex(k, &x2, op3, type, code0, imm8);
+ }
+ // (x, x/m), (y, x/m256), (z, y/m)
+ void checkCvt1(const Operand& x, const Operand& op) const
+ {
+ if (!op.isMEM() && !(x.is(Operand::XMM | Operand::YMM) && op.isXMM()) && !(x.isZMM() && op.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ // (x, x/m), (x, y/m256), (y, z/m)
+ void checkCvt2(const Xmm& x, const Operand& op) const
+ {
+ if (!(x.isXMM() && op.is(Operand::XMM | Operand::YMM | Operand::MEM)) && !(x.isYMM() && op.is(Operand::ZMM | Operand::MEM))) XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ void opCvt(const Xmm& x, const Operand& op, int type, int code)
+ {
+ Operand::Kind kind = x.isXMM() ? (op.isBit(256) ? Operand::YMM : Operand::XMM) : Operand::ZMM;
+ opVex(x.copyAndSetKind(kind), &xm0, op, type, code);
+ }
+ void opCvt2(const Xmm& x, const Operand& op, int type, int code)
+ {
+ checkCvt2(x, op);
+ opCvt(x, op, type, code);
+ }
+ void opCvt3(const Xmm& x1, const Xmm& x2, const Operand& op, int type, int type64, int type32, uint8_t code)
+ {
+ if (!(x1.isXMM() && x2.isXMM() && (op.isREG(i32e) || op.isMEM()))) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
+ Xmm x(op.getIdx());
+ const Operand *p = op.isREG() ? &x : &op;
+ opVex(x1, &x2, *p, type | (op.isBit(64) ? type64 : type32), code);
+ }
+ // (x, x/y/xword/yword), (y, z/m)
+ void checkCvt4(const Xmm& x, const Operand& op) const
+ {
+ if (!(x.isXMM() && op.is(Operand::XMM | Operand::YMM | Operand::MEM) && op.isBit(128|256)) && !(x.isYMM() && op.is(Operand::ZMM | Operand::MEM))) XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ // (x, x/y/z/xword/yword/zword)
+ void opCvt5(const Xmm& x, const Operand& op, int type, int code)
+ {
+ if (!(x.isXMM() && op.isBit(128|256|512))) XBYAK_THROW(ERR_BAD_COMBINATION)
+ Operand::Kind kind = op.isBit(128) ? Operand::XMM : op.isBit(256) ? Operand::YMM : Operand::ZMM;
+ opVex(x.copyAndSetKind(kind), &xm0, op, type, code);
+ }
+ const Xmm& cvtIdx0(const Operand& x) const
+ {
+ return x.isZMM() ? zm0 : x.isYMM() ? ym0 : xm0;
+ }
+ // support (x, x/m, imm), (y, y/m, imm)
+ void opAVX_X_XM_IMM(const Xmm& x, const Operand& op, int type, int code, int imm8 = NONE)
+ {
+ opAVX_X_X_XM(x, cvtIdx0(x), op, type, code, imm8);
+ }
+ // QQQ:need to refactor
+ void opSp1(const Reg& reg, const Operand& op, uint8_t pref, uint8_t code0, uint8_t code1)
+ {
+ if (reg.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
+ bool is16bit = reg.isREG(16) && (op.isREG(16) || op.isMEM());
+ if (!is16bit && !(reg.isREG(i32e) && (op.isREG(reg.getBit()) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION)
+ if (is16bit) db(0x66);
+ db(pref); opModRM(reg.changeBit(i32e == 32 ? 32 : reg.getBit()), op, op.isREG(), true, code0, code1);
+ }
+ void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8_t code, int mode)
+ {
+ const RegExp& regExp = addr.getRegExp();
+ if (!regExp.isVsib(128 | 256)) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING)
+ const int y_vx_y = 0;
+ const int y_vy_y = 1;
+// const int x_vy_x = 2;
+ const bool isAddrYMM = regExp.getIndex().getBit() == 256;
+ if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) {
+ bool isOK = false;
+ if (mode == y_vx_y) {
+ isOK = x1.isYMM() && !isAddrYMM && x2.isYMM();
+ } else if (mode == y_vy_y) {
+ isOK = x1.isYMM() && isAddrYMM && x2.isYMM();
+ } else { // x_vy_x
+ isOK = !x1.isYMM() && isAddrYMM && !x2.isYMM();
+ }
+ if (!isOK) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING)
+ }
+ int i1 = x1.getIdx();
+ int i2 = regExp.getIndex().getIdx();
+ int i3 = x2.getIdx();
+ if (i1 == i2 || i1 == i3 || i2 == i3) XBYAK_THROW(ERR_SAME_REGS_ARE_INVALID);
+ opAVX_X_X_XM(isAddrYMM ? Ymm(i1) : x1, isAddrYMM ? Ymm(i3) : x2, addr, type, code);
+ }
+ enum {
+ xx_yy_zz = 0,
+ xx_yx_zy = 1,
+ xx_xy_yz = 2
+ };
+ void checkGather2(const Xmm& x1, const Reg& x2, int mode) const
+ {
+ if (x1.isXMM() && x2.isXMM()) return;
+ switch (mode) {
+ case xx_yy_zz: if ((x1.isYMM() && x2.isYMM()) || (x1.isZMM() && x2.isZMM())) return;
+ break;
+ case xx_yx_zy: if ((x1.isYMM() && x2.isXMM()) || (x1.isZMM() && x2.isYMM())) return;
+ break;
+ case xx_xy_yz: if ((x1.isXMM() && x2.isYMM()) || (x1.isYMM() && x2.isZMM())) return;
+ break;
+ }
+ XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING)
+ }
+ void opGather2(const Xmm& x, const Address& addr, int type, uint8_t code, int mode)
+ {
+ if (x.hasZero()) XBYAK_THROW(ERR_INVALID_ZERO)
+ const RegExp& regExp = addr.getRegExp();
+ checkGather2(x, regExp.getIndex(), mode);
+ int maskIdx = x.getOpmaskIdx();
+ if ((type & T_M_K) && addr.getOpmaskIdx()) maskIdx = addr.getOpmaskIdx();
+ if (maskIdx == 0) XBYAK_THROW(ERR_K0_IS_INVALID);
+ if (!(type & T_M_K) && x.getIdx() == regExp.getIndex().getIdx()) XBYAK_THROW(ERR_SAME_REGS_ARE_INVALID);
+ opVex(x, 0, addr, type, code);
+ }
+ /*
+ xx_xy_yz ; mode = true
+ xx_xy_xz ; mode = false
+ */
+ void opVmov(const Operand& op, const Xmm& x, int type, uint8_t code, bool mode)
+ {
+ if (mode) {
+ if (!op.isMEM() && !((op.isXMM() && x.isXMM()) || (op.isXMM() && x.isYMM()) || (op.isYMM() && x.isZMM()))) XBYAK_THROW(ERR_BAD_COMBINATION)
+ } else {
+ if (!op.isMEM() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ opVex(x, 0, op, type, code);
+ }
+ void opGatherFetch(const Address& addr, const Xmm& x, int type, uint8_t code, Operand::Kind kind)
+ {
+ if (addr.hasZero()) XBYAK_THROW(ERR_INVALID_ZERO)
+ if (addr.getRegExp().getIndex().getKind() != kind) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING)
+ opVex(x, 0, addr, type, code);
+ }
+ void opEncoding(const Xmm& x1, const Xmm& x2, const Operand& op, int type, int code0, PreferredEncoding encoding)
+ {
+ opAVX_X_X_XM(x1, x2, op, type | orEvexIf(encoding), code0);
+ }
+ int orEvexIf(PreferredEncoding encoding) {
+ if (encoding == DefaultEncoding) {
+ encoding = defaultEncoding_;
+ }
+ if (encoding == EvexEncoding) {
+#ifdef XBYAK_DISABLE_AVX512
+ XBYAK_THROW(ERR_EVEX_IS_INVALID)
+#endif
+ return T_MUST_EVEX;
+ }
+ return 0;
+ }
+ void opInOut(const Reg& a, const Reg& d, uint8_t code)
+ {
+ if (a.getIdx() == Operand::AL && d.getIdx() == Operand::DX && d.getBit() == 16) {
+ switch (a.getBit()) {
+ case 8: db(code); return;
+ case 16: db(0x66); db(code + 1); return;
+ case 32: db(code + 1); return;
+ }
+ }
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ void opInOut(const Reg& a, uint8_t code, uint8_t v)
+ {
+ if (a.getIdx() == Operand::AL) {
+ switch (a.getBit()) {
+ case 8: db(code); db(v); return;
+ case 16: db(0x66); db(code + 1); db(v); return;
+ case 32: db(code + 1); db(v); return;
+ }
+ }
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+#ifdef XBYAK64
+ void opAMX(const Tmm& t1, const Address& addr, int type, int code0)
+ {
+ // require both base and index
+ const RegExp exp = addr.getRegExp(false);
+ if (exp.getBase().getBit() == 0 || exp.getIndex().getBit() == 0) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ opVex(t1, &tmm0, addr, type, code0);
+ }
+#endif
+public:
+ unsigned int getVersion() const { return VERSION; }
+ using CodeArray::db;
+ const Mmx mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
+ const Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
+ const Ymm ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7;
+ const Zmm zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7;
+ const Xmm &xm0, &xm1, &xm2, &xm3, &xm4, &xm5, &xm6, &xm7;
+ const Ymm &ym0, &ym1, &ym2, &ym3, &ym4, &ym5, &ym6, &ym7;
+ const Zmm &zm0, &zm1, &zm2, &zm3, &zm4, &zm5, &zm6, &zm7;
+ const Reg32 eax, ecx, edx, ebx, esp, ebp, esi, edi;
+ const Reg16 ax, cx, dx, bx, sp, bp, si, di;
+ const Reg8 al, cl, dl, bl, ah, ch, dh, bh;
+ const AddressFrame ptr, byte, word, dword, qword, xword, yword, zword; // xword is same as oword of NASM
+ const AddressFrame ptr_b, xword_b, yword_b, zword_b; // broadcast such as {1to2}, {1to4}, {1to8}, {1to16}, {b}
+ const Fpu st0, st1, st2, st3, st4, st5, st6, st7;
+ const Opmask k0, k1, k2, k3, k4, k5, k6, k7;
+ const BoundsReg bnd0, bnd1, bnd2, bnd3;
+ const EvexModifierRounding T_sae, T_rn_sae, T_rd_sae, T_ru_sae, T_rz_sae; // {sae}, {rn-sae}, {rd-sae}, {ru-sae}, {rz-sae}
+ const EvexModifierZero T_z; // {z}
+#ifdef XBYAK64
+ const Reg64 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
+ const Reg32 r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d;
+ const Reg16 r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w;
+ const Reg8 r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b;
+ const Reg8 spl, bpl, sil, dil;
+ const Xmm xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
+ const Xmm xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23;
+ const Xmm xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31;
+ const Ymm ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
+ const Ymm ymm16, ymm17, ymm18, ymm19, ymm20, ymm21, ymm22, ymm23;
+ const Ymm ymm24, ymm25, ymm26, ymm27, ymm28, ymm29, ymm30, ymm31;
+ const Zmm zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15;
+ const Zmm zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23;
+ const Zmm zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31;
+ const Tmm tmm0, tmm1, tmm2, tmm3, tmm4, tmm5, tmm6, tmm7;
+ const Xmm &xm8, &xm9, &xm10, &xm11, &xm12, &xm13, &xm14, &xm15; // for my convenience
+ const Xmm &xm16, &xm17, &xm18, &xm19, &xm20, &xm21, &xm22, &xm23;
+ const Xmm &xm24, &xm25, &xm26, &xm27, &xm28, &xm29, &xm30, &xm31;
+ const Ymm &ym8, &ym9, &ym10, &ym11, &ym12, &ym13, &ym14, &ym15;
+ const Ymm &ym16, &ym17, &ym18, &ym19, &ym20, &ym21, &ym22, &ym23;
+ const Ymm &ym24, &ym25, &ym26, &ym27, &ym28, &ym29, &ym30, &ym31;
+ const Zmm &zm8, &zm9, &zm10, &zm11, &zm12, &zm13, &zm14, &zm15;
+ const Zmm &zm16, &zm17, &zm18, &zm19, &zm20, &zm21, &zm22, &zm23;
+ const Zmm &zm24, &zm25, &zm26, &zm27, &zm28, &zm29, &zm30, &zm31;
+ const RegRip rip;
+#endif
+#ifndef XBYAK_DISABLE_SEGMENT
+ const Segment es, cs, ss, ds, fs, gs;
+#endif
+private:
+ bool isDefaultJmpNEAR_;
+ PreferredEncoding defaultEncoding_;
+public:
+ void L(const std::string& label) { labelMgr_.defineSlabel(label); }
+ void L(Label& label) { labelMgr_.defineClabel(label); }
+ Label L() { Label label; L(label); return label; }
+ void inLocalLabel() { labelMgr_.enterLocal(); }
+ void outLocalLabel() { labelMgr_.leaveLocal(); }
+ /*
+ assign src to dst
+ require
+ dst : does not used by L()
+ src : used by L()
+ */
+ void assignL(Label& dst, const Label& src) { labelMgr_.assign(dst, src); }
+ /*
+ put address of label to buffer
+ @note the put size is 4(32-bit), 8(64-bit)
+ */
+ void putL(std::string label) { putL_inner(label); }
+ void putL(const Label& label) { putL_inner(label); }
+
+ // set default type of `jmp` of undefined label to T_NEAR
+ void setDefaultJmpNEAR(bool isNear) { isDefaultJmpNEAR_ = isNear; }
+ void jmp(const Operand& op, LabelType type = T_AUTO) { opJmpOp(op, type, 4); }
+ void jmp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
+ void jmp(const char *label, LabelType type = T_AUTO) { jmp(std::string(label), type); }
+ void jmp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
+ void jmp(const void *addr, LabelType type = T_AUTO) { opJmpAbs(addr, type, 0xEB, 0xE9); }
+
+ void call(const Operand& op, LabelType type = T_AUTO) { opJmpOp(op, type, 2); }
+ // call(string label), not const std::string&
+ void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
+ void call(const char *label) { call(std::string(label)); }
+ void call(const Label& label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
+ // call(function pointer)
+#ifdef XBYAK_VARIADIC_TEMPLATE
+ template<class Ret, class... Params>
+ void call(Ret(*func)(Params...)) { call(reinterpret_cast<const void*>(func)); }
+#endif
+ void call(const void *addr) { opJmpAbs(addr, T_NEAR, 0, 0xE8); }
+
+ void test(const Operand& op, const Reg& reg)
+ {
+ opModRM(reg, op, op.isREG() && (op.getKind() == reg.getKind()), op.isMEM(), 0x84);
+ }
+ void test(const Operand& op, uint32_t imm)
+ {
+ verifyMemHasSize(op);
+ int immSize = (std::min)(op.getBit() / 8, 4U);
+ if (op.isREG() && op.getIdx() == 0) { // al, ax, eax
+ rex(op);
+ db(0xA8 | (op.isBit(8) ? 0 : 1));
+ } else {
+ opR_ModM(op, 0, 0, 0xF6, NONE, NONE, false, immSize);
+ }
+ db(imm, immSize);
+ }
+ void imul(const Reg& reg, const Operand& op)
+ {
+ opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x0F, 0xAF);
+ }
+ void imul(const Reg& reg, const Operand& op, int imm)
+ {
+ int s = inner::IsInDisp8(imm) ? 1 : 0;
+ int immSize = s ? 1 : reg.isREG(16) ? 2 : 4;
+ opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x69 | (s << 1), NONE, NONE, immSize);
+ db(imm, immSize);
+ }
+ void push(const Operand& op) { opPushPop(op, 0xFF, 6, 0x50); }
+ void pop(const Operand& op) { opPushPop(op, 0x8F, 0, 0x58); }
+ void push(const AddressFrame& af, uint32_t imm)
+ {
+ if (af.bit_ == 8) {
+ db(0x6A); db(imm);
+ } else if (af.bit_ == 16) {
+ db(0x66); db(0x68); dw(imm);
+ } else {
+ db(0x68); dd(imm);
+ }
+ }
+ /* use "push(word, 4)" if you want "push word 4" */
+ void push(uint32_t imm)
+ {
+ if (inner::IsInDisp8(imm)) {
+ push(byte, imm);
+ } else {
+ push(dword, imm);
+ }
+ }
+ void mov(const Operand& reg1, const Operand& reg2)
+ {
+ const Reg *reg = 0;
+ const Address *addr = 0;
+ uint8_t code = 0;
+ if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp]
+ reg = &reg1.getReg();
+ addr= &reg2.getAddress();
+ code = 0xA0;
+ } else
+ if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al
+ reg = &reg2.getReg();
+ addr= &reg1.getAddress();
+ code = 0xA2;
+ }
+#ifdef XBYAK64
+ if (addr && addr->is64bitDisp()) {
+ if (code) {
+ rex(*reg);
+ db(reg1.isREG(8) ? 0xA0 : reg1.isREG() ? 0xA1 : reg2.isREG(8) ? 0xA2 : 0xA3);
+ db(addr->getDisp(), 8);
+ } else {
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ } else
+#else
+ if (code && addr->isOnlyDisp()) {
+ rex(*reg, *addr);
+ db(code | (reg->isBit(8) ? 0 : 1));
+ dd(static_cast<uint32_t>(addr->getDisp()));
+ } else
+#endif
+ {
+ opRM_RM(reg1, reg2, 0x88);
+ }
+ }
+ void mov(const Operand& op, uint64_t imm)
+ {
+ if (op.isREG()) {
+ const int size = mov_imm(op.getReg(), imm);
+ db(imm, size);
+ } else if (op.isMEM()) {
+ verifyMemHasSize(op);
+ int immSize = op.getBit() / 8;
+ if (immSize <= 4) {
+ int64_t s = int64_t(imm) >> (immSize * 8);
+ if (s != 0 && s != -1) XBYAK_THROW(ERR_IMM_IS_TOO_BIG)
+ } else {
+ if (!inner::IsInInt32(imm)) XBYAK_THROW(ERR_IMM_IS_TOO_BIG)
+ immSize = 4;
+ }
+ opModM(op.getAddress(), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize);
+ db(static_cast<uint32_t>(imm), immSize);
+ } else {
+ XBYAK_THROW(ERR_BAD_COMBINATION)
+ }
+ }
+
+ // The template is used to avoid ambiguity when the 2nd argument is 0.
+ // When the 2nd argument is 0 the call goes to
+ // `void mov(const Operand& op, uint64_t imm)`.
+ template <typename T1, typename T2>
+ void mov(const T1&, const T2 *) { T1::unexpected; }
+ void mov(const NativeReg& reg, const Label& label)
+ {
+ mov_imm(reg, dummyAddr);
+ putL(label);
+ }
+ void xchg(const Operand& op1, const Operand& op2)
+ {
+ const Operand *p1 = &op1, *p2 = &op2;
+ if (p1->isMEM() || (p2->isREG(16 | i32e) && p2->getIdx() == 0)) {
+ p1 = &op2; p2 = &op1;
+ }
+ if (p1->isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION)
+ if (p2->isREG() && (p1->isREG(16 | i32e) && p1->getIdx() == 0)
+#ifdef XBYAK64
+ && (p2->getIdx() != 0 || !p1->isREG(32))
+#endif
+ ) {
+ rex(*p2, *p1); db(0x90 | (p2->getIdx() & 7));
+ return;
+ }
+ opModRM(*p1, *p2, (p1->isREG() && p2->isREG() && (p1->getBit() == p2->getBit())), p2->isMEM(), 0x86 | (p1->isBit(8) ? 0 : 1));
+ }
+
+#ifndef XBYAK_DISABLE_SEGMENT
+ void push(const Segment& seg)
+ {
+ switch (seg.getIdx()) {
+ case Segment::es: db(0x06); break;
+ case Segment::cs: db(0x0E); break;
+ case Segment::ss: db(0x16); break;
+ case Segment::ds: db(0x1E); break;
+ case Segment::fs: db(0x0F); db(0xA0); break;
+ case Segment::gs: db(0x0F); db(0xA8); break;
+ default:
+ assert(0);
+ }
+ }
+ void pop(const Segment& seg)
+ {
+ switch (seg.getIdx()) {
+ case Segment::es: db(0x07); break;
+ case Segment::cs: XBYAK_THROW(ERR_BAD_COMBINATION)
+ case Segment::ss: db(0x17); break;
+ case Segment::ds: db(0x1F); break;
+ case Segment::fs: db(0x0F); db(0xA1); break;
+ case Segment::gs: db(0x0F); db(0xA9); break;
+ default:
+ assert(0);
+ }
+ }
+ void putSeg(const Segment& seg)
+ {
+ switch (seg.getIdx()) {
+ case Segment::es: db(0x2E); break;
+ case Segment::cs: db(0x36); break;
+ case Segment::ss: db(0x3E); break;
+ case Segment::ds: db(0x26); break;
+ case Segment::fs: db(0x64); break;
+ case Segment::gs: db(0x65); break;
+ default:
+ assert(0);
+ }
+ }
+ void mov(const Operand& op, const Segment& seg)
+ {
+ opModRM(Reg8(seg.getIdx()), op, op.isREG(16|i32e), op.isMEM(), 0x8C);
+ }
+ void mov(const Segment& seg, const Operand& op)
+ {
+ opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(op.getReg().cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E);
+ }
+#endif
+
+ enum { NONE = 256 };
+ // constructor
+ CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0, Allocator *allocator = 0)
+ : CodeArray(maxSize, userPtr, allocator)
+ , mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7)
+ , xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7)
+ , ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7)
+ , zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7)
+ // for my convenience
+ , xm0(xmm0), xm1(xmm1), xm2(xmm2), xm3(xmm3), xm4(xmm4), xm5(xmm5), xm6(xmm6), xm7(xmm7)
+ , ym0(ymm0), ym1(ymm1), ym2(ymm2), ym3(ymm3), ym4(ymm4), ym5(ymm5), ym6(ymm6), ym7(ymm7)
+ , zm0(zmm0), zm1(zmm1), zm2(zmm2), zm3(zmm3), zm4(zmm4), zm5(zmm5), zm6(zmm6), zm7(zmm7)
+
+ , eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI)
+ , ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI)
+ , al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH)
+ , ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512)
+ , ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true)
+ , st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7)
+ , k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7)
+ , bnd0(0), bnd1(1), bnd2(2), bnd3(3)
+ , T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE)
+ , T_z()
+#ifdef XBYAK64
+ , rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15)
+ , r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15)
+ , r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15)
+ , r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15)
+ , spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true)
+ , xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15)
+ , xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23)
+ , xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31)
+ , ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15)
+ , ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23)
+ , ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31)
+ , zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15)
+ , zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23)
+ , zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31)
+ , tmm0(0), tmm1(1), tmm2(2), tmm3(3), tmm4(4), tmm5(5), tmm6(6), tmm7(7)
+ // for my convenience
+ , xm8(xmm8), xm9(xmm9), xm10(xmm10), xm11(xmm11), xm12(xmm12), xm13(xmm13), xm14(xmm14), xm15(xmm15)
+ , xm16(xmm16), xm17(xmm17), xm18(xmm18), xm19(xmm19), xm20(xmm20), xm21(xmm21), xm22(xmm22), xm23(xmm23)
+ , xm24(xmm24), xm25(xmm25), xm26(xmm26), xm27(xmm27), xm28(xmm28), xm29(xmm29), xm30(xmm30), xm31(xmm31)
+ , ym8(ymm8), ym9(ymm9), ym10(ymm10), ym11(ymm11), ym12(ymm12), ym13(ymm13), ym14(ymm14), ym15(ymm15)
+ , ym16(ymm16), ym17(ymm17), ym18(ymm18), ym19(ymm19), ym20(ymm20), ym21(ymm21), ym22(ymm22), ym23(ymm23)
+ , ym24(ymm24), ym25(ymm25), ym26(ymm26), ym27(ymm27), ym28(ymm28), ym29(ymm29), ym30(ymm30), ym31(ymm31)
+ , zm8(zmm8), zm9(zmm9), zm10(zmm10), zm11(zmm11), zm12(zmm12), zm13(zmm13), zm14(zmm14), zm15(zmm15)
+ , zm16(zmm16), zm17(zmm17), zm18(zmm18), zm19(zmm19), zm20(zmm20), zm21(zmm21), zm22(zmm22), zm23(zmm23)
+ , zm24(zmm24), zm25(zmm25), zm26(zmm26), zm27(zmm27), zm28(zmm28), zm29(zmm29), zm30(zmm30), zm31(zmm31)
+ , rip()
+#endif
+#ifndef XBYAK_DISABLE_SEGMENT
+ , es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs)
+#endif
+ , isDefaultJmpNEAR_(false)
+ , defaultEncoding_(EvexEncoding)
+ {
+ labelMgr_.set(this);
+ }
+ void reset()
+ {
+ ClearError();
+ resetSize();
+ labelMgr_.reset();
+ labelMgr_.set(this);
+ }
+ bool hasUndefinedLabel() const { return labelMgr_.hasUndefSlabel() || labelMgr_.hasUndefClabel(); }
+ /*
+ MUST call ready() to complete generating code if you use AutoGrow mode.
+ It is not necessary for the other mode if hasUndefinedLabel() is true.
+ */
+ void ready(ProtectMode mode = PROTECT_RWE)
+ {
+ if (hasUndefinedLabel()) XBYAK_THROW(ERR_LABEL_IS_NOT_FOUND)
+ if (isAutoGrow()) {
+ calcJmpAddress();
+ if (useProtect()) setProtectMode(mode);
+ }
+ }
+ // set read/exec
+ void readyRE() { return ready(PROTECT_RE); }
+#ifdef XBYAK_TEST
+ void dump(bool doClear = true)
+ {
+ CodeArray::dump();
+ if (doClear) size_ = 0;
+ }
+#endif
+
+#ifdef XBYAK_UNDEF_JNL
+ #undef jnl
+#endif
+
+ // set default encoding to select Vex or Evex
+ void setDefaultEncoding(PreferredEncoding encoding) { defaultEncoding_ = encoding; }
+
+ /*
+ use single byte nop if useMultiByteNop = false
+ */
+ void nop(size_t size = 1, bool useMultiByteNop = true)
+ {
+ if (!useMultiByteNop) {
+ for (size_t i = 0; i < size; i++) {
+ db(0x90);
+ }
+ return;
+ }
+ /*
+ Intel Architectures Software Developer's Manual Volume 2
+ recommended multi-byte sequence of NOP instruction
+ AMD and Intel seem to agree on the same sequences for up to 9 bytes:
+ https://support.amd.com/TechDocs/55723_SOG_Fam_17h_Processors_3.00.pdf
+ */
+ static const uint8_t nopTbl[9][9] = {
+ {0x90},
+ {0x66, 0x90},
+ {0x0F, 0x1F, 0x00},
+ {0x0F, 0x1F, 0x40, 0x00},
+ {0x0F, 0x1F, 0x44, 0x00, 0x00},
+ {0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+ {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+ {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ };
+ const size_t n = sizeof(nopTbl) / sizeof(nopTbl[0]);
+ while (size > 0) {
+ size_t len = (std::min)(n, size);
+ const uint8_t *seq = nopTbl[len - 1];
+ db(seq, len);
+ size -= len;
+ }
+ }
+
+#ifndef XBYAK_DONT_READ_LIST
+#include "xbyak_mnemonic.h"
+ /*
+ use single byte nop if useMultiByteNop = false
+ */
+ void align(size_t x = 16, bool useMultiByteNop = true)
+ {
+ if (x == 1) return;
+ if (x < 1 || (x & (x - 1))) XBYAK_THROW(ERR_BAD_ALIGN)
+ if (isAutoGrow() && x > inner::ALIGN_PAGE_SIZE) fprintf(stderr, "warning:autoGrow mode does not support %d align\n", (int)x);
+ size_t remain = size_t(getCurr()) % x;
+ if (remain) {
+ nop(x - remain, useMultiByteNop);
+ }
+ }
+#endif
+};
+
+template <>
+inline void CodeGenerator::mov(const NativeReg& reg, const char *label) // can't use std::string
+{
+ assert(label);
+ mov_imm(reg, dummyAddr);
+ putL(label);
+}
+
+namespace util {
+static const XBYAK_CONSTEXPR Mmx mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7);
+static const XBYAK_CONSTEXPR Xmm xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7);
+static const XBYAK_CONSTEXPR Ymm ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7);
+static const XBYAK_CONSTEXPR Zmm zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7);
+static const XBYAK_CONSTEXPR Reg32 eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI);
+static const XBYAK_CONSTEXPR Reg16 ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI);
+static const XBYAK_CONSTEXPR Reg8 al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH);
+static const XBYAK_CONSTEXPR AddressFrame ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512);
+static const XBYAK_CONSTEXPR AddressFrame ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true);
+static const XBYAK_CONSTEXPR Fpu st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7);
+static const XBYAK_CONSTEXPR Opmask k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7);
+static const XBYAK_CONSTEXPR BoundsReg bnd0(0), bnd1(1), bnd2(2), bnd3(3);
+static const XBYAK_CONSTEXPR EvexModifierRounding T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE);
+static const XBYAK_CONSTEXPR EvexModifierZero T_z;
+#ifdef XBYAK64
+static const XBYAK_CONSTEXPR Reg64 rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15);
+static const XBYAK_CONSTEXPR Reg32 r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15);
+static const XBYAK_CONSTEXPR Reg16 r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15);
+static const XBYAK_CONSTEXPR Reg8 r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15), spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true);
+static const XBYAK_CONSTEXPR Xmm xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15);
+static const XBYAK_CONSTEXPR Xmm xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23);
+static const XBYAK_CONSTEXPR Xmm xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31);
+static const XBYAK_CONSTEXPR Ymm ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15);
+static const XBYAK_CONSTEXPR Ymm ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23);
+static const XBYAK_CONSTEXPR Ymm ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31);
+static const XBYAK_CONSTEXPR Zmm zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15);
+static const XBYAK_CONSTEXPR Zmm zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23);
+static const XBYAK_CONSTEXPR Zmm zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31);
+static const XBYAK_CONSTEXPR Zmm tmm0(0), tmm1(1), tmm2(2), tmm3(3), tmm4(4), tmm5(5), tmm6(6), tmm7(7);
+static const XBYAK_CONSTEXPR RegRip rip;
+#endif
+#ifndef XBYAK_DISABLE_SEGMENT
+static const XBYAK_CONSTEXPR Segment es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs);
+#endif
+} // util
+
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+ #pragma GCC diagnostic pop
+#endif
+
+} // end of namespace
+
+#endif // XBYAK_XBYAK_H_
diff --git a/xbyak/xbyak_bin2hex.h b/xbyak/xbyak_bin2hex.h
new file mode 100644
index 0000000..69ecdbf
--- /dev/null
+++ b/xbyak/xbyak_bin2hex.h
@@ -0,0 +1,258 @@
+enum {
+ B00000000= 0,
+ B00000001= 1,
+ B00000010= 2,
+ B00000011= 3,
+ B00000100= 4,
+ B00000101= 5,
+ B00000110= 6,
+ B00000111= 7,
+ B00001000= 8,
+ B00001001= 9,
+ B00001010= 10,
+ B00001011= 11,
+ B00001100= 12,
+ B00001101= 13,
+ B00001110= 14,
+ B00001111= 15,
+ B00010000= 16,
+ B00010001= 17,
+ B00010010= 18,
+ B00010011= 19,
+ B00010100= 20,
+ B00010101= 21,
+ B00010110= 22,
+ B00010111= 23,
+ B00011000= 24,
+ B00011001= 25,
+ B00011010= 26,
+ B00011011= 27,
+ B00011100= 28,
+ B00011101= 29,
+ B00011110= 30,
+ B00011111= 31,
+ B00100000= 32,
+ B00100001= 33,
+ B00100010= 34,
+ B00100011= 35,
+ B00100100= 36,
+ B00100101= 37,
+ B00100110= 38,
+ B00100111= 39,
+ B00101000= 40,
+ B00101001= 41,
+ B00101010= 42,
+ B00101011= 43,
+ B00101100= 44,
+ B00101101= 45,
+ B00101110= 46,
+ B00101111= 47,
+ B00110000= 48,
+ B00110001= 49,
+ B00110010= 50,
+ B00110011= 51,
+ B00110100= 52,
+ B00110101= 53,
+ B00110110= 54,
+ B00110111= 55,
+ B00111000= 56,
+ B00111001= 57,
+ B00111010= 58,
+ B00111011= 59,
+ B00111100= 60,
+ B00111101= 61,
+ B00111110= 62,
+ B00111111= 63,
+ B01000000= 64,
+ B01000001= 65,
+ B01000010= 66,
+ B01000011= 67,
+ B01000100= 68,
+ B01000101= 69,
+ B01000110= 70,
+ B01000111= 71,
+ B01001000= 72,
+ B01001001= 73,
+ B01001010= 74,
+ B01001011= 75,
+ B01001100= 76,
+ B01001101= 77,
+ B01001110= 78,
+ B01001111= 79,
+ B01010000= 80,
+ B01010001= 81,
+ B01010010= 82,
+ B01010011= 83,
+ B01010100= 84,
+ B01010101= 85,
+ B01010110= 86,
+ B01010111= 87,
+ B01011000= 88,
+ B01011001= 89,
+ B01011010= 90,
+ B01011011= 91,
+ B01011100= 92,
+ B01011101= 93,
+ B01011110= 94,
+ B01011111= 95,
+ B01100000= 96,
+ B01100001= 97,
+ B01100010= 98,
+ B01100011= 99,
+ B01100100= 100,
+ B01100101= 101,
+ B01100110= 102,
+ B01100111= 103,
+ B01101000= 104,
+ B01101001= 105,
+ B01101010= 106,
+ B01101011= 107,
+ B01101100= 108,
+ B01101101= 109,
+ B01101110= 110,
+ B01101111= 111,
+ B01110000= 112,
+ B01110001= 113,
+ B01110010= 114,
+ B01110011= 115,
+ B01110100= 116,
+ B01110101= 117,
+ B01110110= 118,
+ B01110111= 119,
+ B01111000= 120,
+ B01111001= 121,
+ B01111010= 122,
+ B01111011= 123,
+ B01111100= 124,
+ B01111101= 125,
+ B01111110= 126,
+ B01111111= 127,
+ B10000000= 128,
+ B10000001= 129,
+ B10000010= 130,
+ B10000011= 131,
+ B10000100= 132,
+ B10000101= 133,
+ B10000110= 134,
+ B10000111= 135,
+ B10001000= 136,
+ B10001001= 137,
+ B10001010= 138,
+ B10001011= 139,
+ B10001100= 140,
+ B10001101= 141,
+ B10001110= 142,
+ B10001111= 143,
+ B10010000= 144,
+ B10010001= 145,
+ B10010010= 146,
+ B10010011= 147,
+ B10010100= 148,
+ B10010101= 149,
+ B10010110= 150,
+ B10010111= 151,
+ B10011000= 152,
+ B10011001= 153,
+ B10011010= 154,
+ B10011011= 155,
+ B10011100= 156,
+ B10011101= 157,
+ B10011110= 158,
+ B10011111= 159,
+ B10100000= 160,
+ B10100001= 161,
+ B10100010= 162,
+ B10100011= 163,
+ B10100100= 164,
+ B10100101= 165,
+ B10100110= 166,
+ B10100111= 167,
+ B10101000= 168,
+ B10101001= 169,
+ B10101010= 170,
+ B10101011= 171,
+ B10101100= 172,
+ B10101101= 173,
+ B10101110= 174,
+ B10101111= 175,
+ B10110000= 176,
+ B10110001= 177,
+ B10110010= 178,
+ B10110011= 179,
+ B10110100= 180,
+ B10110101= 181,
+ B10110110= 182,
+ B10110111= 183,
+ B10111000= 184,
+ B10111001= 185,
+ B10111010= 186,
+ B10111011= 187,
+ B10111100= 188,
+ B10111101= 189,
+ B10111110= 190,
+ B10111111= 191,
+ B11000000= 192,
+ B11000001= 193,
+ B11000010= 194,
+ B11000011= 195,
+ B11000100= 196,
+ B11000101= 197,
+ B11000110= 198,
+ B11000111= 199,
+ B11001000= 200,
+ B11001001= 201,
+ B11001010= 202,
+ B11001011= 203,
+ B11001100= 204,
+ B11001101= 205,
+ B11001110= 206,
+ B11001111= 207,
+ B11010000= 208,
+ B11010001= 209,
+ B11010010= 210,
+ B11010011= 211,
+ B11010100= 212,
+ B11010101= 213,
+ B11010110= 214,
+ B11010111= 215,
+ B11011000= 216,
+ B11011001= 217,
+ B11011010= 218,
+ B11011011= 219,
+ B11011100= 220,
+ B11011101= 221,
+ B11011110= 222,
+ B11011111= 223,
+ B11100000= 224,
+ B11100001= 225,
+ B11100010= 226,
+ B11100011= 227,
+ B11100100= 228,
+ B11100101= 229,
+ B11100110= 230,
+ B11100111= 231,
+ B11101000= 232,
+ B11101001= 233,
+ B11101010= 234,
+ B11101011= 235,
+ B11101100= 236,
+ B11101101= 237,
+ B11101110= 238,
+ B11101111= 239,
+ B11110000= 240,
+ B11110001= 241,
+ B11110010= 242,
+ B11110011= 243,
+ B11110100= 244,
+ B11110101= 245,
+ B11110110= 246,
+ B11110111= 247,
+ B11111000= 248,
+ B11111001= 249,
+ B11111010= 250,
+ B11111011= 251,
+ B11111100= 252,
+ B11111101= 253,
+ B11111110= 254,
+ B11111111= 255
+};
diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h
new file mode 100644
index 0000000..cc657fd
--- /dev/null
+++ b/xbyak/xbyak_mnemonic.h
@@ -0,0 +1,2329 @@
+const char *getVersionString() const { return "6.67"; }
+void aadd(const Address& addr, const Reg32e &reg) { opModM(addr, reg, 0x0F, 0x38, 0x0FC); }
+void aand(const Address& addr, const Reg32e &reg) { db(0x66); opModM(addr, reg, 0x0F, 0x38, 0x0FC); }
+void adc(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x10, 2); }
+void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
+void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }
+void add(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x00, 0); }
+void add(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x00); }
+void addpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x66, isXMM_XMMorMEM); }
+void addps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x100, isXMM_XMMorMEM); }
+void addsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF2, isXMM_XMMorMEM); }
+void addss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF3, isXMM_XMMorMEM); }
+void addsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0x66, isXMM_XMMorMEM); }
+void addsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0xF2, isXMM_XMMorMEM); }
+void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); }
+void aesdec(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDE, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesdeclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesenc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDC, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesenclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDD, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesimc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDB, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aeskeygenassist(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void and_(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x20, 4); }
+void and_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x20); }
+void andn(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_0F38, 0xf2, true); }
+void andnpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x66, isXMM_XMMorMEM); }
+void andnps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x100, isXMM_XMMorMEM); }
+void andpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x66, isXMM_XMMorMEM); }
+void andps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x100, isXMM_XMMorMEM); }
+void aor(const Address& addr, const Reg32e &reg) { db(0xF2); opModM(addr, reg, 0x0F, 0x38, 0x0FC); }
+void axor(const Address& addr, const Reg32e &reg) { db(0xF3); opModM(addr, reg, 0x0F, 0x38, 0x0FC); }
+void bextr(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf7, false); }
+void blendpd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0D, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void blendps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0C, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void blendvpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void blendvps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void blsi(const Reg32e& r, const Operand& op) { opGpr(Reg32e(3, r.getBit()), op, r, T_0F38, 0xf3, false); }
+void blsmsk(const Reg32e& r, const Operand& op) { opGpr(Reg32e(2, r.getBit()), op, r, T_0F38, 0xf3, false); }
+void blsr(const Reg32e& r, const Operand& op) { opGpr(Reg32e(1, r.getBit()), op, r, T_0F38, 0xf3, false); }
+void bnd() { db(0xF2); }
+void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
+void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }
+void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
+void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }
+void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }
+void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }
+void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }
+void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }
+void bsf(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBC); }
+void bsr(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBD); }
+void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }
+void bt(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xA3); }
+void bt(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 4, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void btc(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xBB); }
+void btc(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 7, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void btr(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xB3); }
+void btr(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 6, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void bts(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xAB); }
+void bts(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 5, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void bzhi(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf5, false); }
+void cbw() { db(0x66); db(0x98); }
+void cdq() { db(0x99); }
+void clc() { db(0xF8); }
+void cld() { db(0xFC); }
+void cldemote(const Address& addr) { opMIB(addr, eax, 0x0F, 0x1C); }
+void clflush(const Address& addr) { opModM(addr, Reg32(7), 0x0F, 0xAE); }
+void clflushopt(const Address& addr) { db(0x66); opModM(addr, Reg32(7), 0x0F, 0xAE); }
+void cli() { db(0xFA); }
+void clwb(const Address& addr) { db(0x66); opMIB(addr, esi, 0x0F, 0xAE); }
+void clzero() { db(0x0F); db(0x01); db(0xFC); }
+void cmc() { db(0xF5); }
+void cmova(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524
+void cmovae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524
+void cmovb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524
+void cmovbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524
+void cmovc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524
+void cmove(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524
+void cmovg(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524
+void cmovge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524
+void cmovl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524
+void cmovle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524
+void cmovna(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524
+void cmovnae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524
+void cmovnb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524
+void cmovnbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524
+void cmovnc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524
+void cmovne(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524
+void cmovng(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524
+void cmovnge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524
+void cmovnl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524
+void cmovnle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524
+void cmovno(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 1); }//-V524
+void cmovnp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524
+void cmovns(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 9); }//-V524
+void cmovnz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524
+void cmovo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 0); }//-V524
+void cmovp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524
+void cmovpe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524
+void cmovpo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524
+void cmovs(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 8); }//-V524
+void cmovz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524
+void cmp(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x38, 7); }
+void cmp(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x38); }
+void cmpeqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 0); }
+void cmpeqps(const Xmm& x, const Operand& op) { cmpps(x, op, 0); }
+void cmpeqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 0); }
+void cmpeqss(const Xmm& x, const Operand& op) { cmpss(x, op, 0); }
+void cmplepd(const Xmm& x, const Operand& op) { cmppd(x, op, 2); }
+void cmpleps(const Xmm& x, const Operand& op) { cmpps(x, op, 2); }
+void cmplesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 2); }
+void cmpless(const Xmm& x, const Operand& op) { cmpss(x, op, 2); }
+void cmpltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 1); }
+void cmpltps(const Xmm& x, const Operand& op) { cmpps(x, op, 1); }
+void cmpltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 1); }
+void cmpltss(const Xmm& x, const Operand& op) { cmpss(x, op, 1); }
+void cmpneqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 4); }
+void cmpneqps(const Xmm& x, const Operand& op) { cmpps(x, op, 4); }
+void cmpneqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 4); }
+void cmpneqss(const Xmm& x, const Operand& op) { cmpss(x, op, 4); }
+void cmpnlepd(const Xmm& x, const Operand& op) { cmppd(x, op, 6); }
+void cmpnleps(const Xmm& x, const Operand& op) { cmpps(x, op, 6); }
+void cmpnlesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 6); }
+void cmpnless(const Xmm& x, const Operand& op) { cmpss(x, op, 6); }
+void cmpnltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 5); }
+void cmpnltps(const Xmm& x, const Operand& op) { cmpps(x, op, 5); }
+void cmpnltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 5); }
+void cmpnltss(const Xmm& x, const Operand& op) { cmpss(x, op, 5); }
+void cmpordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 7); }
+void cmpordps(const Xmm& x, const Operand& op) { cmpps(x, op, 7); }
+void cmpordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 7); }
+void cmpordss(const Xmm& x, const Operand& op) { cmpss(x, op, 7); }
+void cmppd(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0x66, isXMM_XMMorMEM, imm8); }
+void cmpps(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0x100, isXMM_XMMorMEM, imm8); }
+void cmpsb() { db(0xA6); }
+void cmpsd() { db(0xA7); }
+void cmpsd(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0xF2, isXMM_XMMorMEM, imm8); }
+void cmpss(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0xF3, isXMM_XMMorMEM, imm8); }
+void cmpsw() { db(0x66); db(0xA7); }
+void cmpunordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 3); }
+void cmpunordps(const Xmm& x, const Operand& op) { cmpps(x, op, 3); }
+void cmpunordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 3); }
+void cmpunordss(const Xmm& x, const Operand& op) { cmpss(x, op, 3); }
+void cmpxchg(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xB0 | (reg.isBit(8) ? 0 : 1)); }
+void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); }
+void comisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x66, isXMM_XMMorMEM); }
+void comiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x100, isXMM_XMMorMEM); }
+void cpuid() { db(0x0F); db(0xA2); }
+void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); }
+void cvtdq2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF3, isXMM_XMMorMEM); }
+void cvtdq2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x100, isXMM_XMMorMEM); }
+void cvtpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF2, isXMM_XMMorMEM); }
+void cvtpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x66, isMMX_XMMorMEM); }
+void cvtpd2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x66, isXMM_XMMorMEM); }
+void cvtpi2pd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x66, isXMM_MMXorMEM); }
+void cvtpi2ps(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x100, isXMM_MMXorMEM); }
+void cvtps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x66, isXMM_XMMorMEM); }
+void cvtps2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x100, isXMM_XMMorMEM); }
+void cvtps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x100, isMMX_XMMorMEM); }
+void cvtsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF2, isREG32_XMMorMEM); }
+void cvtsd2ss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF2, isXMM_XMMorMEM); }
+void cvtsi2sd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF2, isXMM_REG32orMEM); }
+void cvtsi2ss(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF3, isXMM_REG32orMEM); }
+void cvtss2sd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF3, isXMM_XMMorMEM); }
+void cvtss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF3, isREG32_XMMorMEM); }
+void cvttpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0x66, isXMM_XMMorMEM); }
+void cvttpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x66, isMMX_XMMorMEM); }
+void cvttps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0xF3, isXMM_XMMorMEM); }
+void cvttps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x100, isMMX_XMMorMEM); }
+void cvttsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF2, isREG32_XMMorMEM); }
+void cvttss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF3, isREG32_XMMorMEM); }
+void cwd() { db(0x66); db(0x99); }
+void cwde() { db(0x98); }
+void dec(const Operand& op) { opIncDec(op, 0x48, 1); }
+void div(const Operand& op) { opR_ModM(op, 0, 6, 0xF6); }
+void divpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x66, isXMM_XMMorMEM); }
+void divps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x100, isXMM_XMMorMEM); }
+void divsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF2, isXMM_XMMorMEM); }
+void divss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF3, isXMM_XMMorMEM); }
+void dppd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void dpps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void emms() { db(0x0F); db(0x77); }
+void endbr32() { db(0xF3); db(0x0F); db(0x1E); db(0xFB); }
+void endbr64() { db(0xF3); db(0x0F); db(0x1E); db(0xFA); }
+void enter(uint16_t x, uint8_t y) { db(0xC8); dw(x); db(y); }
+void extractps(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x17, imm); }
+void f2xm1() { db(0xD9); db(0xF0); }
+void fabs() { db(0xD9); db(0xE1); }
+void fadd(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 0, 0); }
+void fadd(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C0, 0xDCC0); }
+void fadd(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C0, 0xDCC0); }
+void faddp() { db(0xDE); db(0xC1); }
+void faddp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC0); }
+void faddp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC0); }
+void fbld(const Address& addr) { opModM(addr, Reg32(4), 0xDF, 0x100); }
+void fbstp(const Address& addr) { opModM(addr, Reg32(6), 0xDF, 0x100); }
+void fchs() { db(0xD9); db(0xE0); }
+void fclex() { db(0x9B); db(0xDB); db(0xE2); }
+void fcmovb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC0, 0x00C0); }
+void fcmovb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC0, 0x00C0); }
+void fcmovbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD0, 0x00D0); }
+void fcmovbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD0, 0x00D0); }
+void fcmove(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC8, 0x00C8); }
+void fcmove(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC8, 0x00C8); }
+void fcmovnb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC0, 0x00C0); }
+void fcmovnb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC0, 0x00C0); }
+void fcmovnbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD0, 0x00D0); }
+void fcmovnbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD0, 0x00D0); }
+void fcmovne(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC8, 0x00C8); }
+void fcmovne(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC8, 0x00C8); }
+void fcmovnu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD8, 0x00D8); }
+void fcmovnu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD8, 0x00D8); }
+void fcmovu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD8, 0x00D8); }
+void fcmovu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD8, 0x00D8); }
+void fcom() { db(0xD8); db(0xD1); }
+void fcom(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 2, 0); }
+void fcom(const Fpu& reg) { opFpu(reg, 0xD8, 0xD0); }
+void fcomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBF0, 0x00F0); }
+void fcomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBF0, 0x00F0); }
+void fcomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFF0, 0x00F0); }
+void fcomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFF0, 0x00F0); }
+void fcomp() { db(0xD8); db(0xD9); }
+void fcomp(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 3, 0); }
+void fcomp(const Fpu& reg) { opFpu(reg, 0xD8, 0xD8); }
+void fcompp() { db(0xDE); db(0xD9); }
+void fcos() { db(0xD9); db(0xFF); }
+void fdecstp() { db(0xD9); db(0xF6); }
+void fdiv(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 6, 0); }
+void fdiv(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F0, 0xDCF8); }
+void fdiv(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F0, 0xDCF8); }
+void fdivp() { db(0xDE); db(0xF9); }
+void fdivp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF8); }
+void fdivp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF8); }
+void fdivr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 7, 0); }
+void fdivr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F8, 0xDCF0); }
+void fdivr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F8, 0xDCF0); }
+void fdivrp() { db(0xDE); db(0xF1); }
+void fdivrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF0); }
+void fdivrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF0); }
+void ffree(const Fpu& reg) { opFpu(reg, 0xDD, 0xC0); }
+void fiadd(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 0, 0); }
+void ficom(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 2, 0); }
+void ficomp(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 3, 0); }
+void fidiv(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 6, 0); }
+void fidivr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 7, 0); }
+void fild(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 0, 5); }
+void fimul(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 1, 0); }
+void fincstp() { db(0xD9); db(0xF7); }
+void finit() { db(0x9B); db(0xDB); db(0xE3); }
+void fist(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0x00, 2, 0); }
+void fistp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 3, 7); }
+void fisttp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDD, 1, 0); }
+void fisub(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 4, 0); }
+void fisubr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 5, 0); }
+void fld(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 0, 0); }
+void fld(const Fpu& reg) { opFpu(reg, 0xD9, 0xC0); }
+void fld1() { db(0xD9); db(0xE8); }
+void fldcw(const Address& addr) { opModM(addr, Reg32(5), 0xD9, 0x100); }
+void fldenv(const Address& addr) { opModM(addr, Reg32(4), 0xD9, 0x100); }
+void fldl2e() { db(0xD9); db(0xEA); }
+void fldl2t() { db(0xD9); db(0xE9); }
+void fldlg2() { db(0xD9); db(0xEC); }
+void fldln2() { db(0xD9); db(0xED); }
+void fldpi() { db(0xD9); db(0xEB); }
+void fldz() { db(0xD9); db(0xEE); }
+void fmul(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 1, 0); }
+void fmul(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C8, 0xDCC8); }
+void fmul(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C8, 0xDCC8); }
+void fmulp() { db(0xDE); db(0xC9); }
+void fmulp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC8); }
+void fmulp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC8); }
+void fnclex() { db(0xDB); db(0xE2); }
+void fninit() { db(0xDB); db(0xE3); }
+void fnop() { db(0xD9); db(0xD0); }
+void fnsave(const Address& addr) { opModM(addr, Reg32(6), 0xDD, 0x100); }
+void fnstcw(const Address& addr) { opModM(addr, Reg32(7), 0xD9, 0x100); }
+void fnstenv(const Address& addr) { opModM(addr, Reg32(6), 0xD9, 0x100); }
+void fnstsw(const Address& addr) { opModM(addr, Reg32(7), 0xDD, 0x100); }
+void fnstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0xDF); db(0xE0); }
+void fpatan() { db(0xD9); db(0xF3); }
+void fprem() { db(0xD9); db(0xF8); }
+void fprem1() { db(0xD9); db(0xF5); }
+void fptan() { db(0xD9); db(0xF2); }
+void frndint() { db(0xD9); db(0xFC); }
+void frstor(const Address& addr) { opModM(addr, Reg32(4), 0xDD, 0x100); }
+void fsave(const Address& addr) { db(0x9B); opModM(addr, Reg32(6), 0xDD, 0x100); }
+void fscale() { db(0xD9); db(0xFD); }
+void fsin() { db(0xD9); db(0xFE); }
+void fsincos() { db(0xD9); db(0xFB); }
+void fsqrt() { db(0xD9); db(0xFA); }
+void fst(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 2, 0); }
+void fst(const Fpu& reg) { opFpu(reg, 0xDD, 0xD0); }
+void fstcw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xD9, 0x100); }
+void fstenv(const Address& addr) { db(0x9B); opModM(addr, Reg32(6), 0xD9, 0x100); }
+void fstp(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 3, 0); }
+void fstp(const Fpu& reg) { opFpu(reg, 0xDD, 0xD8); }
+void fstsw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xDD, 0x100); }
+void fstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0x9B); db(0xDF); db(0xE0); }
+void fsub(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 4, 0); }
+void fsub(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E0, 0xDCE8); }
+void fsub(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E0, 0xDCE8); }
+void fsubp() { db(0xDE); db(0xE9); }
+void fsubp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE8); }
+void fsubp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE8); }
+void fsubr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 5, 0); }
+void fsubr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E8, 0xDCE0); }
+void fsubr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E8, 0xDCE0); }
+void fsubrp() { db(0xDE); db(0xE1); }
+void fsubrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE0); }
+void fsubrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE0); }
+void ftst() { db(0xD9); db(0xE4); }
+void fucom() { db(0xDD); db(0xE1); }
+void fucom(const Fpu& reg) { opFpu(reg, 0xDD, 0xE0); }
+void fucomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBE8, 0x00E8); }
+void fucomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBE8, 0x00E8); }
+void fucomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFE8, 0x00E8); }
+void fucomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFE8, 0x00E8); }
+void fucomp() { db(0xDD); db(0xE9); }
+void fucomp(const Fpu& reg) { opFpu(reg, 0xDD, 0xE8); }
+void fucompp() { db(0xDA); db(0xE9); }
+void fwait() { db(0x9B); }
+void fxam() { db(0xD9); db(0xE5); }
+void fxch() { db(0xD9); db(0xC9); }
+void fxch(const Fpu& reg) { opFpu(reg, 0xD9, 0xC8); }
+void fxrstor(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xAE); }
+void fxtract() { db(0xD9); db(0xF4); }
+void fyl2x() { db(0xD9); db(0xF1); }
+void fyl2xp1() { db(0xD9); db(0xF9); }
+void gf2p8affineinvqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void gf2p8affineqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCE, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void gf2p8mulb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void haddpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0x66, isXMM_XMMorMEM); }
+void haddps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0xF2, isXMM_XMMorMEM); }
+void hlt() { db(0xF4); }
+void hsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0x66, isXMM_XMMorMEM); }
+void hsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0xF2, isXMM_XMMorMEM); }
+void idiv(const Operand& op) { opR_ModM(op, 0, 7, 0xF6); }
+void imul(const Operand& op) { opR_ModM(op, 0, 5, 0xF6); }
+void in_(const Reg& a, const Reg& d) { opInOut(a, d, 0xEC); }
+void in_(const Reg& a, uint8_t v) { opInOut(a, 0xE4, v); }
+void inc(const Operand& op) { opIncDec(op, 0x40, 0); }
+void insertps(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void int3() { db(0xCC); }
+void int_(uint8_t x) { db(0xCD); db(x); }
+void ja(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void ja(const char *label, LabelType type = T_AUTO) { ja(std::string(label), type); }//-V524
+void ja(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524
+void ja(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void jae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jae(const char *label, LabelType type = T_AUTO) { jae(std::string(label), type); }//-V524
+void jae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524
+void jae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jb(const char *label, LabelType type = T_AUTO) { jb(std::string(label), type); }//-V524
+void jb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524
+void jb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jbe(const char *label, LabelType type = T_AUTO) { jbe(std::string(label), type); }//-V524
+void jbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524
+void jbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jc(const char *label, LabelType type = T_AUTO) { jc(std::string(label), type); }//-V524
+void jc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524
+void jc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void je(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void je(const char *label, LabelType type = T_AUTO) { je(std::string(label), type); }//-V524
+void je(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524
+void je(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void jg(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jg(const char *label, LabelType type = T_AUTO) { jg(std::string(label), type); }//-V524
+void jg(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524
+void jg(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jge(const char *label, LabelType type = T_AUTO) { jge(std::string(label), type); }//-V524
+void jge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524
+void jge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jl(const char *label, LabelType type = T_AUTO) { jl(std::string(label), type); }//-V524
+void jl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524
+void jl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jle(const char *label, LabelType type = T_AUTO) { jle(std::string(label), type); }//-V524
+void jle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524
+void jle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jna(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jna(const char *label, LabelType type = T_AUTO) { jna(std::string(label), type); }//-V524
+void jna(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524
+void jna(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jnae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jnae(const char *label, LabelType type = T_AUTO) { jnae(std::string(label), type); }//-V524
+void jnae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524
+void jnae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jnb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jnb(const char *label, LabelType type = T_AUTO) { jnb(std::string(label), type); }//-V524
+void jnb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524
+void jnb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jnbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void jnbe(const char *label, LabelType type = T_AUTO) { jnbe(std::string(label), type); }//-V524
+void jnbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524
+void jnbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void jnc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jnc(const char *label, LabelType type = T_AUTO) { jnc(std::string(label), type); }//-V524
+void jnc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524
+void jnc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jne(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jne(const char *label, LabelType type = T_AUTO) { jne(std::string(label), type); }//-V524
+void jne(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524
+void jne(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jng(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jng(const char *label, LabelType type = T_AUTO) { jng(std::string(label), type); }//-V524
+void jng(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524
+void jng(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jnge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jnge(const char *label, LabelType type = T_AUTO) { jnge(std::string(label), type); }//-V524
+void jnge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524
+void jnge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jnl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jnl(const char *label, LabelType type = T_AUTO) { jnl(std::string(label), type); }//-V524
+void jnl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524
+void jnl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jnle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jnle(const char *label, LabelType type = T_AUTO) { jnle(std::string(label), type); }//-V524
+void jnle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524
+void jnle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jno(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524
+void jno(const char *label, LabelType type = T_AUTO) { jno(std::string(label), type); }//-V524
+void jno(const void *addr) { opJmpAbs(addr, T_NEAR, 0x71, 0x81, 0x0F); }//-V524
+void jno(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524
+void jnp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void jnp(const char *label, LabelType type = T_AUTO) { jnp(std::string(label), type); }//-V524
+void jnp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524
+void jnp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void jns(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524
+void jns(const char *label, LabelType type = T_AUTO) { jns(std::string(label), type); }//-V524
+void jns(const void *addr) { opJmpAbs(addr, T_NEAR, 0x79, 0x89, 0x0F); }//-V524
+void jns(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524
+void jnz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jnz(const char *label, LabelType type = T_AUTO) { jnz(std::string(label), type); }//-V524
+void jnz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524
+void jnz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524
+void jo(const char *label, LabelType type = T_AUTO) { jo(std::string(label), type); }//-V524
+void jo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x70, 0x80, 0x0F); }//-V524
+void jo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524
+void jp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jp(const char *label, LabelType type = T_AUTO) { jp(std::string(label), type); }//-V524
+void jp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524
+void jp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jpe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jpe(const char *label, LabelType type = T_AUTO) { jpe(std::string(label), type); }//-V524
+void jpe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524
+void jpe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jpo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void jpo(const char *label, LabelType type = T_AUTO) { jpo(std::string(label), type); }//-V524
+void jpo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524
+void jpo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void js(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524
+void js(const char *label, LabelType type = T_AUTO) { js(std::string(label), type); }//-V524
+void js(const void *addr) { opJmpAbs(addr, T_NEAR, 0x78, 0x88, 0x0F); }//-V524
+void js(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524
+void jz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void jz(const char *label, LabelType type = T_AUTO) { jz(std::string(label), type); }//-V524
+void jz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524
+void jz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void lahf() { db(0x9F); }
+void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); }
+void ldmxcsr(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0xAE); }
+void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModM(addr, reg, 0x8D); }
+void leave() { db(0xC9); }
+void lfence() { db(0x0F); db(0xAE); db(0xE8); }
+void lfs(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x0F, 0xB4); }
+void lgs(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x0F, 0xB5); }
+void lock() { db(0xF0); }
+void lodsb() { db(0xAC); }
+void lodsd() { db(0xAD); }
+void lodsw() { db(0x66); db(0xAD); }
+void loop(const Label& label) { opJmp(label, T_SHORT, 0xE2, 0, 0); }
+void loop(const char *label) { loop(std::string(label)); }
+void loop(std::string label) { opJmp(label, T_SHORT, 0xE2, 0, 0); }
+void loope(const Label& label) { opJmp(label, T_SHORT, 0xE1, 0, 0); }
+void loope(const char *label) { loope(std::string(label)); }
+void loope(std::string label) { opJmp(label, T_SHORT, 0xE1, 0, 0); }
+void loopne(const Label& label) { opJmp(label, T_SHORT, 0xE0, 0, 0); }
+void loopne(const char *label) { loopne(std::string(label)); }
+void loopne(std::string label) { opJmp(label, T_SHORT, 0xE0, 0, 0); }
+void lss(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x0F, 0xB2); }
+void lzcnt(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBD); }
+void maskmovdqu(const Xmm& reg1, const Xmm& reg2) { db(0x66); opModR(reg1, reg2, 0x0F, 0xF7); }
+void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModR(reg1, reg2, 0x0F, 0xF7); }
+void maxpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x66, isXMM_XMMorMEM); }
+void maxps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x100, isXMM_XMMorMEM); }
+void maxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF2, isXMM_XMMorMEM); }
+void maxss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF3, isXMM_XMMorMEM); }
+void mfence() { db(0x0F); db(0xAE); db(0xF0); }
+void minpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x66, isXMM_XMMorMEM); }
+void minps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x100, isXMM_XMMorMEM); }
+void minsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF2, isXMM_XMMorMEM); }
+void minss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF3, isXMM_XMMorMEM); }
+void monitor() { db(0x0F); db(0x01); db(0xC8); }
+void monitorx() { db(0x0F); db(0x01); db(0xFA); }
+void movapd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x29); }
+void movapd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x66); }
+void movaps(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x29); }
+void movaps(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x100); }
+void movbe(const Address& addr, const Reg& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF1); }
+void movbe(const Reg& reg, const Address& addr) { opModM(addr, reg, 0x0F, 0x38, 0xF0); }
+void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); }
+void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x6E); }
+void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }
+void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }
+void movddup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF2, isXMM_XMMorMEM, NONE, NONE); }
+void movdir64b(const Reg& reg, const Address& addr) { db(0x66); opModM(addr, reg.cvt32(), 0x0F, 0x38, 0xF8); }
+void movdiri(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF9); }
+void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); }
+void movdqa(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x7F); }
+void movdqa(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0x66); }
+void movdqu(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x7F); }
+void movdqu(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0xF3); }
+void movhlps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x12); }
+void movhpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x66); }
+void movhps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x100); }
+void movlhps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x16); }
+void movlpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x66); }
+void movlps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x100); }
+void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); }
+void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); }
+void movntdq(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0xE7); }
+void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); }
+void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); }
+void movntpd(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0x2B); }
+void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); }
+void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModM(addr, mmx, 0x0F, 0xE7); }
+void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); }
+void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); }
+void movq2dq(const Xmm& xmm, const Mmx& mmx) { db(0xF3); opModR(xmm, mmx, 0x0F, 0xD6); }
+void movsb() { db(0xA4); }
+void movsd() { db(0xA5); }
+void movsd(const Address& addr, const Xmm& xmm) { db(0xF2); opModM(addr, xmm, 0x0F, 0x11); }
+void movsd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF2); }
+void movshdup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x16, 0xF3, isXMM_XMMorMEM, NONE, NONE); }
+void movsldup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF3, isXMM_XMMorMEM, NONE, NONE); }
+void movss(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x11); }
+void movss(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF3); }
+void movsw() { db(0x66); db(0xA5); }
+void movsx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xBE); }
+void movupd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x11); }
+void movupd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x66); }
+void movups(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x11); }
+void movups(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x100); }
+void movzx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xB6); }
+void mpsadbw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x42, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void mul(const Operand& op) { opR_ModM(op, 0, 4, 0xF6); }
+void mulpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x66, isXMM_XMMorMEM); }
+void mulps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x100, isXMM_XMMorMEM); }
+void mulsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF2, isXMM_XMMorMEM); }
+void mulss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF3, isXMM_XMMorMEM); }
+void mulx(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf6, true); }
+void mwait() { db(0x0F); db(0x01); db(0xC9); }
+void mwaitx() { db(0x0F); db(0x01); db(0xFB); }
+void neg(const Operand& op) { opR_ModM(op, 0, 3, 0xF6); }
+void not_(const Operand& op) { opR_ModM(op, 0, 2, 0xF6); }
+void or_(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x08, 1); }
+void or_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x08); }
+void orpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x66, isXMM_XMMorMEM); }
+void orps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x100, isXMM_XMMorMEM); }
+void out_(const Reg& d, const Reg& a) { opInOut(a, d, 0xEE); }
+void out_(uint8_t v, const Reg& a) { opInOut(a, 0xE6, v); }
+void outsb() { db(0x6E); }
+void outsd() { db(0x6F); }
+void outsw() { db(0x66); db(0x6F); }
+void pabsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1C, 0x66, NONE, 0x38); }
+void pabsd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1E, 0x66, NONE, 0x38); }
+void pabsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1D, 0x66, NONE, 0x38); }
+void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); }
+void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); }
+void packusdw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2B, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }
+void paddb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFC); }
+void paddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFE); }
+void paddq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD4); }
+void paddsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEC); }
+void paddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xED); }
+void paddusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDC); }
+void paddusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDD); }
+void paddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFD); }
+void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8_t>(imm), 0x3a); }
+void pand(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDB); }
+void pandn(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDF); }
+void pause() { db(0xF3); db(0x90); }
+void pavgb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE0); }
+void pavgw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE3); }
+void pblendvb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x10, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pblendw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0E, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void pclmulhqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x11); }
+void pclmulhqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x01); }
+void pclmullqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x10); }
+void pclmullqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x00); }
+void pclmulqdq(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x44, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void pcmpeqb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x74); }
+void pcmpeqd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x76); }
+void pcmpeqq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x29, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pcmpeqw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x75); }
+void pcmpestri(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x61, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pcmpestrm(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x60, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pcmpgtb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x64); }
+void pcmpgtd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x66); }
+void pcmpgtq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x37, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pcmpgtw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x65); }
+void pcmpistri(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x63, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pcmpistrm(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x62, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pdep(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf5, true); }
+void pext(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F3 | T_0F38, 0xf5, true); }
+void pextrb(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x14, imm); }
+void pextrd(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x16, imm); }
+void pextrw(const Operand& op, const Mmx& xmm, uint8_t imm) { opExt(op, xmm, 0x15, imm, true); }
+void phaddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x02, 0x66, NONE, 0x38); }
+void phaddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x03, 0x66, NONE, 0x38); }
+void phaddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x01, 0x66, NONE, 0x38); }
+void phminposuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void phsubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x06, 0x66, NONE, 0x38); }
+void phsubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x07, 0x66, NONE, 0x38); }
+void phsubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x05, 0x66, NONE, 0x38); }
+void pinsrb(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); }
+void pinsrd(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); }
+void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); }
+void pmaddubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x04, 0x66, NONE, 0x38); }
+void pmaddwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF5); }
+void pmaxsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3C, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmaxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3D, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmaxsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEE); }
+void pmaxub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDE); }
+void pmaxud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3F, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmaxuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3E, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x38, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x39, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEA); }
+void pminub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDA); }
+void pminud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3B, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3A, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); }
+void pmovsxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x22, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x20, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x25, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x23, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x24, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x31, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x32, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x30, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x35, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x33, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x34, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmuldq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x28, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmulhrsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0B, 0x66, NONE, 0x38); }
+void pmulhuw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE4); }
+void pmulhw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE5); }
+void pmulld(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmullw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD5); }
+void pmuludq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF4); }
+void popcnt(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xB8); }
+void popf() { db(0x9D); }
+void por(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEB); }
+void prefetchnta(const Address& addr) { opModM(addr, Reg32(0), 0x0F, 0x18); }
+void prefetcht0(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x18); }
+void prefetcht1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x18); }
+void prefetcht2(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0x18); }
+void prefetchw(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x0D); }
+void prefetchwt1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x0D); }
+void psadbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF6); }
+void pshufb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x00, 0x66, NONE, 0x38); }
+void pshufd(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0x66, imm8); }
+void pshufhw(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0xF3, imm8); }
+void pshuflw(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0xF2, imm8); }
+void pshufw(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0x00, imm8); }
+void psignb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x08, 0x66, NONE, 0x38); }
+void psignd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0A, 0x66, NONE, 0x38); }
+void psignw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x09, 0x66, NONE, 0x38); }
+void pslld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF2); }
+void pslld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 6); }
+void pslldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 7); }
+void psllq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF3); }
+void psllq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 6); }
+void psllw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF1); }
+void psllw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 6); }
+void psrad(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE2); }
+void psrad(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 4); }
+void psraw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE1); }
+void psraw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 4); }
+void psrld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD2); }
+void psrld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 2); }
+void psrldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 3); }
+void psrlq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD3); }
+void psrlq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 2); }
+void psrlw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD1); }
+void psrlw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 2); }
+void psubb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF8); }
+void psubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFA); }
+void psubq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFB); }
+void psubsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE8); }
+void psubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE9); }
+void psubusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD8); }
+void psubusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD9); }
+void psubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF9); }
+void ptest(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x17, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void punpckhbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x68); }
+void punpckhdq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6A); }
+void punpckhqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6D, 0x66, isXMM_XMMorMEM); }
+void punpckhwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x69); }
+void punpcklbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x60); }
+void punpckldq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x62); }
+void punpcklqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6C, 0x66, isXMM_XMMorMEM); }
+void punpcklwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x61); }
+void pushf() { db(0x9C); }
+void pxor(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEF); }
+void rcl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 2); }
+void rcl(const Operand& op, int imm) { opShift(op, imm, 2); }
+void rcpps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0x100, isXMM_XMMorMEM); }
+void rcpss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0xF3, isXMM_XMMorMEM); }
+void rcr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 3); }
+void rcr(const Operand& op, int imm) { opShift(op, imm, 3); }
+void rdmsr() { db(0x0F); db(0x32); }
+void rdpmc() { db(0x0F); db(0x33); }
+void rdrand(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }
+void rdseed(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }
+void rdtsc() { db(0x0F); db(0x31); }
+void rdtscp() { db(0x0F); db(0x01); db(0xF9); }
+void rep() { db(0xF3); }
+void repe() { db(0xF3); }
+void repne() { db(0xF2); }
+void repnz() { db(0xF2); }
+void repz() { db(0xF3); }
+void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }
+void retf(int imm = 0) { if (imm) { db(0xCA); dw(imm); } else { db(0xCB); } }
+void rol(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 0); }
+void rol(const Operand& op, int imm) { opShift(op, imm, 0); }
+void ror(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 1); }
+void ror(const Operand& op, int imm) { opShift(op, imm, 1); }
+void rorx(const Reg32e& r, const Operand& op, uint8_t imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); }
+void roundpd(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x09, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void roundps(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x08, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void roundsd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0B, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void roundss(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0A, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }
+void rsqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0x100, isXMM_XMMorMEM); }
+void rsqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0xF3, isXMM_XMMorMEM); }
+void sahf() { db(0x9E); }
+void sal(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); }
+void sal(const Operand& op, int imm) { opShift(op, imm, 4); }
+void sar(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 7); }
+void sar(const Operand& op, int imm) { opShift(op, imm, 7); }
+void sarx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F3 | T_0F38, 0xf7, false); }
+void sbb(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x18, 3); }
+void sbb(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x18); }
+void scasb() { db(0xAE); }
+void scasd() { db(0xAF); }
+void scasw() { db(0x66); db(0xAF); }
+void serialize() { db(0x0F); db(0x01); db(0xE8); }
+void seta(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524
+void setae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524
+void setb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524
+void setbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524
+void setc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524
+void sete(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524
+void setg(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524
+void setge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524
+void setl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524
+void setle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524
+void setna(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524
+void setnae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524
+void setnb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524
+void setnbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524
+void setnc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524
+void setne(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524
+void setng(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524
+void setnge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524
+void setnl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524
+void setnle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524
+void setno(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 1); }//-V524
+void setnp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524
+void setns(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 9); }//-V524
+void setnz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524
+void seto(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 0); }//-V524
+void setp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524
+void setpe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524
+void setpo(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524
+void sets(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 8); }//-V524
+void setz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524
+void sfence() { db(0x0F); db(0xAE); db(0xF8); }
+void sha1msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC9, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha1msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCA, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha1nexte(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC8, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha1rnds4(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, imm, 0x3A); }
+void sha256msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha256msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCD, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha256rnds2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCB, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void shl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); }
+void shl(const Operand& op, int imm) { opShift(op, imm, 4); }
+void shld(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xA4, &_cl); }
+void shld(const Operand& op, const Reg& reg, uint8_t imm) { opShxd(op, reg, imm, 0xA4); }
+void shlx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_66 | T_0F38, 0xf7, false); }
+void shr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 5); }
+void shr(const Operand& op, int imm) { opShift(op, imm, 5); }
+void shrd(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xAC, &_cl); }
+void shrd(const Operand& op, const Reg& reg, uint8_t imm) { opShxd(op, reg, imm, 0xAC); }
+void shrx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F2 | T_0F38, 0xf7, false); }
+void shufpd(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC6, 0x66, isXMM_XMMorMEM, imm8); }
+void shufps(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC6, 0x100, isXMM_XMMorMEM, imm8); }
+void sqrtpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x66, isXMM_XMMorMEM); }
+void sqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x100, isXMM_XMMorMEM); }
+void sqrtsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF2, isXMM_XMMorMEM); }
+void sqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF3, isXMM_XMMorMEM); }
+void stac() { db(0x0F); db(0x01); db(0xCB); }
+void stc() { db(0xF9); }
+void std() { db(0xFD); }
+void sti() { db(0xFB); }
+void stmxcsr(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0xAE); }
+void stosb() { db(0xAA); }
+void stosd() { db(0xAB); }
+void stosw() { db(0x66); db(0xAB); }
+void sub(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x28, 5); }
+void sub(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x28); }
+void subpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x66, isXMM_XMMorMEM); }
+void subps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x100, isXMM_XMMorMEM); }
+void subsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF2, isXMM_XMMorMEM); }
+void subss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF3, isXMM_XMMorMEM); }
+void sysenter() { db(0x0F); db(0x34); }
+void sysexit() { db(0x0F); db(0x35); }
+void tpause(const Reg32& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) db(0x66); db(0x0F); db(0xAE); setModRM(3, 6, idx); }
+void tzcnt(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBC); }
+void ucomisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x66, isXMM_XMMorMEM); }
+void ucomiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x100, isXMM_XMMorMEM); }
+void ud2() { db(0x0F); db(0x0B); }
+void umonitor(const Reg& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) int bit = r.getBit(); if (BIT != bit) { if ((BIT == 32 && bit == 16) || (BIT == 64 && bit == 32)) { db(0x67); } else { XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) } } db(0xF3); db(0x0F); db(0xAE); setModRM(3, 6, idx); }
+void umwait(const Reg32& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) db(0xF2); db(0x0F); db(0xAE); setModRM(3, 6, idx); }
+void unpckhpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM); }
+void unpckhps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x100, isXMM_XMMorMEM); }
+void unpcklpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM); }
+void unpcklps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x100, isXMM_XMMorMEM); }
+void vaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x58); }
+void vaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x58); }
+void vaddsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x58); }
+void vaddss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x58); }
+void vaddsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0xD0); }
+void vaddsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0xD0); }
+void vaesdec(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDE); }
+void vaesdeclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDF); }
+void vaesenc(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDC); }
+void vaesenclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDD); }
+void vaesimc(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_W0, 0xDB); }
+void vaeskeygenassist(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0xDF, imm); }
+void vandnpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x55); }
+void vandnps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x55); }
+void vandpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x54); }
+void vandps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x54); }
+void vbcstnebf162ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_F3 | T_0F38 | T_W0 | T_YMM | T_B16, 0xB1); }
+void vbcstnesh2ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_66 | T_0F38 | T_W0 | T_YMM | T_B16, 0xB1); }
+void vblendpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0D, imm); }
+void vblendps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0C, imm); }
+void vblendvpd(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4B, x4.getIdx() << 4); }
+void vblendvps(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4A, x4.getIdx() << 4); }
+void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); }
+void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); }
+void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); }
+void vbroadcastss(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x18); }
+void vcmpeq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 16); }
+void vcmpeq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 16); }
+void vcmpeq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 16); }
+void vcmpeq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 16); }
+void vcmpeq_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 8); }
+void vcmpeq_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 8); }
+void vcmpeq_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 8); }
+void vcmpeq_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 8); }
+void vcmpeq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 24); }
+void vcmpeq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 24); }
+void vcmpeq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 24); }
+void vcmpeq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 24); }
+void vcmpeqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 0); }
+void vcmpeqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 0); }
+void vcmpeqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 0); }
+void vcmpeqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 0); }
+void vcmpfalse_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 27); }
+void vcmpfalse_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 27); }
+void vcmpfalse_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 27); }
+void vcmpfalse_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 27); }
+void vcmpfalsepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 11); }
+void vcmpfalseps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 11); }
+void vcmpfalsesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 11); }
+void vcmpfalsess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 11); }
+void vcmpge_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 29); }
+void vcmpge_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 29); }
+void vcmpge_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 29); }
+void vcmpge_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 29); }
+void vcmpgepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 13); }
+void vcmpgeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 13); }
+void vcmpgesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 13); }
+void vcmpgess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 13); }
+void vcmpgt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 30); }
+void vcmpgt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 30); }
+void vcmpgt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 30); }
+void vcmpgt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 30); }
+void vcmpgtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 14); }
+void vcmpgtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 14); }
+void vcmpgtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 14); }
+void vcmpgtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 14); }
+void vcmple_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 18); }
+void vcmple_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 18); }
+void vcmple_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 18); }
+void vcmple_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 18); }
+void vcmplepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 2); }
+void vcmpleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 2); }
+void vcmplesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 2); }
+void vcmpless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 2); }
+void vcmplt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 17); }
+void vcmplt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 17); }
+void vcmplt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 17); }
+void vcmplt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 17); }
+void vcmpltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 1); }
+void vcmpltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 1); }
+void vcmpltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 1); }
+void vcmpltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 1); }
+void vcmpneq_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 12); }
+void vcmpneq_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 12); }
+void vcmpneq_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 12); }
+void vcmpneq_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 12); }
+void vcmpneq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 28); }
+void vcmpneq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 28); }
+void vcmpneq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 28); }
+void vcmpneq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 28); }
+void vcmpneq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 20); }
+void vcmpneq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 20); }
+void vcmpneq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 20); }
+void vcmpneq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 20); }
+void vcmpneqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 4); }
+void vcmpneqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 4); }
+void vcmpneqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 4); }
+void vcmpneqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 4); }
+void vcmpnge_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 25); }
+void vcmpnge_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 25); }
+void vcmpnge_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 25); }
+void vcmpnge_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 25); }
+void vcmpngepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 9); }
+void vcmpngeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 9); }
+void vcmpngesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 9); }
+void vcmpngess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 9); }
+void vcmpngt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 26); }
+void vcmpngt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 26); }
+void vcmpngt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 26); }
+void vcmpngt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 26); }
+void vcmpngtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 10); }
+void vcmpngtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 10); }
+void vcmpngtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 10); }
+void vcmpngtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 10); }
+void vcmpnle_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 22); }
+void vcmpnle_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 22); }
+void vcmpnle_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 22); }
+void vcmpnle_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 22); }
+void vcmpnlepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 6); }
+void vcmpnleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 6); }
+void vcmpnlesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 6); }
+void vcmpnless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 6); }
+void vcmpnlt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 21); }
+void vcmpnlt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 21); }
+void vcmpnlt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 21); }
+void vcmpnlt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 21); }
+void vcmpnltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 5); }
+void vcmpnltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 5); }
+void vcmpnltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 5); }
+void vcmpnltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 5); }
+void vcmpord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 23); }
+void vcmpord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 23); }
+void vcmpord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 23); }
+void vcmpord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 23); }
+void vcmpordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 7); }
+void vcmpordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 7); }
+void vcmpordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 7); }
+void vcmpordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 7); }
+void vcmppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xC2, imm); }
+void vcmpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_YMM, 0xC2, imm); }
+void vcmpsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F, 0xC2, imm); }
+void vcmpss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0xC2, imm); }
+void vcmptrue_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 31); }
+void vcmptrue_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 31); }
+void vcmptrue_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 31); }
+void vcmptrue_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 31); }
+void vcmptruepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 15); }
+void vcmptrueps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 15); }
+void vcmptruesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 15); }
+void vcmptruess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 15); }
+void vcmpunord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 19); }
+void vcmpunord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 19); }
+void vcmpunord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 19); }
+void vcmpunord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 19); }
+void vcmpunordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 3); }
+void vcmpunordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 3); }
+void vcmpunordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 3); }
+void vcmpunordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 3); }
+void vcomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2F); }
+void vcomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2F); }
+void vcvtdq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0xE6); }
+void vcvtdq2ps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); }
+void vcvtneebf162ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_F3 | T_0F38 | T_W0 | T_YMM, 0xB0); }
+void vcvtneeph2ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_66 | T_0F38 | T_W0 | T_YMM, 0xB0); }
+void vcvtneobf162ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_F2 | T_0F38 | T_W0 | T_YMM, 0xB0); }
+void vcvtneoph2ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_W0 | T_YMM, 0xB0); }
+void vcvtneps2bf16(const Xmm& x, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opCvt2(x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32 | orEvexIf(encoding), 0x72); }
+void vcvtpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0xE6); }
+void vcvtpd2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5A); }
+void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); }
+void vcvtps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); }
+void vcvtps2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x5A); }
+void vcvtps2ph(const Operand& op, const Xmm& x, uint8_t imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y | T_M_K, 0x1D, imm); }
+void vcvtsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_ER_X, 0x2D); }
+void vcvtsd2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x5A); }
+void vcvtsi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F2 | T_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }
+void vcvtsi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F3 | T_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }
+void vcvtss2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x5A); }
+void vcvtss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_ER_X | T_N8, 0x2D); }
+void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); }
+void vcvttps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX | T_SAE_Z | T_B32, 0x5B); }
+void vcvttsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, 0x2C); }
+void vcvttss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_SAE_X | T_N8, 0x2C); }
+void vdivpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5E); }
+void vdivps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5E); }
+void vdivsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5E); }
+void vdivss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5E); }
+void vdppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x41, imm); }
+void vdpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x40, imm); }
+void vextractf128(const Operand& op, const Ymm& y, uint8_t imm) { if (!(op.isXMEM() && y.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); }
+void vextracti128(const Operand& op, const Ymm& y, uint8_t imm) { if (!(op.isXMEM() && y.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); }
+void vextractps(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); }
+void vfmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x98); }
+void vfmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x98); }
+void vfmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x99); }
+void vfmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x99); }
+void vfmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA8); }
+void vfmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA8); }
+void vfmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xA9); }
+void vfmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xA9); }
+void vfmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB8); }
+void vfmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB8); }
+void vfmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xB9); }
+void vfmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xB9); }
+void vfmaddsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x96); }
+void vfmaddsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x96); }
+void vfmaddsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA6); }
+void vfmaddsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA6); }
+void vfmaddsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB6); }
+void vfmaddsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB6); }
+void vfmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9A); }
+void vfmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9A); }
+void vfmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9B); }
+void vfmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9B); }
+void vfmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAA); }
+void vfmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAA); }
+void vfmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAB); }
+void vfmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAB); }
+void vfmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBA); }
+void vfmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBA); }
+void vfmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBB); }
+void vfmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBB); }
+void vfmsubadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x97); }
+void vfmsubadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x97); }
+void vfmsubadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA7); }
+void vfmsubadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA7); }
+void vfmsubadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB7); }
+void vfmsubadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB7); }
+void vfnmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9C); }
+void vfnmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9C); }
+void vfnmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9D); }
+void vfnmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9D); }
+void vfnmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAC); }
+void vfnmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAC); }
+void vfnmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAD); }
+void vfnmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAD); }
+void vfnmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBC); }
+void vfnmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBC); }
+void vfnmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBD); }
+void vfnmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBD); }
+void vfnmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9E); }
+void vfnmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9E); }
+void vfnmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9F); }
+void vfnmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9F); }
+void vfnmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAE); }
+void vfnmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAE); }
+void vfnmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAF); }
+void vfnmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAF); }
+void vfnmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBE); }
+void vfnmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBE); }
+void vfnmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBF); }
+void vfnmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBF); }
+void vgatherdpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x92, 0); }
+void vgatherdps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x92, 1); }
+void vgatherqpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x93, 1); }
+void vgatherqps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x93, 2); }
+void vgf2p8affineinvqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCF, imm); }
+void vgf2p8affineqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCE, imm); }
+void vgf2p8mulb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_SAE_Z, 0xCF); }
+void vhaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7C); }
+void vhaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7C); }
+void vhsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7D); }
+void vhsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7D); }
+void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); }
+void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); }
+void vinsertps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_W0 | T_EW0 | T_EVEX, 0x21, imm); }
+void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); }
+void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); }
+void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); }
+void vmaskmovpd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2F); }
+void vmaskmovpd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2D); }
+void vmaskmovps(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2E); }
+void vmaskmovps(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2C); }
+void vmaxpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5F); }
+void vmaxps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5F); }
+void vmaxsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5F); }
+void vmaxss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5F); }
+void vminpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5D); }
+void vminps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5D); }
+void vminsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5D); }
+void vminss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5D); }
+void vmovapd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x29); }
+void vmovapd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x28); }
+void vmovaps(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x29); }
+void vmovaps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x28); }
+void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); }
+void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); }
+void vmovddup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_DUP | T_F2 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_X | T_ER_Y | T_ER_Z, 0x12); }
+void vmovdqa(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_YMM, 0x7F); }
+void vmovdqa(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_YMM, 0x6F); }
+void vmovdqu(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_F3 | T_0F | T_YMM, 0x7F); }
+void vmovdqu(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM, 0x6F); }
+void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); }
+void vmovhpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x17); }
+void vmovhpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x16); }
+void vmovhps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x17); }
+void vmovhps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x16); }
+void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); }
+void vmovlpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x13); }
+void vmovlpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x12); }
+void vmovlps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x13); }
+void vmovlps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x12); }
+void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); }
+void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); }
+void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); }
+void vmovntdqa(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0, 0x2A); }
+void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); }
+void vmovntps(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_YMM | T_EVEX | T_EW0, 0x2B); }
+void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); }
+void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); }
+void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); }
+void vmovsd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_M_K, 0x11); }
+void vmovsd(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); }
+void vmovsd(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); }
+void vmovshdup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x16); }
+void vmovsldup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x12); }
+void vmovss(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_M_K, 0x11); }
+void vmovss(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); }
+void vmovss(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); }
+void vmovupd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x11); }
+void vmovupd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x10); }
+void vmovups(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x11); }
+void vmovups(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x10); }
+void vmpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x42, imm); }
+void vmulpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x59); }
+void vmulps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x59); }
+void vmulsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x59); }
+void vmulss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x59); }
+void vorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x56); }
+void vorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x56); }
+void vpabsb(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1C); }
+void vpabsd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x1E); }
+void vpabsw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1D); }
+void vpackssdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6B); }
+void vpacksswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x63); }
+void vpackusdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x2B); }
+void vpackuswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x67); }
+void vpaddb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFC); }
+void vpaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFE); }
+void vpaddq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xD4); }
+void vpaddsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEC); }
+void vpaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xED); }
+void vpaddusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDC); }
+void vpaddusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDD); }
+void vpaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFD); }
+void vpalignr(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_YMM | T_EVEX, 0x0F, imm); }
+void vpand(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDB); }
+void vpandn(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDF); }
+void vpavgb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE0); }
+void vpavgw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE3); }
+void vpblendd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x02, imm); }
+void vpblendvb(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4C, x4.getIdx() << 4); }
+void vpblendw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0E, imm); }
+void vpbroadcastb(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x78); }
+void vpbroadcastd(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x58); }
+void vpbroadcastq(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX, 0x59); }
+void vpbroadcastw(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x79); }
+void vpclmulqdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM | T_EVEX, 0x44, imm); }
+void vpcmpeqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x74); }
+void vpcmpeqd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x76); }
+void vpcmpeqq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x29); }
+void vpcmpeqw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x75); }
+void vpcmpestri(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x61, imm); }
+void vpcmpestrm(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x60, imm); }
+void vpcmpgtb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x64); }
+void vpcmpgtd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x66); }
+void vpcmpgtq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x37); }
+void vpcmpgtw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x65); }
+void vpcmpistri(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x63, imm); }
+void vpcmpistrm(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x62, imm); }
+void vpdpbssd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F38 | T_W0 | T_YMM, 0x50); }
+void vpdpbssds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F38 | T_W0 | T_YMM, 0x51); }
+void vpdpbsud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F38 | T_W0 | T_YMM, 0x50); }
+void vpdpbsuds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F38 | T_W0 | T_YMM, 0x51); }
+void vpdpbusd(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x50, encoding); }
+void vpdpbusds(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x51, encoding); }
+void vpdpbuud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F38 | T_W0 | T_YMM, 0x50); }
+void vpdpbuuds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F38 | T_W0 | T_YMM, 0x51); }
+void vpdpwssd(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x52, encoding); }
+void vpdpwssds(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x53, encoding); }
+void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); }
+void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); }
+void vpermd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x36); }
+void vpermilpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x0D); }
+void vpermilpd(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_EVEX | T_B64, 0x05, imm); }
+void vpermilps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x0C); }
+void vpermilps(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_EVEX | T_B32, 0x04, imm); }
+void vpermpd(const Ymm& y, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x01, imm); }
+void vpermpd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x16); }
+void vpermps(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x16); }
+void vpermq(const Ymm& y, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x00, imm); }
+void vpermq(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x36); }
+void vpextrb(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); }
+void vpextrd(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); }
+void vpextrq(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); }
+void vpextrw(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } }
+void vpgatherdd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x90, 1); }
+void vpgatherdq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x90, 0); }
+void vpgatherqd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x91, 2); }
+void vpgatherqq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x91, 1); }
+void vphaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x02); }
+void vphaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x03); }
+void vphaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x01); }
+void vphminposuw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38, 0x41); }
+void vphsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x06); }
+void vphsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x07); }
+void vphsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x05); }
+void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); }
+void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); }
+void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); }
+void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); }
+void vpmadd52huq(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_B64, 0xB5, encoding); }
+void vpmadd52luq(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_B64, 0xB4, encoding); }
+void vpmaddubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x04); }
+void vpmaddwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF5); }
+void vpmaskmovd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8E); }
+void vpmaskmovd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8C); }
+void vpmaskmovq(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8E); }
+void vpmaskmovq(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8C); }
+void vpmaxsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3C); }
+void vpmaxsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3D); }
+void vpmaxsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEE); }
+void vpmaxub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDE); }
+void vpmaxud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3F); }
+void vpmaxuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3E); }
+void vpminsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x38); }
+void vpminsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x39); }
+void vpminsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEA); }
+void vpminub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDA); }
+void vpminud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3B); }
+void vpminuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3A); }
+void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); }
+void vpmovsxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x21); }
+void vpmovsxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x22); }
+void vpmovsxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x20); }
+void vpmovsxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x25); }
+void vpmovsxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x23); }
+void vpmovsxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x24); }
+void vpmovzxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x31); }
+void vpmovzxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x32); }
+void vpmovzxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x30); }
+void vpmovzxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x35); }
+void vpmovzxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x33); }
+void vpmovzxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x34); }
+void vpmuldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x28); }
+void vpmulhrsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x0B); }
+void vpmulhuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE4); }
+void vpmulhw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE5); }
+void vpmulld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x40); }
+void vpmullw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD5); }
+void vpmuludq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xF4); }
+void vpor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEB); }
+void vpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF6); }
+void vpshufb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x00); }
+void vpshufd(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x70, imm); }
+void vpshufhw(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM | T_EVEX, 0x70, imm); }
+void vpshuflw(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_F2 | T_0F | T_YMM | T_EVEX, 0x70, imm); }
+void vpsignb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x08); }
+void vpsignd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x0A); }
+void vpsignw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x09); }
+void vpslld(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); }
+void vpslld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xF2); }
+void vpslldq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 7), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); }
+void vpsllq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); }
+void vpsllq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xF3); }
+void vpsllvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x47); }
+void vpsllvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x47); }
+void vpsllw(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); }
+void vpsllw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xF1); }
+void vpsrad(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); }
+void vpsrad(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xE2); }
+void vpsravd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x46); }
+void vpsraw(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); }
+void vpsraw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xE1); }
+void vpsrld(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); }
+void vpsrld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xD2); }
+void vpsrldq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 3), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); }
+void vpsrlq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); }
+void vpsrlq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xD3); }
+void vpsrlvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x45); }
+void vpsrlvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x45); }
+void vpsrlw(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); }
+void vpsrlw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xD1); }
+void vpsubb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF8); }
+void vpsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFA); }
+void vpsubq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xFB); }
+void vpsubsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE8); }
+void vpsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE9); }
+void vpsubusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD8); }
+void vpsubusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD9); }
+void vpsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF9); }
+void vptest(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x17); }
+void vpunpckhbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x68); }
+void vpunpckhdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6A); }
+void vpunpckhqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6D); }
+void vpunpckhwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x69); }
+void vpunpcklbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x60); }
+void vpunpckldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x62); }
+void vpunpcklqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6C); }
+void vpunpcklwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x61); }
+void vpxor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEF); }
+void vrcpps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x53); }
+void vrcpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x53); }
+void vroundpd(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x09, imm); }
+void vroundps(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x08, imm); }
+void vroundsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0B, imm); }
+void vroundss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0A, imm); }
+void vrsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x52); }
+void vrsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x52); }
+void vshufpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xC6, imm); }
+void vshufps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xC6, imm); }
+void vsqrtpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x51); }
+void vsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x51); }
+void vsqrtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x51); }
+void vsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_ER_X, 0x51); }
+void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); }
+void vsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5C); }
+void vsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5C); }
+void vsubsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5C); }
+void vsubss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5C); }
+void vtestpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0F); }
+void vtestps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0E); }
+void vucomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2E); }
+void vucomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2E); }
+void vunpckhpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x15); }
+void vunpckhps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x15); }
+void vunpcklpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x14); }
+void vunpcklps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x14); }
+void vxorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x57); }
+void vxorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x57); }
+void vzeroall() { db(0xC5); db(0xFC); db(0x77); }
+void vzeroupper() { db(0xC5); db(0xF8); db(0x77); }
+void wait() { db(0x9B); }
+void wbinvd() { db(0x0F); db(0x09); }
+void wrmsr() { db(0x0F); db(0x30); }
+void xadd(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xC0 | (reg.isBit(8) ? 0 : 1)); }
+void xgetbv() { db(0x0F); db(0x01); db(0xD0); }
+void xlatb() { db(0xD7); }
+void xor_(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x30, 6); }
+void xor_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x30); }
+void xorpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x66, isXMM_XMMorMEM); }
+void xorps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x100, isXMM_XMMorMEM); }
+#ifdef XBYAK_ENABLE_OMITTED_OPERAND
+void vblendpd(const Xmm& x, const Operand& op, uint8_t imm) { vblendpd(x, x, op, imm); }
+void vblendps(const Xmm& x, const Operand& op, uint8_t imm) { vblendps(x, x, op, imm); }
+void vblendvpd(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvpd(x1, x1, op, x4); }
+void vblendvps(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvps(x1, x1, op, x4); }
+void vcmpeq_ospd(const Xmm& x, const Operand& op) { vcmpeq_ospd(x, x, op); }
+void vcmpeq_osps(const Xmm& x, const Operand& op) { vcmpeq_osps(x, x, op); }
+void vcmpeq_ossd(const Xmm& x, const Operand& op) { vcmpeq_ossd(x, x, op); }
+void vcmpeq_osss(const Xmm& x, const Operand& op) { vcmpeq_osss(x, x, op); }
+void vcmpeq_uqpd(const Xmm& x, const Operand& op) { vcmpeq_uqpd(x, x, op); }
+void vcmpeq_uqps(const Xmm& x, const Operand& op) { vcmpeq_uqps(x, x, op); }
+void vcmpeq_uqsd(const Xmm& x, const Operand& op) { vcmpeq_uqsd(x, x, op); }
+void vcmpeq_uqss(const Xmm& x, const Operand& op) { vcmpeq_uqss(x, x, op); }
+void vcmpeq_uspd(const Xmm& x, const Operand& op) { vcmpeq_uspd(x, x, op); }
+void vcmpeq_usps(const Xmm& x, const Operand& op) { vcmpeq_usps(x, x, op); }
+void vcmpeq_ussd(const Xmm& x, const Operand& op) { vcmpeq_ussd(x, x, op); }
+void vcmpeq_usss(const Xmm& x, const Operand& op) { vcmpeq_usss(x, x, op); }
+void vcmpeqpd(const Xmm& x, const Operand& op) { vcmpeqpd(x, x, op); }
+void vcmpeqps(const Xmm& x, const Operand& op) { vcmpeqps(x, x, op); }
+void vcmpeqsd(const Xmm& x, const Operand& op) { vcmpeqsd(x, x, op); }
+void vcmpeqss(const Xmm& x, const Operand& op) { vcmpeqss(x, x, op); }
+void vcmpfalse_ospd(const Xmm& x, const Operand& op) { vcmpfalse_ospd(x, x, op); }
+void vcmpfalse_osps(const Xmm& x, const Operand& op) { vcmpfalse_osps(x, x, op); }
+void vcmpfalse_ossd(const Xmm& x, const Operand& op) { vcmpfalse_ossd(x, x, op); }
+void vcmpfalse_osss(const Xmm& x, const Operand& op) { vcmpfalse_osss(x, x, op); }
+void vcmpfalsepd(const Xmm& x, const Operand& op) { vcmpfalsepd(x, x, op); }
+void vcmpfalseps(const Xmm& x, const Operand& op) { vcmpfalseps(x, x, op); }
+void vcmpfalsesd(const Xmm& x, const Operand& op) { vcmpfalsesd(x, x, op); }
+void vcmpfalsess(const Xmm& x, const Operand& op) { vcmpfalsess(x, x, op); }
+void vcmpge_oqpd(const Xmm& x, const Operand& op) { vcmpge_oqpd(x, x, op); }
+void vcmpge_oqps(const Xmm& x, const Operand& op) { vcmpge_oqps(x, x, op); }
+void vcmpge_oqsd(const Xmm& x, const Operand& op) { vcmpge_oqsd(x, x, op); }
+void vcmpge_oqss(const Xmm& x, const Operand& op) { vcmpge_oqss(x, x, op); }
+void vcmpgepd(const Xmm& x, const Operand& op) { vcmpgepd(x, x, op); }
+void vcmpgeps(const Xmm& x, const Operand& op) { vcmpgeps(x, x, op); }
+void vcmpgesd(const Xmm& x, const Operand& op) { vcmpgesd(x, x, op); }
+void vcmpgess(const Xmm& x, const Operand& op) { vcmpgess(x, x, op); }
+void vcmpgt_oqpd(const Xmm& x, const Operand& op) { vcmpgt_oqpd(x, x, op); }
+void vcmpgt_oqps(const Xmm& x, const Operand& op) { vcmpgt_oqps(x, x, op); }
+void vcmpgt_oqsd(const Xmm& x, const Operand& op) { vcmpgt_oqsd(x, x, op); }
+void vcmpgt_oqss(const Xmm& x, const Operand& op) { vcmpgt_oqss(x, x, op); }
+void vcmpgtpd(const Xmm& x, const Operand& op) { vcmpgtpd(x, x, op); }
+void vcmpgtps(const Xmm& x, const Operand& op) { vcmpgtps(x, x, op); }
+void vcmpgtsd(const Xmm& x, const Operand& op) { vcmpgtsd(x, x, op); }
+void vcmpgtss(const Xmm& x, const Operand& op) { vcmpgtss(x, x, op); }
+void vcmple_oqpd(const Xmm& x, const Operand& op) { vcmple_oqpd(x, x, op); }
+void vcmple_oqps(const Xmm& x, const Operand& op) { vcmple_oqps(x, x, op); }
+void vcmple_oqsd(const Xmm& x, const Operand& op) { vcmple_oqsd(x, x, op); }
+void vcmple_oqss(const Xmm& x, const Operand& op) { vcmple_oqss(x, x, op); }
+void vcmplepd(const Xmm& x, const Operand& op) { vcmplepd(x, x, op); }
+void vcmpleps(const Xmm& x, const Operand& op) { vcmpleps(x, x, op); }
+void vcmplesd(const Xmm& x, const Operand& op) { vcmplesd(x, x, op); }
+void vcmpless(const Xmm& x, const Operand& op) { vcmpless(x, x, op); }
+void vcmplt_oqpd(const Xmm& x, const Operand& op) { vcmplt_oqpd(x, x, op); }
+void vcmplt_oqps(const Xmm& x, const Operand& op) { vcmplt_oqps(x, x, op); }
+void vcmplt_oqsd(const Xmm& x, const Operand& op) { vcmplt_oqsd(x, x, op); }
+void vcmplt_oqss(const Xmm& x, const Operand& op) { vcmplt_oqss(x, x, op); }
+void vcmpltpd(const Xmm& x, const Operand& op) { vcmpltpd(x, x, op); }
+void vcmpltps(const Xmm& x, const Operand& op) { vcmpltps(x, x, op); }
+void vcmpltsd(const Xmm& x, const Operand& op) { vcmpltsd(x, x, op); }
+void vcmpltss(const Xmm& x, const Operand& op) { vcmpltss(x, x, op); }
+void vcmpneq_oqpd(const Xmm& x, const Operand& op) { vcmpneq_oqpd(x, x, op); }
+void vcmpneq_oqps(const Xmm& x, const Operand& op) { vcmpneq_oqps(x, x, op); }
+void vcmpneq_oqsd(const Xmm& x, const Operand& op) { vcmpneq_oqsd(x, x, op); }
+void vcmpneq_oqss(const Xmm& x, const Operand& op) { vcmpneq_oqss(x, x, op); }
+void vcmpneq_ospd(const Xmm& x, const Operand& op) { vcmpneq_ospd(x, x, op); }
+void vcmpneq_osps(const Xmm& x, const Operand& op) { vcmpneq_osps(x, x, op); }
+void vcmpneq_ossd(const Xmm& x, const Operand& op) { vcmpneq_ossd(x, x, op); }
+void vcmpneq_osss(const Xmm& x, const Operand& op) { vcmpneq_osss(x, x, op); }
+void vcmpneq_uspd(const Xmm& x, const Operand& op) { vcmpneq_uspd(x, x, op); }
+void vcmpneq_usps(const Xmm& x, const Operand& op) { vcmpneq_usps(x, x, op); }
+void vcmpneq_ussd(const Xmm& x, const Operand& op) { vcmpneq_ussd(x, x, op); }
+void vcmpneq_usss(const Xmm& x, const Operand& op) { vcmpneq_usss(x, x, op); }
+void vcmpneqpd(const Xmm& x, const Operand& op) { vcmpneqpd(x, x, op); }
+void vcmpneqps(const Xmm& x, const Operand& op) { vcmpneqps(x, x, op); }
+void vcmpneqsd(const Xmm& x, const Operand& op) { vcmpneqsd(x, x, op); }
+void vcmpneqss(const Xmm& x, const Operand& op) { vcmpneqss(x, x, op); }
+void vcmpnge_uqpd(const Xmm& x, const Operand& op) { vcmpnge_uqpd(x, x, op); }
+void vcmpnge_uqps(const Xmm& x, const Operand& op) { vcmpnge_uqps(x, x, op); }
+void vcmpnge_uqsd(const Xmm& x, const Operand& op) { vcmpnge_uqsd(x, x, op); }
+void vcmpnge_uqss(const Xmm& x, const Operand& op) { vcmpnge_uqss(x, x, op); }
+void vcmpngepd(const Xmm& x, const Operand& op) { vcmpngepd(x, x, op); }
+void vcmpngeps(const Xmm& x, const Operand& op) { vcmpngeps(x, x, op); }
+void vcmpngesd(const Xmm& x, const Operand& op) { vcmpngesd(x, x, op); }
+void vcmpngess(const Xmm& x, const Operand& op) { vcmpngess(x, x, op); }
+void vcmpngt_uqpd(const Xmm& x, const Operand& op) { vcmpngt_uqpd(x, x, op); }
+void vcmpngt_uqps(const Xmm& x, const Operand& op) { vcmpngt_uqps(x, x, op); }
+void vcmpngt_uqsd(const Xmm& x, const Operand& op) { vcmpngt_uqsd(x, x, op); }
+void vcmpngt_uqss(const Xmm& x, const Operand& op) { vcmpngt_uqss(x, x, op); }
+void vcmpngtpd(const Xmm& x, const Operand& op) { vcmpngtpd(x, x, op); }
+void vcmpngtps(const Xmm& x, const Operand& op) { vcmpngtps(x, x, op); }
+void vcmpngtsd(const Xmm& x, const Operand& op) { vcmpngtsd(x, x, op); }
+void vcmpngtss(const Xmm& x, const Operand& op) { vcmpngtss(x, x, op); }
+void vcmpnle_uqpd(const Xmm& x, const Operand& op) { vcmpnle_uqpd(x, x, op); }
+void vcmpnle_uqps(const Xmm& x, const Operand& op) { vcmpnle_uqps(x, x, op); }
+void vcmpnle_uqsd(const Xmm& x, const Operand& op) { vcmpnle_uqsd(x, x, op); }
+void vcmpnle_uqss(const Xmm& x, const Operand& op) { vcmpnle_uqss(x, x, op); }
+void vcmpnlepd(const Xmm& x, const Operand& op) { vcmpnlepd(x, x, op); }
+void vcmpnleps(const Xmm& x, const Operand& op) { vcmpnleps(x, x, op); }
+void vcmpnlesd(const Xmm& x, const Operand& op) { vcmpnlesd(x, x, op); }
+void vcmpnless(const Xmm& x, const Operand& op) { vcmpnless(x, x, op); }
+void vcmpnlt_uqpd(const Xmm& x, const Operand& op) { vcmpnlt_uqpd(x, x, op); }
+void vcmpnlt_uqps(const Xmm& x, const Operand& op) { vcmpnlt_uqps(x, x, op); }
+void vcmpnlt_uqsd(const Xmm& x, const Operand& op) { vcmpnlt_uqsd(x, x, op); }
+void vcmpnlt_uqss(const Xmm& x, const Operand& op) { vcmpnlt_uqss(x, x, op); }
+void vcmpnltpd(const Xmm& x, const Operand& op) { vcmpnltpd(x, x, op); }
+void vcmpnltps(const Xmm& x, const Operand& op) { vcmpnltps(x, x, op); }
+void vcmpnltsd(const Xmm& x, const Operand& op) { vcmpnltsd(x, x, op); }
+void vcmpnltss(const Xmm& x, const Operand& op) { vcmpnltss(x, x, op); }
+void vcmpord_spd(const Xmm& x, const Operand& op) { vcmpord_spd(x, x, op); }
+void vcmpord_sps(const Xmm& x, const Operand& op) { vcmpord_sps(x, x, op); }
+void vcmpord_ssd(const Xmm& x, const Operand& op) { vcmpord_ssd(x, x, op); }
+void vcmpord_sss(const Xmm& x, const Operand& op) { vcmpord_sss(x, x, op); }
+void vcmpordpd(const Xmm& x, const Operand& op) { vcmpordpd(x, x, op); }
+void vcmpordps(const Xmm& x, const Operand& op) { vcmpordps(x, x, op); }
+void vcmpordsd(const Xmm& x, const Operand& op) { vcmpordsd(x, x, op); }
+void vcmpordss(const Xmm& x, const Operand& op) { vcmpordss(x, x, op); }
+void vcmppd(const Xmm& x, const Operand& op, uint8_t imm) { vcmppd(x, x, op, imm); }
+void vcmpps(const Xmm& x, const Operand& op, uint8_t imm) { vcmpps(x, x, op, imm); }
+void vcmpsd(const Xmm& x, const Operand& op, uint8_t imm) { vcmpsd(x, x, op, imm); }
+void vcmpss(const Xmm& x, const Operand& op, uint8_t imm) { vcmpss(x, x, op, imm); }
+void vcmptrue_uspd(const Xmm& x, const Operand& op) { vcmptrue_uspd(x, x, op); }
+void vcmptrue_usps(const Xmm& x, const Operand& op) { vcmptrue_usps(x, x, op); }
+void vcmptrue_ussd(const Xmm& x, const Operand& op) { vcmptrue_ussd(x, x, op); }
+void vcmptrue_usss(const Xmm& x, const Operand& op) { vcmptrue_usss(x, x, op); }
+void vcmptruepd(const Xmm& x, const Operand& op) { vcmptruepd(x, x, op); }
+void vcmptrueps(const Xmm& x, const Operand& op) { vcmptrueps(x, x, op); }
+void vcmptruesd(const Xmm& x, const Operand& op) { vcmptruesd(x, x, op); }
+void vcmptruess(const Xmm& x, const Operand& op) { vcmptruess(x, x, op); }
+void vcmpunord_spd(const Xmm& x, const Operand& op) { vcmpunord_spd(x, x, op); }
+void vcmpunord_sps(const Xmm& x, const Operand& op) { vcmpunord_sps(x, x, op); }
+void vcmpunord_ssd(const Xmm& x, const Operand& op) { vcmpunord_ssd(x, x, op); }
+void vcmpunord_sss(const Xmm& x, const Operand& op) { vcmpunord_sss(x, x, op); }
+void vcmpunordpd(const Xmm& x, const Operand& op) { vcmpunordpd(x, x, op); }
+void vcmpunordps(const Xmm& x, const Operand& op) { vcmpunordps(x, x, op); }
+void vcmpunordsd(const Xmm& x, const Operand& op) { vcmpunordsd(x, x, op); }
+void vcmpunordss(const Xmm& x, const Operand& op) { vcmpunordss(x, x, op); }
+void vcvtsd2ss(const Xmm& x, const Operand& op) { vcvtsd2ss(x, x, op); }
+void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); }
+void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); }
+void vcvtss2sd(const Xmm& x, const Operand& op) { vcvtss2sd(x, x, op); }
+void vdppd(const Xmm& x, const Operand& op, uint8_t imm) { vdppd(x, x, op, imm); }
+void vdpps(const Xmm& x, const Operand& op, uint8_t imm) { vdpps(x, x, op, imm); }
+void vinsertps(const Xmm& x, const Operand& op, uint8_t imm) { vinsertps(x, x, op, imm); }
+void vmpsadbw(const Xmm& x, const Operand& op, uint8_t imm) { vmpsadbw(x, x, op, imm); }
+void vpackssdw(const Xmm& x, const Operand& op) { vpackssdw(x, x, op); }
+void vpacksswb(const Xmm& x, const Operand& op) { vpacksswb(x, x, op); }
+void vpackusdw(const Xmm& x, const Operand& op) { vpackusdw(x, x, op); }
+void vpackuswb(const Xmm& x, const Operand& op) { vpackuswb(x, x, op); }
+void vpaddb(const Xmm& x, const Operand& op) { vpaddb(x, x, op); }
+void vpaddd(const Xmm& x, const Operand& op) { vpaddd(x, x, op); }
+void vpaddq(const Xmm& x, const Operand& op) { vpaddq(x, x, op); }
+void vpaddsb(const Xmm& x, const Operand& op) { vpaddsb(x, x, op); }
+void vpaddsw(const Xmm& x, const Operand& op) { vpaddsw(x, x, op); }
+void vpaddusb(const Xmm& x, const Operand& op) { vpaddusb(x, x, op); }
+void vpaddusw(const Xmm& x, const Operand& op) { vpaddusw(x, x, op); }
+void vpaddw(const Xmm& x, const Operand& op) { vpaddw(x, x, op); }
+void vpalignr(const Xmm& x, const Operand& op, uint8_t imm) { vpalignr(x, x, op, imm); }
+void vpand(const Xmm& x, const Operand& op) { vpand(x, x, op); }
+void vpandn(const Xmm& x, const Operand& op) { vpandn(x, x, op); }
+void vpavgb(const Xmm& x, const Operand& op) { vpavgb(x, x, op); }
+void vpavgw(const Xmm& x, const Operand& op) { vpavgw(x, x, op); }
+void vpblendd(const Xmm& x, const Operand& op, uint8_t imm) { vpblendd(x, x, op, imm); }
+void vpblendvb(const Xmm& x1, const Operand& op, const Xmm& x4) { vpblendvb(x1, x1, op, x4); }
+void vpblendw(const Xmm& x, const Operand& op, uint8_t imm) { vpblendw(x, x, op, imm); }
+void vpclmulqdq(const Xmm& x, const Operand& op, uint8_t imm) { vpclmulqdq(x, x, op, imm); }
+void vpcmpeqb(const Xmm& x, const Operand& op) { vpcmpeqb(x, x, op); }
+void vpcmpeqd(const Xmm& x, const Operand& op) { vpcmpeqd(x, x, op); }
+void vpcmpeqq(const Xmm& x, const Operand& op) { vpcmpeqq(x, x, op); }
+void vpcmpeqw(const Xmm& x, const Operand& op) { vpcmpeqw(x, x, op); }
+void vpcmpgtb(const Xmm& x, const Operand& op) { vpcmpgtb(x, x, op); }
+void vpcmpgtd(const Xmm& x, const Operand& op) { vpcmpgtd(x, x, op); }
+void vpcmpgtq(const Xmm& x, const Operand& op) { vpcmpgtq(x, x, op); }
+void vpcmpgtw(const Xmm& x, const Operand& op) { vpcmpgtw(x, x, op); }
+void vphaddd(const Xmm& x, const Operand& op) { vphaddd(x, x, op); }
+void vphaddsw(const Xmm& x, const Operand& op) { vphaddsw(x, x, op); }
+void vphaddw(const Xmm& x, const Operand& op) { vphaddw(x, x, op); }
+void vphsubd(const Xmm& x, const Operand& op) { vphsubd(x, x, op); }
+void vphsubsw(const Xmm& x, const Operand& op) { vphsubsw(x, x, op); }
+void vphsubw(const Xmm& x, const Operand& op) { vphsubw(x, x, op); }
+void vpinsrb(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrb(x, x, op, imm); }
+void vpinsrd(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrd(x, x, op, imm); }
+void vpinsrq(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrq(x, x, op, imm); }
+void vpinsrw(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrw(x, x, op, imm); }
+void vpmaddubsw(const Xmm& x, const Operand& op) { vpmaddubsw(x, x, op); }
+void vpmaddwd(const Xmm& x, const Operand& op) { vpmaddwd(x, x, op); }
+void vpmaxsb(const Xmm& x, const Operand& op) { vpmaxsb(x, x, op); }
+void vpmaxsd(const Xmm& x, const Operand& op) { vpmaxsd(x, x, op); }
+void vpmaxsw(const Xmm& x, const Operand& op) { vpmaxsw(x, x, op); }
+void vpmaxub(const Xmm& x, const Operand& op) { vpmaxub(x, x, op); }
+void vpmaxud(const Xmm& x, const Operand& op) { vpmaxud(x, x, op); }
+void vpmaxuw(const Xmm& x, const Operand& op) { vpmaxuw(x, x, op); }
+void vpminsb(const Xmm& x, const Operand& op) { vpminsb(x, x, op); }
+void vpminsd(const Xmm& x, const Operand& op) { vpminsd(x, x, op); }
+void vpminsw(const Xmm& x, const Operand& op) { vpminsw(x, x, op); }
+void vpminub(const Xmm& x, const Operand& op) { vpminub(x, x, op); }
+void vpminud(const Xmm& x, const Operand& op) { vpminud(x, x, op); }
+void vpminuw(const Xmm& x, const Operand& op) { vpminuw(x, x, op); }
+void vpmuldq(const Xmm& x, const Operand& op) { vpmuldq(x, x, op); }
+void vpmulhrsw(const Xmm& x, const Operand& op) { vpmulhrsw(x, x, op); }
+void vpmulhuw(const Xmm& x, const Operand& op) { vpmulhuw(x, x, op); }
+void vpmulhw(const Xmm& x, const Operand& op) { vpmulhw(x, x, op); }
+void vpmulld(const Xmm& x, const Operand& op) { vpmulld(x, x, op); }
+void vpmullw(const Xmm& x, const Operand& op) { vpmullw(x, x, op); }
+void vpmuludq(const Xmm& x, const Operand& op) { vpmuludq(x, x, op); }
+void vpor(const Xmm& x, const Operand& op) { vpor(x, x, op); }
+void vpsadbw(const Xmm& x, const Operand& op) { vpsadbw(x, x, op); }
+void vpsignb(const Xmm& x, const Operand& op) { vpsignb(x, x, op); }
+void vpsignd(const Xmm& x, const Operand& op) { vpsignd(x, x, op); }
+void vpsignw(const Xmm& x, const Operand& op) { vpsignw(x, x, op); }
+void vpslld(const Xmm& x, const Operand& op) { vpslld(x, x, op); }
+void vpslld(const Xmm& x, uint8_t imm) { vpslld(x, x, imm); }
+void vpslldq(const Xmm& x, uint8_t imm) { vpslldq(x, x, imm); }
+void vpsllq(const Xmm& x, const Operand& op) { vpsllq(x, x, op); }
+void vpsllq(const Xmm& x, uint8_t imm) { vpsllq(x, x, imm); }
+void vpsllw(const Xmm& x, const Operand& op) { vpsllw(x, x, op); }
+void vpsllw(const Xmm& x, uint8_t imm) { vpsllw(x, x, imm); }
+void vpsrad(const Xmm& x, const Operand& op) { vpsrad(x, x, op); }
+void vpsrad(const Xmm& x, uint8_t imm) { vpsrad(x, x, imm); }
+void vpsraw(const Xmm& x, const Operand& op) { vpsraw(x, x, op); }
+void vpsraw(const Xmm& x, uint8_t imm) { vpsraw(x, x, imm); }
+void vpsrld(const Xmm& x, const Operand& op) { vpsrld(x, x, op); }
+void vpsrld(const Xmm& x, uint8_t imm) { vpsrld(x, x, imm); }
+void vpsrldq(const Xmm& x, uint8_t imm) { vpsrldq(x, x, imm); }
+void vpsrlq(const Xmm& x, const Operand& op) { vpsrlq(x, x, op); }
+void vpsrlq(const Xmm& x, uint8_t imm) { vpsrlq(x, x, imm); }
+void vpsrlw(const Xmm& x, const Operand& op) { vpsrlw(x, x, op); }
+void vpsrlw(const Xmm& x, uint8_t imm) { vpsrlw(x, x, imm); }
+void vpsubb(const Xmm& x, const Operand& op) { vpsubb(x, x, op); }
+void vpsubd(const Xmm& x, const Operand& op) { vpsubd(x, x, op); }
+void vpsubq(const Xmm& x, const Operand& op) { vpsubq(x, x, op); }
+void vpsubsb(const Xmm& x, const Operand& op) { vpsubsb(x, x, op); }
+void vpsubsw(const Xmm& x, const Operand& op) { vpsubsw(x, x, op); }
+void vpsubusb(const Xmm& x, const Operand& op) { vpsubusb(x, x, op); }
+void vpsubusw(const Xmm& x, const Operand& op) { vpsubusw(x, x, op); }
+void vpsubw(const Xmm& x, const Operand& op) { vpsubw(x, x, op); }
+void vpunpckhbw(const Xmm& x, const Operand& op) { vpunpckhbw(x, x, op); }
+void vpunpckhdq(const Xmm& x, const Operand& op) { vpunpckhdq(x, x, op); }
+void vpunpckhqdq(const Xmm& x, const Operand& op) { vpunpckhqdq(x, x, op); }
+void vpunpckhwd(const Xmm& x, const Operand& op) { vpunpckhwd(x, x, op); }
+void vpunpcklbw(const Xmm& x, const Operand& op) { vpunpcklbw(x, x, op); }
+void vpunpckldq(const Xmm& x, const Operand& op) { vpunpckldq(x, x, op); }
+void vpunpcklqdq(const Xmm& x, const Operand& op) { vpunpcklqdq(x, x, op); }
+void vpunpcklwd(const Xmm& x, const Operand& op) { vpunpcklwd(x, x, op); }
+void vpxor(const Xmm& x, const Operand& op) { vpxor(x, x, op); }
+void vrcpss(const Xmm& x, const Operand& op) { vrcpss(x, x, op); }
+void vroundsd(const Xmm& x, const Operand& op, uint8_t imm) { vroundsd(x, x, op, imm); }
+void vroundss(const Xmm& x, const Operand& op, uint8_t imm) { vroundss(x, x, op, imm); }
+void vrsqrtss(const Xmm& x, const Operand& op) { vrsqrtss(x, x, op); }
+void vshufpd(const Xmm& x, const Operand& op, uint8_t imm) { vshufpd(x, x, op, imm); }
+void vshufps(const Xmm& x, const Operand& op, uint8_t imm) { vshufps(x, x, op, imm); }
+void vsqrtsd(const Xmm& x, const Operand& op) { vsqrtsd(x, x, op); }
+void vsqrtss(const Xmm& x, const Operand& op) { vsqrtss(x, x, op); }
+void vunpckhpd(const Xmm& x, const Operand& op) { vunpckhpd(x, x, op); }
+void vunpckhps(const Xmm& x, const Operand& op) { vunpckhps(x, x, op); }
+void vunpcklpd(const Xmm& x, const Operand& op) { vunpcklpd(x, x, op); }
+void vunpcklps(const Xmm& x, const Operand& op) { vunpcklps(x, x, op); }
+#endif
+#ifdef XBYAK64
+void jecxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jecxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jrcxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jrcxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void cdqe() { db(0x48); db(0x98); }
+void cqo() { db(0x48); db(0x99); }
+void cmpsq() { db(0x48); db(0xA7); }
+void popfq() { db(0x9D); }
+void pushfq() { db(0x9C); }
+void lodsq() { db(0x48); db(0xAD); }
+void movsq() { db(0x48); db(0xA5); }
+void scasq() { db(0x48); db(0xAF); }
+void stosq() { db(0x48); db(0xAB); }
+void syscall() { db(0x0F); db(0x05); }
+void sysret() { db(0x0F); db(0x07); }
+void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xC7); }
+void fxrstor64(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xAE); }
+void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }
+void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }
+void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) XBYAK_THROW(ERR_BAD_COMBINATION) opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); }
+void pextrq(const Operand& op, const Xmm& xmm, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); }
+void pinsrq(const Xmm& xmm, const Operand& op, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); }
+void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); }
+void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); }
+void vcvtsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_ER_X, 0x2D); }
+void vcvttsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_SAE_X, 0x2C); }
+void vmovq(const Xmm& x, const Reg64& r) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x6E); }
+void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); }
+void cmpbexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE6, false); }
+void cmpbxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE2, false); }
+void cmplexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEE, false); }
+void cmplxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEC, false); }
+void cmpnbexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE7, false); }
+void cmpnbxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE3, false); }
+void cmpnlexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEF, false); }
+void cmpnlxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xED, false); }
+void cmpnoxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE1, false); }
+void cmpnpxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEB, false); }
+void cmpnsxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE9, false); }
+void cmpnzxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE5, false); }
+void cmpoxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE0, false); }
+void cmppxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEA, false); }
+void cmpsxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE8, false); }
+void cmpzxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE4, false); }
+void ldtilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_0F38 | T_W0, 0x49); }
+void sttilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_66 | T_0F38 | T_W0, 0x49); }
+void tileloadd(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_F2 | T_0F38 | T_W0, 0x4b); }
+void tileloaddt1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66 | T_0F38 | T_W0, 0x4b); }
+void tilerelease() { db(0xc4); db(0xe2); db(0x78); db(0x49); db(0xc0); }
+void tilestored(const Address& addr, const Tmm& tm) { opVex(tm, &tmm0, addr, T_F3 | T_0F38 | T_W0, 0x4b); }
+void tilezero(const Tmm& Tmm) { opVex(Tmm, &tmm0, tmm0, T_F2 | T_0F38 | T_W0, 0x49); }
+void tdpbssd(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F2 | T_0F38 | T_W0, 0x5e); }
+void tdpbsud(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3 | T_0F38 | T_W0, 0x5e); }
+void tdpbusd(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_66 | T_0F38 | T_W0, 0x5e); }
+void tdpbuud(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_0F38 | T_W0, 0x5e); }
+void tdpfp16ps(const Tmm &x1, const Tmm &x2, const Tmm &x3) { opVex(x1, &x3, x2, T_F2 | T_0F38 | T_W0, 0x5c); }
+void tdpbf16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3 | T_0F38 | T_W0, 0x5c); }
+#else
+void jcxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jcxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jecxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jecxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void aaa() { db(0x37); }
+void aad() { db(0xD5); db(0x0A); }
+void aam() { db(0xD4); db(0x0A); }
+void aas() { db(0x3F); }
+void daa() { db(0x27); }
+void das() { db(0x2F); }
+void into() { db(0xCE); }
+void popad() { db(0x61); }
+void popfd() { db(0x9D); }
+void pusha() { db(0x60); }
+void pushad() { db(0x60); }
+void pushfd() { db(0x9C); }
+void popa() { db(0x61); }
+void lds(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0xC5, 0x100); }
+void les(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0xC4, 0x100); }
+#endif
+#ifndef XBYAK_NO_OP_NAMES
+void and(const Operand& op1, const Operand& op2) { and_(op1, op2); }
+void and(const Operand& op, uint32_t imm) { and_(op, imm); }
+void or(const Operand& op1, const Operand& op2) { or_(op1, op2); }
+void or(const Operand& op, uint32_t imm) { or_(op, imm); }
+void xor(const Operand& op1, const Operand& op2) { xor_(op1, op2); }
+void xor(const Operand& op, uint32_t imm) { xor_(op, imm); }
+void not(const Operand& op) { not_(op); }
+#endif
+#ifndef XBYAK_DISABLE_AVX512
+void kaddb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4A); }
+void kaddd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x4A); }
+void kaddq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4A); }
+void kaddw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4A); }
+void kandb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x41); }
+void kandd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x41); }
+void kandnb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x42); }
+void kandnd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x42); }
+void kandnq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x42); }
+void kandnw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x42); }
+void kandq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x41); }
+void kandw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x41); }
+void kmovb(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W0, 0x91); }
+void kmovb(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W0, 0x90); }
+void kmovb(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_66 | T_W0, 0x92); }
+void kmovb(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_66 | T_W0, 0x93); }
+void kmovd(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W1, 0x91); }
+void kmovd(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W1, 0x90); }
+void kmovd(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W0, 0x92); }
+void kmovd(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W0, 0x93); }
+void kmovq(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W1, 0x91); }
+void kmovq(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_W1, 0x90); }
+void kmovw(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W0, 0x91); }
+void kmovw(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_W0, 0x90); }
+void kmovw(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_W0, 0x92); }
+void kmovw(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_W0, 0x93); }
+void knotb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x44); }
+void knotd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x44); }
+void knotq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x44); }
+void knotw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x44); }
+void korb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x45); }
+void kord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x45); }
+void korq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x45); }
+void kortestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x98); }
+void kortestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x98); }
+void kortestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x98); }
+void kortestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x98); }
+void korw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x45); }
+void kshiftlb(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x32, imm); }
+void kshiftld(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x33, imm); }
+void kshiftlq(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x33, imm); }
+void kshiftlw(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x32, imm); }
+void kshiftrb(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x30, imm); }
+void kshiftrd(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x31, imm); }
+void kshiftrq(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x31, imm); }
+void kshiftrw(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x30, imm); }
+void ktestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x99); }
+void ktestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x99); }
+void ktestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x99); }
+void ktestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x99); }
+void kunpckbw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4B); }
+void kunpckdq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4B); }
+void kunpckwd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4B); }
+void kxnorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x46); }
+void kxnord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x46); }
+void kxnorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x46); }
+void kxnorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x46); }
+void kxorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x47); }
+void kxord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x47); }
+void kxorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x47); }
+void kxorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x47); }
+void v4fmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x9A); }
+void v4fmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0x9B); }
+void v4fnmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0xAA); }
+void v4fnmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0xAB); }
+void vaddph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x58); }
+void vaddsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x58); }
+void valignd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x03, imm); }
+void valignq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x03, imm); }
+void vblendmpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x65); }
+void vblendmps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x65); }
+void vbroadcastf32x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x19); }
+void vbroadcastf32x4(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x1A); }
+void vbroadcastf32x8(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x1B); }
+void vbroadcastf64x2(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x1A); }
+void vbroadcastf64x4(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x1B); }
+void vbroadcasti32x2(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x59); }
+void vbroadcasti32x4(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x5A); }
+void vbroadcasti32x8(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x5B); }
+void vbroadcasti64x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x5A); }
+void vbroadcasti64x4(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x5B); }
+void vcmpeq_ospd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 16); }
+void vcmpeq_osps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 16); }
+void vcmpeq_ossd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 16); }
+void vcmpeq_osss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 16); }
+void vcmpeq_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 8); }
+void vcmpeq_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 8); }
+void vcmpeq_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 8); }
+void vcmpeq_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 8); }
+void vcmpeq_uspd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 24); }
+void vcmpeq_usps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 24); }
+void vcmpeq_ussd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 24); }
+void vcmpeq_usss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 24); }
+void vcmpeqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 0); }
+void vcmpeqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 0); }
+void vcmpeqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 0); }
+void vcmpeqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 0); }
+void vcmpfalse_ospd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 27); }
+void vcmpfalse_osps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 27); }
+void vcmpfalse_ossd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 27); }
+void vcmpfalse_osss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 27); }
+void vcmpfalsepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 11); }
+void vcmpfalseps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 11); }
+void vcmpfalsesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 11); }
+void vcmpfalsess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 11); }
+void vcmpge_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 29); }
+void vcmpge_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 29); }
+void vcmpge_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 29); }
+void vcmpge_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 29); }
+void vcmpgepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 13); }
+void vcmpgeps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 13); }
+void vcmpgesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 13); }
+void vcmpgess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 13); }
+void vcmpgt_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 30); }
+void vcmpgt_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 30); }
+void vcmpgt_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 30); }
+void vcmpgt_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 30); }
+void vcmpgtpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 14); }
+void vcmpgtps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 14); }
+void vcmpgtsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 14); }
+void vcmpgtss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 14); }
+void vcmple_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 18); }
+void vcmple_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 18); }
+void vcmple_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 18); }
+void vcmple_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 18); }
+void vcmplepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 2); }
+void vcmpleps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 2); }
+void vcmplesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 2); }
+void vcmpless(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 2); }
+void vcmplt_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 17); }
+void vcmplt_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 17); }
+void vcmplt_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 17); }
+void vcmplt_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 17); }
+void vcmpltpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 1); }
+void vcmpltps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 1); }
+void vcmpltsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 1); }
+void vcmpltss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 1); }
+void vcmpneq_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 12); }
+void vcmpneq_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 12); }
+void vcmpneq_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 12); }
+void vcmpneq_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 12); }
+void vcmpneq_ospd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 28); }
+void vcmpneq_osps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 28); }
+void vcmpneq_ossd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 28); }
+void vcmpneq_osss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 28); }
+void vcmpneq_uspd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 20); }
+void vcmpneq_usps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 20); }
+void vcmpneq_ussd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 20); }
+void vcmpneq_usss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 20); }
+void vcmpneqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 4); }
+void vcmpneqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 4); }
+void vcmpneqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 4); }
+void vcmpneqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 4); }
+void vcmpnge_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 25); }
+void vcmpnge_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 25); }
+void vcmpnge_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 25); }
+void vcmpnge_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 25); }
+void vcmpngepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 9); }
+void vcmpngeps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 9); }
+void vcmpngesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 9); }
+void vcmpngess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 9); }
+void vcmpngt_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 26); }
+void vcmpngt_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 26); }
+void vcmpngt_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 26); }
+void vcmpngt_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 26); }
+void vcmpngtpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 10); }
+void vcmpngtps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 10); }
+void vcmpngtsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 10); }
+void vcmpngtss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 10); }
+void vcmpnle_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 22); }
+void vcmpnle_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 22); }
+void vcmpnle_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 22); }
+void vcmpnle_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 22); }
+void vcmpnlepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 6); }
+void vcmpnleps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 6); }
+void vcmpnlesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 6); }
+void vcmpnless(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 6); }
+void vcmpnlt_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 21); }
+void vcmpnlt_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 21); }
+void vcmpnlt_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 21); }
+void vcmpnlt_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 21); }
+void vcmpnltpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 5); }
+void vcmpnltps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 5); }
+void vcmpnltsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 5); }
+void vcmpnltss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 5); }
+void vcmpord_spd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 23); }
+void vcmpord_sps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 23); }
+void vcmpord_ssd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 23); }
+void vcmpord_sss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 23); }
+void vcmpordpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 7); }
+void vcmpordps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 7); }
+void vcmpordsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 7); }
+void vcmpordss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 7); }
+void vcmppd(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0xC2, imm); }
+void vcmpph(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0xC2, imm); }
+void vcmpps(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0xC2, imm); }
+void vcmpsd(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_N8 | T_F2 | T_0F | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
+void vcmpsh(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_N2 | T_F3 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xC2, imm); }
+void vcmpss(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_N4 | T_F3 | T_0F | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
+void vcmptrue_uspd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 31); }
+void vcmptrue_usps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 31); }
+void vcmptrue_ussd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 31); }
+void vcmptrue_usss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 31); }
+void vcmptruepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 15); }
+void vcmptrueps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 15); }
+void vcmptruesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 15); }
+void vcmptruess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 15); }
+void vcmpunord_spd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 19); }
+void vcmpunord_sps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 19); }
+void vcmpunord_ssd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 19); }
+void vcmpunord_sss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 19); }
+void vcmpunordpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 3); }
+void vcmpunordps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 3); }
+void vcmpunordsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 3); }
+void vcmpunordss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 3); }
+void vcomish(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_MUST_EVEX | T_EW0 | T_SAE_X | T_N2, 0x2F); }
+void vcompressb(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x63); }
+void vcompresspd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8A); }
+void vcompressps(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8A); }
+void vcompressw(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x63); }
+void vcvtdq2ph(const Xmm& x, const Operand& op) { checkCvt4(x, op); opCvt(x, op, T_N16 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x5B); }
+void vcvtne2ps2bf16(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x72); }
+void vcvtpd2ph(const Xmm& x, const Operand& op) { opCvt5(x, op, T_N16 | T_N_VL | T_66 | T_MAP5 | T_EW1 | T_ER_Z | T_MUST_EVEX | T_B64, 0x5A); }
+void vcvtpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7B); }
+void vcvtpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); }
+void vcvtpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); }
+void vcvtph2dq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B16, 0x5B); }
+void vcvtph2pd(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_SAE_X | T_MUST_EVEX | T_B16, 0x5A); }
+void vcvtph2psx(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_MAP6 | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B16, 0x13); }
+void vcvtph2qq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_X | T_MUST_EVEX | T_B16, 0x7B); }
+void vcvtph2udq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B16, 0x79); }
+void vcvtph2uqq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_X | T_MUST_EVEX | T_B16, 0x79); }
+void vcvtph2uw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); }
+void vcvtph2w(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); }
+void vcvtps2phx(const Xmm& x, const Operand& op) { checkCvt4(x, op); opCvt(x, op, T_N16 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_ER_Z | T_MUST_EVEX | T_B32, 0x1D); }
+void vcvtps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B32, 0x7B); }
+void vcvtps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x79); }
+void vcvtps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B32, 0x79); }
+void vcvtqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0xE6); }
+void vcvtqq2ph(const Xmm& x, const Operand& op) { opCvt5(x, op, T_N16 | T_N_VL | T_MAP5 | T_EW1 | T_ER_Z | T_MUST_EVEX | T_B64, 0x5B); }
+void vcvtqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x5B); }
+void vcvtsd2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_MAP5 | T_EW1 | T_ER_X | T_MUST_EVEX, 0x5A); }
+void vcvtsd2usi(const Reg32e& r, const Operand& op) { int type = (T_N8 | T_F2 | T_0F | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x79); }
+void vcvtsh2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x5A); }
+void vcvtsh2si(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x2D); }
+void vcvtsh2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_MAP6 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x13); }
+void vcvtsh2usi(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x79); }
+void vcvtsi2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { if (!(x1.isXMM() && x2.isXMM() && op.isBit(32|64))) XBYAK_THROW(ERR_BAD_COMBINATION) int type = (T_F3 | T_MAP5 | T_ER_R | T_MUST_EVEX | T_M_K) | (op.isBit(32) ? (T_EW0 | T_N4) : (T_EW1 | T_N8)); opVex(x1, &x2, op, type, 0x2A); }
+void vcvtss2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_MAP5 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x1D); }
+void vcvtss2usi(const Reg32e& r, const Operand& op) { int type = (T_N4 | T_F3 | T_0F | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x79); }
+void vcvttpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x7A); }
+void vcvttpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x78); }
+void vcvttpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x78); }
+void vcvttph2dq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_F3 | T_MAP5 | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B16, 0x5B); }
+void vcvttph2qq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_SAE_X | T_MUST_EVEX | T_B16, 0x7A); }
+void vcvttph2udq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B16, 0x78); }
+void vcvttph2uqq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_SAE_X | T_MUST_EVEX | T_B16, 0x78); }
+void vcvttph2uw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x7C); }
+void vcvttph2w(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP5 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x7C); }
+void vcvttps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B32, 0x7A); }
+void vcvttps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x78); }
+void vcvttps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B32, 0x78); }
+void vcvttsd2usi(const Reg32e& r, const Operand& op) { int type = (T_N8 | T_F2 | T_0F | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x78); }
+void vcvttsh2si(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_EW0 | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x2C); }
+void vcvttsh2usi(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_EW0 | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x78); }
+void vcvttss2usi(const Reg32e& r, const Operand& op) { int type = (T_N4 | T_F3 | T_0F | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x78); }
+void vcvtudq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_F3 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7A); }
+void vcvtudq2ph(const Xmm& x, const Operand& op) { checkCvt4(x, op); opCvt(x, op, T_N16 | T_N_VL | T_F2 | T_MAP5 | T_EW0 | T_ER_Z | T_MUST_EVEX | T_B32, 0x7A); }
+void vcvtudq2ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x7A); }
+void vcvtuqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); }
+void vcvtuqq2ph(const Xmm& x, const Operand& op) { opCvt5(x, op, T_N16 | T_N_VL | T_F2 | T_MAP5 | T_EW1 | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); }
+void vcvtuqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); }
+void vcvtusi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F2 | T_0F | T_MUST_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); }
+void vcvtusi2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { if (!(x1.isXMM() && x2.isXMM() && op.isBit(32|64))) XBYAK_THROW(ERR_BAD_COMBINATION) int type = (T_F3 | T_MAP5 | T_ER_R | T_MUST_EVEX | T_M_K) | (op.isBit(32) ? (T_EW0 | T_N4) : (T_EW1 | T_N8)); opVex(x1, &x2, op, type, 0x7B); }
+void vcvtusi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F3 | T_0F | T_MUST_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); }
+void vcvtuw2ph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); }
+void vcvtw2ph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); }
+void vdbpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x42, imm); }
+void vdivph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5E); }
+void vdivsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5E); }
+void vdpbf16ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x52); }
+void vexp2pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xC8); }
+void vexp2ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xC8); }
+void vexpandpd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x88); }
+void vexpandps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x88); }
+void vextractf32x4(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x19, imm); }
+void vextractf32x8(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1B, imm); }
+void vextractf64x2(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x19, imm); }
+void vextractf64x4(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1B, imm); }
+void vextracti32x4(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x39, imm); }
+void vextracti32x8(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3B, imm); }
+void vextracti64x2(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x39, imm); }
+void vextracti64x4(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3B, imm); }
+void vfcmaddcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x56); }
+void vfcmulcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0xD6); }
+void vfixupimmpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x54, imm); }
+void vfixupimmps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x54, imm); }
+void vfixupimmsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); }
+void vfixupimmss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); }
+void vfmadd132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x98); }
+void vfmadd132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x99); }
+void vfmadd213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xA8); }
+void vfmadd213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xA9); }
+void vfmadd231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xB8); }
+void vfmadd231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xB9); }
+void vfmaddcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x56); }
+void vfmaddsub132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x96); }
+void vfmaddsub213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xA6); }
+void vfmaddsub231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xB6); }
+void vfmsub132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x9A); }
+void vfmsub132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x9B); }
+void vfmsub213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xAA); }
+void vfmsub213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xAB); }
+void vfmsub231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xBA); }
+void vfmsub231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xBB); }
+void vfmsubadd132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x97); }
+void vfmsubadd213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xA7); }
+void vfmsubadd231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xB7); }
+void vfmulcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0xD6); }
+void vfnmadd132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x9C); }
+void vfnmadd132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x9D); }
+void vfnmadd213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xAC); }
+void vfnmadd213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xAD); }
+void vfnmadd231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xBC); }
+void vfnmadd231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xBD); }
+void vfnmsub132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x9E); }
+void vfnmsub132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x9F); }
+void vfnmsub213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xAE); }
+void vfnmsub213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xAF); }
+void vfnmsub231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xBE); }
+void vfnmsub231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xBF); }
+void vfpclasspd(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW1 | T_B64, 0x66, imm); }
+void vfpclassph(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B16, 0x66, imm); }
+void vfpclassps(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); }
+void vfpclasssd(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); }
+void vfpclasssh(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_0F3A | T_MUST_EVEX | T_EW0 | T_N2, 0x67, imm); }
+void vfpclassss(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); }
+void vgatherdpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 1); }
+void vgatherdps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 0); }
+void vgatherpf0dpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vgatherpf0dps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vgatherpf0qpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherpf0qps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherpf1dpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vgatherpf1dps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vgatherpf1qpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherpf1qps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherqpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 0); }
+void vgatherqps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 2); }
+void vgetexppd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x42); }
+void vgetexpph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x42); }
+void vgetexpps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x42); }
+void vgetexpsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x43); }
+void vgetexpsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x43); }
+void vgetexpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x43); }
+void vgetmantpd(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x26, imm); }
+void vgetmantph(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x26, imm); }
+void vgetmantps(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x26, imm); }
+void vgetmantsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x27, imm); }
+void vgetmantsh(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x27, imm); }
+void vgetmantss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x27, imm); }
+void vinsertf32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x18, imm); }
+void vinsertf32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1A, imm); }
+void vinsertf64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x18, imm); }
+void vinsertf64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1A, imm); }
+void vinserti32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x38, imm); }
+void vinserti32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3A, imm); }
+void vinserti64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x38, imm); }
+void vinserti64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3A, imm); }
+void vmaxph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5F); }
+void vmaxsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5F); }
+void vminph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5D); }
+void vminsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5D); }
+void vmovdqa32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqa32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqa64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqa64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu16(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu16(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu8(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu8(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovsh(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_MUST_EVEX | T_M_K, 0x11); }
+void vmovsh(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_MUST_EVEX, 0x10); }
+void vmovsh(const Xmm& x1, const Xmm& x2, const Xmm& x3) { opAVX_X_X_XM(x1, x2, x3, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_MUST_EVEX, 0x10); }
+void vmovw(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_N2 | T_66 | T_MAP5 | T_MUST_EVEX, 0x7E); }
+void vmovw(const Reg32e& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, r, T_N2 | T_66 | T_MAP5 | T_MUST_EVEX, 0x7E); }
+void vmovw(const Xmm& x, const Operand& op) { if (!op.isREG(32|64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_N2 | T_66 | T_MAP5 | T_MUST_EVEX, 0x6E); }
+void vmulph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x59); }
+void vmulsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x59); }
+void vp2intersectd(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_EW0 | T_B32, 0x68); }
+void vp2intersectq(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_EW1 | T_B64, 0x68); }
+void vp4dpwssd(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x52); }
+void vp4dpwssds(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x53); }
+void vpabsq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_MUST_EVEX | T_EW1 | T_B64 | T_YMM, 0x1F); }
+void vpandd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDB); }
+void vpandnd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDF); }
+void vpandnq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDF); }
+void vpandq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDB); }
+void vpblendmb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x66); }
+void vpblendmd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x64); }
+void vpblendmq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x64); }
+void vpblendmw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x66); }
+void vpbroadcastb(const Xmm& x, const Reg8& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7A); }
+void vpbroadcastd(const Xmm& x, const Reg32& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7C); }
+void vpbroadcastmb2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1, 0x2A); }
+void vpbroadcastmw2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0, 0x3A); }
+void vpbroadcastw(const Xmm& x, const Reg16& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7B); }
+void vpcmpb(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3F, imm); }
+void vpcmpd(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1F, imm); }
+void vpcmpeqb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x74); }
+void vpcmpeqd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_B32, 0x76); }
+void vpcmpeqq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x29); }
+void vpcmpeqw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x75); }
+void vpcmpgtb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x64); }
+void vpcmpgtd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x66); }
+void vpcmpgtq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x37); }
+void vpcmpgtw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x65); }
+void vpcmpq(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1F, imm); }
+void vpcmpub(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3E, imm); }
+void vpcmpud(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1E, imm); }
+void vpcmpuq(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1E, imm); }
+void vpcmpuw(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3E, imm); }
+void vpcmpw(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3F, imm); }
+void vpcompressd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8B); }
+void vpcompressq(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8B); }
+void vpconflictd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xC4); }
+void vpconflictq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xC4); }
+void vpermb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8D); }
+void vpermi2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x75); }
+void vpermi2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x76); }
+void vpermi2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x77); }
+void vpermi2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x77); }
+void vpermi2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x76); }
+void vpermi2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x75); }
+void vpermt2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7D); }
+void vpermt2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7E); }
+void vpermt2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7F); }
+void vpermt2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7F); }
+void vpermt2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7E); }
+void vpermt2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7D); }
+void vpermw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8D); }
+void vpexpandb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); }
+void vpexpandd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x89); }
+void vpexpandq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x89); }
+void vpexpandw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); }
+void vpgatherdd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 0); }
+void vpgatherdq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 1); }
+void vpgatherqd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 2); }
+void vpgatherqq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 0); }
+void vplzcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x44); }
+void vplzcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x44); }
+void vpmaxsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3D); }
+void vpmaxuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3F); }
+void vpminsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x39); }
+void vpminuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3B); }
+void vpmovb2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x29); }
+void vpmovd2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x39); }
+void vpmovdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x31, false); }
+void vpmovdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x33, true); }
+void vpmovm2b(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x28); }
+void vpmovm2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x38); }
+void vpmovm2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x38); }
+void vpmovm2w(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x28); }
+void vpmovq2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x39); }
+void vpmovqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x32, false); }
+void vpmovqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x35, true); }
+void vpmovqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x34, false); }
+void vpmovsdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x21, false); }
+void vpmovsdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x23, true); }
+void vpmovsqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x22, false); }
+void vpmovsqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x25, true); }
+void vpmovsqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x24, false); }
+void vpmovswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x20, true); }
+void vpmovusdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x11, false); }
+void vpmovusdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x13, true); }
+void vpmovusqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x12, false); }
+void vpmovusqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x15, true); }
+void vpmovusqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x14, false); }
+void vpmovuswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x10, true); }
+void vpmovw2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x29); }
+void vpmovwb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x30, true); }
+void vpmullq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x40); }
+void vpmultishiftqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x83); }
+void vpopcntb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); }
+void vpopcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x55); }
+void vpopcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x55); }
+void vpopcntw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); }
+void vpord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEB); }
+void vporq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEB); }
+void vprold(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); }
+void vprolq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); }
+void vprolvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x15); }
+void vprolvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x15); }
+void vprord(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); }
+void vprorq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); }
+void vprorvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x14); }
+void vprorvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x14); }
+void vpscatterdd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 0); }
+void vpscatterdq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 1); }
+void vpscatterqd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 2); }
+void vpscatterqq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 0); }
+void vpshldd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71, imm); }
+void vpshldq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71, imm); }
+void vpshldvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71); }
+void vpshldvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71); }
+void vpshldvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70); }
+void vpshldw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70, imm); }
+void vpshrdd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73, imm); }
+void vpshrdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73, imm); }
+void vpshrdvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73); }
+void vpshrdvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73); }
+void vpshrdvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72); }
+void vpshrdw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72, imm); }
+void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); }
+void vpsllvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x12); }
+void vpsraq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); }
+void vpsraq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX, 0xE2); }
+void vpsravq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x46); }
+void vpsravw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x11); }
+void vpsrlvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x10); }
+void vpternlogd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x25, imm); }
+void vpternlogq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x25, imm); }
+void vptestmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); }
+void vptestmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); }
+void vptestmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); }
+void vptestmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); }
+void vptestnmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); }
+void vptestnmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); }
+void vptestnmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); }
+void vptestnmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); }
+void vpxord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEF); }
+void vpxorq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEF); }
+void vrangepd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x50, imm); }
+void vrangeps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x50, imm); }
+void vrangesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x51, imm); }
+void vrangess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x51, imm); }
+void vrcp14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4C); }
+void vrcp14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4C); }
+void vrcp14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX, 0x4D); }
+void vrcp14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX, 0x4D); }
+void vrcp28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCA); }
+void vrcp28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCA); }
+void vrcp28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCB); }
+void vrcp28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCB); }
+void vrcpph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_MUST_EVEX | T_B16, 0x4C); }
+void vrcpsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_MUST_EVEX, 0x4D); }
+void vreducepd(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x56, imm); }
+void vreduceph(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x56, imm); }
+void vreduceps(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x56, imm); }
+void vreducesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x57, imm); }
+void vreducesh(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x57, imm); }
+void vreducess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x57, imm); }
+void vrndscalepd(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x09, imm); }
+void vrndscaleph(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x08, imm); }
+void vrndscaleps(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x08, imm); }
+void vrndscalesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x0B, imm); }
+void vrndscalesh(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x0A, imm); }
+void vrndscaless(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x0A, imm); }
+void vrsqrt14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4E); }
+void vrsqrt14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4E); }
+void vrsqrt14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x4F); }
+void vrsqrt14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x4F); }
+void vrsqrt28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCC); }
+void vrsqrt28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCC); }
+void vrsqrt28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCD); }
+void vrsqrt28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCD); }
+void vrsqrtph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_MUST_EVEX | T_B16, 0x4E); }
+void vrsqrtsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_MUST_EVEX, 0x4F); }
+void vscalefpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x2C); }
+void vscalefph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x2C); }
+void vscalefps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x2C); }
+void vscalefsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_ER_X | T_MUST_EVEX, 0x2D); }
+void vscalefsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x2D); }
+void vscalefss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x2D); }
+void vscatterdpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 1); }
+void vscatterdps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 0); }
+void vscatterpf0dpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vscatterpf0dps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vscatterpf0qpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterpf0qps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterpf1dpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vscatterpf1dps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vscatterpf1qpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterpf1qps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterqpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 0); }
+void vscatterqps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 2); }
+void vshuff32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x23, imm); }
+void vshuff64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x23, imm); }
+void vshufi32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x43, imm); }
+void vshufi64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x43, imm); }
+void vsqrtph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x51); }
+void vsqrtsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x51); }
+void vsubph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5C); }
+void vsubsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5C); }
+void vucomish(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_MUST_EVEX | T_EW0 | T_SAE_X | T_N2, 0x2E); }
+#ifdef XBYAK64
+void kmovq(const Opmask& k, const Reg64& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W1, 0x92); }
+void kmovq(const Reg64& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W1, 0x93); }
+void vpbroadcastq(const Xmm& x, const Reg64& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7C); }
+#endif
+#endif
diff --git a/xbyak/xbyak_util.h b/xbyak/xbyak_util.h
new file mode 100644
index 0000000..ebf15e6
--- /dev/null
+++ b/xbyak/xbyak_util.h
@@ -0,0 +1,998 @@
+#ifndef XBYAK_XBYAK_UTIL_H_
+#define XBYAK_XBYAK_UTIL_H_
+
+#ifdef XBYAK_ONLY_CLASS_CPU
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#ifndef XBYAK_THROW
+ #define XBYAK_THROW(x) ;
+ #define XBYAK_THROW_RET(x, y) return y;
+#endif
+#else
+#include <string.h>
+
+/**
+ utility class and functions for Xbyak
+ Xbyak::util::Clock ; rdtsc timer
+ Xbyak::util::Cpu ; detect CPU
+*/
+#include "xbyak.h"
+#endif // XBYAK_ONLY_CLASS_CPU
+
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+ #define XBYAK_INTEL_CPU_SPECIFIC
+#endif
+
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+#ifdef _WIN32
+ #if defined(_MSC_VER) && (_MSC_VER < 1400) && defined(XBYAK32)
+ static inline __declspec(naked) void __cpuid(int[4], int)
+ {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+ }
+ #else
+ #include <intrin.h> // for __cpuid
+ #endif
+#else
+ #ifndef __GNUC_PREREQ
+ #define __GNUC_PREREQ(major, minor) ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+ #endif
+ #if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+ #include <cpuid.h>
+ #else
+ #if defined(__APPLE__) && defined(XBYAK32) // avoid err : can't find a register in class `BREG' while reloading `asm'
+ #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+ #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+ #else
+ #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+ #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+ #endif
+ #endif
+#endif
+#endif
+
+#ifdef XBYAK_USE_VTUNE
+ // -I /opt/intel/vtune_amplifier/include/ -L /opt/intel/vtune_amplifier/lib64 -ljitprofiling -ldl
+ #include <jitprofiling.h>
+ #ifdef _MSC_VER
+ #pragma comment(lib, "libittnotify.lib")
+ #endif
+ #ifdef __linux__
+ #include <dlfcn.h>
+ #endif
+#endif
+#ifdef __linux__
+ #define XBYAK_USE_PERF
+#endif
+
+namespace Xbyak { namespace util {
+
+typedef enum {
+ SmtLevel = 1,
+ CoreLevel = 2
+} IntelCpuTopologyLevel;
+
+namespace local {
+
+template<uint64_t L, uint64_t H = 0>
+struct TypeT {
+};
+
+template<uint64_t L1, uint64_t H1, uint64_t L2, uint64_t H2>
+TypeT<L1 | L2, H1 | H2> operator|(TypeT<L1, H1>, TypeT<L2, H2>) { return TypeT<L1 | L2, H1 | H2>(); }
+
+template<typename T>
+inline T max_(T x, T y) { return x >= y ? x : y; }
+template<typename T>
+inline T min_(T x, T y) { return x < y ? x : y; }
+
+} // local
+
+/**
+ CPU detection class
+ @note static inline const member is supported by c++17 or later, so use template hack
+*/
+class Cpu {
+public:
+ class Type {
+ uint64_t L;
+ uint64_t H;
+ public:
+ Type(uint64_t L = 0, uint64_t H = 0) : L(L), H(H) { }
+ template<uint64_t L_, uint64_t H_>
+ Type(local::TypeT<L_, H_>) : L(L_), H(H_) {}
+ Type& operator&=(const Type& rhs) { L &= rhs.L; H &= rhs.H; return *this; }
+ Type& operator|=(const Type& rhs) { L |= rhs.L; H |= rhs.H; return *this; }
+ Type operator&(const Type& rhs) const { Type t = *this; t &= rhs; return t; }
+ Type operator|(const Type& rhs) const { Type t = *this; t |= rhs; return t; }
+ bool operator==(const Type& rhs) const { return H == rhs.H && L == rhs.L; }
+ bool operator!=(const Type& rhs) const { return !operator==(rhs); }
+ // without explicit because backward compatilibity
+ operator bool() const { return (H | L) != 0; }
+ uint64_t getL() const { return L; }
+ uint64_t getH() const { return H; }
+ };
+private:
+ Type type_;
+ //system topology
+ bool x2APIC_supported_;
+ static const size_t maxTopologyLevels = 2;
+ uint32_t numCores_[maxTopologyLevels];
+
+ static const uint32_t maxNumberCacheLevels = 10;
+ uint32_t dataCacheSize_[maxNumberCacheLevels];
+ uint32_t coresSharignDataCache_[maxNumberCacheLevels];
+ uint32_t dataCacheLevels_;
+
+ uint32_t get32bitAsBE(const char *x) const
+ {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+ }
+ uint32_t mask(int n) const
+ {
+ return (1U << n) - 1;
+ }
+ void setFamily()
+ {
+ uint32_t data[4] = {};
+ getCpuid(1, data);
+ stepping = data[0] & mask(4);
+ model = (data[0] >> 4) & mask(4);
+ family = (data[0] >> 8) & mask(4);
+ // type = (data[0] >> 12) & mask(2);
+ extModel = (data[0] >> 16) & mask(4);
+ extFamily = (data[0] >> 20) & mask(8);
+ if (family == 0x0f) {
+ displayFamily = family + extFamily;
+ } else {
+ displayFamily = family;
+ }
+ if (family == 6 || family == 0x0f) {
+ displayModel = (extModel << 4) + model;
+ } else {
+ displayModel = model;
+ }
+ }
+ uint32_t extractBit(uint32_t val, uint32_t base, uint32_t end)
+ {
+ return (val >> base) & ((1u << (end - base)) - 1);
+ }
+ void setNumCores()
+ {
+ if (!has(tINTEL)) return;
+
+ uint32_t data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ getCpuidEx(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2APIC_supported_ = true;
+ for (uint32_t i = 0; i < maxTopologyLevels; i++) {
+ getCpuidEx(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extractBit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ numCores_[level - 1] = extractBit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ numCores_[SmtLevel - 1] = local::max_(1u, numCores_[SmtLevel - 1]);
+ numCores_[CoreLevel - 1] = local::max_(numCores_[SmtLevel - 1], numCores_[CoreLevel - 1]);
+ } else {
+ /*
+ Failed to deremine num of cores without x2APIC support.
+ TODO: USE initial APIC ID to determine ncores.
+ */
+ numCores_[SmtLevel - 1] = 0;
+ numCores_[CoreLevel - 1] = 0;
+ }
+
+ }
+ void setCacheHierarchy()
+ {
+ if (!has(tINTEL)) return;
+ const uint32_t NO_CACHE = 0;
+ const uint32_t DATA_CACHE = 1;
+// const uint32_t INSTRUCTION_CACHE = 2;
+ const uint32_t UNIFIED_CACHE = 3;
+ uint32_t smt_width = 0;
+ uint32_t logical_cores = 0;
+ uint32_t data[4] = {};
+
+ if (x2APIC_supported_) {
+ smt_width = numCores_[0];
+ logical_cores = numCores_[1];
+ }
+
+ /*
+ Assumptions:
+ the first level of data cache is not shared (which is the
+ case for every existing architecture) and use this to
+ determine the SMT width for arch not supporting leaf 11.
+ when leaf 4 reports a number of core less than numCores_
+ on socket reported by leaf 11, then it is a correct number
+ of cores not an upperbound.
+ */
+ for (int i = 0; dataCacheLevels_ < maxNumberCacheLevels; i++) {
+ getCpuidEx(0x4, i, data);
+ uint32_t cacheType = extractBit(data[0], 0, 4);
+ if (cacheType == NO_CACHE) break;
+ if (cacheType == DATA_CACHE || cacheType == UNIFIED_CACHE) {
+ uint32_t actual_logical_cores = extractBit(data[0], 14, 25) + 1;
+ if (logical_cores != 0) { // true only if leaf 0xB is supported and valid
+ actual_logical_cores = local::min_(actual_logical_cores, logical_cores);
+ }
+ assert(actual_logical_cores != 0);
+ dataCacheSize_[dataCacheLevels_] =
+ (extractBit(data[1], 22, 31) + 1)
+ * (extractBit(data[1], 12, 21) + 1)
+ * (extractBit(data[1], 0, 11) + 1)
+ * (data[2] + 1);
+ if (cacheType == DATA_CACHE && smt_width == 0) smt_width = actual_logical_cores;
+ assert(smt_width != 0);
+ coresSharignDataCache_[dataCacheLevels_] = local::max_(actual_logical_cores / smt_width, 1u);
+ dataCacheLevels_++;
+ }
+ }
+ }
+
+public:
+ int model;
+ int family;
+ int stepping;
+ int extModel;
+ int extFamily;
+ int displayFamily; // family + extFamily
+ int displayModel; // model + extModel
+
+ uint32_t getNumCores(IntelCpuTopologyLevel level) const {
+ if (!x2APIC_supported_) XBYAK_THROW_RET(ERR_X2APIC_IS_NOT_SUPPORTED, 0)
+ switch (level) {
+ case SmtLevel: return numCores_[level - 1];
+ case CoreLevel: return numCores_[level - 1] / numCores_[SmtLevel - 1];
+ default: XBYAK_THROW_RET(ERR_X2APIC_IS_NOT_SUPPORTED, 0)
+ }
+ }
+
+ uint32_t getDataCacheLevels() const { return dataCacheLevels_; }
+ uint32_t getCoresSharingDataCache(uint32_t i) const
+ {
+ if (i >= dataCacheLevels_) XBYAK_THROW_RET(ERR_BAD_PARAMETER, 0)
+ return coresSharignDataCache_[i];
+ }
+ uint32_t getDataCacheSize(uint32_t i) const
+ {
+ if (i >= dataCacheLevels_) XBYAK_THROW_RET(ERR_BAD_PARAMETER, 0)
+ return dataCacheSize_[i];
+ }
+
+ /*
+ data[] = { eax, ebx, ecx, edx }
+ */
+ static inline void getCpuid(uint32_t eaxIn, uint32_t data[4])
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _WIN32
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+ #else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+ #endif
+#else
+ (void)eaxIn;
+ (void)data;
+#endif
+ }
+ static inline void getCpuidEx(uint32_t eaxIn, uint32_t ecxIn, uint32_t data[4])
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _WIN32
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+ #else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+ #endif
+#else
+ (void)eaxIn;
+ (void)ecxIn;
+ (void)data;
+#endif
+ }
+ static inline uint64_t getXfeature()
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _MSC_VER
+ return _xgetbv(0);
+ #else
+ uint32_t eax, edx;
+ // xgetvb is not support on gcc 4.2
+// __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
+ __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
+ return ((uint64_t)edx << 32) | eax;
+ #endif
+#else
+ return 0;
+#endif
+ }
+
+#define XBYAK_SPLIT_ID(id) ((0 <= id && id < 64) ? (1ull << (id % 64)) : 0), (id >= 64 ? (1ull << (id % 64)) : 0)
+#if (__cplusplus >= 201103) || (defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012 */
+ #define XBYAK_DEFINE_TYPE(id, NAME) static const constexpr local::TypeT<XBYAK_SPLIT_ID(id)> NAME{}
+#else
+ #define XBYAK_DEFINE_TYPE(id, NAME) static const local::TypeT<XBYAK_SPLIT_ID(id)> NAME
+#endif
+ XBYAK_DEFINE_TYPE(0, tMMX);
+ XBYAK_DEFINE_TYPE(1, tMMX2);
+ XBYAK_DEFINE_TYPE(2, tCMOV);
+ XBYAK_DEFINE_TYPE(3, tSSE);
+ XBYAK_DEFINE_TYPE(4, tSSE2);
+ XBYAK_DEFINE_TYPE(5, tSSE3);
+ XBYAK_DEFINE_TYPE(6, tSSSE3);
+ XBYAK_DEFINE_TYPE(7, tSSE41);
+ XBYAK_DEFINE_TYPE(8, tSSE42);
+ XBYAK_DEFINE_TYPE(9, tPOPCNT);
+ XBYAK_DEFINE_TYPE(10, tAESNI);
+ XBYAK_DEFINE_TYPE(11, tAVX512_FP16);
+ XBYAK_DEFINE_TYPE(12, tOSXSAVE);
+ XBYAK_DEFINE_TYPE(13, tPCLMULQDQ);
+ XBYAK_DEFINE_TYPE(14, tAVX);
+ XBYAK_DEFINE_TYPE(15, tFMA);
+ XBYAK_DEFINE_TYPE(16, t3DN);
+ XBYAK_DEFINE_TYPE(17, tE3DN);
+ XBYAK_DEFINE_TYPE(18, tWAITPKG);
+ XBYAK_DEFINE_TYPE(19, tRDTSCP);
+ XBYAK_DEFINE_TYPE(20, tAVX2);
+ XBYAK_DEFINE_TYPE(21, tBMI1); // andn, bextr, blsi, blsmsk, blsr, tzcnt
+ XBYAK_DEFINE_TYPE(22, tBMI2); // bzhi, mulx, pdep, pext, rorx, sarx, shlx, shrx
+ XBYAK_DEFINE_TYPE(23, tLZCNT);
+ XBYAK_DEFINE_TYPE(24, tINTEL);
+ XBYAK_DEFINE_TYPE(25, tAMD);
+ XBYAK_DEFINE_TYPE(26, tENHANCED_REP); // enhanced rep movsb/stosb
+ XBYAK_DEFINE_TYPE(27, tRDRAND);
+ XBYAK_DEFINE_TYPE(28, tADX); // adcx, adox
+ XBYAK_DEFINE_TYPE(29, tRDSEED); // rdseed
+ XBYAK_DEFINE_TYPE(30, tSMAP); // stac
+ XBYAK_DEFINE_TYPE(31, tHLE); // xacquire, xrelease, xtest
+ XBYAK_DEFINE_TYPE(32, tRTM); // xbegin, xend, xabort
+ XBYAK_DEFINE_TYPE(33, tF16C); // vcvtph2ps, vcvtps2ph
+ XBYAK_DEFINE_TYPE(34, tMOVBE); // mobve
+ XBYAK_DEFINE_TYPE(35, tAVX512F);
+ XBYAK_DEFINE_TYPE(36, tAVX512DQ);
+ XBYAK_DEFINE_TYPE(37, tAVX512_IFMA);
+ XBYAK_DEFINE_TYPE(37, tAVX512IFMA);// = tAVX512_IFMA;
+ XBYAK_DEFINE_TYPE(38, tAVX512PF);
+ XBYAK_DEFINE_TYPE(39, tAVX512ER);
+ XBYAK_DEFINE_TYPE(40, tAVX512CD);
+ XBYAK_DEFINE_TYPE(41, tAVX512BW);
+ XBYAK_DEFINE_TYPE(42, tAVX512VL);
+ XBYAK_DEFINE_TYPE(43, tAVX512_VBMI);
+ XBYAK_DEFINE_TYPE(43, tAVX512VBMI); // = tAVX512_VBMI; // changed by Intel's manual
+ XBYAK_DEFINE_TYPE(44, tAVX512_4VNNIW);
+ XBYAK_DEFINE_TYPE(45, tAVX512_4FMAPS);
+ XBYAK_DEFINE_TYPE(46, tPREFETCHWT1);
+ XBYAK_DEFINE_TYPE(47, tPREFETCHW);
+ XBYAK_DEFINE_TYPE(48, tSHA);
+ XBYAK_DEFINE_TYPE(49, tMPX);
+ XBYAK_DEFINE_TYPE(50, tAVX512_VBMI2);
+ XBYAK_DEFINE_TYPE(51, tGFNI);
+ XBYAK_DEFINE_TYPE(52, tVAES);
+ XBYAK_DEFINE_TYPE(53, tVPCLMULQDQ);
+ XBYAK_DEFINE_TYPE(54, tAVX512_VNNI);
+ XBYAK_DEFINE_TYPE(55, tAVX512_BITALG);
+ XBYAK_DEFINE_TYPE(56, tAVX512_VPOPCNTDQ);
+ XBYAK_DEFINE_TYPE(57, tAVX512_BF16);
+ XBYAK_DEFINE_TYPE(58, tAVX512_VP2INTERSECT);
+ XBYAK_DEFINE_TYPE(59, tAMX_TILE);
+ XBYAK_DEFINE_TYPE(60, tAMX_INT8);
+ XBYAK_DEFINE_TYPE(61, tAMX_BF16);
+ XBYAK_DEFINE_TYPE(62, tAVX_VNNI);
+ XBYAK_DEFINE_TYPE(63, tCLFLUSHOPT);
+ XBYAK_DEFINE_TYPE(64, tCLDEMOTE);
+ XBYAK_DEFINE_TYPE(65, tMOVDIRI);
+ XBYAK_DEFINE_TYPE(66, tMOVDIR64B);
+ XBYAK_DEFINE_TYPE(67, tCLZERO); // AMD Zen
+ XBYAK_DEFINE_TYPE(68, tAMX_FP16);
+ XBYAK_DEFINE_TYPE(69, tAVX_VNNI_INT8);
+ XBYAK_DEFINE_TYPE(70, tAVX_NE_CONVERT);
+ XBYAK_DEFINE_TYPE(71, tAVX_IFMA);
+ XBYAK_DEFINE_TYPE(72, tRAO_INT);
+ XBYAK_DEFINE_TYPE(73, tCMPCCXADD);
+
+#undef XBYAK_SPLIT_ID
+#undef XBYAK_DEFINE_TYPE
+
+ Cpu()
+ : type_()
+ , x2APIC_supported_(false)
+ , numCores_()
+ , dataCacheSize_()
+ , coresSharignDataCache_()
+ , dataCacheLevels_(0)
+ {
+ uint32_t data[4] = {};
+ const uint32_t& EAX = data[0];
+ const uint32_t& EBX = data[1];
+ const uint32_t& ECX = data[2];
+ const uint32_t& EDX = data[3];
+ getCpuid(0, data);
+ const uint32_t maxNum = EAX;
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bitAsBE(amd)) {
+ type_ |= tAMD;
+ getCpuid(0x80000001, data);
+ if (EDX & (1U << 31)) {
+ type_ |= t3DN;
+ // 3DNow! implies support for PREFETCHW on AMD
+ type_ |= tPREFETCHW;
+ }
+
+ if (EDX & (1U << 29)) {
+ // Long mode implies support for PREFETCHW on AMD
+ type_ |= tPREFETCHW;
+ }
+ }
+ if (ECX == get32bitAsBE(intel)) {
+ type_ |= tINTEL;
+ }
+
+ // Extended flags information
+ getCpuid(0x80000000, data);
+ const uint32_t maxExtendedNum = EAX;
+ if (maxExtendedNum >= 0x80000001) {
+ getCpuid(0x80000001, data);
+
+ if (EDX & (1U << 31)) type_ |= t3DN;
+ if (EDX & (1U << 30)) type_ |= tE3DN;
+ if (EDX & (1U << 27)) type_ |= tRDTSCP;
+ if (EDX & (1U << 22)) type_ |= tMMX2;
+ if (EDX & (1U << 15)) type_ |= tCMOV;
+ if (ECX & (1U << 5)) type_ |= tLZCNT;
+ if (ECX & (1U << 8)) type_ |= tPREFETCHW;
+ }
+
+ if (maxExtendedNum >= 0x80000008) {
+ getCpuid(0x80000008, data);
+ if (EBX & (1U << 0)) type_ |= tCLZERO;
+ }
+
+ getCpuid(1, data);
+ if (ECX & (1U << 0)) type_ |= tSSE3;
+ if (ECX & (1U << 9)) type_ |= tSSSE3;
+ if (ECX & (1U << 19)) type_ |= tSSE41;
+ if (ECX & (1U << 20)) type_ |= tSSE42;
+ if (ECX & (1U << 22)) type_ |= tMOVBE;
+ if (ECX & (1U << 23)) type_ |= tPOPCNT;
+ if (ECX & (1U << 25)) type_ |= tAESNI;
+ if (ECX & (1U << 1)) type_ |= tPCLMULQDQ;
+ if (ECX & (1U << 27)) type_ |= tOSXSAVE;
+ if (ECX & (1U << 30)) type_ |= tRDRAND;
+ if (ECX & (1U << 29)) type_ |= tF16C;
+
+ if (EDX & (1U << 15)) type_ |= tCMOV;
+ if (EDX & (1U << 23)) type_ |= tMMX;
+ if (EDX & (1U << 25)) type_ |= tMMX2 | tSSE;
+ if (EDX & (1U << 26)) type_ |= tSSE2;
+
+ if (type_ & tOSXSAVE) {
+ // check XFEATURE_ENABLED_MASK[2:1] = '11b'
+ uint64_t bv = getXfeature();
+ if ((bv & 6) == 6) {
+ if (ECX & (1U << 28)) type_ |= tAVX;
+ if (ECX & (1U << 12)) type_ |= tFMA;
+ // do *not* check AVX-512 state on macOS because it has on-demand AVX-512 support
+#if !defined(__APPLE__)
+ if (((bv >> 5) & 7) == 7)
+#endif
+ {
+ getCpuidEx(7, 0, data);
+ if (EBX & (1U << 16)) type_ |= tAVX512F;
+ if (type_ & tAVX512F) {
+ if (EBX & (1U << 17)) type_ |= tAVX512DQ;
+ if (EBX & (1U << 21)) type_ |= tAVX512_IFMA;
+ if (EBX & (1U << 26)) type_ |= tAVX512PF;
+ if (EBX & (1U << 27)) type_ |= tAVX512ER;
+ if (EBX & (1U << 28)) type_ |= tAVX512CD;
+ if (EBX & (1U << 30)) type_ |= tAVX512BW;
+ if (EBX & (1U << 31)) type_ |= tAVX512VL;
+ if (ECX & (1U << 1)) type_ |= tAVX512_VBMI;
+ if (ECX & (1U << 6)) type_ |= tAVX512_VBMI2;
+ if (ECX & (1U << 11)) type_ |= tAVX512_VNNI;
+ if (ECX & (1U << 12)) type_ |= tAVX512_BITALG;
+ if (ECX & (1U << 14)) type_ |= tAVX512_VPOPCNTDQ;
+ if (EDX & (1U << 2)) type_ |= tAVX512_4VNNIW;
+ if (EDX & (1U << 3)) type_ |= tAVX512_4FMAPS;
+ if (EDX & (1U << 8)) type_ |= tAVX512_VP2INTERSECT;
+ if ((type_ & tAVX512BW) && (EDX & (1U << 23))) type_ |= tAVX512_FP16;
+ }
+ }
+ }
+ }
+ if (maxNum >= 7) {
+ getCpuidEx(7, 0, data);
+ const uint32_t maxNumSubLeaves = EAX;
+ if (type_ & tAVX && (EBX & (1U << 5))) type_ |= tAVX2;
+ if (EBX & (1U << 3)) type_ |= tBMI1;
+ if (EBX & (1U << 8)) type_ |= tBMI2;
+ if (EBX & (1U << 9)) type_ |= tENHANCED_REP;
+ if (EBX & (1U << 18)) type_ |= tRDSEED;
+ if (EBX & (1U << 19)) type_ |= tADX;
+ if (EBX & (1U << 20)) type_ |= tSMAP;
+ if (EBX & (1U << 23)) type_ |= tCLFLUSHOPT;
+ if (EBX & (1U << 4)) type_ |= tHLE;
+ if (EBX & (1U << 11)) type_ |= tRTM;
+ if (EBX & (1U << 14)) type_ |= tMPX;
+ if (EBX & (1U << 29)) type_ |= tSHA;
+ if (ECX & (1U << 0)) type_ |= tPREFETCHWT1;
+ if (ECX & (1U << 5)) type_ |= tWAITPKG;
+ if (ECX & (1U << 8)) type_ |= tGFNI;
+ if (ECX & (1U << 9)) type_ |= tVAES;
+ if (ECX & (1U << 10)) type_ |= tVPCLMULQDQ;
+ if (ECX & (1U << 25)) type_ |= tCLDEMOTE;
+ if (ECX & (1U << 27)) type_ |= tMOVDIRI;
+ if (ECX & (1U << 28)) type_ |= tMOVDIR64B;
+ if (EDX & (1U << 24)) type_ |= tAMX_TILE;
+ if (EDX & (1U << 25)) type_ |= tAMX_INT8;
+ if (EDX & (1U << 22)) type_ |= tAMX_BF16;
+ if (maxNumSubLeaves >= 1) {
+ getCpuidEx(7, 1, data);
+ if (EAX & (1U << 3)) type_ |= tRAO_INT;
+ if (EAX & (1U << 4)) type_ |= tAVX_VNNI;
+ if (type_ & tAVX512F) {
+ if (EAX & (1U << 5)) type_ |= tAVX512_BF16;
+ }
+ if (EAX & (1U << 7)) type_ |= tCMPCCXADD;
+ if (EAX & (1U << 21)) type_ |= tAMX_FP16;
+ if (EAX & (1U << 23)) type_ |= tAVX_IFMA;
+ if (EDX & (1U << 4)) type_ |= tAVX_VNNI_INT8;
+ if (EDX & (1U << 5)) type_ |= tAVX_NE_CONVERT;
+ }
+ }
+ setFamily();
+ setNumCores();
+ setCacheHierarchy();
+ }
+ void putFamily() const
+ {
+#ifndef XBYAK_ONLY_CLASS_CPU
+ printf("family=%d, model=%X, stepping=%d, extFamily=%d, extModel=%X\n",
+ family, model, stepping, extFamily, extModel);
+ printf("display:family=%X, model=%X\n", displayFamily, displayModel);
+#endif
+ }
+ bool has(const Type& type) const
+ {
+ return (type & type_) == type;
+ }
+};
+
+#ifndef XBYAK_ONLY_CLASS_CPU
+class Clock {
+public:
+ static inline uint64_t getRdtsc()
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _MSC_VER
+ return __rdtsc();
+ #else
+ uint32_t eax, edx;
+ __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx));
+ return ((uint64_t)edx << 32) | eax;
+ #endif
+#else
+ // TODO: Need another impl of Clock or rdtsc-equivalent for non-x86 cpu
+ return 0;
+#endif
+ }
+ Clock()
+ : clock_(0)
+ , count_(0)
+ {
+ }
+ void begin()
+ {
+ clock_ -= getRdtsc();
+ }
+ void end()
+ {
+ clock_ += getRdtsc();
+ count_++;
+ }
+ int getCount() const { return count_; }
+ uint64_t getClock() const { return clock_; }
+ void clear() { count_ = 0; clock_ = 0; }
+private:
+ uint64_t clock_;
+ int count_;
+};
+
+#ifdef XBYAK64
+const int UseRCX = 1 << 6;
+const int UseRDX = 1 << 7;
+
+class Pack {
+ static const size_t maxTblNum = 15;
+ Xbyak::Reg64 tbl_[maxTblNum];
+ size_t n_;
+public:
+ Pack() : tbl_(), n_(0) {}
+ Pack(const Xbyak::Reg64 *tbl, size_t n) { init(tbl, n); }
+ Pack(const Pack& rhs)
+ : n_(rhs.n_)
+ {
+ for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i];
+ }
+ Pack& operator=(const Pack& rhs)
+ {
+ n_ = rhs.n_;
+ for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i];
+ return *this;
+ }
+ Pack(const Xbyak::Reg64& t0)
+ { n_ = 1; tbl_[0] = t0; }
+ Pack(const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 2; tbl_[0] = t0; tbl_[1] = t1; }
+ Pack(const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 3; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; }
+ Pack(const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 4; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; }
+ Pack(const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 5; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; }
+ Pack(const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 6; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; }
+ Pack(const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 7; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; }
+ Pack(const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 8; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; }
+ Pack(const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 9; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; }
+ Pack(const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 10; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; tbl_[9] = t9; }
+ Pack(const Xbyak::Reg64& ta, const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 11; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; tbl_[9] = t9; tbl_[10] = ta; }
+ Pack(const Xbyak::Reg64& tb, const Xbyak::Reg64& ta, const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 12; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; tbl_[9] = t9; tbl_[10] = ta; tbl_[11] = tb; }
+ Pack& append(const Xbyak::Reg64& t)
+ {
+ if (n_ == maxTblNum) {
+ fprintf(stderr, "ERR Pack::can't append\n");
+ XBYAK_THROW_RET(ERR_BAD_PARAMETER, *this)
+ }
+ tbl_[n_++] = t;
+ return *this;
+ }
+ void init(const Xbyak::Reg64 *tbl, size_t n)
+ {
+ if (n > maxTblNum) {
+ fprintf(stderr, "ERR Pack::init bad n=%d\n", (int)n);
+ XBYAK_THROW(ERR_BAD_PARAMETER)
+ }
+ n_ = n;
+ for (size_t i = 0; i < n; i++) {
+ tbl_[i] = tbl[i];
+ }
+ }
+ const Xbyak::Reg64& operator[](size_t n) const
+ {
+ if (n >= n_) {
+ fprintf(stderr, "ERR Pack bad n=%d(%d)\n", (int)n, (int)n_);
+ XBYAK_THROW_RET(ERR_BAD_PARAMETER, rax)
+ }
+ return tbl_[n];
+ }
+ size_t size() const { return n_; }
+ /*
+ get tbl[pos, pos + num)
+ */
+ Pack sub(size_t pos, size_t num = size_t(-1)) const
+ {
+ if (num == size_t(-1)) num = n_ - pos;
+ if (pos + num > n_) {
+ fprintf(stderr, "ERR Pack::sub bad pos=%d, num=%d\n", (int)pos, (int)num);
+ XBYAK_THROW_RET(ERR_BAD_PARAMETER, Pack())
+ }
+ Pack pack;
+ pack.n_ = num;
+ for (size_t i = 0; i < num; i++) {
+ pack.tbl_[i] = tbl_[pos + i];
+ }
+ return pack;
+ }
+ void put() const
+ {
+ for (size_t i = 0; i < n_; i++) {
+ printf("%s ", tbl_[i].toString());
+ }
+ printf("\n");
+ }
+};
+
+class StackFrame {
+#ifdef XBYAK64_WIN
+ static const int noSaveNum = 6;
+ static const int rcxPos = 0;
+ static const int rdxPos = 1;
+#else
+ static const int noSaveNum = 8;
+ static const int rcxPos = 3;
+ static const int rdxPos = 2;
+#endif
+ static const int maxRegNum = 14; // maxRegNum = 16 - rsp - rax
+ Xbyak::CodeGenerator *code_;
+ int pNum_;
+ int tNum_;
+ bool useRcx_;
+ bool useRdx_;
+ int saveNum_;
+ int P_;
+ bool makeEpilog_;
+ Xbyak::Reg64 pTbl_[4];
+ Xbyak::Reg64 tTbl_[maxRegNum];
+ Pack p_;
+ Pack t_;
+ StackFrame(const StackFrame&);
+ void operator=(const StackFrame&);
+public:
+ const Pack& p;
+ const Pack& t;
+ /*
+ make stack frame
+ @param sf [in] this
+ @param pNum [in] num of function parameter(0 <= pNum <= 4)
+ @param tNum [in] num of temporary register(0 <= tNum, with UseRCX, UseRDX) #{pNum + tNum [+rcx] + [rdx]} <= 14
+ @param stackSizeByte [in] local stack size
+ @param makeEpilog [in] automatically call close() if true
+
+ you can use
+ rax
+ gp0, ..., gp(pNum - 1)
+ gt0, ..., gt(tNum-1)
+ rcx if tNum & UseRCX
+ rdx if tNum & UseRDX
+ rsp[0..stackSizeByte - 1]
+ */
+ StackFrame(Xbyak::CodeGenerator *code, int pNum, int tNum = 0, int stackSizeByte = 0, bool makeEpilog = true)
+ : code_(code)
+ , pNum_(pNum)
+ , tNum_(tNum & ~(UseRCX | UseRDX))
+ , useRcx_((tNum & UseRCX) != 0)
+ , useRdx_((tNum & UseRDX) != 0)
+ , saveNum_(0)
+ , P_(0)
+ , makeEpilog_(makeEpilog)
+ , p(p_)
+ , t(t_)
+ {
+ using namespace Xbyak;
+ if (pNum < 0 || pNum > 4) XBYAK_THROW(ERR_BAD_PNUM)
+ const int allRegNum = pNum + tNum_ + (useRcx_ ? 1 : 0) + (useRdx_ ? 1 : 0);
+ if (tNum_ < 0 || allRegNum > maxRegNum) XBYAK_THROW(ERR_BAD_TNUM)
+ const Reg64& _rsp = code->rsp;
+ saveNum_ = local::max_(0, allRegNum - noSaveNum);
+ const int *tbl = getOrderTbl() + noSaveNum;
+ for (int i = 0; i < saveNum_; i++) {
+ code->push(Reg64(tbl[i]));
+ }
+ P_ = (stackSizeByte + 7) / 8;
+ if (P_ > 0 && (P_ & 1) == (saveNum_ & 1)) P_++; // (rsp % 16) == 8, then increment P_ for 16 byte alignment
+ P_ *= 8;
+ if (P_ > 0) code->sub(_rsp, P_);
+ int pos = 0;
+ for (int i = 0; i < pNum; i++) {
+ pTbl_[i] = Xbyak::Reg64(getRegIdx(pos));
+ }
+ for (int i = 0; i < tNum_; i++) {
+ tTbl_[i] = Xbyak::Reg64(getRegIdx(pos));
+ }
+ if (useRcx_ && rcxPos < pNum) code_->mov(code_->r10, code_->rcx);
+ if (useRdx_ && rdxPos < pNum) code_->mov(code_->r11, code_->rdx);
+ p_.init(pTbl_, pNum);
+ t_.init(tTbl_, tNum_);
+ }
+ /*
+ make epilog manually
+ @param callRet [in] call ret() if true
+ */
+ void close(bool callRet = true)
+ {
+ using namespace Xbyak;
+ const Reg64& _rsp = code_->rsp;
+ const int *tbl = getOrderTbl() + noSaveNum;
+ if (P_ > 0) code_->add(_rsp, P_);
+ for (int i = 0; i < saveNum_; i++) {
+ code_->pop(Reg64(tbl[saveNum_ - 1 - i]));
+ }
+
+ if (callRet) code_->ret();
+ }
+ ~StackFrame()
+ {
+ if (!makeEpilog_) return;
+ close();
+ }
+private:
+ const int *getOrderTbl() const
+ {
+ using namespace Xbyak;
+ static const int tbl[] = {
+#ifdef XBYAK64_WIN
+ Operand::RCX, Operand::RDX, Operand::R8, Operand::R9, Operand::R10, Operand::R11, Operand::RDI, Operand::RSI,
+#else
+ Operand::RDI, Operand::RSI, Operand::RDX, Operand::RCX, Operand::R8, Operand::R9, Operand::R10, Operand::R11,
+#endif
+ Operand::RBX, Operand::RBP, Operand::R12, Operand::R13, Operand::R14, Operand::R15
+ };
+ return &tbl[0];
+ }
+ int getRegIdx(int& pos) const
+ {
+ assert(pos < maxRegNum);
+ using namespace Xbyak;
+ const int *tbl = getOrderTbl();
+ int r = tbl[pos++];
+ if (useRcx_) {
+ if (r == Operand::RCX) { return Operand::R10; }
+ if (r == Operand::R10) { r = tbl[pos++]; }
+ }
+ if (useRdx_) {
+ if (r == Operand::RDX) { return Operand::R11; }
+ if (r == Operand::R11) { return tbl[pos++]; }
+ }
+ return r;
+ }
+};
+#endif
+
+class Profiler {
+ int mode_;
+ const char *suffix_;
+ const void *startAddr_;
+#ifdef XBYAK_USE_PERF
+ FILE *fp_;
+#endif
+public:
+ enum {
+ None = 0,
+ Perf = 1,
+ VTune = 2
+ };
+ Profiler()
+ : mode_(None)
+ , suffix_("")
+ , startAddr_(0)
+#ifdef XBYAK_USE_PERF
+ , fp_(0)
+#endif
+ {
+ }
+ // append suffix to funcName
+ void setNameSuffix(const char *suffix)
+ {
+ suffix_ = suffix;
+ }
+ void setStartAddr(const void *startAddr)
+ {
+ startAddr_ = startAddr;
+ }
+ void init(int mode)
+ {
+ mode_ = None;
+ switch (mode) {
+ default:
+ case None:
+ return;
+ case Perf:
+#ifdef XBYAK_USE_PERF
+ close();
+ {
+ const int pid = getpid();
+ char name[128];
+ snprintf(name, sizeof(name), "/tmp/perf-%d.map", pid);
+ fp_ = fopen(name, "a+");
+ if (fp_ == 0) {
+ fprintf(stderr, "can't open %s\n", name);
+ return;
+ }
+ }
+ mode_ = Perf;
+#endif
+ return;
+ case VTune:
+#ifdef XBYAK_USE_VTUNE
+ dlopen("dummy", RTLD_LAZY); // force to load dlopen to enable jit profiling
+ if (iJIT_IsProfilingActive() != iJIT_SAMPLING_ON) {
+ fprintf(stderr, "VTune profiling is not active\n");
+ return;
+ }
+ mode_ = VTune;
+#endif
+ return;
+ }
+ }
+ ~Profiler()
+ {
+ close();
+ }
+ void close()
+ {
+#ifdef XBYAK_USE_PERF
+ if (fp_ == 0) return;
+ fclose(fp_);
+ fp_ = 0;
+#endif
+ }
+ void set(const char *funcName, const void *startAddr, size_t funcSize) const
+ {
+ if (mode_ == None) return;
+#if !defined(XBYAK_USE_PERF) && !defined(XBYAK_USE_VTUNE)
+ (void)funcName;
+ (void)startAddr;
+ (void)funcSize;
+#endif
+#ifdef XBYAK_USE_PERF
+ if (mode_ == Perf) {
+ if (fp_ == 0) return;
+ fprintf(fp_, "%llx %zx %s%s", (long long)startAddr, funcSize, funcName, suffix_);
+ /*
+ perf does not recognize the function name which is less than 3,
+ so append '_' at the end of the name if necessary
+ */
+ size_t n = strlen(funcName) + strlen(suffix_);
+ for (size_t i = n; i < 3; i++) {
+ fprintf(fp_, "_");
+ }
+ fprintf(fp_, "\n");
+ fflush(fp_);
+ }
+#endif
+#ifdef XBYAK_USE_VTUNE
+ if (mode_ != VTune) return;
+ char className[] = "";
+ char fileName[] = "";
+ iJIT_Method_Load jmethod = {};
+ jmethod.method_id = iJIT_GetNewMethodID();
+ jmethod.class_file_name = className;
+ jmethod.source_file_name = fileName;
+ jmethod.method_load_address = const_cast<void*>(startAddr);
+ jmethod.method_size = funcSize;
+ jmethod.line_number_size = 0;
+ char buf[128];
+ snprintf(buf, sizeof(buf), "%s%s", funcName, suffix_);
+ jmethod.method_name = buf;
+ iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
+#endif
+ }
+ /*
+ for continuous set
+ funcSize = endAddr - <previous set endAddr>
+ */
+ void set(const char *funcName, const void *endAddr)
+ {
+ set(funcName, startAddr_, (size_t)endAddr - (size_t)startAddr_);
+ startAddr_ = endAddr;
+ }
+};
+#endif // XBYAK_ONLY_CLASS_CPU
+
+} } // end of util
+
+#endif