protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit bc992fca6e51118dc3f739be0cb39d1bee825ebf
parent 8b8cb7097b3e812a31e4f13be13f4e07dca8c687
Author: William Casarin <jb55@jb55.com>
Date:   Sun,  1 Aug 2021 10:17:27 -0700

bitcount instrs

Diffstat:
Msrc/wasm.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/wasm.h | 2++
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,