Created
September 5, 2023 14:10
-
-
Save Two9A/427985064d360342caaf4f7d5769aeef to your computer and use it in GitHub Desktop.
WASM definition macro preprocessor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(module (func $io_r (import "func" "io_r") (param i32) (result i32)) (func $io_w (import "func" "io_w") (param i32) (param i32)) (memory (import "buffers" "mem") 2) (table 16 anyfunc) (elem (i32.const 0) $r_ram $r_ram $r_ram $r_ram $r_ram $r_ram $r_ram $r_ram $r_ram $r_ram $r_basic $r_basic $r_ram $r_char $r_kernal $r_kernal) (func $r_ram (param $addr i32) (result i32) (i32.load8_u (i32.and (get_local $addr) (i32.const 0xFFFF)))) (func $r_basic (param $addr i32) (result i32) (i32.load8_u (if (result i32) (i32.eq (i32.and (i32.load (i32.const 0x0001)) (i32.const 3)) (i32.const 3)) (then (i32.add (i32.and (get_local $addr) (i32.const 0xFFFF)) (i32.const 0x10000))) (else (i32.and (get_local $addr) (i32.const 0xFFFF)))))) (func $r_kernal (param $addr i32) (result i32) (i32.load8_u (if (result i32) (i32.and (i32.load (i32.const 0x0001)) (i32.const 2)) (then (i32.add (i32.and (get_local $addr) (i32.const 0xFFFF)) (i32.const 0x10000))) (else (i32.and (get_local $addr) (i32.const 0xFFFF)))))) (func $r_char (param $addr i32) (result i32) (i32.and (i32.const 0xFF) (if (result i32) (i32.gt_u (i32.and (i32.load (i32.const 0x0001)) (i32.const 7)) (i32.const 4)) (then (call $io_r (get_local $addr))) (else (i32.load8_u (if (result i32) (i32.and (i32.gt_u (i32.and (i32.load (i32.const 0x0001)) (i32.const 7)) (i32.const 0)) (i32.lt_u (i32.and (i32.load (i32.const 0x0001)) (i32.const 7)) (i32.const 4))) (then (i32.add (i32.and (get_local $addr) (i32.const 0xFFFF)) (i32.const 0x10000))) (else (i32.and (get_local $addr) (i32.const 0xFFFF))))))))) (type $readfunc (func (param i32) (result i32))) (func $r (param $addr i32) (result i32) (call_indirect (type $readfunc) (get_local $addr) (i32.shr_u (i32.and (get_local $addr) (i32.const 0xF000)) (i32.const 12)))) (func $w (param $addr i32) (param $val i32) (if (i32.and (i32.and (i32.load (i32.const 0x0001)) (i32.const 4)) (i32.eq (i32.and (get_local $addr) (i32.const 0xF000)) (i32.const 0xD000))) (then (call $io_w (get_local $addr) (get_local $val))) (else (i32.store8 (i32.and (get_local $addr) (i32.const 0xFFFF)) (i32.and (get_local $val) (i32.const 0xFF)))))) (export "r" (func $r)) (export "w" (func $w))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(module | |
(define CPUPORT (i32.const 0x0001)) | |
(define LORAM (i32.const 1)) | |
(define HIRAM (i32.const 2)) | |
(define CHAREN (i32.const 4)) | |
(define ROM_START (i32.const 0x10000)) | |
(func $io_r (import "func" "io_r") (param i32) (result i32)) | |
(func $io_w (import "func" "io_w") (param i32) (param i32)) | |
(memory (import "buffers" "mem") 2) | |
(table 16 anyfunc) | |
(elem (i32.const 0) | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_ram | |
$r_basic | |
$r_basic | |
$r_ram | |
$r_char | |
$r_kernal | |
$r_kernal | |
) | |
(func $r_ram (param $addr i32) (result i32) | |
(i32.load8_u | |
(i32.and (get_local $addr) (i32.const 0xFFFF)) | |
) | |
) | |
(func $r_basic (param $addr i32) (result i32) | |
(define BOTHRAM (i32.const 3)) | |
(i32.load8_u | |
;; If LORAM is high and HIRAM is high, ROM is swapped in | |
(if (result i32) | |
(i32.eq (i32.and (i32.load CPUPORT) BOTHRAM) BOTHRAM) | |
(then | |
(i32.add (i32.and (get_local $addr) (i32.const 0xFFFF)) ROM_START) | |
) | |
(else | |
(i32.and (get_local $addr) (i32.const 0xFFFF)) | |
) | |
) | |
) | |
) | |
(func $r_kernal (param $addr i32) (result i32) | |
(i32.load8_u | |
;; If HIRAM is high, ROM is swapped in | |
(if (result i32) | |
(i32.and (i32.load CPUPORT) HIRAM) | |
(then | |
(i32.add (i32.and (get_local $addr) (i32.const 0xFFFF)) ROM_START) | |
) | |
(else | |
(i32.and (get_local $addr) (i32.const 0xFFFF)) | |
) | |
) | |
) | |
) | |
(func $r_char (param $addr i32) (result i32) | |
(i32.and | |
(i32.const 0xFF) | |
(if (result i32) | |
;; If CHAREN is on and either LORAM or HIRAM is on, read I/O | |
(i32.gt_u (i32.and (i32.load CPUPORT) (i32.const 7)) CHAREN) | |
(then | |
(call $io_r (get_local $addr)) | |
) | |
(else | |
(i32.load8_u | |
;; If CHAREN is off and either LORAM or HIRAM is on, read char ROM | |
(if (result i32) | |
(i32.and | |
(i32.gt_u (i32.and (i32.load CPUPORT) (i32.const 7)) (i32.const 0)) | |
(i32.lt_u (i32.and (i32.load CPUPORT) (i32.const 7)) CHAREN) | |
) | |
(then | |
(i32.add (i32.and (get_local $addr) (i32.const 0xFFFF)) ROM_START) | |
) | |
(else | |
(i32.and (get_local $addr) (i32.const 0xFFFF)) | |
) | |
) | |
) | |
) | |
) | |
) | |
) | |
(type $readfunc (func (param i32) (result i32))) | |
(func $r (param $addr i32) (result i32) | |
(call_indirect (type $readfunc) | |
(get_local $addr) | |
(i32.shr_u | |
(i32.and (get_local $addr) (i32.const 0xF000)) | |
(i32.const 12) | |
) | |
) | |
) | |
(func $w (param $addr i32) (param $val i32) | |
(if | |
(i32.and | |
;; If CHAREN is high, 0xDxxx maps to I/O on write | |
(i32.and (i32.load CPUPORT) CHAREN) | |
(i32.eq (i32.and (get_local $addr) (i32.const 0xF000)) (i32.const 0xD000)) | |
) | |
(then | |
(call $io_w (get_local $addr) (get_local $val)) | |
) | |
(else | |
(i32.store8 | |
(i32.and (get_local $addr) (i32.const 0xFFFF)) | |
(i32.and (get_local $val) (i32.const 0xFF)) | |
) | |
) | |
) | |
) | |
(export "r" (func $r)) | |
(export "w" (func $w)) | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# WAT preprocessor to add "define" support | |
# Imran Nazar, 2023 | |
import sys | |
import numpy as np | |
from sexpdata import load, dumps, Symbol | |
def sscalar(i): | |
return np.isscalar(i) or isinstance(i, Symbol) | |
def tr(sexp, defines): | |
# First pass: Find immediate descendent s-exp's which define macros | |
new_defines = {} | |
for i in sexp: | |
if not sscalar(i): | |
if i[0] == Symbol('define'): | |
new_defines[i[1]] = i[2] | |
# Macros defined at this level override any of the same name higher up | |
merged_defines = defines.copy() | new_defines | |
# Second pass: Replace at this level, recurse if deeper levels encountered | |
return [ | |
merged_defines[i] if (sscalar(i) and merged_defines.get(i)) | |
else i if sscalar(i) | |
else tr(i, merged_defines) | |
for i in sexp | |
if sscalar(i) or i[0] != Symbol('define') | |
] | |
def main(): | |
assert len(sys.argv) == 2, 'Filename not provided' | |
filename = sys.argv[1] | |
print(dumps(tr(load(open(filename)), {}))) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment