diff --git a/wipforth.wat b/wipforth.wat index b575502..57f8b7f 100644 --- a/wipforth.wat +++ b/wipforth.wat @@ -19,6 +19,9 @@ (global $cfa (mut i32) (i32.const 0)) (global $fn (mut i32) (i32.const 0)) + ;; Trampoline control flag + (global $run (mut i32) (i32.const 0)) + ;; Some little helper functions (func $push (param $x i32) @@ -585,6 +588,8 @@ i32.load global.set $fn) + (func $halt i32.const 0 global.set $run) + ;; Return and parameter stack primitives (func $tor @@ -1118,13 +1123,13 @@ "\64\05\00\00" "\04HERE\00\00\00" "\02\00\00\00" - "\c0\0b\00\00") + "\10\0c\00\00") (data (i32.const 0x058c) "\78\05\00\00" "\06LATEST\00" "\02\00\00\00" - "\b0\0b\00\00") + "\00\0c\00\00") (data (i32.const 0x05a0) "\8c\05\00\00" @@ -1749,6 +1754,12 @@ "\04COPY\00\00\00" "\3d\00\00\00") + (elem (i32.const 0x3e) $halt) + (data (i32.const 0x0c00) + "\f0\0b\00\00" + "\04HALT\00\00\00" + "\3e\00\00\00") + ;; The trampoline is a workaround for WebAssembly's lack of indirect ;; jumps and code addresses. Instead of jumping into the next ;; codeword, NEXT sets the $fn global to the function index of the @@ -1760,9 +1771,8 @@ (func $trampoline loop $loop - global.get $fn - call_indirect (type $codeword) - br $loop + global.get $fn call_indirect (type $codeword) + global.get $run br_if $loop end) (func (export "reset") @@ -1770,4 +1780,6 @@ i32.const 0xf000 global.set $sp ;; Set the stack pointer i32.const 0x0bac global.set $ip ;; Set the IP to the cold start call $next + + i32.const 1 global.set $run call $trampoline))