summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcolin <colin@cicadas.surf>2024-06-01 10:22:45 -0700
committercolin <colin@cicadas.surf>2024-06-01 10:22:45 -0700
commitc169d4fd94660039be481e41d740983beaa066ae (patch)
tree79d571abf8ef6936aaa5e0eaa43e32fad93f8dd1
parent597e64a252b3d000ac5fd925e2b48d4e7716cb18 (diff)
Add: raw instrs, instrs, and ast skeletal module
-rw-r--r--sarcasm.asd12
-rw-r--r--src/ast.lisp90
-rw-r--r--src/instr.lisp49
-rw-r--r--src/raw-instrs.lisp498
-rw-r--r--src/util.lisp84
5 files changed, 733 insertions, 0 deletions
diff --git a/sarcasm.asd b/sarcasm.asd
new file mode 100644
index 0000000..dc8b4e8
--- /dev/null
+++ b/sarcasm.asd
@@ -0,0 +1,12 @@
+;;;; sarcasm.asd
+
+(asdf:defsystem #:sarcasm
+ :description "WASM runtime in Common Lisp"
+ :author "Colin <colin@cicadas.surf>"
+ :license "GPL3"
+ :version "0.0.1"
+ :depends-on (#:alexandria #:yacc)
+ :pathname "src/"
+ :serial t
+ :components ((:file "util")
+ (:file "ast")))
diff --git a/src/ast.lisp b/src/ast.lisp
new file mode 100644
index 0000000..eef5c05
--- /dev/null
+++ b/src/ast.lisp
@@ -0,0 +1,90 @@
+(defpackage #:sarcasm.ast
+ (:use #:cl)
+ (:import-from #:sarcasm.util #:def/class)
+ (:local-nicknames
+ (#:a #:alexandria-2)
+ (#:util #:sarcasm.util)))
+
+(in-package #:sarcasm.ast)
+
+;;; TYPES
+
+
+
+(deftype i32 ()
+ '(integer 0 #.(expt 2 32)))
+
+(deftype i64 ()
+ '(integer 0 #. (expt 2 64)))
+
+(deftype f32 ()
+ 'single-float)
+
+(deftype f64 ()
+ 'double-float)
+
+(deftype numtype ()
+ '(or i32 i64 f32 f64))
+
+(deftype typeidx ()
+ 'i32)
+
+(deftype vectype ()
+ '(bit-vector 128))
+
+(deftype funcref ()
+ 't)
+
+(deftype externref ()
+ 't)
+
+(deftype reftype ()
+ '(or funcref externref))
+
+(deftype valtype ()
+ '(or numtype vectype reftype))
+
+(defun stack-effect-type-p (thing)
+ "A stack effect type is a two element list of lists of keywords.
+
+It describes the types of values consumed off the stack and returned
+to the stack by instructions."
+ (and (listp thing)
+ (= 2 (length thing))
+ (listp (first thing))
+ (listp (second thing))
+ (every #'keywordp (first thing))
+ (every #'keywordp (second thing))))
+
+(deftype stack-effect-type ()
+ "This is not part of the standard grammar, but appears implicitly in
+the WASM table of instructions found
+
+ https://webassembly.github.io/spec/core/appendix/index-instructions.html
+
+In the `Type` column."
+ '(satisfies stack-effect-type-p))
+
+;;; MODULE-STRUCTURES
+
+(def/class instr ()
+ ((name :prefix :type keyword)
+ (code :prefix :type (vector byte))
+ (type :prefix :type stack-effect-type)))
+
+(def/class numeric-instr (instr))
+
+(def/class func ()
+ (type :prefix :type typeidx)
+ (locals :type (vector valtype))
+ (body :prefix :type expr))
+
+;;; MODULES
+
+(def/class module ()
+ (types funcs tables mems globals elems datas imports exports
+ :type vector :initform (vector))
+ (start :type (or null t) ; TODO: what is this value type?
+ :initform nil))
+
+
diff --git a/src/instr.lisp b/src/instr.lisp
new file mode 100644
index 0000000..a5c94c6
--- /dev/null
+++ b/src/instr.lisp
@@ -0,0 +1,49 @@
+(defpackage #:sarcasm.instr
+ (:use #:cl)
+ (:shadow cl:return cl:if cl:block cl:loop cl:t)
+ (:local-nicknames
+ (#:a #:alexandria-2)))
+
+(in-package #:sarcasm.instr)
+
+(defclass instr () ())
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (defun expand-instr-plist (plist)
+ (destructuring-bind (&key instr code type) plist
+ (let* ((class-name
+ (intern (string-upcase (first instr))))
+ (immediates
+ (cl:loop
+ :for arg :in (rest instr)
+ :for slot-name := (intern (string-upcase arg))
+ :for reader := (intern (format nil "~a-~a" class-name slot-name))
+ :for initarg := (a:make-keyword slot-name)
+ :collect `(,slot-name
+ :reader ,reader
+ :initarg ,initarg
+ :initform (error "~a required" ',slot-name)))))
+ `(defclass ,class-name (instr)
+ ((instr-name
+ :allocation :class
+ :type string
+ :initform ,(first instr)
+ :reader instr-name)
+ (instr-code
+ :allocation :class
+ :type (vector (unsigned-byte 8) ,(length code))
+ :initform (make-array ,(length code)
+ :element-type '(unsigned-byte 8)
+ :initial-contents ',code))
+ (instr-type
+ :allocation :class
+ :type t
+ :initform ',type)
+ ,@immediates))))))
+
+(macrolet ((create-instr-classes (raw)
+ `(progn
+ ,@(mapcar #'expand-instr-plist raw))))
+ (create-instr-classes #.sarcasm.raw-instrs:raw-instrs))
+
+
diff --git a/src/raw-instrs.lisp b/src/raw-instrs.lisp
new file mode 100644
index 0000000..bdbde12
--- /dev/null
+++ b/src/raw-instrs.lisp
@@ -0,0 +1,498 @@
+(defpackage #:sarcasm.raw-instrs
+ (:use :cl)
+ (:export #:raw-instrs))
+
+(in-package #:sarcasm.raw-instrs)
+(defparameter raw-instrs
+ '((:INSTR ("unreachable") :CODE (0) :TYPE ((:|t1*|) (:|t2*|)))
+ (:INSTR ("nop") :CODE (1) :TYPE (NIL NIL))
+ (:INSTR ("block" "Xbt") :CODE (2) :TYPE ((:|t1*|) (:|t2*|)))
+ (:INSTR ("loop" "Xbt") :CODE (3) :TYPE ((:|t1*|) (:|t2*|)))
+ (:INSTR ("if" "Xbt") :CODE (4) :TYPE ((:|t1*| :I32) (:|t2*|)))
+ (:INSTR ("else") :CODE NIL :TYPE NIL) (:INSTR ("end") :CODE NIL :TYPE NIL)
+ (:INSTR ("br" "l") :CODE (12) :TYPE ((:|t1*| :|t*|) (:|t2*|)))
+ (:INSTR ("brif" "l") :CODE (13) :TYPE ((:|t*| :I32) (:|t*|)))
+ (:INSTR ("brtable" "l^*" "l") :CODE (14) :TYPE ((:|t1*| :|t*| :I32) (:|t2*|)))
+ (:INSTR ("return") :CODE (15) :TYPE ((:|t1*| :|t*|) (:|t2*|)))
+ (:INSTR ("call" "x") :CODE (16) :TYPE ((:|t1*|) (:|t2*|)))
+ (:INSTR ("callindirect" "x" "y") :CODE (17) :TYPE ((:|t1*| :I32) (:|t2*|)))
+ (:INSTR ("drop") :CODE (26) :TYPE ((:|t|) NIL))
+ (:INSTR ("select") :CODE (27) :TYPE ((:|t| :|t| :I32) (:|t|)))
+ (:INSTR ("select" "t") :CODE (28) :TYPE ((:|t| :|t| :I32) (:|t|)))
+ (:INSTR ("local.get" "x") :CODE (32) :TYPE (NIL (:|t|)))
+ (:INSTR ("local.set" "x") :CODE (33) :TYPE ((:|t|) NIL))
+ (:INSTR ("local.tee" "x") :CODE (34) :TYPE ((:|t|) (:|t|)))
+ (:INSTR ("global.get" "x") :CODE (35) :TYPE (NIL (:|t|)))
+ (:INSTR ("global.set" "x") :CODE (36) :TYPE ((:|t|) NIL))
+ (:INSTR ("table.get" "x") :CODE (37) :TYPE ((:I32) (:|t|)))
+ (:INSTR ("table.set" "x") :CODE (38) :TYPE ((:I32 :|t|) NIL))
+ (:INSTR ("i32.load" "memarg") :CODE (40) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i64.load" "memarg") :CODE (41) :TYPE ((:I32) (:I64)))
+ (:INSTR ("f32.load" "memarg") :CODE (42) :TYPE ((:I32) (:F32)))
+ (:INSTR ("f64.load" "memarg") :CODE (43) :TYPE ((:I32) (:F64)))
+ (:INSTR ("i32.load8_s" "memarg") :CODE (44) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.load8_u" "memarg") :CODE (45) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.load16_s" "memarg") :CODE (46) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.load16_u" "memarg") :CODE (47) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i64.load8_s" "memarg") :CODE (48) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i64.load8_u" "memarg") :CODE (49) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i64.load16_s" "memarg") :CODE (50) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i64.load16_u" "memarg") :CODE (51) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i64.load32_s" "memarg") :CODE (52) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i64.load32_u" "memarg") :CODE (53) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i32.store" "memarg") :CODE (54) :TYPE ((:I32 :I32) NIL))
+ (:INSTR ("i64.store" "memarg") :CODE (55) :TYPE ((:I32 :I64) NIL))
+ (:INSTR ("f32.store" "memarg") :CODE (56) :TYPE ((:I32 :F32) NIL))
+ (:INSTR ("f64.store" "memarg") :CODE (57) :TYPE ((:I32 :F64) NIL))
+ (:INSTR ("i32.store8" "memarg") :CODE (58) :TYPE ((:I32 :I32) NIL))
+ (:INSTR ("i32.store16" "memarg") :CODE (59) :TYPE ((:I32 :I32) NIL))
+ (:INSTR ("i64.store8" "memarg") :CODE (60) :TYPE ((:I32 :I64) NIL))
+ (:INSTR ("i64.store16" "memarg") :CODE (61) :TYPE ((:I32 :I64) NIL))
+ (:INSTR ("i64.store32" "memarg") :CODE (62) :TYPE ((:I32 :I64) NIL))
+ (:INSTR ("memory.size") :CODE (63) :TYPE (NIL (:I32)))
+ (:INSTR ("memory.grow") :CODE (64) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.const" "i32") :CODE (65) :TYPE (NIL (:I32)))
+ (:INSTR ("i64.const" "i64") :CODE (66) :TYPE (NIL (:I64)))
+ (:INSTR ("f32.const" "f32") :CODE (67) :TYPE (NIL (:F32)))
+ (:INSTR ("f64.const" "f64") :CODE (68) :TYPE (NIL (:F64)))
+ (:INSTR ("i32.eqz") :CODE (69) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.eq") :CODE (70) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.ne") :CODE (71) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.lt_s") :CODE (72) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.lt_u") :CODE (73) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.gt_s") :CODE (74) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.gt_u") :CODE (75) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.le_s") :CODE (76) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.le_u") :CODE (77) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.ge_s") :CODE (78) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.ge_u") :CODE (79) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i64.eqz") :CODE (80) :TYPE ((:I64) (:I32)))
+ (:INSTR ("i64.eq") :CODE (81) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.ne") :CODE (82) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.lt_s") :CODE (83) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.lt_u") :CODE (84) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.gt_s") :CODE (85) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.gt_u") :CODE (86) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.le_s") :CODE (87) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.le_u") :CODE (88) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.ge_s") :CODE (89) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("i64.ge_u") :CODE (90) :TYPE ((:I64 :I64) (:I32)))
+ (:INSTR ("f32.eq") :CODE (91) :TYPE ((:F32 :F32) (:I32)))
+ (:INSTR ("f32.ne") :CODE (92) :TYPE ((:F32 :F32) (:I32)))
+ (:INSTR ("f32.lt") :CODE (93) :TYPE ((:F32 :F32) (:I32)))
+ (:INSTR ("f32.gt") :CODE (94) :TYPE ((:F32 :F32) (:I32)))
+ (:INSTR ("f32.le") :CODE (95) :TYPE ((:F32 :F32) (:I32)))
+ (:INSTR ("f32.ge") :CODE (96) :TYPE ((:F32 :F32) (:I32)))
+ (:INSTR ("f64.eq") :CODE (97) :TYPE ((:F64 :F64) (:I32)))
+ (:INSTR ("f64.ne") :CODE (98) :TYPE ((:F64 :F64) (:I32)))
+ (:INSTR ("f64.lt") :CODE (99) :TYPE ((:F64 :F64) (:I32)))
+ (:INSTR ("f64.gt") :CODE (100) :TYPE ((:F64 :F64) (:I32)))
+ (:INSTR ("f64.le") :CODE (101) :TYPE ((:F64 :F64) (:I32)))
+ (:INSTR ("f64.ge") :CODE (102) :TYPE ((:F64 :F64) (:I32)))
+ (:INSTR ("i32.clz") :CODE (103) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.ctz") :CODE (104) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.popcnt") :CODE (105) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.add") :CODE (106) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.sub") :CODE (107) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.mul") :CODE (108) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.div_s") :CODE (109) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.div_u") :CODE (110) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.rem_s") :CODE (111) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.rem_u") :CODE (112) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.and") :CODE (113) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.or") :CODE (114) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.xor") :CODE (115) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.shl") :CODE (116) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.shr_s") :CODE (117) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.shr_u") :CODE (118) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.rotl") :CODE (119) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i32.rotr") :CODE (120) :TYPE ((:I32 :I32) (:I32)))
+ (:INSTR ("i64.clz") :CODE (121) :TYPE ((:I64) (:I64)))
+ (:INSTR ("i64.ctz") :CODE (122) :TYPE ((:I64) (:I64)))
+ (:INSTR ("i64.popcnt") :CODE (123) :TYPE ((:I64) (:I64)))
+ (:INSTR ("i64.add") :CODE (124) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.sub") :CODE (125) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.mul") :CODE (126) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.div_s") :CODE (127) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.div_u") :CODE (128) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.rem_s") :CODE (129) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.rem_u") :CODE (130) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.and") :CODE (131) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.or") :CODE (132) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.xor") :CODE (133) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.shl") :CODE (134) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.shr_s") :CODE (135) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.shr_u") :CODE (136) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.rotl") :CODE (137) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("i64.rotr") :CODE (138) :TYPE ((:I64 :I64) (:I64)))
+ (:INSTR ("f32.abs") :CODE (139) :TYPE ((:F32) (:F32)))
+ (:INSTR ("f32.neg") :CODE (140) :TYPE ((:F32) (:F32)))
+ (:INSTR ("f32.ceil") :CODE (141) :TYPE ((:F32) (:F32)))
+ (:INSTR ("f32.floor") :CODE (142) :TYPE ((:F32) (:F32)))
+ (:INSTR ("f32.trunc") :CODE (143) :TYPE ((:F32) (:F32)))
+ (:INSTR ("f32.nearest") :CODE (144) :TYPE ((:F32) (:F32)))
+ (:INSTR ("f32.sqrt") :CODE (145) :TYPE ((:F32) (:F32)))
+ (:INSTR ("f32.add") :CODE (146) :TYPE ((:F32 :F32) (:F32)))
+ (:INSTR ("f32.sub") :CODE (147) :TYPE ((:F32 :F32) (:F32)))
+ (:INSTR ("f32.mul") :CODE (148) :TYPE ((:F32 :F32) (:F32)))
+ (:INSTR ("f32.div") :CODE (149) :TYPE ((:F32 :F32) (:F32)))
+ (:INSTR ("f32.fmin") :CODE (150) :TYPE ((:F32 :F32) (:F32)))
+ (:INSTR ("f32.fmax") :CODE (151) :TYPE ((:F32 :F32) (:F32)))
+ (:INSTR ("f32.copysign") :CODE (152) :TYPE ((:F32 :F32) (:F32)))
+ (:INSTR ("f64.abs") :CODE (153) :TYPE ((:F64) (:F64)))
+ (:INSTR ("f64.neg") :CODE (154) :TYPE ((:F64) (:F64)))
+ (:INSTR ("f64.ceil") :CODE (155) :TYPE ((:F64) (:F64)))
+ (:INSTR ("f64.floor") :CODE (156) :TYPE ((:F64) (:F64)))
+ (:INSTR ("f64.trunc") :CODE (157) :TYPE ((:F64) (:F64)))
+ (:INSTR ("f64.nearest") :CODE (158) :TYPE ((:F64) (:F64)))
+ (:INSTR ("f64.sqrt") :CODE (159) :TYPE ((:F64) (:F64)))
+ (:INSTR ("f64.add") :CODE (160) :TYPE ((:F64 :F64) (:F64)))
+ (:INSTR ("f64.sub") :CODE (161) :TYPE ((:F64 :F64) (:F64)))
+ (:INSTR ("f64.mul") :CODE (162) :TYPE ((:F64 :F64) (:F64)))
+ (:INSTR ("f64.div") :CODE (163) :TYPE ((:F64 :F64) (:F64)))
+ (:INSTR ("f64.fmin") :CODE (164) :TYPE ((:F64 :F64) (:F64)))
+ (:INSTR ("f64.fmax") :CODE (165) :TYPE ((:F64 :F64) (:F64)))
+ (:INSTR ("f64.copysign") :CODE (166) :TYPE ((:F64 :F64) (:F64)))
+ (:INSTR ("i32.wrap_i64") :CODE (167) :TYPE ((:I64) (:I32)))
+ (:INSTR ("i32.trunc_f32k_s") :CODE (168) :TYPE ((:F32) (:I32)))
+ (:INSTR ("i32.trunc_f32k_u") :CODE (169) :TYPE ((:F32) (:I32)))
+ (:INSTR ("i32.trunc_f64k_s") :CODE (170) :TYPE ((:F64) (:I32)))
+ (:INSTR ("i32.trunc_f64k_u") :CODE (171) :TYPE ((:F64) (:I32)))
+ (:INSTR ("i64.extend_i32k_s") :CODE (172) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i64.extend_i32k_u") :CODE (173) :TYPE ((:I32) (:I64)))
+ (:INSTR ("i64.trunc_f32k_s") :CODE (174) :TYPE ((:F32) (:I64)))
+ (:INSTR ("i64.trunc_f32k_u") :CODE (175) :TYPE ((:F32) (:I64)))
+ (:INSTR ("i64.trunc_f64k_s") :CODE (176) :TYPE ((:F64) (:I64)))
+ (:INSTR ("i64.trunc_f64k_u") :CODE (177) :TYPE ((:F64) (:I64)))
+ (:INSTR ("f32.convert_i32k_s") :CODE (178) :TYPE ((:I32) (:F32)))
+ (:INSTR ("f32.convert_i32k_u") :CODE (179) :TYPE ((:I32) (:F32)))
+ (:INSTR ("f32.convert_i64k_s") :CODE (180) :TYPE ((:I64) (:F32)))
+ (:INSTR ("f32.convert_i64k_u") :CODE (181) :TYPE ((:I64) (:F32)))
+ (:INSTR ("f32.demote_f64") :CODE (182) :TYPE ((:F64) (:F32)))
+ (:INSTR ("f64.convert_i32k_s") :CODE (183) :TYPE ((:I32) (:F64)))
+ (:INSTR ("f64.convert_i32k_u") :CODE (184) :TYPE ((:I32) (:F64)))
+ (:INSTR ("f64.convert_i64k_s") :CODE (185) :TYPE ((:I64) (:F64)))
+ (:INSTR ("f64.convert_i64k_u") :CODE (186) :TYPE ((:I64) (:F64)))
+ (:INSTR ("f64.promote_f32") :CODE (187) :TYPE ((:F32) (:F64)))
+ (:INSTR ("i32.reinterpret_f32") :CODE (188) :TYPE ((:F32) (:I32)))
+ (:INSTR ("i64.reinterpret_f64") :CODE (189) :TYPE ((:F64) (:I64)))
+ (:INSTR ("f32.reinterpret_i32") :CODE (190) :TYPE ((:I32) (:F32)))
+ (:INSTR ("f64.reinterpret_i64") :CODE (191) :TYPE ((:I64) (:F64)))
+ (:INSTR ("i32.extend8_s") :CODE (192) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i32.extend16_s") :CODE (193) :TYPE ((:I32) (:I32)))
+ (:INSTR ("i64.extend8_s") :CODE (194) :TYPE ((:I64) (:I64)))
+ (:INSTR ("i64.extend16_s") :CODE (195) :TYPE ((:I64) (:I64)))
+ (:INSTR ("i64.extend32_s") :CODE (196) :TYPE ((:I64) (:I64)))
+ (:INSTR ("ref.null" "t") :CODE (208) :TYPE (NIL (:|t|)))
+ (:INSTR ("ref.isnull") :CODE (209) :TYPE ((:|t|) (:I32)))
+ (:INSTR ("ref.func" "x") :CODE (210) :TYPE (NIL (:FUNCREF)))
+ (:INSTR ("i32.trunc_sat_f32k_s") :CODE (252 0) :TYPE ((:F32) (:I32)))
+ (:INSTR ("i32.trunc_sat_f32k_u") :CODE (252 1) :TYPE ((:F32) (:I32)))
+ (:INSTR ("i32.trunc_sat_f64k_s") :CODE (252 2) :TYPE ((:F64) (:I32)))
+ (:INSTR ("i32.trunc_sat_f64k_u") :CODE (252 3) :TYPE ((:F64) (:I32)))
+ (:INSTR ("i64.trunc_sat_f32k_s") :CODE (252 4) :TYPE ((:F32) (:I64)))
+ (:INSTR ("i64.trunc_sat_f32k_u") :CODE (252 5) :TYPE ((:F32) (:I64)))
+ (:INSTR ("i64.trunc_sat_f64k_s") :CODE (252 6) :TYPE ((:F64) (:I64)))
+ (:INSTR ("i64.trunc_sat_f64k_u") :CODE (252 7) :TYPE ((:F64) (:I64)))
+ (:INSTR ("memory.init" "x") :CODE (252 8) :TYPE ((:I32 :I32 :I32) NIL))
+ (:INSTR ("data.drop" "x") :CODE (252 9) :TYPE (NIL NIL))
+ (:INSTR ("memory.copy") :CODE (252 10) :TYPE ((:I32 :I32 :I32) NIL))
+ (:INSTR ("memory.fill") :CODE (252 11) :TYPE ((:I32 :I32 :I32) NIL))
+ (:INSTR ("table.init" "x" "y") :CODE (252 12) :TYPE ((:I32 :I32 :I32) NIL))
+ (:INSTR ("elem.drop" "x") :CODE (252 13) :TYPE (NIL NIL))
+ (:INSTR ("table.copy" "x" "y") :CODE (252 14) :TYPE ((:I32 :I32 :I32) NIL))
+ (:INSTR ("table.grow" "x") :CODE (252 15) :TYPE ((:|t| :I32) (:I32)))
+ (:INSTR ("table.size" "x") :CODE (252 16) :TYPE (NIL (:I32)))
+ (:INSTR ("table.fill" "x") :CODE (252 17) :TYPE ((:I32 :|t| :I32) NIL))
+ (:INSTR ("v128.load" "memarg") :CODE (253 0) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load8x8_s" "memarg") :CODE (253 1) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load8x8_u" "memarg") :CODE (253 2) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load16x4_s" "memarg") :CODE (253 3) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load16x4_u" "memarg") :CODE (253 4) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load32x2_s" "memarg") :CODE (253 5) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load32x2_u" "memarg") :CODE (253 6) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load8_splat" "memarg") :CODE (253 7) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load16_splat" "memarg") :CODE (253 8) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load32_splat" "memarg") :CODE (253 9) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load64_splat" "memarg") :CODE (253 10) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.store" "memarg") :CODE (253 11) :TYPE ((:I32 :V128) NIL))
+ (:INSTR ("v128.vconst" "i128") :CODE (253 12) :TYPE (NIL (:V128)))
+ (:INSTR ("i8x16.shuffle" "laneidx^16") :CODE (253 13) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.swizzle") :CODE (253 14) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.splat") :CODE (253 15) :TYPE ((:I32) (:V128)))
+ (:INSTR ("i16x8.splat") :CODE (253 16) :TYPE ((:I32) (:V128)))
+ (:INSTR ("i32x4.splat") :CODE (253 17) :TYPE ((:I32) (:V128)))
+ (:INSTR ("i64x2.splat") :CODE (253 18) :TYPE ((:I64) (:V128)))
+ (:INSTR ("f32x4.splat") :CODE (253 19) :TYPE ((:F32) (:V128)))
+ (:INSTR ("f64x2.splat") :CODE (253 20) :TYPE ((:F64) (:V128)))
+ (:INSTR ("i8x16.extractlane_s" "laneidx") :CODE (253 21) :TYPE
+ ((:V128) (:I32)))
+ (:INSTR ("i8x16.extractlane_u" "laneidx") :CODE (253 22) :TYPE
+ ((:V128) (:I32)))
+ (:INSTR ("i8x16.replacelane" "laneidx") :CODE (253 23) :TYPE
+ ((:V128 :I32) (:V128)))
+ (:INSTR ("i16x8.extractlane_s" "laneidx") :CODE (253 24) :TYPE
+ ((:V128) (:I32)))
+ (:INSTR ("i16x8.extractlane_u" "laneidx") :CODE (253 25) :TYPE
+ ((:V128) (:I32)))
+ (:INSTR ("i16x8.replacelane" "laneidx") :CODE (253 26) :TYPE
+ ((:V128 :I32) (:V128)))
+ (:INSTR ("i32x4.extractlane" "laneidx") :CODE (253 27) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i32x4.replacelane" "laneidx") :CODE (253 28) :TYPE
+ ((:V128 :I32) (:V128)))
+ (:INSTR ("i64x2.extractlane" "laneidx") :CODE (253 29) :TYPE ((:V128) (:I64)))
+ (:INSTR ("i64x2.replacelane" "laneidx") :CODE (253 30) :TYPE
+ ((:V128 :I64) (:V128)))
+ (:INSTR ("f32x4.extractlane" "laneidx") :CODE (253 31) :TYPE ((:V128) (:F32)))
+ (:INSTR ("f32x4.replacelane" "laneidx") :CODE (253 32) :TYPE
+ ((:V128 :F32) (:V128)))
+ (:INSTR ("f64x2.extractlane" "laneidx") :CODE (253 33) :TYPE ((:V128) (:F64)))
+ (:INSTR ("f64x2.replacelane" "laneidx") :CODE (253 34) :TYPE
+ ((:V128 :F64) (:V128)))
+ (:INSTR ("i8x16.veq") :CODE (253 35) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vne") :CODE (253 36) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vlt_s") :CODE (253 37) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vlt_u") :CODE (253 38) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vgt_s") :CODE (253 39) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vgt_u") :CODE (253 40) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vle_s") :CODE (253 41) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vle_u") :CODE (253 42) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vge_s") :CODE (253 43) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vge_u") :CODE (253 44) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.veq") :CODE (253 45) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vne") :CODE (253 46) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vlt_s") :CODE (253 47) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vlt_u") :CODE (253 48) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vgt_s") :CODE (253 49) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vgt_u") :CODE (253 50) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vle_s") :CODE (253 51) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vle_u") :CODE (253 52) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vge_s") :CODE (253 53) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vge_u") :CODE (253 54) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.veq") :CODE (253 55) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vne") :CODE (253 56) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vlt_s") :CODE (253 57) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vlt_u") :CODE (253 58) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vgt_s") :CODE (253 59) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vgt_u") :CODE (253 60) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vle_s") :CODE (253 61) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vle_u") :CODE (253 62) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vge_s") :CODE (253 63) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vge_u") :CODE (253 64) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.veq") :CODE (253 65) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vne") :CODE (253 66) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vlt") :CODE (253 67) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vgt") :CODE (253 68) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vle") :CODE (253 69) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vge") :CODE (253 70) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.veq") :CODE (253 71) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vne") :CODE (253 72) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vlt") :CODE (253 73) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vgt") :CODE (253 74) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vle") :CODE (253 75) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vge") :CODE (253 76) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("v128.vnot") :CODE (253 77) :TYPE ((:V128) (:V128)))
+ (:INSTR ("v128.vand") :CODE (253 78) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("v128.vandnot") :CODE (253 79) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("v128.vor") :CODE (253 80) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("v128.vxor") :CODE (253 81) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("v128.bitselect") :CODE (253 82) :TYPE ((:V128 :V128 :V128) (:V128)))
+ (:INSTR ("v128.anytrue") :CODE (253 83) :TYPE ((:V128) (:I32)))
+ (:INSTR ("v128.load8_lane" "memarg" "laneidx") :CODE (253 84) :TYPE
+ ((:I32 :V128) (:V128)))
+ (:INSTR ("v128.load16_lane" "memarg" "laneidx") :CODE (253 85) :TYPE
+ ((:I32 :V128) (:V128)))
+ (:INSTR ("v128.load32_lane" "memarg" "laneidx") :CODE (253 86) :TYPE
+ ((:I32 :V128) (:V128)))
+ (:INSTR ("v128.load64_lane" "memarg" "laneidx") :CODE (253 87) :TYPE
+ ((:I32 :V128) (:V128)))
+ (:INSTR ("v128.store8_lane" "memarg" "laneidx") :CODE (253 88) :TYPE
+ ((:I32 :V128) NIL))
+ (:INSTR ("v128.store16_lane" "memarg" "laneidx") :CODE (253 89) :TYPE
+ ((:I32 :V128) NIL))
+ (:INSTR ("v128.store32_lane" "memarg" "laneidx") :CODE (253 90) :TYPE
+ ((:I32 :V128) NIL))
+ (:INSTR ("v128.store64_lane" "memarg" "laneidx") :CODE (253 91) :TYPE
+ ((:I32 :V128) NIL))
+ (:INSTR ("v128.load32_zero" "memarg") :CODE (253 92) :TYPE ((:I32) (:V128)))
+ (:INSTR ("v128.load64_zero" "memarg") :CODE (253 93) :TYPE ((:I32) (:V128)))
+ (:INSTR ("f32x4.vdemote_f64x2_zero") :CODE (253 94) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f64x2.vpromote_low_f32x4") :CODE (253 95) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i8x16.vabs") :CODE (253 96) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i8x16.vneg") :CODE (253 97) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i8x16.vpopcnt") :CODE (253 98) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i8x16.alltrue") :CODE (253 99) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i8x16.bitmask") :CODE (253 100) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i8x16.narrow_i16x8_s") :CODE (253 101) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.narrow_i16x8_u") :CODE (253 102) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vceil") :CODE (253 103) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vfloor") :CODE (253 104) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vtrunc") :CODE (253 105) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vnearest") :CODE (253 106) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i8x16.vshl") :CODE (253 107) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i8x16.vshr_s") :CODE (253 108) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i8x16.vshr_u") :CODE (253 109) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i8x16.vadd") :CODE (253 110) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vadd_sat_s") :CODE (253 111) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vadd_sat_u") :CODE (253 112) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vsub") :CODE (253 113) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vsub_sat_s") :CODE (253 114) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vsub_sat_u") :CODE (253 115) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vceil") :CODE (253 116) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f64x2.vfloor") :CODE (253 117) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i8x16.vmin_s") :CODE (253 118) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vmin_u") :CODE (253 119) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vmax_s") :CODE (253 120) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i8x16.vmax_u") :CODE (253 121) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vtrunc") :CODE (253 122) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i8x16.avgr_u") :CODE (253 123) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.extaddpairwise_i8x16_s") :CODE (253 124) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i16x8.extaddpairwise_i8x16_u") :CODE (253 125) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i32x4.extaddpairwise_i16x8_s") :CODE (253 126) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i32x4.extaddpairwise_i16x8_u") :CODE (253 127) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i16x8.vabs") :CODE (253 128 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i16x8.vneg") :CODE (253 129 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i16x8.q15mulrsat_s") :CODE (253 130 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.alltrue") :CODE (253 131 1) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i16x8.bitmask") :CODE (253 132 1) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i16x8.narrow_i32x4_s") :CODE (253 133 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.narrow_i32x4_u") :CODE (253 134 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vextend_low_i8x16_s") :CODE (253 135 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i16x8.vextend_high_i8x16_s") :CODE (253 136 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i16x8.vextend_low_i8x16_u") :CODE (253 137 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i16x8.vextend_high_i8x16_u") :CODE (253 138 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i16x8.vshl") :CODE (253 139 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i16x8.vshr_s") :CODE (253 140 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i16x8.vshr_u") :CODE (253 141 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i16x8.vadd") :CODE (253 142 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vadd_sat_s") :CODE (253 143 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vadd_sat_u") :CODE (253 144 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vsub") :CODE (253 145 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vsub_sat_s") :CODE (253 146 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vsub_sat_u") :CODE (253 147 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vnearest") :CODE (253 148 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i16x8.vmul") :CODE (253 149 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vmin_s") :CODE (253 150 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vmin_u") :CODE (253 151 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vmax_s") :CODE (253 152 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.vmax_u") :CODE (253 153 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.avgr_u") :CODE (253 155 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.extmul_low_i8x16_s") :CODE (253 156 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.extmul_high_i8x16_s") :CODE (253 157 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.extmul_low_i8x16_u") :CODE (253 158 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i16x8.extmul_high_i8x16_u") :CODE (253 159 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vabs") :CODE (253 160 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i32x4.vneg") :CODE (253 161 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i32x4.alltrue") :CODE (253 163 1) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i32x4.bitmask") :CODE (253 164 1) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i32x4.vextend_low_i16x8_s") :CODE (253 167 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i32x4.vextend_high_i16x8_s") :CODE (253 168 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i32x4.vextend_low_i16x8_u") :CODE (253 169 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i32x4.vextend_high_i16x8_u") :CODE (253 170 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i32x4.vshl") :CODE (253 171 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i32x4.vshr_s") :CODE (253 172 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i32x4.vshr_u") :CODE (253 173 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i32x4.vadd") :CODE (253 174 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vsub") :CODE (253 177 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vmul") :CODE (253 181 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vmin_s") :CODE (253 182 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vmin_u") :CODE (253 183 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vmax_s") :CODE (253 184 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.vmax_u") :CODE (253 185 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.dot_i16x8_s") :CODE (253 186 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.extmul_low_i16x8_s") :CODE (253 188 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.extmul_high_i16x8_s") :CODE (253 189 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.extmul_low_i16x8_u") :CODE (253 190 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.extmul_high_i16x8_u") :CODE (253 191 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vabs") :CODE (253 192 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i64x2.vneg") :CODE (253 193 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i64x2.alltrue") :CODE (253 195 1) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i64x2.bitmask") :CODE (253 196 1) :TYPE ((:V128) (:I32)))
+ (:INSTR ("i64x2.vextend_low_i32x4_s") :CODE (253 199 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i64x2.vextend_high_i32x4_s") :CODE (253 200 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i64x2.vextend_low_i32x4_u") :CODE (253 201 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i64x2.vextend_high_i32x4_u") :CODE (253 202 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i64x2.vshl") :CODE (253 203 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i64x2.vshr_s") :CODE (253 204 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i64x2.vshr_u") :CODE (253 205 1) :TYPE ((:V128 :I32) (:V128)))
+ (:INSTR ("i64x2.vadd") :CODE (253 206 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vsub") :CODE (253 209 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vmul") :CODE (253 213 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.veq") :CODE (253 214 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vne") :CODE (253 215 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vlt_s") :CODE (253 216 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vgt_s") :CODE (253 217 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vle_s") :CODE (253 218 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.vge_s") :CODE (253 219 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.extmul_low_i32x4_s") :CODE (253 220 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.extmul_high_i32x4_s") :CODE (253 221 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.extmul_low_i32x4_u") :CODE (253 222 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("i64x2.extmul_high_i32x4_u") :CODE (253 223 1) :TYPE
+ ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vabs") :CODE (253 224 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vneg") :CODE (253 225 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vsqrt") :CODE (253 227 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vadd") :CODE (253 228 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vsub") :CODE (253 229 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vmul") :CODE (253 230 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vdiv") :CODE (253 231 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vmin") :CODE (253 232 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vmax") :CODE (253 233 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vpmin") :CODE (253 234 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f32x4.vpmax") :CODE (253 235 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vabs") :CODE (253 236 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f64x2.vneg") :CODE (253 237 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f64x2.vsqrt") :CODE (253 239 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f64x2.vadd") :CODE (253 240 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vsub") :CODE (253 241 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vmul") :CODE (253 242 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vdiv") :CODE (253 243 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vmin") :CODE (253 244 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vmax") :CODE (253 245 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vpmin") :CODE (253 246 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("f64x2.vpmax") :CODE (253 247 1) :TYPE ((:V128 :V128) (:V128)))
+ (:INSTR ("i32x4.trunc_sat_f32x4_s") :CODE (253 248 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i32x4.trunc_sat_f32x4_u") :CODE (253 249 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vconvert_i32x4_s") :CODE (253 250 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("f32x4.vconvert_i32x4_u") :CODE (253 251 1) :TYPE ((:V128) (:V128)))
+ (:INSTR ("i32x4.vtrunc_sat_f64x2_s_zero") :CODE (253 252 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("i32x4.vtrunc_sat_f64x2_u_zero") :CODE (253 253 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("f64x2.vconvert_low_i32x4_s") :CODE (253 254 1) :TYPE
+ ((:V128) (:V128)))
+ (:INSTR ("f64x2.vconvert_low_i32x4_u") :CODE (253 255 1) :TYPE
+ ((:V128) (:V128)))))
diff --git a/src/util.lisp b/src/util.lisp
new file mode 100644
index 0000000..5899b36
--- /dev/null
+++ b/src/util.lisp
@@ -0,0 +1,84 @@
+(defpackage #:sarcasm.util
+ (:use #:cl)
+ (:export
+ #:take-until
+ #:def/class))
+
+(in-package #:sarcasm.util)
+
+(defun take-until (pred list)
+ "Returns two values: FRONT BACK.
+
+FRONT contains the first N members X of LIST for which (PRED X) is NIL.
+BACK contains everything after the members of FRONT.
+
+(EQUALP LIST
+ (MULTIPLE-VALUE-BIND (FRONT BACK) (TAKE-UNTIL PRED LIST)
+ (APPEND FRONT BACK))
+
+Is always T."
+ (loop :for (x . back) :on list
+ :for fx? := (funcall pred x)
+ :until fx?
+ :collect x :into front
+ :finally (return (values front (if fx? (cons x back) nil)))))
+
+(defun partition (pred list)
+ "Returns two list values: YES NO.
+
+YES is everything for which PRED is T, NO is everything else."
+ (loop :for e :in list
+ :when (funcall pred e)
+ :collect e :into yes
+ :else
+ :collect e :into no
+ :finally (return (values yes no))))
+
+(defmacro def/class (name (&rest supers) &body slots-and-options)
+ "Define a class.
+
+SLOTS-AND-OPTIONS := (SLOT-SPEC1 ... SLOT-SPECN . CLASS-OPTIONS)
+
+Each SLOT-SPEC is a list of slot names followed by keyword slot
+options, E.g:
+
+(X Y Z :type integer :initarg 0)
+
+Would expand into three slot definitions
+(X :accessor X :initarg :X :type integer :initarg 0)
+(Y :accessor Y :initarg :Y :type integer :initarg 0)
+(Z :accessor Z :initarg :Z :type integer :initarg 0)
+
+CLASS-OPTIONS is a PLIST of class options."
+ (labels
+ ((make-accessor-name (slot &optional prefix?)
+ (if prefix?
+ (intern (format nil "~a-~a" name slot))
+ slot))
+ (singlep (x)
+ (find x '(:prefix) :test #'eq))
+ (parse-slot-spec-expr (expr)
+ " (names ... &key kwargs)"
+ (multiple-value-bind (slot-names kwargs) (take-until #'keywordp expr)
+ (multiple-value-bind (kwargs singles) (partition #'singlep kwargs)
+ (loop
+ :with prefix-accessor? := (find ':prefix singles :test #'eq)
+ :for slot :in slot-names
+ :collect `(,slot
+ :accessor ,(make-accessor-name slot prefix-accessor?)
+ :initarg ,(alexandria:make-keyword slot)
+ ,@kwargs)))))
+
+ (parse-class-options (kwargs)
+ (loop :for (key val . more) :on kwargs :by #'cddr
+ :collect (list key val))))
+
+ (let* ((slot-defs (loop :for expr :in slots-and-options
+ :while (listp expr)
+ :append (parse-slot-spec-expr expr)))
+ (options (parse-class-options
+ (nth-value 1 (take-until #'keywordp slots-and-options)))))
+
+ `(defclass ,name ,supers
+ (,@slot-defs)
+ ,@options))))