feat: iteration 36 task 4 — runtime bitwise opcodes, .wob v6
- WOP_BAND..WOP_SHR = 42..46 (wob.h), WOP_MAX 46, WOB_VERSION 6 - trap kind WO_T_SHIFT=12: shift count outside 0..63 traps (DIV0 precedent, never x86's silent count%64); SHR arithmetic - vm.c: one shared case-body serves both dispatch flavors; SHL shifts the unsigned word (wrapping), SHR casts int64_t (sign extends) - loader.c + test runner battery + disasm: v6 accepted, new opcodes validated three-register, rendered BAND/BOR/BXOR/SHL/SHR - woc-test 543/0, wovm-test ASan both flavors green, cli_smoke OK Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
3d75196121
commit
c2c9b240f1
6 changed files with 77 additions and 7 deletions
|
|
@ -159,6 +159,12 @@ let ins_str (i : int) (pc : int) : string =
|
|||
| 39 -> Printf.sprintf "FEQ r%d, r%d, r%d" a b c
|
||||
| 40 -> Printf.sprintf "FLT r%d, r%d, r%d" a b c
|
||||
| 41 -> Printf.sprintf "FLE r%d, r%d, r%d" a b c
|
||||
(* iteration 36 (v6): the Int bitwise set, same three-register shape *)
|
||||
| 42 -> Printf.sprintf "BAND r%d, r%d, r%d" a b c
|
||||
| 43 -> Printf.sprintf "BOR r%d, r%d, r%d" a b c
|
||||
| 44 -> Printf.sprintf "BXOR r%d, r%d, r%d" a b c
|
||||
| 45 -> Printf.sprintf "SHL r%d, r%d, r%d" a b c
|
||||
| 46 -> Printf.sprintf "SHR r%d, r%d, r%d" a b c
|
||||
| op -> Printf.sprintf "?OP%d" op
|
||||
|
||||
(* ---- the dump ---- *)
|
||||
|
|
@ -173,10 +179,11 @@ let dump (img : string) : string =
|
|||
let line fmt = Buffer.add_string out (fmt ^ "\n") in
|
||||
if u32 img 0 <> magic then raise (Bad "bad magic");
|
||||
let ver = u32 img 4 in
|
||||
(* iteration 19 bumped the format to v5 (Float constant tag, kinds 6/7,
|
||||
(* iteration 36 bumped the format to v6 (opcodes 42-46, the Int bitwise
|
||||
set; iteration 19's v5 added the Float constant tag, kinds 6/7 and
|
||||
opcodes 34-41). The disassembler tracks the emitter, not a range: an old
|
||||
image is a different format and reading it as this one would misrender. *)
|
||||
if ver <> 5 then raise (Bad (Printf.sprintf "unsupported version %d" ver));
|
||||
if ver <> 6 then raise (Bad (Printf.sprintf "unsupported version %d" ver));
|
||||
let coff = u32 img 8 and ccnt = u32 img 12 in
|
||||
let koff = u32 img 16 and kcnt = u32 img 20 in
|
||||
let ioff = u32 img 24 and icnt = u32 img 28 in
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ let wob_magic = 0x31424F57 (* "WOB1" read as an LE u32 *)
|
|||
|
||||
(* v5 (iteration 19): the Float constant tag, field kinds 6/7, opcodes 34-41,
|
||||
builtins 70-83. v4 (iteration 7b): RC opcodes retired; gc mask = GC roots *)
|
||||
let wob_version = 5
|
||||
let wob_version = 6
|
||||
|
||||
let wob_hdr_size = 44
|
||||
let wob_none = 0xFFFFFFFF
|
||||
|
|
|
|||
|
|
@ -2278,7 +2278,7 @@ let validate_image (img : string) : string list =
|
|||
let u64 o = if ok 8 o then String.get_int64_le img o else 0L in
|
||||
let none = 0xFFFFFFFF in
|
||||
if u32 0 <> 0x31424F57 then fail "bad magic";
|
||||
if u32 4 <> 5 then fail "unsupported version"; (* v5: iteration 19 *)
|
||||
if u32 4 <> 6 then fail "unsupported version"; (* v6: iteration 36 *)
|
||||
let coff = u32 8 and ccnt = u32 12 in
|
||||
let koff = u32 16 and kcnt = u32 20 in
|
||||
let ioff = u32 24 and icnt = u32 28 in
|
||||
|
|
@ -2554,7 +2554,9 @@ let validate_image (img : string) : string list =
|
|||
| 38 ->
|
||||
rchk pc a;
|
||||
rchk pc b
|
||||
| 34 | 35 | 36 | 37 | 39 | 40 | 41 ->
|
||||
(* iteration 36 (v6): 42-46, the Int bitwise set — same
|
||||
three-register shape *)
|
||||
| 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 ->
|
||||
rchk pc a;
|
||||
rchk pc b;
|
||||
rchk pc c
|
||||
|
|
|
|||
|
|
@ -441,6 +441,14 @@ int wo_load_buf(wo_module *m, const uint8_t *buf, size_t len, char *err,
|
|||
case WOP_FEQ:
|
||||
case WOP_FLT:
|
||||
case WOP_FLE:
|
||||
/* iteration 36 (v6): same three-register shape; the shift
|
||||
count is range-checked at RUN time (WO_T_SHIFT), not here
|
||||
— it lives in a register, not an immediate. */
|
||||
case WOP_BAND:
|
||||
case WOP_BOR:
|
||||
case WOP_BXOR:
|
||||
case WOP_SHL:
|
||||
case WOP_SHR:
|
||||
RCHK(A);
|
||||
RCHK(B);
|
||||
RCHK(C);
|
||||
|
|
|
|||
|
|
@ -859,6 +859,10 @@ static int vm_run(wo_vm *vm, uint64_t *ret, wo_err *err) {
|
|||
[WOP_FMUL] = &&L_FMUL, [WOP_FDIV] = &&L_FDIV,
|
||||
[WOP_FNEG] = &&L_FNEG, [WOP_FEQ] = &&L_FEQ,
|
||||
[WOP_FLT] = &&L_FLT, [WOP_FLE] = &&L_FLE,
|
||||
/* iteration 36 (v6): the Int bitwise set */
|
||||
[WOP_BAND] = &&L_BAND, [WOP_BOR] = &&L_BOR,
|
||||
[WOP_BXOR] = &&L_BXOR, [WOP_SHL] = &&L_SHL,
|
||||
[WOP_SHR] = &&L_SHR,
|
||||
};
|
||||
#define CASE(name) L_##name
|
||||
#define NEXT() \
|
||||
|
|
@ -935,6 +939,38 @@ dispatch:
|
|||
NEXT();
|
||||
}
|
||||
|
||||
/* iteration 36 (v6): Int bitwise. AND/OR/XOR are sign-agnostic on
|
||||
* the u64 register word. SHL shifts the unsigned word (wrapping,
|
||||
* like ADD); SHR casts to int64_t first — ARITHMETIC, the sign bit
|
||||
* extends (gcc/clang define signed >> as arithmetic, the only
|
||||
* compilers this runtime targets). A count outside 0..63 traps
|
||||
* WO_T_SHIFT rather than silently masking like the hardware would;
|
||||
* literal counts were rejected at compile time (WO-E223). */
|
||||
CASE(BAND) : {
|
||||
R[wo_ins_a(ins)] = R[wo_ins_b(ins)] & R[wo_ins_c(ins)];
|
||||
NEXT();
|
||||
}
|
||||
CASE(BOR) : {
|
||||
R[wo_ins_a(ins)] = R[wo_ins_b(ins)] | R[wo_ins_c(ins)];
|
||||
NEXT();
|
||||
}
|
||||
CASE(BXOR) : {
|
||||
R[wo_ins_a(ins)] = R[wo_ins_b(ins)] ^ R[wo_ins_c(ins)];
|
||||
NEXT();
|
||||
}
|
||||
CASE(SHL) : {
|
||||
int64_t s = (int64_t)R[wo_ins_c(ins)];
|
||||
if (s < 0 || s > 63) TRAPF(WO_T_SHIFT, "shift count out of range 0..63");
|
||||
R[wo_ins_a(ins)] = R[wo_ins_b(ins)] << s;
|
||||
NEXT();
|
||||
}
|
||||
CASE(SHR) : {
|
||||
int64_t s = (int64_t)R[wo_ins_c(ins)];
|
||||
if (s < 0 || s > 63) TRAPF(WO_T_SHIFT, "shift count out of range 0..63");
|
||||
R[wo_ins_a(ins)] = (uint64_t)((int64_t)R[wo_ins_b(ins)] >> s);
|
||||
NEXT();
|
||||
}
|
||||
|
||||
/* iteration 19: f64 arithmetic. Registers are u64, so each op bitcasts in
|
||||
* and out (wo_f64/wo_bits — memcpy-based, the only strict-aliasing-clean
|
||||
* way). Nothing here traps: IEEE 754 quiet semantics are the contract, so
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@
|
|||
|
||||
/* ---- file header (44 bytes, absolute offsets) ---- */
|
||||
#define WOB_MAGIC 0x31424F57u /* "WOB1" read as LE u32 */
|
||||
#define WOB_VERSION 5u /* v5 (iteration 19): the two missing scalars. New
|
||||
#define WOB_VERSION 6u /* v6 (iteration 36): opcodes 42-46 (the Int
|
||||
* bitwise set BAND/BOR/BXOR/SHL/SHR), trap kind WO_T_SHIFT.
|
||||
* v5 (iteration 19): the two missing scalars. New
|
||||
* constant tag WOB_K_FLOAT, field kinds WO_K_FLOAT/WO_K_BYTES (WO_K_MAX 5->7),
|
||||
* opcodes 34-41 (the f64 arithmetic/compare set), builtins 70-82.
|
||||
* v4 (iteration 7b): opcodes 27-28 (RC_INC/RC_DEC) retired; the drop table's
|
||||
|
|
@ -184,6 +186,10 @@ enum {
|
|||
/* iteration 9b: deleting a row still referenced by a `ref` traps here
|
||||
(restrict) — the employee sample's DROP-of-a-department-with-staff */
|
||||
WO_T_FK = 11,
|
||||
/* iteration 36: a shift count outside 0..63 at run time — the Int
|
||||
honesty precedent DIV0 set (trap, never x86's silent count%64).
|
||||
Literal counts never get here: woc rejects them (WO-E223). */
|
||||
WO_T_SHIFT = 12,
|
||||
};
|
||||
|
||||
/* ---- opcodes (spec section 5; semantics in the format doc) ---- */
|
||||
|
|
@ -247,8 +253,19 @@ enum {
|
|||
WOP_FEQ = 39, /* A B C: IEEE equality, so NaN == NaN is 0 */
|
||||
WOP_FLT = 40, /* IEEE ordered <: any comparison with NaN is 0 */
|
||||
WOP_FLE = 41,
|
||||
/* iteration 36 (v6): the Int bitwise set. A B C on i64, Int-only —
|
||||
* woc's checker refuses Float/Bool/Text operands, so no F-twin
|
||||
* exists. SHL/SHR trap WO_T_SHIFT when the count register is
|
||||
* outside 0..63 (never x86's silent count%64; literal counts were
|
||||
* already rejected at compile time as WO-E223). SHR is ARITHMETIC:
|
||||
* the sign bit extends, Go's own choice for a signed integer. */
|
||||
WOP_BAND = 42, /* A B C: r[A] = r[B] & r[C] */
|
||||
WOP_BOR = 43,
|
||||
WOP_BXOR = 44,
|
||||
WOP_SHL = 45, /* A B C: r[A] = r[B] << r[C]; C outside 0..63 traps */
|
||||
WOP_SHR = 46, /* A B C: arithmetic; C outside 0..63 traps */
|
||||
};
|
||||
#define WOP_MAX 41u
|
||||
#define WOP_MAX 46u
|
||||
|
||||
/* ---- builtin ids (WOP_BUILTIN operand C) ---- */
|
||||
enum {
|
||||
|
|
|
|||
Loading…
Reference in a new issue