-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathans-forth.asm
3974 lines (3468 loc) · 119 KB
/
ans-forth.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;===============================================================================
; _ _ _ ____ _____ _ _ _ ___ _ __
; / \ | \ | / ___| | ___|__ _ __| |_| |__ ( )( _ )/ |/ /_
; / _ \ | \| \___ \ | |_ / _ \| '__| __| '_ \ |/ / _ \| | '_ \
; / ___ \| |\ |___) | | _| (_) | | | |_| | | | | (_) | | (_) |
; /_/ \_\_| \_|____/ |_| \___/|_| \__|_| |_| \___/|_|\___/
;
; A Direct Threaded ANS Forth for the WDC 65C816
;-------------------------------------------------------------------------------
; Copyright (C)2015-2016 HandCoded Software Ltd.
; All rights reserved.
;
; This work is made available under the terms of the Creative Commons
; Attribution-NonCommercial-ShareAlike 4.0 International license. Open the
; following URL to see the details.
;
; http://creativecommons.org/licenses/by-nc-sa/4.0/
;
;===============================================================================
; Notes:
;
; This implementation is designed to run in the 65C816's native mode with both
; the accumulator and index registers in 16-bit mode except when the word needs
; 8-bit memory access.
;
; The DP register is used for the Forth data stack is values can be accessed
; using the direct-page addressing modes. The code uses the same offsets as
; would be used with the stack relative instructions (i.e <1, <3, etc.).
;
; The Y register holds the forth instruction pointer leaving X free for general
; use in words. Some words push Y if they need an extra register.
;
; Some of the high-level definitions are based on Bradford J. Rodriguez's
; CamelForth implementations.
;
;-------------------------------------------------------------------------------
pw 132
inclist on
maclist off
chip 65816
longi off
longa off
include "w65c816.inc"
;===============================================================================
; Macros
;-------------------------------------------------------------------------------
; The LINK macro deposits the link section of a word header automatically
; linking the new word to the last.
WORDZ set 0 ; Word counter
WORD0 equ 0 ; Null address for first word
LINK macro TYPE
dw WORD@<WORDZ> ; Link
db TYPE ; Type
WORDZ set WORDZ+1
WORD@<WORDZ>:
endm
; Deposits a word header containing the name which is linked back to the
; previous word.
;
; The WDC assembler does not handle string parameters to macros very well,
; stopping at the first comma or space in them, so some headers must be
; manually constructed.
NORMAL equ $00
IMMEDIATE equ $80
HEADER macro LEN,NAME,TYPE
LINK TYPE
db LEN,NAME
endm
; The CONTINUE macro is used at the end of a native word to invoke the next
; word pointer.
CONTINUE macro
tyx ; Copy IP to X
iny
iny
jmp (0,x) ; Then execute word
endm
TRAILER macro
LAST_WORD equ WORD@<WORDZ>
endm
;===============================================================================
; Definitions
;-------------------------------------------------------------------------------
USER_SIZE equ 22
DSTACK_SIZE equ 128
RSTACK_SIZE equ 128
TO_IN_OFFSET equ 0
BASE_OFFSET equ 2
BLK_OFFSET equ 4
DP_OFFSET equ 6
LATEST_OFFSET equ 8
SCR_OFFSET equ 10
SOURCEID_OFFSET equ 12 ; Input source flag
STATE_OFFSET equ 14 ; Compiling/Interpreting flag
BUFFER_OFFSET equ 16 ; Address of the input buffer
LENGTH_OFFSET equ 18 ; Length of the input buffer
HP_OFFSET equ 20
TIB_SIZE equ 128
PAD_SIZE equ 48
;===============================================================================
; Data Areas
;-------------------------------------------------------------------------------
page0
org $00
USER_AREA ds USER_SIZE ; User Variables
DSTACK_START equ $0100
DSTACK_END equ DSTACK_START+DSTACK_SIZE
RSTACK_START equ $0180
RSTACK_END equ RSTACK_START+RSTACK_SIZE
data
org $0200
TIB_AREA: ds TIB_SIZE ; Terminal Input Buffer
ds PAD_SIZE ; Pad area
PAD_AREA: ds 0
;===============================================================================
; Forth Entry Point
;-------------------------------------------------------------------------------
FORTH section OFFSET $0400
public Start
Start:
native ; Go to native mode
long_ai ; And all 16-bit registers
lda #RSTACK_END-1 ; Initialise return stack
tcs
lda #DSTACK_END-1 ; .. and data stack
tcd
ldy #COLD ; Then perform COLD start
CONTINUE
COLD:
dw DECIMAL
dw ZERO
dw BLK
dw STORE
dw FALSE
dw STATE
dw STORE
dw DO_LITERAL,NEXT_WORD
dw DP
dw STORE
dw DO_LITERAL,LAST_WORD
dw LATEST
dw STORE
dw CR
dw CR
dw DO_TITLE
dw TYPE
dw CR
dw CR
dw ABORT
;===============================================================================
; System/User Variables
;-------------------------------------------------------------------------------
; #TIB ( -- a-addr )
;
; a-addr is the address of a cell containing the number of characters in the
; terminal input buffer.
HEADER 4,"#TIB",NORMAL
HASH_TIB: jsr DO_CONSTANT
dw $+2
dw TIB_SIZE-2
; >IN ( -- a-addr )
;
; a-addr is the address of a cell containing the offset in characters from the
; start of the input buffer to the start of the parse area.
HEADER 3,">IN",NORMAL
TO_IN: jsr DO_USER
dw TO_IN_OFFSET
; BASE ( -- a-addr )
;
; a-addr is the address of a cell containing the current number-conversion
; radix {{2...36}}.
HEADER 4,"BASE",NORMAL
BASE: jsr DO_USER
dw BASE_OFFSET
; BLK ( -- a-addr )
;
; a-addr is the address of a cell containing zero or the number of the mass-
; storage block being interpreted. If BLK contains zero, the input source is
; not a block and can be identified by SOURCE-ID, if SOURCE-ID is available. An
; ambiguous condition exists if a program directly alters the contents of BLK.
HEADER 3,"BLK",NORMAL
BLK: jsr DO_USER
dw BLK_OFFSET
; (BUFFER)
BUFFER: jsr DO_USER
dw BUFFER_OFFSET
; DP ( -- a-addr )
;
; Dictionary Pointer
HEADER 2,"DP",NORMAL
DP: jsr DO_USER
dw DP_OFFSET
; HP ( -- a-addr )
;
; Hold Pointer
HP: jsr DO_USER
dw HP_OFFSET
; LATEST ( -- a-addr )
HEADER 6,"LATEST",NORMAL
LATEST: jsr DO_USER
dw LATEST_OFFSET
; (LENGTH)
LENGTH: jsr DO_USER
dw LENGTH_OFFSET
; SCR ( -- a-addr )
;
; a-addr is the address of a cell containing the block number of the block most
; recently LISTed.
HEADER 3,"SCR",NORMAL
SCR: jsr DO_USER
dw SCR_OFFSET
; (SOURCE-ID)
SOURCEID: jsr DO_USER
dw SOURCEID_OFFSET
; STATE ( -- a-addr )
;
; a-addr is the address of a cell containing the compilation-state flag. STATE
; is true when in compilation state, false otherwise. The true value in STATE
; is non-zero, but is otherwise implementation-defined.
HEADER 5,"STATE",NORMAL
STATE: jsr DO_USER
dw STATE_OFFSET
; TIB ( -- c-addr )
;
; c-addr is the address of the terminal input buffer.
HEADER 3,"TIB",NORMAL
TIB: jsr DO_CONSTANT
dw TIB_AREA
;===============================================================================
; Constants
;-------------------------------------------------------------------------------
; 0 ( -- 0 )
;
; Push the constant value zero on the stack
HEADER 1,"0",NORMAL
ZERO:
tdc
dec a ; Make space on the stack
dec a
tcd
stz <1 ; And create a zero value
CONTINUE ; Done
; BL ( -- char )
;
; char is the character value for a space.
HEADER 2,"BL",NORMAL
BL:
tdc
dec a ; Make space on the stack
dec a
tcd
lda #' ' ; And save a space value
sta <1
CONTINUE ; Done
; FALSE ( -- false )
;
; Return a false flag.
HEADER 5,"FALSE",NORMAL
FALSE:
tdc
dec a ; Make space on the stack
dec a
tcd
stz <1 ; And create a false value
CONTINUE ; Done
; TRUE ( -- true )
;
; Return a true flag, a single-cell value with all bits set.
HEADER 4,"TRUE",NORMAL
TRUE:
tdc
dec a ; Make space on the stack
dec a
tcd
stz <1 ; And create a true value
dec <1
CONTINUE ; Done
;===============================================================================
; Radix
;-------------------------------------------------------------------------------
; DECIMAL ( -- )
;
; Set the numeric conversion radix to ten (decimal).
HEADER 7,"DECIMAL",NORMAL
DECIMAL: jsr DO_COLON
dw DO_LITERAL,10
dw BASE
dw STORE
dw EXIT
; HEX ( -- )
;
; Set contents of BASE to sixteen.
HEADER 3,"HEX",NORMAL
HEX: jsr DO_COLON
dw DO_LITERAL,16
dw BASE
dw STORE
dw EXIT
;===============================================================================
; Memory Operations
;-------------------------------------------------------------------------------
; ! ( x a-addr -- )
;
; Store x at a-addr.
HEADER 1,"!",NORMAL
STORE:
lda <3 ; Fetch data value
sta (1) ; .. and store
tdc ; Clean up data stack
inc a
inc a
inc a
inc a
tcd
CONTINUE ; Done
; +! ( n|u a-addr -- )
;
; Add n|u to the single-cell number at a-addr.
HEADER 2,"+!",NORMAL
PLUS_STORE:
clc
lda <3 ; Fetch data value
adc (1)
sta (1)
tdc ; Clean up data stack
inc a
inc a
inc a
inc a
tcd
CONTINUE ; Done
; , ( x -- )
;
; Reserve one cell of data space and store x in the cell. If the data-space
; pointer is aligned when , begins execution, it will remain aligned when ,
; finishes execution. An ambiguous condition exists if the data-space pointer
; is not aligned prior to execution of ,.
;
; In this implementation is its defined as:
;
; HERE ! 1 CELLS ALLOT
LINK NORMAL
db 1,","
COMMA: jsr DO_COLON
dw HERE
dw STORE
dw DO_LITERAL,1
dw CELLS
dw ALLOT
dw EXIT
; 2! ( x1 x2 a-addr -- )
;
; Store the cell pair x1 x2 at a-addr, with x2 at a-addr and x1 at the next
; consecutive cell.
;
; In this implementation is its defined as:
;
; SWAP OVER ! CELL+ !.
HEADER 2,"2!",NORMAL
TWO_STORE: jsr DO_COLON
dw SWAP
dw OVER
dw STORE
dw CELL_PLUS
dw STORE
dw EXIT
; 2@ ( a-addr -- x1 x2 )
;
; Fetch the cell pair x1 x2 stored at a-addr. x2 is stored at a-addr and x1 at
; the next consecutive cell.
;
; In this implementation is its defined as:
;
; DUP CELL+ @ SWAP @
HEADER 2,"2@",NORMAL
TWO_FETCH: jsr DO_COLON
dw DUP
dw CELL_PLUS
dw FETCH
dw SWAP
dw FETCH
dw EXIT
; @ ( a-addr -- x )
;
; x is the value stored at a-addr.
HEADER 1,"@",NORMAL
FETCH:
lda (1) ; Fetch from memory
sta <1 ; .. and replace top value
CONTINUE ; Done
; ALLOT ( n -- )
;
; If n is greater than zero, reserve n address units of data space. If n is
; less than zero, release |n| address units of data space. If n is zero, leave
; the data-space pointer unchanged.
;
; In this implementation its is defined as:
;
; DP +!
HEADER 5,"ALLOT",NORMAL
ALLOT: jsr DO_COLON
dw DP
dw PLUS_STORE
dw EXIT
; C! ( char c-addr -- )
;
; Store char at c-addr. When character size is smaller than cell size, only the
; number of low-order bits corresponding to character size are transferred.
HEADER 2,"C!",NORMAL
C_STORE:
lda <3 ; Fetch the data value
short_a
sta (1) ; And store it
long_a
tdc ; Clean up the stack
inc a
inc a
inc a
inc a
tcd
CONTINUE ; Done
; C, ( char -- )
;
; Reserve space for one character in the data space and store char in the
; space. If the data-space pointer is character aligned when C, begins
; execution, it will remain character aligned when C, finishes execution.
; An ambiguous condition exists if the data-space pointer is not character-
; aligned prior to execution of C,
;
; HERE C! 1 CHARS ALLOT
LINK NORMAL
db 2,"C,"
C_COMMA: jsr DO_COLON
dw HERE
dw C_STORE
dw DO_LITERAL,1
dw CHARS
dw ALLOT
dw EXIT
; C@ ( c-addr -- char )
;
; Fetch the character stored at c-addr. When the cell size is greater than
; character size, the unused high-order bits are all zeroes.
HEADER 2,"C@",NORMAL
C_FETCH:
short_a
lda (1) ; Fetch the data byte
sta <1 ; .. and replace stack value
stz <2
long_a
CONTINUE ; Done
; HERE ( -- addr )
;
; addr is the data-space pointer.
HEADER 4,"HERE",NORMAL
HERE: jsr DO_COLON
dw DP
dw FETCH
dw EXIT
;===============================================================================
; Alignment
;-------------------------------------------------------------------------------
; ALIGN ( -- )
;
; If the data-space pointer is not aligned, reserve enough space to align it.
HEADER 5,"ALIGN",NORMAL
ALIGN:
CONTINUE ; Done
; ALIGNED ( addr -- a-addr )
;
; a-addr is the first aligned address greater than or equal to addr.
HEADER 7,"ALIGNED",NORMAL
ALIGNED:
CONTINUE ; Done
; CELL+ ( a-addr1 -- a-addr2 )
;
; Add the size in address units of a cell to a-addr1, giving a-addr2.
HEADER 5,"CELL+",NORMAL
CELL_PLUS:
inc <1 ; Bump the address by two
inc <1
CONTINUE ; Done
; CELLS ( n1 -- n2 )
;
; n2 is the size in address units of n1 cells.
HEADER 5,"CELLS",NORMAL
CELLS:
asl <1 ; Two bytes per cell
CONTINUE ; Done
; CHAR+ ( c-addr1 -- c-addr2 )
;
; Add the size in address units of a character to c-addr1, giving c-addr2.
HEADER 5,"CHAR+",NORMAL
CHAR_PLUS:
inc <1 ; Bump the address by one
CONTINUE ; Done
; CHAR- ( c-addr1 -- c-addr2 )
;
; Subtract the size in address units of a character to c-addr1, giving c-addr2.
HEADER 5,"CHAR-",NORMAL
CHAR_MINUS:
dec <1
CONTINUE ; Done
; CHARS ( n1 -- n2 )
;
; n2 is the size in address units of n1 characters.
HEADER 5,"CHARS",NORMAL
CHARS:
CONTINUE ; Done
;===============================================================================
; Stack Operations
;-------------------------------------------------------------------------------
; 2DROP ( x1 x2 -- )
;
; Drop cell pair x1 x2 from the stack.
HEADER 5,"2DROP",NORMAL
TWO_DROP:
tdc ; Removed two words from stack
inc a
inc a
inc a
inc a
tcd
CONTINUE ; Done
; 2DUP ( x1 x2 -- x1 x2 x1 x2 )
;
; Duplicate cell pair x1 x2.
HEADER 4,"2DUP",NORMAL
TWO_DUP:
tdc ; Make space for new value
dec a
dec a
dec a
dec a
tcd
lda <5 ; Copy top two values
sta <1
lda <7
sta <3
CONTINUE ; Done
; 2OVER ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )
;
; Copy cell pair x1 x2 to the top of the stack.
HEADER 5,"2OVER",NORMAL
TWO_OVER:
tdc ; Make space for new value
dec a
dec a
dec a
dec a
tcd
lda <9 ; Ciopy top two values
sta <1
lda <11
sta <3
CONTINUE ; Done
; 2ROT ( x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2 )
;
; Rotate the top three cell pairs on the stack bringing cell pair x1 x2 to
; the top of the stack.
HEADER 4,"2ROT",NORMAL
TWO_ROT:
lda <11 ; Save x1
pha
lda <9 ; Save x2
pha
lda <7 ; Move x3
sta <11
lda <5 ; Move x4
sta <9
lda <3 ; Move x5
sta <7
lda <1 ; Move x6
sta <5
pla ; Restore x2
sta <1
pla ; Restore x1
sta <3
CONTINUE ; Done
; 2SWAP ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
;
; Exchange the top two cell pairs.
HEADER 5,"2SWAP",NORMAL
TWO_SWAP:
lda <3 ; Save x3
pha
lda <1 ; Save x4
pha
lda <7 ; Move x1
sta <3
lda <5 ; Move x2
sta <1
pla ; Move x4
sta <5
pla ; Move x3
sta <7
CONTINUE ; Done
; ?DUP ( x -- 0 | x x )
;
; Duplicate x if it is non-zero.
HEADER 4,"?DUP",NORMAL
QUERY_DUP:
lda <1 ; Fetch top value
bne DUP ; Non-zero value?
CONTINUE ; Done
; DEPTH ( -- +n )
;
; +n is the number of single-cell values contained in the data stack before +n
; was placed on the stack.
HEADER 5,"DEPTH",NORMAL
DEPTH: jsr DO_COLON
dw AT_DP
dw DO_LITERAL,DSTACK_END-1
dw SWAP
dw MINUS
dw TWO_SLASH
dw EXIT
; DROP ( x -- )
;
; Remove x from the stack.
HEADER 4,"DROP",NORMAL
DROP:
tdc ; Drop the top value
inc a
inc a
tcd
CONTINUE ; Done
; DUP ( x -- x x )
;
; Duplicate x.
HEADER 3,"DUP",NORMAL
DUP:
tdc
dec a
dec a
tcd
lda <3 ; Fetch top value
sta <1 ; And make a copy
CONTINUE ; Done
; NIP ( x1 x2 -- x2 )
;
; Drop the first item below the top of stack.
HEADER 3,"NIP",NORMAL
NIP:
lda <1 ; Copy x2 over x1
sta <3
bra DROP
; OVER ( x1 x2 -- x1 x2 x1 )
;
; Place a copy of x1 on top of the stack.
HEADER 4,"OVER",NORMAL
OVER:
tdc
dec a
dec a
tcd
lda <5 ; Fetch second value
sta <1 ; And make a copy
CONTINUE ; Done
; PICK ( xu ... x1 x0 u -- xu ... x1 x0 xu )
;
; Remove u. Copy the xu to the top of the stack. An ambiguous condition exists
; if there are less than u+2 items on the stack before PICK is executed.
HEADER 4,"PICK",NORMAL
PICK:
lda <1 ; Fetch the index
asl a
tax
lda <3,x ; Load the target value
sta <1 ; .. and save
CONTINUE ; Done
; ROLL ( xu xu-1 ... x0 u -- xu-1 ... x0 xu )
;
; Remove u. Rotate u+1 items on the top of the stack. An ambiguous condition
; exists if there are less than u+2 items on the stack before ROLL is executed.
HEADER 4,"ROLL",NORMAL
ROLL:
asl <1 ; Convert count to index
ldx <1
beq ROLL_2 ; Zero? Nothing to do
lda <3,x ; Save the final value
pha
ROLL_1: lda <1,x ; Move x-1 to x
sta <3,x
dex ; And repeat
dex
bne ROLL_1
pla ; Recover the new top value
sta <3
ROLL_2: jmp DROP ; Drop the count
; ROT ( x1 x2 x3 -- x2 x3 x1 )
;
; Rotate the top three stack entries.
HEADER 3,"ROT",NORMAL
ROT:
ldx <5 ; Save x1
lda <3 ; Move x2
sta <5
lda <1 ; Move x3
sta <3
stx <1 ; Restore x1
CONTINUE
; SWAP ( x1 x2 -- x2 x1 )
;
; Exchange the top two stack items.
HEADER 4,"SWAP",NORMAL
SWAP:
lda <1 ; Switch top two words
ldx <3
sta <3
stx <1
CONTINUE ; Done
; TUCK ( x1 x2 -- x2 x1 x2 )
;
; Copy the first (top) stack item below the second stack item.
HEADER 4,"TUCK",NORMAL
TUCK: jsr DO_COLON
dw SWAP
dw OVER
dw EXIT
;===============================================================================
; Return Stack Operations
;-------------------------------------------------------------------------------
; 2>R ( x1 x2 -- ) ( R: -- x1 x2 )
;
; Transfer cell pair x1 x2 to the return stack. Semantically equivalent to
; SWAP >R >R.
HEADER 3,"2>R",NORMAL
TWO_TO_R:
lda <3 ; Transfer x1
pha
lda <1 ; Transfer x2
pha
tdc
inc a ; Clean up data stack
inc a
inc a
inc a
tcd
CONTINUE ; Done
; 2R> ( -- x1 x2 ) ( R: x1 x2 -- )
;
; Transfer cell pair x1 x2 from the return stack. Semantically equivalent to R>
; R> SWAP.
HEADER 3,"2R>",NORMAL
TWO_R_FROM:
tdc
dec a ; Make space for values
dec a
dec a
dec a
tcd
pla ; Transfer x2
sta <1
pla ; Transfer x1
sta <3
CONTINUE ; Done
; 2R@ ( -- x1 x2 ) ( R: x1 x2 -- x1 x2 )
;
; Copy cell pair x1 x2 from the return stack. Semantically equivalent to R> R>
; 2DUP >R >R SWAP.
HEADER 3,"2R@",NORMAL
TWO_R_FETCH:
tdc
dec a ; Make space for values
dec a
dec a
dec a
tcd
lda 1,s ; Transfer x2
sta <1
lda 3,s ; Transfer x1
sta <3
CONTINUE ; Done
; >R ( x -- ) ( R: -- x )
;
; Move x to the return stack.
HEADER 2,">R",NORMAL
TO_R:
lda <1 ; Transfer top value
pha ; .. to return stack
tdc
inc a
inc a
tcd
CONTINUE ; Done
; I ( -- n|u ) ( R: loop-sys -- loop-sys )
;
; n|u is a copy of the current (innermost) loop index. An ambiguous condition
; exists if the loop control parameters are unavailable.
HEADER 1,"I",NORMAL
I:
tdc
dec a
dec a
tcd
lda 1,s
sta <1
CONTINUE
; J ( -- n|u ) ( R: loop-sys1 loop-sys2 -- loop-sys1 loop-sys2 )
;
; n|u is a copy of the next-outer loop index. An ambiguous condition exists if
; the loop control parameters of the next-outer loop, loop-sys1, are
; unavailable.
HEADER 1,"J",NORMAL
J:
tdc
dec a
dec a
tcd
lda 5,s
sta <1
CONTINUE
; R> ( -- x ) ( R: x -- )
;
; Move x from the return stack to the data stack.
HEADER 2,"R>",NORMAL
R_FROM:
tdc
dec a
dec a
tcd
pla ; Fetch return stack value
sta <1
CONTINUE ; Done
; R@ ( -- x ) ( R: x -- x )
;
; Copy x from the return stack to the data stack.
HEADER 2,"R@",NORMAL
R_FETCH:
tdc
dec a
dec a
tcd
lda 1,s
sta <1
CONTINUE
;===============================================================================
; Single Precision Arithmetic
;-------------------------------------------------------------------------------