commit bc992fca6e51118dc3f739be0cb39d1bee825ebf
parent 8b8cb7097b3e812a31e4f13be13f4e07dca8c687
Author: William Casarin <jb55@jb55.com>
Date: Sun, 1 Aug 2021 10:17:27 -0700
bitcount instrs
Diffstat:
2 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/src/wasm.c b/src/wasm.c
@@ -579,6 +579,8 @@ static char *instr_name(enum instr_tag tag)
case i_f64_le: return "f64_le";
case i_f64_ge: return "f64_ge";
case i_i32_clz: return "i32_clz";
+ case i_i32_ctz: return "i32_ctz";
+ case i_i32_popcnt: return "i32_popcnt";
case i_i32_add: return "i32_add";
case i_i32_sub: return "i32_sub";
case i_i32_mul: return "i32_mul";
@@ -1933,6 +1935,8 @@ static const char *show_instr(struct instr *instr)
case i_f64_le:
case i_f64_ge:
case i_i32_clz:
+ case i_i32_ctz:
+ case i_i32_popcnt:
case i_i32_add:
case i_i32_sub:
case i_i32_mul:
@@ -4190,7 +4194,7 @@ static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op)
op->pos = p->code->p - 1 - p->code->start;
op->tag = tag;
- switch (tag) {
+ switch ((enum instr_tag)tag) {
// two-byte instrs
case i_select:
case i_selects:
@@ -4238,6 +4242,7 @@ static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op)
}
return 1;
+ case i_ref_is_null:
case i_i32_load:
case i_i64_load:
case i_f32_load:
@@ -4266,6 +4271,9 @@ static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op)
case i_br_table:
return parse_br_table(p->code, p->errs, &op->br_table);
+ case i_table_op:
+ return note_error(p->errs, p->code, "parse table op");
+
case i_call_indirect:
return parse_call_indirect(p->code, &op->call_indirect);
@@ -4318,6 +4326,8 @@ static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op)
case i_f64_le:
case i_f64_ge:
case i_i32_clz:
+ case i_i32_ctz:
+ case i_i32_popcnt:
case i_i32_add:
case i_i32_sub:
case i_i32_mul:
@@ -4495,7 +4505,46 @@ static int interp_if(struct wasm_interp *interp)
return 1;
}
-static int interp_i32_eqz(struct wasm_interp *interp)
+static INLINE int clz(u32 x)
+{
+ return x ? __builtin_clz(x) : sizeof(x) * 8;
+}
+
+static INLINE int ctz(u32 x)
+{
+ return x ? __builtin_ctz(x) : (int)sizeof(x) * 8;
+}
+
+static INLINE int popcnt(u32 x)
+{
+ return x ? __builtin_popcount(x) : 0;
+}
+
+static INLINE int interp_i32_popcnt(struct wasm_interp *interp)
+{
+ struct val a;
+ if (unlikely(!stack_pop_valtype(interp, val_i32, &a)))
+ return interp_error(interp, "if pop val");
+ return stack_push_i32(interp, popcnt(a.num.u32));
+}
+
+static INLINE int interp_i32_ctz(struct wasm_interp *interp)
+{
+ struct val a;
+ if (unlikely(!stack_pop_valtype(interp, val_i32, &a)))
+ return interp_error(interp, "if pop val");
+ return stack_push_i32(interp, ctz(a.num.u32));
+}
+
+static INLINE int interp_i32_clz(struct wasm_interp *interp)
+{
+ struct val a;
+ if (unlikely(!stack_pop_valtype(interp, val_i32, &a)))
+ return interp_error(interp, "if pop val");
+ return stack_push_i32(interp, clz(a.num.u32));
+}
+
+static INLINE int interp_i32_eqz(struct wasm_interp *interp)
{
struct val a;
if (unlikely(!stack_pop_valtype(interp, val_i32, &a)))
@@ -5643,6 +5692,9 @@ static int interp_instr(struct wasm_interp *interp, struct instr *instr)
case i_global_get: return interp_global_get(interp, instr->i32);
case i_global_set: return interp_global_set(interp, instr->i32);
+ case i_i32_clz: return interp_i32_clz(interp);
+ case i_i32_ctz: return interp_i32_ctz(interp);
+ case i_i32_popcnt: return interp_i32_popcnt(interp);
case i_i32_eqz: return interp_i32_eqz(interp);
case i_i32_add: return interp_i32_add(interp);
case i_i32_sub: return interp_i32_sub(interp);
diff --git a/src/wasm.h b/src/wasm.h
@@ -396,6 +396,8 @@ enum instr_tag {
i_f64_ge = 0x66,
i_i32_clz = 0x67,
+ i_i32_ctz = 0x68,
+ i_i32_popcnt = 0x69,
i_i32_add = 0x6A,
i_i32_sub = 0x6B,