commit bd5a5cb

neauoire  ·  2023-08-29 17:47:49 +0000 UTC
parent 54b136b
(uxn.c) Added macros for multi-write
3 files changed,  +390, -13
+373, -0
  1@@ -0,0 +1,373 @@
  2+( Opcode Tester )
  3+
  4+|0013
  5+
  6+	@Zeropage &byte $1 &short $2
  7+
  8+|0100
  9+
 10+	( part 1
 11+		> LIT2: Puts a short on the stack
 12+		> #18 DEO: Write a letter in terminal )
 13+
 14+	LIT2 "kO #18 DEO #18 DEO #0a18 DEO
 15+
 16+	( part 2
 17+		> LITr: Put a byte on return stack
 18+		> LIT: Puts a byte on the stack
 19+		> STH: Move a byte from working stack to return stack
 20+		> STH2r: Move a short from return stack to working stack )
 21+
 22+	LITr "k LIT "O STH STH2r #18 DEO #18 DEO #0a18 DEO
 23+
 24+	( part 3
 25+		> LIT2r: Put a short on return stack
 26+		> DUP: Duplicate byte
 27+		> ADDr: Add bytes on return stack )
 28+
 29+	LIT2r "k 4d #01 DUP STH ADDr STH ADDr STH2r #18 DEO #18 DEO #0a18 DEO
 30+
 31+	( part 4
 32+		> JSI: Subroutine to relative absolute address
 33+		> JMP2r: Jumps to absolute address on return stack )
 34+
 35+	subroutine
 36+
 37+	( part 5
 38+		> POP2: Removes a short from the stack
 39+		> INC2: Increments short on stack
 40+		> LDAk: Non-destructive load byte from absolute address
 41+		> JCI: Conditional subroutine to relative absolute address )
 42+
 43+	;Dict/ok pstr #0a18 DEO
 44+
 45+	( part 6
 46+		> GTH2k: Non-destructive greater-than short
 47+		> LDA2k: Non-destructive load short from absolute address
 48+		> STA2: Store short at absolute address )
 49+
 50+	LIT2r 0000
 51+	;tests/end ;tests
 52+	&l
 53+		run-test STH ADDr
 54+		INC2 INC2 GTH2k ?&l
 55+	POP2 POP2
 56+	STH2r ;Dict/done pstr
 57+
 58+	( halt )
 59+
 60+	#010f DEO
 61+
 62+BRK
 63+
 64+@run-test ( addr* -- addr* f )
 65+
 66+	LDA2k JSR2 DUP ?&pass
 67+		;Dict/failed pstr
 68+		[ LIT2 &name $2 ] pstr #0a18 DEO JMP2r
 69+		&pass
 70+
 71+JMP2r
 72+
 73+@set ( name* -- f )
 74+
 75+	;run-test/name STA2 #01
 76+
 77+JMP2r
 78+
 79+@pstr ( str* -- )
 80+
 81+	LDAk ?&w POP2 JMP2r
 82+	&w LDAk #18 DEO INC2 LDAk ?&w
 83+	POP2
 84+
 85+JMP2r
 86+
 87+@tests
 88+=op-equ [
 89+	=op-equ/a =op-equ/b =op-equ/c =op-equ/d
 90+	=op-equ/e =op-equ/f =op-equ/g =op-equ/h ]
 91+=op-neq [
 92+	=op-neq/a =op-neq/b =op-neq/c =op-neq/d
 93+	=op-neq/e =op-neq/f =op-neq/g =op-neq/h ]
 94+=op-gth [
 95+	=op-gth/a =op-gth/b =op-gth/c =op-gth/d
 96+	=op-gth/e =op-gth/f =op-gth/g =op-gth/h ]
 97+=op-lth [
 98+	=op-lth/a =op-lth/b =op-lth/c =op-lth/d
 99+	=op-lth/e =op-lth/f =op-lth/g =op-lth/h ]
100+=op-add [
101+	=op-add/a =op-add/b =op-add/c =op-add/d
102+	=op-add/e =op-add/f =op-add/g =op-add/h ]
103+=op-sub [
104+	=op-sub/a =op-sub/b =op-sub/c =op-sub/d
105+	=op-sub/e =op-sub/f =op-sub/g =op-sub/h ]
106+=op-mul [
107+	=op-mul/a =op-mul/b =op-mul/c =op-mul/d
108+	=op-mul/e =op-mul/f =op-mul/g =op-mul/h ]
109+=op-div [
110+	=op-div/a =op-div/b =op-div/c =op-div/d
111+	=op-div/e =op-div/f =op-div/g =op-div/h ]
112+=op-inc [
113+	=op-inc/a =op-inc/b =op-inc/c =op-inc/d
114+	=op-inc/e =op-inc/f =op-inc/g =op-inc/h ]
115+=op-pop [
116+	=op-pop/a =op-pop/b =op-pop/c =op-pop/d
117+	=op-pop/e =op-pop/f =op-pop/g =op-pop/h ]
118+=op-dup [
119+	=op-dup/a =op-dup/b ]
120+=op-nip [
121+	=op-nip/a =op-nip/b =op-nip/c =op-nip/d ]
122+=op-swp [
123+	=op-swp/a =op-swp/b ]
124+=op-ovr [
125+	=op-ovr/a =op-ovr/b ]
126+=op-rot [
127+	=op-rot/a =op-rot/b ]
128+=op-and [
129+	=op-and/a =op-and/b =op-and/c =op-and/d
130+	=op-and/e =op-and/f =op-and/g =op-and/h ]
131+=op-ora [
132+	=op-ora/a =op-ora/b =op-ora/c =op-ora/d
133+	=op-ora/e =op-ora/f =op-ora/g =op-ora/h ]
134+=op-eor [
135+	=op-eor/a =op-eor/b =op-eor/c =op-eor/d
136+	=op-eor/e =op-eor/f =op-eor/g =op-eor/h ]
137+=op-sft [
138+	=op-sft/a =op-sft/b =op-sft/c =op-sft/d
139+	=op-sft/e =op-sft/f =op-sft/g =op-sft/h ]
140+=op-stz [
141+	=op-stz/a =op-stz/b =op-stz/c =op-stz/d ]
142+=op-str [
143+	=op-str/a =op-str/b =op-str/c =op-str/d ]
144+=op-sta [
145+	=op-sta/a =op-sta/b =op-sta/c =op-sta/d ]
146+=op-jmp [
147+	=op-jmp/a =op-jmp/b ]
148+=op-jcn [
149+	=op-jcn/a =op-jcn/b =op-jcn/c =op-jcn/d ]
150+=op-jsr [
151+	=op-jsr/a =op-jsr/b ]
152+=op-sth [
153+	=op-sth/a =op-sth/b ]
154+=op-jci [
155+	=op-jci/a =op-jci/b =op-jci/c ]
156+=op-jmi [
157+	=op-jmi/a ]
158+=op-jsi [
159+	=op-jsi/a =op-jsi/b ]
160+	&end
161+
162+@op-equ ;Dict/equ !set
163+	&a #f8 #f8 EQU [ #01 ] EQU JMP2r
164+	&b #01 #01 EQU [ #01 ] EQU JMP2r
165+	&c #f8 #01 EQU [ #00 ] EQU JMP2r
166+	&d #00 #ff EQU [ #00 ] EQU JMP2r
167+	&e #f801 #f801 EQU2 [ #01 ] EQU JMP2r
168+	&f #01f8 #01f8 EQU2 [ #01 ] EQU JMP2r
169+	&g #f801 #01f8 EQU2 [ #00 ] EQU JMP2r ( HERE )
170+	&h #01f8 #f801 EQU2 [ #00 ] EQU JMP2r
171+@op-neq ;Dict/neq !set
172+	&a #f8 #f8 NEQ [ #00 ] EQU JMP2r
173+	&b #01 #01 NEQ [ #00 ] EQU JMP2r
174+	&c #f8 #01 NEQ [ #01 ] EQU JMP2r
175+	&d #01 #f8 NEQ [ #01 ] EQU JMP2r
176+	&e #f801 #f801 NEQ2 [ #00 ] EQU JMP2r
177+	&f #01f8 #01f8 NEQ2 [ #00 ] EQU JMP2r
178+	&g #f801 #01f8 NEQ2 [ #01 ] EQU JMP2r
179+	&h #01f8 #f801 NEQ2 [ #01 ] EQU JMP2r
180+@op-gth ;Dict/gth !set
181+	&a #f8 #f8 GTH [ #00 ] EQU JMP2r
182+	&b #01 #01 GTH [ #00 ] EQU JMP2r
183+	&c #f8 #01 GTH [ #01 ] EQU JMP2r
184+	&d #01 #f8 GTH [ #00 ] EQU JMP2r
185+	&e #f801 #f801 GTH2 [ #00 ] EQU JMP2r
186+	&f #01f8 #01f8 GTH2 [ #00 ] EQU JMP2r
187+	&g #f801 #01f8 GTH2 [ #01 ] EQU JMP2r
188+	&h #01f8 #f801 GTH2 [ #00 ] EQU JMP2r
189+@op-lth ;Dict/lth !set
190+	&a #f8 #f8 LTH [ #00 ] EQU JMP2r
191+	&b #01 #01 LTH [ #00 ] EQU JMP2r
192+	&c #f8 #01 LTH [ #00 ] EQU JMP2r
193+	&d #01 #ff LTH [ #01 ] EQU JMP2r
194+	&e #f801 #f801 LTH2 [ #00 ] EQU JMP2r
195+	&f #01f8 #01f8 LTH2 [ #00 ] EQU JMP2r
196+	&g #f801 #01f8 LTH2 [ #00 ] EQU JMP2r
197+	&h #01f8 #f801 LTH2 [ #01 ] EQU JMP2r
198+@op-add ;Dict/add !set
199+	&a #ff #00 ADD [ #ff ] EQU JMP2r
200+	&b #01 #ff ADD [ #00 ] EQU JMP2r
201+	&c #ff #ff ADD [ #fe ] EQU JMP2r
202+	&d #12 #34 ADDk ADD ADD [ #8c ] EQU JMP2r
203+	&e #ffff #0000 ADD2 [ #ffff ] EQU2 JMP2r
204+	&f #0001 #ffff ADD2 [ #0000 ] EQU2 JMP2r
205+	&g #ffff #ffff ADD2 [ #fffe ] EQU2 JMP2r
206+	&h #fffe #ffff ADD2 [ #fffd ] EQU2 JMP2r
207+@op-sub ;Dict/sub !set
208+	&a #ff #00 SUB [ #ff ] EQU JMP2r
209+	&b #01 #ff SUB [ #02 ] EQU JMP2r
210+	&c #ff #ff SUB [ #00 ] EQU JMP2r
211+	&d #fe #ff SUB [ #ff ] EQU JMP2r
212+	&e #ffff #0000 SUB2 [ #ffff ] EQU2 JMP2r
213+	&f #0001 #ffff SUB2 [ #0002 ] EQU2 JMP2r
214+	&g #ffff #ffff SUB2 [ #0000 ] EQU2 JMP2r
215+	&h #fffe #ffff SUB2 [ #ffff ] EQU2 JMP2r
216+@op-mul ;Dict/mul !set
217+	&a #00 #01 MUL [ #00 ] EQU JMP2r
218+	&b #3f #e7 MUL [ #d9 ] EQU JMP2r
219+	&c #37 #3f MUL [ #89 ] EQU JMP2r
220+	&d #10 #02 MUL [ #20 ] EQU JMP2r
221+	&e #1000 #0003 MUL2 [ #3000 ] EQU2 JMP2r
222+	&f #abcd #1234 MUL2 [ #4fa4 ] EQU2 JMP2r
223+	&g #8000 #0200 MUL2 [ #0000 ] EQU2 JMP2r
224+	&h #2222 #0003 MUL2 [ #6666 ] EQU2 JMP2r
225+@op-div ;Dict/div !set
226+	&a #10 #02 DIV [ #08 ] EQU JMP2r
227+	&b #20 #20 DIV [ #01 ] EQU JMP2r
228+	&c #34 #01 DIV [ #34 ] EQU JMP2r
229+	&d #02 #ef DIV [ #00 ] EQU JMP2r
230+	&e #1000 #0040 DIV2 [ #0040 ] EQU2 JMP2r
231+	&f #abcd #1234 DIV2 [ #0009 ] EQU2 JMP2r
232+	&g #8000 #0200 DIV2 [ #0040 ] EQU2 JMP2r
233+	&h #2222 #0003 DIV2 [ #0b60 ] EQU2 JMP2r
234+@op-inc ;Dict/inc !set
235+	&a #01 INC [ #02 ] EQU JMP2r
236+	&b #ff INC [ #00 ] EQU JMP2r
237+	&c #fe INC [ #ff ] EQU JMP2r
238+	&d #00 INC [ #01 ] EQU JMP2r
239+	&e #0001 INC2 [ #0002 ] EQU2 JMP2r
240+	&f #ffff INC2 [ #0000 ] EQU2 JMP2r
241+	&g #fffe INC2 [ #ffff ] EQU2 JMP2r
242+	&h #0000 INC2 [ #0001 ] EQU2 JMP2r
243+@op-pop ;Dict/pop !set
244+	&a #0a #0b POP [ #0a ] EQU JMP2r
245+	&b #0a #0b #0c POP POP [ #0a ] EQU JMP2r
246+	&c #0a #0b #0c ADD POP [ #0a ] EQU JMP2r
247+	&d #0a #0b #0c POP ADD [ #15 ] EQU JMP2r
248+	&e #0a0b #0c0d POP2 [ #0a0b ] EQU2 JMP2r
249+	&f #0a0b #0c0d #0e0f POP2 POP2 [ #0a0b ] EQU2 JMP2r
250+	&g #0a0b #0c0d #0e0f ADD2 POP2 [ #0a0b ] EQU2 JMP2r
251+	&h #0a0b #0c0d #0e0f POP2 ADD2 [ #1618 ] EQU2 JMP2r
252+@op-dup ;Dict/dup !set
253+	&a #0a #0b DUP ADD ADD [ #20 ] EQU JMP2r
254+	&b #0a0b DUP2 ADD2 [ #1416 ] EQU2 JMP2r
255+@op-nip ;Dict/nip !set
256+	&a #12 #34 #56 NIP ADD [ #68 ] EQU JMP2r
257+	&b #12 #34 #56 NIPk ADD2 ADD [ #f2 ] EQU JMP2r
258+	&c #1234 #5678 #9abc NIP2 ADD2 [ #acf0 ] EQU2 JMP2r
259+	&d #1234 #5678 #9abc NIP2k ADD2 ADD2 ADD2 [ #9e24 ] EQU2 JMP2r
260+@op-swp ;Dict/swp !set
261+	&a #02 #10 SWP DIV [ #08 ] EQU JMP2r
262+	&b #0a0b #0c0d SWP2 NIP2 [ #0a0b ] EQU2 JMP2r
263+@op-ovr ;Dict/ovr !set
264+	&a #02 #10 OVR DIV ADD [ #0a ] EQU JMP2r
265+	&b #0a0b #0c0d OVR2 NIP2 ADD2 [ #1416 ] EQU2 JMP2r
266+@op-rot ;Dict/rot !set
267+	&a #02 #04 #10 ROT DIV ADD [ #0c ] EQU JMP2r
268+	&b #0a0b #0c0d #0c0f ROT2 ADD2 NIP2 [ #161a ] EQU2 JMP2r
269+@op-and ;Dict/and !set
270+	&a #fc #3f AND [ #3c ] EQU JMP2r
271+	&b #f0 #0f AND [ #00 ] EQU JMP2r
272+	&c #ff #3c AND [ #3c ] EQU JMP2r
273+	&d #02 #03 AND [ #02 ] EQU JMP2r
274+	&e #f0f0 #00f0 AND2 [ #00f0 ] EQU2 JMP2r
275+	&f #aaaa #5555 AND2 [ #0000 ] EQU2 JMP2r
276+	&g #ffff #1234 AND2 [ #1234 ] EQU2 JMP2r
277+	&h #abcd #0a0c AND2 [ #0a0c ] EQU2 JMP2r
278+@op-ora ;Dict/ora !set
279+	&a #0f #f0 ORA [ #ff ] EQU JMP2r
280+	&b #ab #cd ORA [ #ef ] EQU JMP2r
281+	&c #12 #34 ORA [ #36 ] EQU JMP2r
282+	&d #88 #10 ORA [ #98 ] EQU JMP2r
283+	&e #0f0f #f0f0 ORA2 [ #ffff ] EQU2 JMP2r
284+	&f #abab #cdcd ORA2 [ #efef ] EQU2 JMP2r
285+	&g #1122 #1234 ORA2 [ #1336 ] EQU2 JMP2r
286+	&h #8888 #1000 ORA2 [ #9888 ] EQU2 JMP2r
287+@op-eor ;Dict/eor !set
288+	&a #00 #00 EOR [ #00 ] EQU JMP2r
289+	&b #ff #00 EOR [ #ff ] EQU JMP2r
290+	&c #aa #55 EOR [ #ff ] EQU JMP2r
291+	&d #ff #ff EOR [ #00 ] EQU JMP2r
292+	&e #ffff #ff00 EOR2 [ #00ff ] EQU2 JMP2r
293+	&f #aaaa #5555 EOR2 [ #ffff ] EQU2 JMP2r
294+	&g #1122 #1234 EOR2 [ #0316 ] EQU2 JMP2r
295+	&h #8888 #1000 EOR2 [ #9888 ] EQU2 JMP2r
296+@op-sft ;Dict/sft !set
297+	&a #ff #08 SFT [ #00 ] EQU JMP2r
298+	&b #ff #e0 SFT [ #00 ] EQU JMP2r
299+	&c #ff #11 SFT [ #fe ] EQU JMP2r
300+	&d #ff #12 SFT [ #7e ] EQU JMP2r
301+	&e #ffff #01 SFT2 [ #7fff ] EQU2 JMP2r
302+	&f #ffff #70 SFT2 [ #ff80 ] EQU2 JMP2r
303+	&g #ffff #7e SFT2 [ #0180 ] EQU2 JMP2r
304+	&h #ffff #e3 SFT2 [ #c000 ] EQU2 JMP2r
305+@op-stz ;Dict/stz !set
306+	&a #ab .Zeropage/byte STZ .Zeropage/byte LDZ [ #ab ] EQU JMP2r
307+	&b #cd .Zeropage/byte STZ .Zeropage/byte LDZ [ #cd ] EQU JMP2r
308+	&c #1234 .Zeropage/short STZ2 .Zeropage/short LDZ2 [ #1234 ] EQU2 JMP2r
309+	&d #5678 .Zeropage/short STZ2 .Zeropage/short LDZ2 [ #5678 ] EQU2 JMP2r
310+@op-str ;Dict/str !set
311+	[ LIT &before1 $1 ] [ LIT2 &before2 $2 ]
312+	&a #22 ,&before1 STR ,&before1 LDR [ #22 ] EQU JMP2r
313+	&b #ef ,&after1 STR ,&after1 LDR [ #ef ] EQU JMP2r
314+	&c #1234 ,&before2 STR2 ,&before2 LDR2 [ #1234 ] EQU2 JMP2r
315+	&d #5678 ,&after2 STR2 ,&after2 LDR2 [ #5678 ] EQU2 JMP2r
316+	[ LIT &after1 $1 ] [ LIT2 &after2 $2 ]
317+@op-sta ;Dict/sta !set
318+	&a #34 ;Absolute/byte STA ;Absolute/byte LDA [ #34 ] EQU JMP2r
319+	&b #56 ;Absolute/byte STA ;Absolute/byte LDA [ #56 ] EQU JMP2r
320+	&c #1234 ;Absolute/short STA2 ;Absolute/short LDA2 [ #1234 ] EQU2 JMP2r
321+	&d #5678 ;Absolute/short STA2 ;Absolute/short LDA2 [ #5678 ] EQU2 JMP2r
322+@op-jmp ;Dict/jmp !set
323+	&a #12 #34 ,&reljmp JMP SWP &reljmp POP [ #12 ] EQU JMP2r
324+	&b #56 #78 ;&absjmp JMP2 SWP &absjmp POP [ #56 ] EQU JMP2r
325+@op-jcn ;Dict/jcn !set
326+	&a #23 #01 ,&reljcn-y JCN INC &reljcn-y [ #23 ] EQU JMP2r
327+	&b #23 #00 ,&reljcn-n JCN INC &reljcn-n [ #24 ] EQU JMP2r
328+	&c #23 #01 ;&absjcn-y JCN2 INC &absjcn-y [ #23 ] EQU JMP2r
329+	&d #23 #00 ;&absjcn-n JCN2 INC &absjcn-n [ #24 ] EQU JMP2r
330+@op-jsr ;Dict/jsr !set
331+	&a #1234 #5678 ,&routine JSR [ #68ac ] EQU2 JMP2r
332+	&b #12 #34 ;routine JSR2 [ #46 ] EQU JMP2r
333+	&routine ADD2 JMP2r
334+@op-sth ;Dict/sth !set
335+	&a #0a STH #0b STH ADDr STHr [ #15 ] EQU JMP2r
336+	&b #000a STH2 #000b STH2 ADD2r STH2r [ #0015 ] EQU2 JMP2r
337+@op-jci ;Dict/jci !set
338+	&before #01 JMP2r
339+	&a #01 ?&skip-a #00 JMP2r &skip-a #01 JMP2r
340+	&b #00 ?&skip-b #01 JMP2r &skip-b #00 JMP2r
341+	&c #01 ?&before #00 JMP2r
342+@op-jmi ;Dict/jmi !set
343+	&a !&skip-a #00 JMP2r &skip-a #01 JMP2r
344+@op-jsi ;Dict/jsi !set
345+	&a #02 #04 routine #06 EQU JMP2r
346+	&b ;&return special &return JMP2r
347+
348+@special ( routine* -- f )
349+
350+	( test the stack order )
351+	DUP2 STH2kr EQU2
352+	ROT ROT DUP2r STHr STHr SWP EQU2 AND
353+
354+JMP2r
355+
356+@routine ( a b -- c ) ADD JMP2r
357+@subroutine ( -- ) LIT2 "kO #18 DEO #18 DEO #0a18 DEO JMP2r
358+@Absolute &byte $1 &short $2
359+@phex ( short* -- ) SWP phex/b &b ( byte -- ) DUP #04 SFT phex/c &c ( char -- ) #0f AND DUP #09 GTH #27 MUL ADD #30 ADD #18 DEO JMP2r
360+
361+@Dict [
362+	&ok "Ok $1
363+	&done "Tests 20 "Complete. 0a $1
364+	&failed "-- 20 "failed: 20 $1
365+	&equ "EQU $1 &neq "NEQ $1 &gth "GTH $1 &lth "LTH $1
366+	&add "ADD $1 &sub "SUB $1 &mul "MUL $1 &div "DIV $1
367+	&inc "INC $1 &pop "POP $1 &dup "DUP $1 &nip "NIP $1
368+	&swp "SWP $1 &ovr "OVR $1 &rot "ROT $1
369+	&and "AND $1 &ora "ORA $1 &eor "EOR $1 &sft "SFT $1
370+	&stz "STZ $1 &str "STR $1 &sta "STA $1
371+	&jmp "JMP $1 &jcn "JCN $1 &jsr "JSR $1 &sth "STH $1
372+	&jmi "JMI $1 &jci "JCI $1 &jsi "JSI $1
373+]
374+
+2, -2
 1@@ -16,8 +16,8 @@ rom:
 2 run: bin/uxnasm bin/uxncli bin/uxn11 rom
 3 	@ ./bin/uxn11 bin/polycat.rom
 4 cli: bin/uxnasm bin/uxncli
 5-	@ ./bin/uxnasm etc/link.tal bin/link.rom
 6-	@ ./bin/uxncli bin/link.rom
 7+	@ ./bin/uxnasm etc/opctest.tal bin/opctest.rom
 8+	@ ./bin/uxncli bin/opctest.rom
 9 test: bin/uxnasm bin/uxncli bin/uxn11
10 	@ ./bin/uxnasm && ./bin/uxncli && ./bin/uxn11 && ./bin/uxnasm -v && ./bin/uxncli -v && ./bin/uxn11 -v
11 install: bin/uxnasm bin/uxncli bin/uxn11
+15, -11
 1@@ -28,8 +28,12 @@ WITH REGARD TO THIS SOFTWARE.
 2 #define HALT(c)   { return emu_halt(u, ins, c, pc - 1); }
 3 #define FLIP      { s = ins & 0x40 ? &u->wst : &u->rst; }
 4 #define SET(x, y) { r = s->ptr; if(x > r) HALT(1) r += (x & k) + y; if(r > 254) HALT(2) ptr = s->dat + r - 1; s->ptr = r; }
 5-#define PUT1(v)   { *(ptr--) = v; }
 6-#define PUT2(v)   { r = (v); *(ptr--) = r; *(ptr--) = r >> 8; }
 7+#define PUT1(a)         { *(ptr) = a; }
 8+#define PUT1x2(a, b)    { *(ptr) = a; *(ptr - 1) = b; }
 9+#define PUT1x3(a, b, c) { *(ptr) = a; *(ptr - 1) = b; *(ptr - 2) = c; }
10+#define PUT2(a)         { POKE2(ptr - 1, a) }
11+#define PUT2x2(a, b)    { POKE2(ptr - 1, a) POKE2(ptr - 3, b) }
12+#define PUT2x3(a, b, c) { POKE2(ptr - 1, a) POKE2(ptr - 3, b) POKE2(ptr - 5, c) }
13 
14 int
15 uxn_eval(Uxn *u, Uint16 pc)
16@@ -57,14 +61,14 @@ uxn_eval(Uxn *u, Uint16 pc)
17 			case 0x22: /* POP2 */                 SET(2,-2) break;
18 			case 0x03: /* NIP  */ t=T;            SET(2,-1) PUT1(t) break;
19 			case 0x23: /* NIP2 */ t=T2;           SET(4,-2) PUT2(t) break;
20-			case 0x04: /* SWP  */ t=T;n=N;        SET(2, 0) PUT1(n) PUT1(t) break;
21-			case 0x24: /* SWP2 */ t=T2;n=N2;      SET(4, 0) PUT2(n) PUT2(t) break;
22-			case 0x05: /* ROT  */ t=T;n=N;l=L;    SET(3, 0) PUT1(l) PUT1(t) PUT1(n) break;
23-			case 0x25: /* ROT2 */ t=T2;n=N2;l=L2; SET(6, 0) PUT2(l) PUT2(t) PUT2(n) break;
24-			case 0x06: /* DUP  */ t=T;            SET(1, 1) PUT1(t) PUT1(t) break;
25-			case 0x26: /* DUP2 */ t=T2;           SET(2, 2) PUT2(t) PUT2(t) break;
26-			case 0x07: /* OVR  */ t=T;n=N;        SET(2, 1) PUT1(n) PUT1(t) PUT1(n) break;
27-			case 0x27: /* OVR2 */ t=T2;n=N2;      SET(4, 2) PUT2(n) PUT2(t) PUT2(n) break;
28+			case 0x04: /* SWP  */ t=T;n=N;        SET(2, 0) PUT1x2(n, t) break;
29+			case 0x24: /* SWP2 */ t=T2;n=N2;      SET(4, 0) PUT2x2(n, t) break;
30+			case 0x05: /* ROT  */ t=T;n=N;l=L;    SET(3, 0) PUT1x3(l, t, n) break;
31+			case 0x25: /* ROT2 */ t=T2;n=N2;l=L2; SET(6, 0) PUT2x3(l, t, n) break;
32+			case 0x06: /* DUP  */ t=T;            SET(1, 1) PUT1x2(t, t) break;
33+			case 0x26: /* DUP2 */ t=T2;           SET(2, 2) PUT2x2(t, t) break;
34+			case 0x07: /* OVR  */ t=T;n=N;        SET(2, 1) PUT1x3(n, t, n) break;
35+			case 0x27: /* OVR2 */ t=T2;n=N2;      SET(4, 2) PUT2x3(n, t, n) break;
36 			case 0x08: /* EQU  */ t=T;n=N;        SET(2,-1) PUT1(n == t) break;
37 			case 0x28: /* EQU2 */ t=T2;n=N2;      SET(4,-3) PUT1(n == t) break;
38 			case 0x09: /* NEQ  */ t=T;n=N;        SET(2,-1) PUT1(n != t) break;
39@@ -94,7 +98,7 @@ uxn_eval(Uxn *u, Uint16 pc)
40 			case 0x15: /* STA  */ t=T2;n=L;       SET(3,-3) ram[t] = n; break;
41 			case 0x35: /* STA2 */ t=T2;n=N2;      SET(4,-4) POKE2(ram + t, n) break;
42 			case 0x16: /* DEI  */ t=T;            SET(1, 0) PUT1(DEI(t)) break;
43-			case 0x36: /* DEI2 */ t=T;            SET(1, 1) PUT1(DEI(t + 1)) PUT1(DEI(t)) break;
44+			case 0x36: /* DEI2 */ t=T;            SET(1, 1) PUT1x2(DEI(t + 1), DEI(t)) break;
45 			case 0x17: /* DEO  */ t=T;n=N;        SET(2,-2) DEO(t, n) break;
46 			case 0x37: /* DEO2 */ t=T;n=N;l=L;    SET(3,-3) DEO(t, l) DEO((t + 1), n) break;
47 			case 0x18: /* ADD  */ t=T;n=N;        SET(2,-1) PUT1(n + t) break;