-
Notifications
You must be signed in to change notification settings - Fork 6
/
figforth.asm
3917 lines (3917 loc) · 59.5 KB
/
figforth.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
.TITLE Z80 fig-FORTH 1.3
;
;
; Modified frm FIG document keyed by Dennis L. Wilson 800907
; Converted frm "8080 FIG-FORTH VERSION A0 15SEP79"
;
; fig-FORTH release 1.1 for the 8080 processor.
;
; ALL PUBLICATIONS OF THE FORTH INTEREST GROUP
; ARE PUBLIC DOMAIN. THEY MAY BE FURTHER
; DISTRIBUTED BY THE INCLUSION OF THIS CREDIT NOTICE:
;
; This publication has been made available by the
; Forth Interest Group
; P.O.Box 1105
; San Carlos, CA 94070
; U.S.A.
;
; Implementation on 8080 by:
; John Cassady
; 339 15th Street
; Oakland, CA 94612
; U.S.A
; on 790528
; Modified by:
; Kim Harris
; Acknowledgements:
; George Flammer
; Robt. D. Villwock
; ----------------------------------------------------------------------
; Z80 Version for Cromemco CDOS & Digital Research CP/M by:
; Dennis Lee Wilson c/o
; Aristotelian Logicians
; 2631 East Pinchot Avenue
; Phoenix, AZ 85016
; U.S.A.
; ----------------------------------------------------------------------
; The 2 byte Z80 code for Jump Relative (JR) has been substituted for
; the 3 byte Jump (JP) wherever practical. The port I/O words P@ & P!
; have been made ROMable by use of Z80 instructions.
; ----------------------------------------------------------------------
; Further modifications (marked ;/) by:
; Edmund Ramm
; Anderheitsallee 24
; 2000 Hamburg 71
; Fed. Rep. of Germany 840418
; ----------------------------------------------------------------------
; Disc I/O has been modified a la Albert van der Horst (HCCH) to employ
; CP/M 2.x's random access feature.
; ----------------------------------------------------------------------
; Adaptive version by EHR
; ----------------------------------------------------------------------
; Upgraded to v1.3 by Dimitri Theulings - 11/2020 - changes marked 1.3
; Changes are based on '8080 FIG-FORTH 1.3 VERSION 0 18JUL81'
; ----------------------------------------------------------------------
; Added CASE statement as proposed by Charles Eaker, FD II/3, 37-40 - DT
; ----------------------------------------------------------------------
;
; Release & Version numbers
;
FIGREL .EQU 1 ;FIG RELEASE #
FIGREV .EQU 3 ;FIG REVISION #
USRVER .EQU 63H ;USER VERSION # DT - 2021/01/17
;
;Console & printer drivers are in external source named
;CONPRTIO.FTH & disc drivers in DISCIO.FTH. It has 4 screen
;buffers & end of memory is set to FBASE from locn. 0007H.
.EJECT
; ASCII characters used
;
ABL .EQU 20H ;BLANK
ACR .EQU 0DH ;CR
ADOT .EQU 2EH ;.
BELL .EQU 07H ;^G
BSIN .EQU 08H ;backspace chr = ^H
BSOUT .EQU 08H
HT .EQU 09H ;^T
DLE .EQU 10H ;^P
LF .EQU 0AH ;^J
FF .EQU 0CH ;^L
;
; Memory allocation
;
BDOSS .EQU 0005H ;/ system entry
NSCR .EQU 4 ; # of 1024 byte screens
KBBUF .EQU 128 ; bytes/disc buffer
US .EQU 40H ; user variables space
RTS .EQU 400H ; Return Stack & term buff space
CO .EQU KBBUF+4 ; Disc buff + 2 header + 2 tail
NBUF .EQU NSCR*400H/KBBUF ; # of buffers
BUFSIZ .EQU CO*NBUF ;/ total disc buffer size
.EJECT
;ABS
;
.ORG 0100H
ORIG: NOP
JP CLD ;VECTOR TO COLD START
NOP
JP WRM ;VECTOR TO WARM START
.BYTE FIGREL ;FIG RELEASE #
.BYTE FIGREV ;FIG REVISION #
.BYTE USRVER ;USER VERSION #
.BYTE 0EH ;IMPLEMENTATION ATTRIBUTES
;
;
;
; 0EH = 0000:1110
; ---------
; B +ORIGIN ...W:IEBA
;
; W: 0=above sufficient
; 1=other differences exist
; I: Interpreter is 0=pre-
; 1=post incrementing
; E: Addr must be even: 0 yes
; 1 no
; B: High byte @ 0=low addr.
; 1=high addr.
; A: CPU Addr. 0=BYTE
; 1=WORD
;
;
;
.WORD TASK-7 ; TOPMOST WORD IN FORTH VOCABULARY
.WORD BSIN ; BACKSPACE CHR
UPINIT: .WORD 0 ;/ INIT (UP)
;
; * FOLLOWING USED BY COLD; MUST BE IN SAME ORDER AS USER VARIABLES *
;
S0INIT: .WORD 0 ;/ INIT (S0)
R0INIT: .WORD 0 ;/ INIT (R0)
TIBINI: .WORD 0 ;/ INIT (TIB)
.WORD 1FH ; INIT (WIDTH)
.WORD 0 ; INIT (WARNING)
.WORD INITDP ; INIT (FENCE)
.WORD INITDP ; INIT (DP)
.WORD FORTH+8 ; INIT (VOC-LINK)
;
; * END DATA USED BY COLD *
;
.WORD 0H,0B250H ;Z80 CPU NAME (HW,LW)
;(32 BIT BASE 36 INTEGER)
#IFDEF ROMWBW
.WORD 0 ;VIDEO DEVICE ID
.WORD 0,0,0 ;RTC DATE/TIME
#ENDIF
.EJECT
; REGISTERS
;
; FORTH Z80 FORTH PRESERVATION RULES
; ----- --- -----------------------
; IP BC should be preserved
; accross FORTH words.
; W DE sometimes output from
; NEXT, may be altered
; b4 JP'ing to NEXT,
; input only when
; "DPUSH" called.
; SP SP should be used only as
; Data Stack accross
; FORTH words, may be
; used within FORTH
; words if restored
; b4 "NEXT"
; HL Never output frm NEXT
; input only when
; "HPUSH" called
;
;
UP: .WORD 0 ;/ USER AREA PTR
RPP: .WORD 0 ;/ RETURN STACK PTR
BUF1: .WORD 0 ;/ address of 1st disc buffer
;
;
; COMMENT CONVENTIONS:
;
; = MEANS "IS EQUAL TO"
; <-- MEANS ASSIGNMENT
; NAME = ADDR OF NAME
; (NAME) = CONTENTS @ NAME
; ((NAME))= INDIRECT CONTENTS
; CFA = CODE FIELD ADDR
; LFA = LINK FIELD ADDR
; NFA = NAME FIELD ADDR
; PFA = PARAMETER FIELD ADDR
; S1 = ADDR OF 1st WORD OF PARAMETER STACK
; S2 = -"- OF 2nd -"- OF -"- -"-
; R1 = -"- OF 1st -"- OF RETURN STACK
; R2 = -"- OF 2nd -"- OF -"- -"-
; ( above Stack posn. valid b4 & after execution of any word, not during)
;
; LSB = LEAST SIGNIFICANT BIT
; MSB = MOST SIGNIFICANT BIT
; LB = LOW BYTE
; HB = HIGH BYTE
; LW = LOW WORD
; HW = HIGH WORD
; (May be used as suffix to above names)
.EJECT
; FORTH ADDRESS INTERPRETER
; POST INCREMENTING VERSION
;
DPUSH: PUSH DE
HPUSH: PUSH HL ; IY points here
NEXT: LD A,(BC) ;(W)<--((IP)) IX points here
LD L,A
INC BC ;INC IP
LD A,(BC)
LD H,A ;(HL)<--CFA
INC BC ;INC IP
NEXT1: LD E,(HL) ;(PC)<--((W))
INC HL
LD D,(HL)
EX DE,HL
JP (HL) ;NOTE: (DE)=CFA+1
;
;
#DEFINE JNEXT JP (IX)
;
;
#DEFINE JHPUSH JP (IY)
;
;
.EJECT
; FORTH DICTIONARY
; DICTIONARY FORMAT:
;
; BYTE
; ADDRESS NAME CONTENTS
; ------- ---- --------
; (MSB=1
; (P=PRECEDENCE BIT
; (S=SMUDGE BIT
; NFA NAME FIELD 1PS<LEN> <NAME LENGTH
; 0<1CHAR> MSB=0, NAME'S 1st CHAR
; 0<2CHAR>
; ...
; 1<LCHAR> MSB=1, NAME'S LAST CHAR
; LFA LINK FIELD <LINKLB> =PREVIOUS WORD'S NFA
; <LINKHB>
;LABEL: CFA CODE FIELD <CODELB> =ADDR CPU CODE
; <CODEHB>
; PFA PARAMETER <1PARAM> 1st PARAMETER BYTE
; FIELD <2PARAM>
; ...
;
;
;
DP0: .BYTE 83H ;LIT
.TEXT "LI"
.BYTE 'T'+$80
.WORD 0 ;(LFA)=0 MARKS END OF DICTIONARY
LIT: .WORD $+2 ;(S1)<--((IP))
LD A,(BC) ;(HL)<--((IP))=LITERAL
INC BC ;(IP)<--(IP)+2
LD L,A ;LB
LD A,(BC) ;HB
INC BC
LD H,A
JHPUSH ;(S1)<--(HL)
;
.BYTE 87H ;EXECUTE
.TEXT "EXECUT"
.BYTE 'E'+$80
.WORD LIT-6
EXEC: .WORD $+2
POP HL
JP NEXT1
;
.BYTE 86H ;BRANCH
.TEXT "BRANC"
.BYTE 'H'+$80
.WORD EXEC-0AH
BRAN: .WORD $+2 ;(IP)<--(IP)+((IP))
BRAN1: LD H,B ;(HL)<--(IP)
LD L,C
LD E,(HL) ;(DE)<--((IP))=BRANCH OFFSET
INC HL
LD D,(HL)
DEC HL
ADD HL,DE ;(HL)<--(HL)+((IP))
LD C,L ;(IP)<--(HL)
LD B,H
JNEXT
;
.BYTE 87H ;0BRANCH
.TEXT "0BRANC"
.BYTE 'H'+$80
.WORD BRAN-9
ZBRAN: .WORD $+2
POP HL
LD A,L
OR H
JR Z,BRAN1 ;IF (S1)=0 THEN BRANCH
INC BC ;ELSE SKIP BRANCH OFFSET
INC BC
JNEXT
;
.BYTE 86H ;(LOOP)
.TEXT "(LOOP"
.BYTE ')'+$80
.WORD ZBRAN-0AH
XLOOP: .WORD $+2
LD HL,(RPP) ; ((HL))=INDEX=(R1)
inc (hl) ;/ index(lb) += 1
LD E,(HL) ;/
INC HL ;/ (hl)-->index(hb)
jr nz,xloop1 ;/ jump if ((hl)) < 256
inc (hl) ;/ else index(hb) += 1
xloop1: LD D,(HL) ;/ (DE)<-- new INDEX
INC HL ;/ ((HL))=LIMIT
LD A,E
SUB (HL)
LD A,D
INC HL
SBC A,(HL) ; INDEX<LIMIT?
JP M,BRAN1 ; YES, LOOP AGAIN
INC HL ; NO, DONE
LD (RPP),HL ; DISCARD R1 & R2
INC BC
INC BC ; SKIP BRANCH OFFSET
JNEXT
;
.BYTE 87H ;(+LOOP)
.TEXT "(+LOOP"
.BYTE ')'+$80
.WORD XLOOP-9
XPLOO: .WORD $+2
POP DE ;(DE)<--INCR
LD HL,(RPP) ;((HL))=INDEX
LD A,(HL) ;INDEX<--INDEX+INCR
ADD A,E
LD (HL),A
LD E,A
INC HL
LD A,(HL)
ADC A,D
LD (HL),A
INC HL ;((HL))=LIMIT
INC D
DEC D
LD D,A ;(DE)<--NEW INDEX
JP M,XLOO2 ;IF INCR>0
LD A,E
SUB (HL) ;THEN (A)<--INDEX - LIMIT
LD A,D
INC HL
SBC A,(HL)
JP XLOO3
XLOO2: LD A,(HL) ;ELSE (A)<--LIMIT - INDEX
SUB E
INC HL
LD A,(HL)
SBC A,D
; ;IF (A)<0
XLOO3: JP M,BRAN1 ;THEN LOOP AGN
INC HL ;ELSE DONE
LD (RPP),HL ;DISCARD R1 & R2
INC BC ;SKIP BRANCH OFFSET
INC BC
JNEXT
;
.BYTE 84H ; (DO)
.TEXT "(DO"
.BYTE ')'+$80
.WORD XPLOO-0AH
XDO: .WORD $+2
EXX ;/ SAVE IP
POP DE ; (DE)<--INITIAL INDEX
POP BC ;/ (BC)<--LIMIT
LD HL,(RPP) ; (HL)<--(RP)
DEC HL
LD (HL),B
DEC HL
LD (HL),C ;/ (R2)<--LIMIT
DEC HL
LD (HL),D
DEC HL
LD (HL),E ; (R1)<--INITIAL INDEX
LD (RPP),HL ; (RP)<--(RP)-4
EXX ;/ RESTORE IP
JNEXT
;
.BYTE 81H ;I
.BYTE 'I'+$80
.WORD XDO-7
IDO: .WORD $+2 ;(S1)<--(R1), (R1) UNCHANGED
LD HL,(RPP)
IDO1: LD E,(HL) ;(DE)<--(R1)
INC HL
LD D,(HL)
PUSH DE ;(S1)<--(DE)
JNEXT
;
.BYTE 82H ; I' 1.3
.BYTE 'I'
.BYTE $27+$80
.WORD IDO-4
IPRIM .DW $+2
LD HL,(RPP)
INC HL
INC HL ; ((HL)) = (R2)
JR IDO1
;
.BYTE 81H ; J 1.3
.BYTE 'J'+$80
.WORD IPRIM-5
J .WORD $+2
LD HL,(RPP)
INC HL
INC HL
INC HL
INC HL ; ((HL)) = (R3)
JR IDO1
;
.BYTE 85H ;DIGIT
.TEXT "DIGI"
.BYTE 'T'+$80
.WORD J-4
DIGIT: .WORD $+2
POP HL ;(L)<--(S1)LB = BASE VALUE
POP DE ;(E)<--(S2)LB = ASCII CHR TO BE CONVERTED
LD A,E ;ACCU<--CHR
SUB '0' ;>=0?
JR C,DIGI2 ;/ <0 IS INVALID
CP 0AH ;>9?
JR C,DIGI1 ;/ NO, TEST BASE VALUE
SUB 07H ;GAP BETWEEN "9" & "A", NW "A"=0AH
CP 0AH ;>="A"?
JR C,DIGI2 ;/ CHRs BETWEEN "9" & "A" ARE INVALID
DIGI1: CP L ;<BASE VALUE?
JR NC,DIGI2 ;/ NO, INVALID
LD E,A ;(S2)<--(DE) = CONVERTED DIGIT
LD HL,0001H ;(S1)<--TRUE
JP DPUSH
DIGI2: LD L,H ;(HL)<--FALSE
JHPUSH ;(S1)<--FALSE
;
.BYTE 86H ;(FIND) (2-1)FAILURE
.TEXT "(FIND" ; (2-3)SUCCESS
.BYTE ')'+$80
.WORD DIGIT-8
PFIND: .WORD $+2
POP DE ;(DE)<--NFA
PFIN1: POP HL ;(HL)<--STRING ADDR
PUSH HL ;SAVE FOR NEXT ITERATION
LD A,(DE)
XOR (HL) ;FILTER DEVIATIONS
AND 3FH ;MASK MSB & PRECEDENCE BIT
JR NZ,PFIN4 ;LENGTHS DIFFER
PFIN2: INC HL ;(HL)<--ADDR NEXT CHR IN STRING
INC DE ;(DE)<--ADDR NEXT CHR IN NF
LD A,(DE)
XOR (HL) ;FILTER DEVIATIONS
ADD A,A
JR NZ,PFIN3 ;NO MATCH
JR NC,PFIN2 ;MATCH SO FAR, LOOP AGN
LD HL,0005H ;STRING MATCHES
ADD HL,DE ;((SP))<--PFA
EX (SP),HL
PFIN6: DEC DE ;POSN DE ON NFA
LD A,(DE)
OR A ;MSB=1? =LENGTH BYTE
JP P,PFIN6 ;NO, TRY NEXT CHR
LD E,A ;(E)<--LENGTH BYTE
LD D,00H
LD HL,0001H ;(HL)<--TRUE
JP DPUSH ;NF FOUND, RETURN
;
;ABOVE NF NOT A MATCH, TRY NEXT ONE
;
PFIN3: JR C,PFIN5 ;CARRY=END OF NF
PFIN4: INC DE ;FIND END OF NF
LD A,(DE)
OR A ;MSB=1?
JP P,PFIN4 ;NO, LOOP
PFIN5: INC DE ;(DE)<--LFA
EX DE,HL
LD E,(HL)
INC HL
LD D,(HL) ;(DE)<--(LFA)
LD A,D
OR E ;END OF DICTIONARY? (LFA)=0
JR NZ,PFIN1 ;NO, TRY PREVIOUS DEFINITION
POP HL ;DROP STRING ADDR
LD HL,0 ;(HL)<--FALSE
JHPUSH ;NO MATCH FOUND, RETURN
;
.BYTE 87H ;ENCLOSE
.TEXT "ENCLOS"
.BYTE 'E'+$80
.WORD PFIND-9
ENCL: .WORD $+2
POP DE ;(DE)<--(S1)=DELIMITER CHR
POP HL ;(HL)<--(S2)=ADDR OF TEXT TO SCAN
PUSH HL ;(S4)<--ADDR
LD A,E
LD D,A ;(D)<--DELIM CHR
LD E,-1 ;INIT CHR OFFSET COUNTER
DEC HL ;(HL)<--ADDR-1
ENCL1: INC HL ;SKIP OVER LEADING DELIM CHRs
INC E
CP (HL) ;DELIM CHR?
JR Z,ENCL1 ;YES, LOOP
LD D,0
PUSH DE ;(S3)<--(E)=OFFSET TO 1st NON DELIM
LD D,A ;(D)<--DELIM CHR
LD A,(HL)
AND A ;1st non-DELIM=NULL?
JR NZ,ENCL2 ;NO
LD D,0 ;YES
INC E
PUSH DE ;(S2)<--OFFSET TO BYTE FOLLOWING NULL
DEC E
PUSH DE ;(S1)<--OFFSET TO NULL
JNEXT
ENCL2: LD A,D ;(A)<--DELIM CHR
INC HL ;(HL)<--ADDR NEXT CHR
INC E ;(E)<--OFFSET TO NEXT CHR
CP (HL) ;DELIM CHR?
JR Z,ENCL4 ;YES
LD A,(HL)
AND A ;NULL?
JR NZ,ENCL2 ;NO, CONT SCAN
ENCL3: LD D,0
PUSH DE ;(S2)<--OFFSET TO NULL
PUSH DE ;(S1)<--OFFSET TO NULL
JNEXT
ENCL4: LD D,0
PUSH DE ;(S2)<--OFFSET TO BYTE FOLLOWING TEXT
INC E
PUSH DE ;(S1)<--OFFSET TO 2 BYTES AFTER END OF WORD
JNEXT
;
.BYTE 84H ;EMIT
.TEXT "EMI"
.BYTE 'T'+$80
.WORD ENCL-0AH
EMIT: .WORD DOCOL
.WORD PEMIT
.WORD ONE,OUTT
.WORD PSTOR,SEMIS
;
.BYTE 83H ;KEY
.TEXT "KE"
.BYTE 'Y'+$80
.WORD EMIT-7
KEY: .WORD $+2
JP PKEY
;
.BYTE 89H ;?TERMINAL
.TEXT "?TERMINA"
.BYTE 'L'+$80
.WORD KEY-6
QTERM: .WORD $+2
LD HL,0
JP PQTER
;
.BYTE 82H ;CR
.BYTE 'C'
.BYTE 'R'+$80
.WORD QTERM-0CH
CR: .WORD $+2
JP PCR
;
.BYTE 85H ;CMOVE
.TEXT "CMOV"
.BYTE 'E'+$80
.WORD CR-5
CMOVE: .WORD $+2
EXX ;/ SAVE IP
POP BC ; (BC)<--(S1)= #CHRs
POP DE ; (DE)<--(S2)= DEST ADDR
POP HL ;/ (HL)<--(S3)= SOURCE ADDR
LD A,B
OR C ; BC=0?
JR Z,EXCMOV ; YES, DON'T MOVE ANYTHING
LDIR ;/ XFER STRING
EXCMOV: EXX ;/ RESTORE IP
JNEXT
;
.BYTE 86H ; >CMOVE 1.3
.TEXT ">CMOV"
.BYTE 'E'+$80
.WORD CMOVE-8
GCMOV .WORD $+2
EXX ; SAVE IP
POP BC ; (BC)<--(S1)= #CHRs
POP DE ; (DE)<--(S2)= DEST ADDR
POP HL ; (HL)<--(S3)= SOURCE ADDR
ADD HL,BC ; (HL) <- END SOURCE ADDR
EX DE,HL
ADD HL,BC ; (DE) <- END DEST ADDR
EX DE,HL
LD A,B
OR C ; BC=0?
JR Z,EXCMOV ; YES, DON'T MOVE ANYTHING
LDDR ; REVERSE XFER STRING
JR EXCMOV ;
;
.BYTE 82H ;U* 16*16 unsigned multiply
.BYTE 'U' ;994 T cycles average (8080)
.BYTE '*'+$80
.WORD GCMOV-9
USTAR: .WORD $+2
POP DE ;(DE)<--MPLIER
POP HL ;(HL)<--MPCAND
PUSH BC ;SAVE IP
LD B,H
LD A,L ;(BA)<--MPCAND
CALL MPYX ;(AHL)1<--MPCAND.LB*MPLIER
; 1st PARTIAL PRODUCT
PUSH HL ;SAVE (HL)1
LD H,A
LD A,B
LD B,H ;SAVE (A)1
CALL MPYX ;(AHL)2<--MPCAND.HB*MPLIER
; 2nd PARTIAL PRODUCT
POP DE ;(DE)<--(HL)1
LD C,D ;(BC)<--(AH)1
; FORM SUM OF PARTIALS:
; ; (AHL)1
; ;+(AHL)2
; ;-------
; ; (AHLE)
ADD HL,BC ;(HL)<--(HL)2+(AH)1
ADC A,00H ;(AHLE)<--(BA)*(DE)
LD D,L
LD L,H
LD H,A ;(HLDE)<--MPLIER*MPCAND
POP BC ;RESTORE IP
PUSH DE ;(S2)<--PRODUCT.LW
JHPUSH ;(S1)<--PRODUCT.HW
;
; MULTIPLY PRIMITIVE
; (AHL)<--(A)*(DE)
; #BITS: 24 8 16
;
MPYX: LD HL,0 ;(HL)<--0=PARTIAL PRODUCT.LW
LD C,08H ;LOOP COUNTER
MPYX1: ADD HL,HL ;LEFT SHIFT (AHL) 24 BITS
RLA
JR NC,MPYX2 ;IF NEXT MPLIER BIT = 1
ADD HL,DE ;THEN ADD MPCAND
ADC A,0
MPYX2: DEC C ;LAST MPLIER BIT?
JR NZ,MPYX1 ;NO, LOOP AGN
RET ;YES, DONE
;
.BYTE 82H ;U/
.BYTE 'U'
.BYTE '/'+$80
.WORD USTAR-5
USLAS: .WORD $+2
LD HL,0004H
ADD HL,SP ;((HL))<--NUMERATOR.LW
LD E,(HL) ;(DE)<--NUMER.LW
LD (HL),C ;SAVE IP ON STACK
INC HL
LD D,(HL)
LD (HL),B
POP BC ;(BC)<--DENOMINATOR
POP HL ;(HL)<--NUMER.HW
LD A,L
SUB C
LD A,H
SBC A,B ;NUMER >= DENOM?
JR C,USLA1 ;NO, GO AHEAD
LD HL,0FFFFH ;YES, OVERFLOW
LD D,H
LD E,L ;/ SET REM & QUOT TO MAX
JP USLA7
USLA1: LD A,10H ;LOOP COUNTER
USLA2: ADD HL,HL ;LEFT SHIFT (HLDE) THRU CARRY
RLA ;ROT CARRY INTO ACCU BIT 0
EX DE,HL
ADD HL,HL
JR NC,USLA3
INC DE ;ADD CARRY
AND A ;RESET CARRY
USLA3: EX DE,HL ;SHIFT DONE
RRA ;RESTORE 1st CARRY & COUNTER
JR NC,USLA4 ;IF CARRY=1
OR A ;/ RESET CARRY
SBC HL,BC ;/ THEN (HL)<--(HL)-(BC)
JP USLA5
USLA4: SBC HL,BC ;/ (HL)<--PARTIAL REMAINDER
JR NC,USLA5
ADD HL,BC ;UNDERFLOW, RESTORE
DEC DE
USLA5: INC DE ;INC QUOT
DEC A ;COUNTER=0?
JP NZ,USLA2 ;NO, LOOP AGN
USLA7: POP BC ;RESTORE IP
PUSH HL ;(S2)<--REMAINDER
PUSH DE ;(S1)<--QUOTIENT
JNEXT
;
.BYTE 85H ; U/MOD 1.3
.TEXT "U/MO" ; SAME AS U/
.BYTE 'D'+80H
.WORD USLAS-5
USLMD .WORD USLAS+2
;
.BYTE 83H ;AND
.TEXT "AN"
.BYTE 'D'+$80
.WORD USLMD-8
ANDD: .WORD $+2 ;(S1)<--(S1) AND (S2)
POP DE
POP HL
LD A,E
AND L
LD L,A
LD A,D
AND H
LD H,A
JHPUSH
;
.BYTE 82H ;OR
.BYTE 'O'
.BYTE 'R'+$80
.WORD ANDD-6
ORR: .WORD $+2 ;(S1)<--(S1) OR (S2)
POP DE
POP HL
LD A,E
OR L
LD L,A
LD A,D
OR H
LD H,A
JHPUSH
;
.BYTE 83H ;XOR
.TEXT "XO"
.BYTE 'R'+$80
.WORD ORR-5
XORR: .WORD $+2 ;(S1)<--(S1) XOR (S2)
POP DE
POP HL
LD A,E
XOR L
LD L,A
LD A,D
XOR H
LD H,A
JHPUSH
;
.BYTE 83H ;SP@
.TEXT "SP"
.BYTE '@'+$80
.WORD XORR-6
SPAT: .WORD $+2 ;(S1)<--(SP)
LD HL,0
ADD HL,SP ;(HL)<--(SP)
JHPUSH
;
.BYTE 83H ;SP!
.TEXT "SP"
.BYTE '!'+$80
.WORD SPAT-6
SPSTO: .WORD $+2 ;(SP)<--(S0) (USER VARIABLE)
LD HL,(UP) ;(HL)<--USER VAR BASE ADDR
LD DE,0006H
ADD HL,DE ;(HL)<--S0
LD E,(HL)
INC HL
LD D,(HL) ;(DE)<--(S0)
EX DE,HL
LD SP,HL ;(SP)<--(S0)
JNEXT
;
.BYTE 83H ;RP@
.TEXT "RP"
.BYTE '@'+$80
.WORD SPSTO-6
RPAT: .WORD $+2 ;(S1)<--(RP)
LD HL,(RPP)
JHPUSH
;
.BYTE 83H ;RP!
.TEXT "RP"
.BYTE '!'+$80
.WORD RPAT-6
RPSTO: .WORD $+2 ;(RP)<--(R0) (USER VARIABLE)
LD HL,(UP) ;(HL)<--USER VAR BASE ADDR
LD DE,0008H
ADD HL,DE ;(HL)<--R0
LD E,(HL)
INC HL
LD D,(HL) ;(DE)<--(R0)
LD (RPP),DE ;/ (RP)<--(R0)
JNEXT
;
.BYTE 82H ; ;S
.BYTE ';'
.BYTE 'S'+$80
.WORD RPSTO-6
SEMIS: .WORD $+2 ;(IP)<--(R1)
LD HL,(RPP)
LD C,(HL)
INC HL
LD B,(HL) ;(BC)<--(R1)
INC HL
LD (RPP),HL ;(RP)<--(RP)+2
JNEXT
;
.BYTE 84H ; EXIT 1.3
.TEXT "EXI"
.BYTE 'T'+80H
.WORD SEMIS-5
EXIT .WORD SEMIS+2
;
.BYTE 85H ;LEAVE
.TEXT "LEAV"
.BYTE 'E'+$80
.WORD EXIT-7
LEAVE: .WORD $+2 ;LIMIT<--INDEX
LD HL,(RPP)
LD E,(HL)
INC HL
LD D,(HL) ;(DE)<--(R1)=INDEX
INC HL
LD (HL),E
INC HL
LD (HL),D ;(R2)<--(DE)=LIMIT
JNEXT
;
.BYTE 82H ;>R
.BYTE '>'
.BYTE 'R'+$80
.WORD LEAVE-8
TOR: .WORD $+2
POP DE
LD HL,(RPP)
DEC HL
LD (HL),D
DEC HL
LD (HL),E ;/ (R1)<--(DE)
LD (RPP),HL ; (RP)<--(RP)
JNEXT
;
.BYTE 82H ;R>
.BYTE 'R'
.BYTE '>'+$80
.WORD TOR-5
FROMR: .WORD $+2
LD HL,(RPP)
LD E,(HL)
INC HL
LD D,(HL)
INC HL
LD (RPP),HL
PUSH DE ;(S1)<--(R1)
JNEXT
;
.BYTE 81H ;R
.BYTE 'R'+$80
.WORD FROMR-5
RR: .WORD IDO+2
;
.BYTE 82H ; R@ 1.3
.BYTE 'R'
.BYTE '@'+$80
.WORD RR-4
RAT .WORD IDO+2
;
.BYTE 82H ;0=
.BYTE '0'
.BYTE '='+$80
.WORD RAT-5
ZEQU: .WORD $+2
POP HL
LD A,L
OR H
LD HL,0
JR NZ,ZEQU1
INC L ;(HL)<--TRUE
ZEQU1: JHPUSH
;
.BYTE 82H ;0<
.BYTE '0'
.BYTE '<'+$80
.WORD ZEQU-5
ZLESS: .WORD $+2
POP AF ;/ (A)<--(S1)H
RLA ;/ (CARRY)<--BIT 7
LD HL,0 ; (HL)<--FALSE
JR NC,ZLES1
INC L ; (HL)<--TRUE
ZLES1: JHPUSH
;
.BYTE 81H ;+
.BYTE '+'+$80
.WORD ZLESS-5
PLUS: .WORD $+2
POP DE
POP HL
ADD HL,DE
JHPUSH
;
.BYTE 82H ;D+ ( d1L d1H d2L d2h -- d3L d3H)
.BYTE 'D'
.BYTE '+'+$80
.WORD PLUS-4
DPLUS: .WORD $+2
EXX ;/ SAVE IP
POP BC ; (BC)<--d2H
POP HL ; (HL)<--d2L
POP AF ;d (AF)<--d1H
POP DE ; (DE)<--d1L
PUSH AF ;/ (S1)<--d1H
ADD HL,DE ; (HL)<--d2L+d1L=d3L
EX DE,HL ; (DE)<--d3L
POP HL ; (HL)<--d1H
ADC HL,BC ;/ (HL)<--d1H+d2H+CARRY=d3H
PUSH DE ; (S2)<--d3L
PUSH HL ;/ (S1)<--d3H
EXX ;/ RESTORE IP
JNEXT
;
.BYTE 85H ;MINUS
.TEXT "MINU"
.BYTE 'S'+$80
.WORD DPLUS-5
MINUS: .WORD $+2
POP DE ;/
XOR A ;/ RESET CARRY, (A)<--0
LD H,A ;/
LD L,A ;/ LD HL,0
SBC HL,DE ;/ (HL)<--(DE)2's COMPL.
JHPUSH
;
.BYTE 86H ; NEGATE 1.3
.TEXT "NEGAT"
.BYTE 'E'+$80
.WORD MINUS-8
NEG .WORD MINUS+2
;
.BYTE 86H ;DMINUS
.TEXT "DMINU"
.BYTE 'S'+$80
.WORD NEG-9
DMINU: .WORD $+2
POP HL ;(HL)<--d1H
POP DE ;(DE)<--d1L
SUB A ;(A)<--0
SUB E
LD E,A ;(E)<--NEG(E)
LD A,00H
SBC A,D
LD D,A ;(D)<--NEG(D)
LD A,00H
SBC A,L
LD L,A ;(L)<--NEG(L)
LD A,00H
SBC A,H
LD H,A ;(H)<--NEG(H)
JP DPUSH ;(S2)<--d2L, (S1)<--d2H
;
.BYTE 84H ;OVER
.TEXT "OVE"
.BYTE 'R'+$80
.WORD DMINU-9
OVER: .WORD $+2
POP DE
POP HL
PUSH HL
JP DPUSH
;
.BYTE 84H ;DROP
.TEXT "DRO"
.BYTE 'P'+$80
.WORD OVER-7
DROP: .WORD $+2
POP HL
JNEXT
;
.BYTE 84H ;SWAP
.TEXT "SWA"
.BYTE 'P'+$80
.WORD DROP-7
SWAP: .WORD $+2
POP HL
EX (SP),HL
JHPUSH
;
.BYTE 83H ;DUP
.TEXT "DU"
.BYTE 'P'+$80
.WORD SWAP-7
DUP: .WORD $+2
POP HL
PUSH HL
JHPUSH
;
.BYTE 84H ;2DUP
.TEXT "2DU"
.BYTE 'P'+$80