-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfth_core_65816.fs
941 lines (819 loc) · 10.3 KB
/
fth_core_65816.fs
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
( -*- forth-asm -*- )
HEADLESSCODE
HIGH_W .macro name_len, name, act=w_enter, flgs=0, prev
dict:
.byte (\flgs << 7) | len(\name)
.text format("%-7s", \name[:7])
.addr \prev
cfa:
jmp \act ; CFA
.endmacro ; PFA implicit, follows macro
CODE_W .macro name_len, name, flgs=0, prev
dict:
.byte (\flgs << 7) | len(\name)
.text format("%-7s", \name[:7])
.addr \prev
cfa:
.ax16
.endmacro ; PFA implicit, follows macro
NEXT .macro
jmp do_next
.endmacro
w_core_dict .HIGH_W 9, "core_dict", w_const, , "0"
.addr dict_head
source_id_stk: .fill 16 ;8 addresses
source_id_sp: .word 0
;; Byte is in A. Put at here and advance here
puthere8:
.a8
sta (here_store)
.a16
inc here_store
rts
puthere16:
.a16
sta (here_store)
inc here_store
inc here_store
rts
rpush1
.x16
ldx rsp
dex
dex
stx rsp
rts
rpop1
.x16
ldx rsp
inx
inx
stx rsp
rts
rpush2
.a16
lda rsp
sec
sbc #4
sta rsp
rts
rpop2
.a16
lda rsp
clc
adc #4
sta rsp
rts
w_enter .block
cfa
;jsr debug_dump
.ax16
jsr rpush1
lda ip
sta 1,x
clc
lda w
adc #3
sta ip
.NEXT
.endblock
w_var .block
cfa
.a16
lda w
clc
adc #3
pha
.NEXT
.endblock
w_const .block
cfa
.a16
.x8
ldy #3
lda (w),y
pha
.NEXT
.endblock
END-CODE
next_immediate
CODE brk
brk
.byte $55
END-CODE
next_unlisted
CODE init_serial
jsr con_init
END-CODE
( Low-level Forth engine support )
CODE lit
lda (ip)
pha
clc
lda ip
adc #2
sta ip
END-CODE
CODE exit
ldx rsp
lda 1,x
sta ip
jsr rpop1
END-CODE
next_unlisted
CODE p0
ldx #$1ff
txs
END-CODE
CODE r0
lda #rstk_top
sta rsp
END-CODE
CODE emit
pla
jsr con_tx
END-CODE
CODE at-xy
pla
tay
pla
tax
jsr gotoxy
END-CODE
CODE pagesize
pla
tay
pla
tax
jsr pagesize
END-CODE
CODE page
.ax8
lda #255 ; Hopefully worst-case terminal size
jsr scroll_up
ldx #0
ldy #0
jsr gotoxy
END-CODE
( c-addr u char -- )
CODE fill
plx ; char
ply ; count
pla ; base addr
sta mac
txa
.a8
_again:
dey
bmi _done
sta (mac),y
bra _again
_done:
END-CODE
( -- c )
CODE key
.a8
lda #0
pha
jsr con_rx
.a8
pha
END-CODE
next_unlisted
CODE unloop
jsr rpop2
END-CODE
CODE depth
tsc
eor #$1ff ; one's comp because zero stack == #$1ff
lsr ; now div by two since cells are two bytes
pha
END-CODE
CODE rdepth
lda #rstk_top
sec
sbc rsp
lsr
pha
END-CODE
next_unlisted
CODE rbase
lda #rstk_top
dec a
pha
END-CODE
CODE dup
lda 1,s
pha
END-CODE
CODE ?dup
lda 1,s
beq _done
pha
_done:
END-CODE
CODE drop
pla
END-CODE
CODE swap
lda 1,s
tax
lda 3,s
sta 1,s
txa
sta 3,s
END-CODE
CODE over
lda 3,s
pha
END-CODE
CODE nip
pla
sta 1,s
END-CODE
CODE tuck
lda 1,s
tax
lda 3,s
sta 1,s
txa
sta 3,s
pha
END-CODE
CODE pick
tsx
txa
asl 1,x
clc
adc 1,x
tay
lda 3,y
sta 1,x
END-CODE
CODE 2drop
pla
pla
END-CODE
CODE 2dup
lda 3,s
pha
lda 3,s
pha
END-CODE
CODE 2over
lda 7,s
pha
lda 7,s
pha
END-CODE
CODE 2swap
lda 1,s
tax
lda 5,s
sta 1,s
txa
sta 5,s
lda 3,s
tax
lda 7,s
sta 3,s
txa
sta 7,s
END-CODE
CODE rot
lda 5,s
tax
lda 3,s
sta 5,s
lda 1,s
sta 3,s
txa
sta 1,s
END-CODE
CODE and
pla
and 1,s
sta 1,s
END-CODE
CODE or
pla
ora 1,s
sta 1,s
END-CODE
CODE xor
pla
eor 1,s
sta 1,s
END-CODE
CODE lshift
ply
pla
cpy #0
beq done
again:
asl a
dey
bne again
done:
pha
END-CODE
CODE rshift
ply
pla
cpy #0
beq done
again:
lsr a
dey
bne again
done:
pha
END-CODE
CODE =
pla
cmp 1,s
bne _notequal
lda #$ffff
bra _finished
_notequal:
lda #0
_finished:
sta 1,s
END-CODE
CODE <>
pla
cmp 1,s
bne _notequal
lda #0
bra _finished
_notequal:
lda #$ffff
_finished:
sta 1,s
END-CODE
CODE 0=
pla
beq _iszero
lda #0
bra _done
_iszero:
lda #$ffff
_done:
pha
END-CODE
CODE 0<>
pla
beq _iszero
lda #$ffff
bra _done
_iszero:
lda #0
_done:
pha
END-CODE
CODE invert
lda #$ffff
eor 1,s
sta 1,s
END-CODE
CODE abs
lda 1,s
bpl _done
eor #$ffff
inc a
sta 1,s
_done:
END-CODE
CODE negate
lda 1,s
eor #$ffff
inc a
sta 1,s
END-CODE
CODE ALIGN
END-CODE
CODE ALIGNED
END-CODE
CODE 0<
pla
bmi _set_true
lda #0
bra _save_flag
_set_true:
lda #$ffff
_save_flag:
pha
END-CODE
CODE 0>
pla
bmi _set_false
beq _set_false
lda #$ffff
bra _save_flag
_set_false:
lda #0
_save_flag:
pha
END-CODE
CODE <
pla
cmp 1,s
beq _set_false
bmi _set_false
lda #$ffff
bra _set_flag
_set_false:
lda #0
_set_flag:
sta 1,s
END-CODE
CODE >
pla
cmp 1,s
bcc _set_true
lda #0
bra _set_flag
_set_true:
lda #$ffff
_set_flag:
sta 1,s
END-CODE
CODE +
pla
clc
adc 1,s
sta 1,s
END-CODE
CODE -
lda 3,s
sec
sbc 1,s
sta 3,s
pla
END-CODE
CODE 1+
tsx
inc 1,x
END-CODE
CODE 1-
tsx
dec 1,x
END-CODE
CODE *
jmp ll_mult
END-CODE
CODE 2*
tsx
asl 1,x
END-CODE
CODE 2/
tsx
clc
lda 1,x
bpl _is_positive
sec
_is_positive:
ror 1,x
END-CODE
CODE /mod
jmp ll_slash_mod
END-CODE
CODE 2@
.x8
pla
sta mac
ldy #2
lda (mac),y
pha
lda (mac)
pha
END-CODE
CODE @
.x8
ldy #0
lda (1,s),y
sta 1,s
END-CODE
CODE c@
.ax8
ldy #0
lda (1,s),y
.a16
and #$ff
sta 1,s
END-CODE
CODE 2!
.x8
ldy #2
pla
sta mac
pla
sta (mac)
pla
sta (mac),y
END-CODE
CODE !
pla
sta mac
pla
sta (mac)
END-CODE
CODE +!
pla
sta mac
clc
pla
adc (mac)
sta (mac)
END-CODE
CODE c!
pla
sta mac
pla
.a8
sta (mac)
END-CODE
next_unlisted
CODE branch
lda (ip)
sta ip
END-CODE
next_unlisted
CODE qbranch
pla
bne _no_branch
lda (ip)
sta ip
bra _done
_no_branch:
inc ip
inc ip
_done:
END-CODE
CODE bye
jmp start
END-CODE
CODE >r
jsr rpush1
pla
sta 1,x
END-CODE
CODE r>
ldx rsp
lda 1,x
pha
jsr rpop1
END-CODE
CODE r@
ldx rsp
lda 1,x
pha
END-CODE
CODE 2>r
jsr rpush2
tax
pla
sta 1,x
pla
sta 3,x
END-CODE
CODE 2r>
ldx rsp
lda 3,x
pha
lda 1,x
pha
jsr rpop2
END-CODE
CODE 2r@
ldx rsp
lda 3,x
pha
lda 1,x
pha
END-CODE
CODE 2rdrop
jsr rpop2
END-CODE
CODE >cf
ldx cfp
dex
dex
stx cfp
pla
sta 1,x
END-CODE
CODE cf>
ldx cfp
lda 1,x
pha
inx
inx
stx cfp
END-CODE
CODE cf@
ldx cfp
lda 1,x
pha
END-CODE
CODE cfnip
;; fixme: not yet tested
ldx cfp
lda 1,x
sta 3,x
inx
inx
stx cfp
END-CODE
CODE i
ldx rsp
lda 1,x
pha
END-CODE
CODE j
ldx rsp
lda 5,x
pha
END-CODE
CODE k
ldx rsp
lda 9,x
pha
END-CODE
( full loop terminator include dropping loop counters from rstk )
next_unlisted
CODE do_loop
;; Increment loop counter
ldx rsp
inc 1,x
;; Compare counter with limit
lda 3,x
cmp 1,x
bne _loop_again
;; Loop finished. Remove loop context. Skip backpointer.
jsr rpop2
inc ip
inc ip
bra _finished
_loop_again:
lda (ip)
sta ip
_finished:
END-CODE
( full loop terminator include dropping loop counters from rstk )
next_unlisted
CODE do_plus_loop
;; Increment loop counter
ldx rsp
clc
pla
adc 1,x
sta 1,x
;; Compare counter with limit, (count - limit here though)
lda 1,x
cmp 3,x
bcc loop_again ; If carry is clear, counter < limit
jsr rpop2
inc ip
inc ip
bra finished
loop_again:
lda (ip)
sta ip
finished:
END-CODE
( loop terminator that does not clear the rstk )
next_unlisted
CODE do_loop1
ldx rsp
inc 1,x
lda 3,x
cmp 1,x
bne loop_again
; jsr rpop2 ; This is the only difference compared to do_loop (currently)
inc ip
inc ip
bra finished
loop_again:
lda (ip)
sta ip
finished:
END-CODE
next_unlisted
CODE do_plus_loop1
;; Increment loop counter
ldx rsp
clc
pla
adc 1,x
sta 1,x
;; Compare counter with limit, (count - limit here though)
lda 1,x
cmp 3,x
bcc loop_again ; If carry is clear, counter < limit
;jsr rpop2 ; This is the only difference compared to do_plus_loop (currently)
inc ip
inc ip
bra finished
loop_again:
lda (ip)
sta ip
finished:
END-CODE
next_unlisted
CODE here0
lda edata
sta here_store
END-CODE
CODE here
lda here_store
pha
END-CODE
CODE ,
pla
jsr puthere16
END-CODE
CODE c,
pla
jsr puthere8
END-CODE
CODE allot
clc
pla
adc here_store
sta here_store
END-CODE
CODE cell+
tsx
inc 1,x
inc 1,x
END-CODE
CODE cells
lda 1,s
asl
sta 1,s
END-CODE
CODE char+
tsx
inc 1,x
END-CODE
CODE chars
;; nop
END-CODE
CODE halt
brk
.byte $66
END-CODE
CODE execute
pla
sta w
jmp (w)
END-CODE
CODE move
pla
dec a ; mvn, mvp need count-1
sta mac
pla
cmp 1,s
beq _done
bcs _move_positive
_move_negative:
;; uses beginning addresses
tay
plx
lda mac
mvn 0,0
bra _done
_move_positive:
clc
adc mac
tay
pla
clc
adc mac
tax
lda mac
mvp 0,0
_done:
END-CODE
next_unlisted
CODE get_bs
.a8
lda #0
pha
jsr raw_bs
pha
END-CODE
CODE hex_char
jmp mach_hex_char
END-CODE
next_unlisted
CODE dec_num
pla
jsr prt_dec_num
END-CODE
8 CONSTANT HDR_SIZE
7 CONSTANT MAX_NM_LEN
: dict_to_cfa ( entry-addr -- cfa-addr )
HDR_SIZE + 1 cells +
;