mirror of
https://github.com/bobbimanners/Zapple-II.git
synced 2025-01-02 11:31:48 +00:00
3495 lines
60 KiB
Plaintext
3495 lines
60 KiB
Plaintext
;
|
|
; PROCESSOR TECHNOLOGY BASIC-5
|
|
; USING ZILOG OPCODES, COURTESY OF A SED FILE
|
|
;
|
|
; SYSTEM GLOBAL EQUATES
|
|
;
|
|
BDOS EQU 0005H ;ADDRESS OF JUMP TO BDOS
|
|
CONIN EQU 1 ;CONSOLE IN
|
|
CONOUT EQU 2 ;CONSOLE OUT
|
|
CONSTS EQU 11 ;CONSOLE STATUS
|
|
FPSIZ EQU 5
|
|
LINLEN EQU 73 ;# OF CHARS IN LEGAL INPUT LINE
|
|
FP123 EQU FPSIZ-2
|
|
FPNIB EQU FP123*2
|
|
DIGIT EQU FPNIB/2
|
|
CR EQU 15Q ;CARRIAGE RETURN
|
|
NULL EQU 0
|
|
LF EQU 12Q ;LINE FEED
|
|
ESC EQU 3Q ;CONTROL C
|
|
EOF EQU 1 ;END OF FILE
|
|
BELL EQU 7 ;BELL CHARACTER
|
|
STESIZ EQU 2+FPSIZ ;SYMBOL TABLE ELEMENT SIZE
|
|
OPBASE EQU '('
|
|
FTYPE EQU 1 ;CONTROL STACK FOR ENTRY TYPE
|
|
FORSZ EQU FPSIZ*2+2+2+1 ;'FOR' CONTROL STACK ENTRY SIZE
|
|
GTYPE EQU 2 ;CONTROL STACK GOSUB ENTRY TYPE
|
|
ETYPE EQU 0 ;CONTROL STACK UNDERFLOW TYPE
|
|
UMINUS EQU 61Q ;UNARY MINUS
|
|
;
|
|
; STARTUP BASIC SYSTEM
|
|
;
|
|
ORG 100H
|
|
;
|
|
START: LD SP,CMNDSP
|
|
XOR A
|
|
LD (NULLCT),A ;NULL COUNT.
|
|
LD HL,BASEND ;START OF USER MEMORY
|
|
LD (BOFA),HL ;IS RIGHT AFTER THE BASIC CODE.
|
|
LD HL,(BDOS+1) ;THE ADDRESS OF BDOS IS
|
|
DEC HL ; ** Bobbi / Qkumba fix **
|
|
LD (MEMTOP),HL ;THE END OF USER MEMORY.
|
|
ST0: LD HL,PLS ;"PROGRAM LOADED?" MESSAGE
|
|
CALL PRNT
|
|
CALL INLINE
|
|
LD A,(IBUF)
|
|
;
|
|
; OPTIONAL ENTRY POINT FOR TAPE OR DISK ROUTINES
|
|
;
|
|
; ALLOWS DIRECT PROGRAM INPUT FROM HIGH SPEED DEVICES
|
|
; SEE OPERATING INSTRUCTIONS FOR PROPER IMPLEMENTATION
|
|
;
|
|
STAR1: CP 'N'
|
|
JP Z,ST1 ;IF NO PROGRAM CLEAR AND INITIALIZE
|
|
CP 'Y'
|
|
JP NZ,ST0
|
|
LD HL,(BOFA)
|
|
ST2: LD A,(HL) ;FIND END OF PROGRAM
|
|
CP EOF
|
|
JP Z,ST3
|
|
CALL ADR
|
|
JP ST2
|
|
ST3: LD (EOFA),HL
|
|
CALL CCLEAR
|
|
JP ST4
|
|
ST1: CALL CSCR
|
|
ST4: LD A,2*FPNIB
|
|
LD (INFES),A
|
|
; INITIALIZE RANDOM NUMBER
|
|
LD DE,FRAND
|
|
LD HL,RANDS
|
|
CALL VCOPY ;FRAND=RANDOM NUMBER SEED
|
|
;
|
|
; COMMAND PROCESSOR
|
|
;
|
|
CMND1: CALL CRLF2
|
|
LD HL,RDYS ;PRINT READY MESSAGE
|
|
CALL PRNT
|
|
CMNDR: LD A,1 ;SET DIRECT INPUT FLAG
|
|
LD (DIRF),A
|
|
LD SP,CMNDSP
|
|
CALL CRLF
|
|
CMND2: CALL INLINE ;GET INPUT LINE FROM OPERATOR
|
|
CALL PP ;PRE-PROCESS IT
|
|
JP C,CMND3
|
|
CALL LINE ;LINE NUMBER...GO EDIT
|
|
JP CMND2
|
|
CMND3: CALL CMND4
|
|
JP CMNDR
|
|
CMND4: LD HL,IBUF ;POINT TO COMMAND OR STATEMENT
|
|
LD (TXA),HL
|
|
CALL GC
|
|
AND 240Q
|
|
CP 240Q ;CHECK FOR COMMAND
|
|
LD DE,CMNDD
|
|
JP Z,ISTA1 ;PROCESS COMMAND
|
|
CALL ISTAT ;PROCESS STATEMENT (IF ALLOWED)
|
|
CALL GCI
|
|
CP CR
|
|
RET Z
|
|
E1: LD BC,'BS'
|
|
JP ERROR
|
|
; ERROR MESSAGE PRINTOUT
|
|
E3: LD BC,'BA'
|
|
JP ERROR
|
|
E4: LD BC,'CS'
|
|
JP ERROR
|
|
E5: LD BC,'OB'
|
|
JP ERROR
|
|
E6: LD BC,'DM'
|
|
;
|
|
ERROR: PUSH BC
|
|
CALL CRLF
|
|
POP BC
|
|
CALL CHOUT
|
|
LD B,C
|
|
CALL CHOUT
|
|
LD HL,ERS
|
|
ERM1: CALL PRNT
|
|
LD A,(DIRF)
|
|
OR A
|
|
JP NZ,CMND1
|
|
LD HL,INS
|
|
CALL PRNT
|
|
; FIND LINE NUMBER
|
|
LD HL,(BOFA)
|
|
ERM2: LD B,H
|
|
LD C,L
|
|
LD E,(HL)
|
|
LD D,0
|
|
ADD HL,DE
|
|
EX DE,HL
|
|
LD HL,TXA
|
|
CALL DCMP
|
|
EX DE,HL
|
|
JP C,ERM2
|
|
INC BC
|
|
LD A,(BC)
|
|
LD L,A
|
|
INC BC
|
|
LD A,(BC)
|
|
LD H,A
|
|
LD DE,IBUF ;USE IBUF TO ACCUMULATE THE LINE NUMBER STRING
|
|
CALL CNS
|
|
LD A,CR
|
|
LD (DE),A
|
|
LD HL,IBUF
|
|
CALL PRNTCR
|
|
JP CMND1
|
|
;
|
|
; LINE EDITOR
|
|
;
|
|
LINE: LD HL,(BOFA) ;CHECK FOR EMPTY FILE
|
|
FIN: LD A,(HL) ;CHECK IF APPENDING LINE AT END
|
|
DEC A
|
|
JP Z,APP
|
|
EX DE,HL
|
|
INC DE
|
|
LD HL,(IBLN) ;GET INPUT LINE NUMBER
|
|
EX DE,HL
|
|
CALL DCMP ;COMPARE WITH FILE LINE NUMBER
|
|
DEC HL
|
|
JP C,INSR ;LESS THAN
|
|
JP Z,INSR ;EQUAL
|
|
LD A,(HL) ;LENGTH OF LINE
|
|
CALL ADR ;JUMP FORWARD
|
|
JP FIN
|
|
; APPEND LINE AT END CASE
|
|
APP: LD A,(IBCNT) ;DON'T APPEND NULL LINE
|
|
CP 4
|
|
RET Z
|
|
CALL FULL ;CHECK FOR ROOM IN FILE
|
|
LD HL,(EOFA) ;PLACE LINE IN FILE
|
|
CALL IMOV
|
|
LD (HL),EOF
|
|
LD (EOFA),HL
|
|
RET
|
|
; INSERT LINE IN FILE CASE
|
|
INSR: LD B,(HL) ;OLD LINE COUNT
|
|
LD (INSA),HL ;INSERT LINE POINTER
|
|
LD A,(IBCNT) ;NEW LINE COUNT
|
|
JP C,LT ;JMP IF NEW LINE # NOT = OLD LINE NUMBER
|
|
SUB 4
|
|
JP Z,LT1 ;TEST IF SHOULD DELETE NULL LINE
|
|
ADD A,4
|
|
LT1: SUB B
|
|
JP Z,LIN1 ;LINE LENGTHS EQUAL
|
|
JP C,GT
|
|
; EXPAND FILE FOR NEW OR LARGER LINE
|
|
LT: LD B,A
|
|
LD A,(IBCNT)
|
|
CP 4 ;DON'T INSERT NULL LINE
|
|
RET Z
|
|
LD A,B
|
|
CALL FULL
|
|
LD HL,(INSA)
|
|
CALL NMOV
|
|
LD HL,(EOFA)
|
|
EX DE,HL
|
|
LD (EOFA),HL
|
|
INC BC
|
|
CALL RMOV
|
|
JP LIN1
|
|
; CONTRACT FILE FOR SMALLER LINE
|
|
GT: CPL
|
|
INC A
|
|
CALL ADR
|
|
CALL NMOV
|
|
EX DE,HL
|
|
LD HL,(INSA)
|
|
CALL NZ,LMOV
|
|
LD (HL),EOF
|
|
LD (EOFA),HL
|
|
; INSERT CURRENT LINE INTO FILE
|
|
LIN1: LD HL,(INSA)
|
|
LD A,(IBCNT)
|
|
CP 4
|
|
RET Z
|
|
; INSERT CURRENT LINE AT ADDR HL
|
|
IMOV: LD DE,IBCNT
|
|
LD A,(DE)
|
|
LD C,A
|
|
LD B,0
|
|
; COPY BLOCK FROM BEGINNING
|
|
; HL IS DEST ADDR, DE IS SOURCE ADDR, BC IS COUNT
|
|
LMOV: LD A,(DE)
|
|
LD (HL),A
|
|
INC DE
|
|
INC HL
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JP NZ,LMOV
|
|
RET
|
|
; COPY BLOCK STARTING AT END
|
|
; HL IS DEST, DE IS SOURCE, BC IS COUNT
|
|
RMOV: LD A,(DE)
|
|
LD (HL),A
|
|
DEC HL
|
|
DEC DE
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JP NZ,RMOV
|
|
RET
|
|
; COMPUTE FILE MOVE COUNT
|
|
; BC GETS (EOFA) - (HL), RET Z SET MEANS ZERO COUNT
|
|
NMOV: LD A,(EOFA)
|
|
SUB L
|
|
LD C,A
|
|
LD A,(EOFA+1)
|
|
SBC A,H
|
|
LD B,A
|
|
OR C
|
|
RET
|
|
; ADD A TO HL
|
|
ADR: ADD A,L
|
|
LD L,A
|
|
RET NC
|
|
INC H
|
|
RET
|
|
; CHECK FOR FILE OVERFLOW, LEAVES NEW EOFA IN DE
|
|
; A HAS INCREASE IN SIZE
|
|
FULL: LD HL,(EOFA)
|
|
CALL ADR
|
|
EX DE,HL
|
|
LD HL,MEMTOP
|
|
CALL DCMP
|
|
JP NC,E8
|
|
RET
|
|
;
|
|
; COMMANDS
|
|
;
|
|
CSCR: LD HL,(BOFA)
|
|
LD (HL),EOF
|
|
LD (EOFA),HL
|
|
; "CLEAR"
|
|
CCLEAR: LD HL,(EOFA) ;CLEAR FROM EOFA TO MEMTOP
|
|
INC HL
|
|
LD (MATA),HL
|
|
EX DE,HL
|
|
LD HL,MEMTOP ;END OF ASSIGNED MEMORY
|
|
CCLR1: XOR A
|
|
LD (DE),A
|
|
CALL DCMP
|
|
INC DE
|
|
JP NZ,CCLR1
|
|
LD HL,(MEMTOP)
|
|
LD (STAA),HL
|
|
LD HL,CSTKL+CSTKSZ-1
|
|
LD (HL),ETYPE
|
|
LD (CSTKA),HL
|
|
LD HL,ASTKL+ASTKSZ+FPSIZ-1
|
|
LD (ASTKA),HL
|
|
RET
|
|
; "NULL"
|
|
CNULL: CALL INTGER
|
|
JP C,E3 ;NO ARGUMENT SUPPLIED
|
|
LD A,L
|
|
LD (NULLCT),A
|
|
JP CMND1
|
|
; "LIST"
|
|
CLIST: CALL GC
|
|
CP CR
|
|
LD DE,0
|
|
JP Z,CL0 ;JUMP IF NO ARGUMENT SUPPLIED
|
|
CALL INTGER ;ERROR DEFAULT IS LIST
|
|
CL0: LD HL,(BOFA)
|
|
CL1: LD A,(HL)
|
|
DEC A
|
|
RET Z
|
|
INC HL
|
|
CALL DCMP
|
|
DEC HL ;POINT TO COUNT CHAR AGAIN
|
|
JP C,CL2
|
|
JP Z,CL2
|
|
; INCREMENT TO NEXT LINE
|
|
LD A,(HL)
|
|
CALL ADR
|
|
JP CL1
|
|
CL2: PUSH DE
|
|
LD DE,IBUF ;AREA TO UNPREPROCESS TO
|
|
CALL UPPL
|
|
INC HL
|
|
PUSH HL
|
|
LD HL,IBUF
|
|
CALL PRNTCR
|
|
CALL PCHECK
|
|
CALL CRLF
|
|
POP HL
|
|
POP DE
|
|
JP CL1
|
|
; "RUN"
|
|
CRUN: CALL CCLEAR
|
|
LD HL,(BOFA)
|
|
LD A,(HL)
|
|
DEC A ;CHECK FOR NULL PROGRAM
|
|
JP Z,ENDX
|
|
INC HL
|
|
INC HL
|
|
INC HL
|
|
LD (TXA),HL
|
|
LD (RTXA),HL ;POINTER FOR 'READ' STATEMENT
|
|
XOR A
|
|
LD (DIRF),A ;CLEAR DIRECT FLAG AND FALL THROUGH TO DRIVER
|
|
CALL CRLF
|
|
;
|
|
; INTERPRETER DRIVER
|
|
;
|
|
ILOOP: CALL PCHECK
|
|
CALL ISTAT ;INTERPRET CURRENT STATEMENT
|
|
CALL JOE ;TEST FOR JUNK ON END
|
|
JP NC,ILOOP ;CONTINUE IF NOT AT END OF PROGRAM
|
|
JP ENDX ;EXECUTE END STATEMENT
|
|
; INTERPRET STATEMENT LOCATED BY TXA
|
|
ISTAT: CALL GC ;GET FIRST NON BLANK
|
|
OR A
|
|
JP P,LET ;MUST BE LET IF NOT RW
|
|
CP IRWLIM ;IS IT AN INITIAL RW
|
|
JP NC,E1
|
|
LD DE,STATD ;STATEMENT DISPATCH TABLE BASE
|
|
ISTA1: CALL GCI ;ADVANCE TEXT POINTER
|
|
AND 37Q
|
|
RLCA ;MULTIPLY BY TWO PREPARING FOR TABLE LOOKUP
|
|
LD L,A
|
|
LD H,0
|
|
ADD HL,DE
|
|
CALL LHLI
|
|
JP (HL) ;BRANCK TO STATEMENT OR COMMAND
|
|
;
|
|
; STATEMENTS
|
|
;
|
|
; "LET"
|
|
LET: CALL VAR ;CHECK FOR VARIABLE
|
|
JP C,E1
|
|
PUSH HL ;SAVE VALUE ADDRESS
|
|
LD B,EQRW
|
|
CALL EATC
|
|
CALL EXPRB
|
|
POP DE ;DESTINATION ADDRESS
|
|
CALL POPA1 ;COPY EXPR VALUE TO VARIABLE
|
|
RET ;******* CALL, RET???!!!****************
|
|
; "FOR"
|
|
SFOR: CALL DIRT
|
|
CALL VAR ;CONTROL VARIABLE
|
|
JP C,E1
|
|
PUSH HL ;CONTROLVARIABLE VALUE ADDRESS
|
|
LD B,EQRW
|
|
CALL EATC
|
|
CALL EXPRB ;INITIAL VALUE
|
|
POP DE ;VARIABLE VALUE ADDRESS
|
|
PUSH DE ;SAVE
|
|
CALL POPA1 ;SET INITIAL VALUE
|
|
LD B,TORW ;RW FOR 'TO'
|
|
CALL EATC
|
|
CALL EXPRB ;LIMIT VALUE COMPUTATION
|
|
CALL GC ;CHECK NEXT CHARACTER FOR POSSIBLE STEP EXPR
|
|
CP STEPRW
|
|
JP Z,FOR1
|
|
; USE STEP OF 1
|
|
LD DE,FPONE
|
|
CALL PSHA1
|
|
JP FOR2
|
|
; COMPUTE STEP VALUE
|
|
FOR1: CALL GCI ;EAT THE STEP RW
|
|
CALL EXPRB ;THE STEP VALUE
|
|
; HERE THE STEP AND LIMIT ARE ON THE ARG STACK
|
|
FOR2: LD DE,-2 ;PREPARE TO ALLOCATE 2 BYTES ON CONTROL STACK
|
|
CALL PSHCS ;RETURNS ADDRESS OF THOSE 2 BYTES IN HL
|
|
EX DE,HL
|
|
CALL JOE ;TEST FOR JUNK ON END
|
|
JP C,E4 ;NO "FOR" STATEMENT AT END OF PROGRAM
|
|
EX DE,HL ;DE HAS LOOP TEST ADDR, HL HAS CONTROL STACK ADR
|
|
LD (HL),D ;HIGH ORDER TEXT ADDRESS BYTE
|
|
DEC HL
|
|
LD (HL),E ;LOW ORDER TEXT ADDRESS BYTE
|
|
LD DE,-FPSIZ ;ALLOCATE SPACE FOR LIMIT ON CONTROL STACK
|
|
CALL PSHCS
|
|
PUSH HL ;ADDR ON CONTROL STACK FOR LIMIT
|
|
LD DE,-FPSIZ ;ALLOCATE SPACE FOR STEP ON CONTROL STACK
|
|
CALL PSHCS
|
|
CALL POPAS ;COPY STEP VALUE TO CONTROL STACK
|
|
POP DE ;CONTROL STACK ADDR FOR LIMIT VLAUE
|
|
CALL POPA1 ;LIMIT VALUE TO CONTROL STACK
|
|
LD DE,-3 ;ALLOCATE SPACE FOR TEST ADDRESS AND CS ENTRY
|
|
CALL PSHCS
|
|
POP DE ;CONTROL VARIABLE ADDRESS
|
|
LD (HL),D ;HIGH ORDER BYTE OF CONTROL VAR ADDR
|
|
DEC HL
|
|
LD (HL),E ;LOW ORDER BYTE
|
|
DEC HL
|
|
LD (HL),FTYPE ;SET CONTROL STACK ENTRY TYPE FOR "FOR"
|
|
JP NEXT5 ;GO FINISH OFF CAREFULLY
|
|
; "NEXT"
|
|
NEXT: CALL DIRT
|
|
LD HL,(CSTKA) ;CONTROL STACK ADDRESS
|
|
LD A,(HL) ;STACK ENTRY TYPE BYTE
|
|
DEC A ;MUST BE FOR TYPE ELSE ERROR
|
|
JP NZ,E4 ;IMPROPER NEXTING ERROR
|
|
INC HL ;CONTROL STACK POINTER TO CONTROL VAR ADDR
|
|
PUSH HL
|
|
CALL VAR ;CHECK VARIABLE, IN CASE USER WANTS
|
|
JP C,NEXT1 ;SKIP CHECK IF VAR NOT THERE
|
|
EX DE,HL
|
|
POP HL ;CONTROL VARIABLE ADDRESS
|
|
PUSH HL ;SAVE IT AGAIN
|
|
CALL DCMP
|
|
JP NZ,E4 ;IMPROPER NESTING IF NOT THE SAME
|
|
NEXT1: POP HL ;CONTROL VARIABLE ADDRESS
|
|
PUSH HL
|
|
PUSH HL
|
|
LD DE,FPSIZ+2-1 ;COMPUTE ADDRESS TO STEP VALUE
|
|
ADD HL,DE
|
|
EX (SP),HL ;NOW ADDRESS TO VAR IN HL
|
|
CALL LHLI ;VARIABLE ADDRESS
|
|
LD B,H ;COPY VAR ADDRESS TO BC
|
|
LD C,L
|
|
POP DE ;STEP VALUE ADDRESS
|
|
PUSH DE
|
|
CALL FADD ;DO INCREMENT
|
|
POP HL ;STEP VALUE
|
|
DEC HL ;POINT TO SIGN OF STEP VALUE
|
|
LD A,(HL) ;SIGN 0=POS, 1=NEG
|
|
LD DE,FPSIZ+1
|
|
ADD HL,DE ;PUTS LIMIT ADDRESS IN HL
|
|
EX DE,HL
|
|
POP HL ;VARIABLE ADDRESS
|
|
CALL LHLI ;GET ADDRESS
|
|
PUSH DE ;SAVE CONTROL STACK POINTER TO GET TEXT ADDR
|
|
OR A ;SET CONDITIONS BASED ON SIGN OF STEP VALUE
|
|
JP Z,NEXT2 ;REVERSE TEST ON NEGATIVE STEP VALUE
|
|
EX DE,HL
|
|
NEXT2: LD B,H ;SET UP ARGS FOR COMPARE
|
|
LD C,L
|
|
CALL RELOP ;TEST <=
|
|
POP DE ;TEXT ADDRESS
|
|
JP M,NEXT3 ;STILL SMALLER?
|
|
JP Z,NEXT3 ;JUMP IF WANT TO CONTINUE LOOP
|
|
; TERMINATE LOOP
|
|
LD HL,3 ;REMOVE CSTACK ENTRY
|
|
ADD HL,DE
|
|
LD (CSTKA),HL
|
|
RET
|
|
NEXT3: INC DE ;TEXT ADDRESS
|
|
EX DE,HL
|
|
CALL LHLI ;GET TEXT ADDRESS IN HL
|
|
; ITERATE, SKIPPING NORMAL JUNK ON END TEST AT ILOOP
|
|
NEXT4: EX DE,HL ;SAVE NEW TEXT ADDRESS IN DE
|
|
CALL JOE
|
|
EX DE,HL
|
|
NEXT6: LD (TXA),HL
|
|
NEXT5: LD HL,ILOOP
|
|
EX (SP),HL
|
|
RET ;TO DISPATCHER SKIPPING JOE CALL THERE
|
|
; "IF"
|
|
SIF: LD B,1 ;SPECIFY PRINCIPAL OPERATOR IS RELATIONAL
|
|
CALL EXPB1
|
|
LD HL,(ASTKA) ;ADDRESS ON BOOLEAN VALUE ON ARG STACK
|
|
INC (HL) ;SETS ZERO CONDITION IF RELATIONAL TEST TRUE
|
|
PUSH AF ;SAVE CONDITIONS TO TEST LATER
|
|
CALL POPAS ;REMOVE VALUE FROM ARG STACK COPY TO SELF
|
|
POP AF
|
|
JP NZ,REM ;IF TEST FALSE TREAT REST OF STATEMENT AS REM
|
|
; TEST SUCCEEDED
|
|
LD B,THENRW
|
|
CALL EATC
|
|
CALL INTGER ;CHECK IF LINE NUMBER IS DESIRED ACTION
|
|
JP C,ISTAT
|
|
JP GOTO1
|
|
; "GOTO"
|
|
SGOTO: XOR A
|
|
LD (DIRF),A ;CLEAR DIRECT STATEMENT FLAG
|
|
CALL INTGER ;RETURNS INTEGER IN HL IF LINE NUMBER PRESENT
|
|
JP C,E1 ;SYNTAX ERROR NO LINE NUMBER
|
|
GOTO1: EX DE,HL ;LN IN DE
|
|
CALL FINDLN ;RETURNS TEST ADDRESS POINTS TO COUNT VALUE
|
|
GOTO2: INC HL
|
|
INC HL
|
|
INC HL ;ADVANCE TEXT POINTER PAST LINE NUMBER ANDCOUNT
|
|
JP NEXT4
|
|
; "GOSUB"
|
|
GOSUB: CALL DIRT
|
|
LD DE,-3 ;CREATE CONTROL STACK ENTRY
|
|
CALL PSHCS
|
|
PUSH HL ;SAVE STACK ADDRESS
|
|
CALL INTGER
|
|
JP C,E1
|
|
EX DE,HL ;LINE NUMBER TO DE
|
|
CALL JOE
|
|
LD B,H
|
|
LD C,L
|
|
POP HL ;STACK ADDRESS
|
|
LD (HL),B ;STACK RETURN ADDRESS RETURNED BY JOE
|
|
DEC HL
|
|
LD (HL),C
|
|
DEC HL
|
|
LD (HL),GTYPE ;MAKE CONTROL STACK ENTRY TYPE "GOSUB"
|
|
CALL FINDLN
|
|
INC HL
|
|
INC HL
|
|
INC HL
|
|
JP NEXT6
|
|
; "RETURN"
|
|
RETRN: CALL DIRT
|
|
LD (DIRF),A ;CLEARS DIRF IN ACC IS CLEAR
|
|
LD HL,(CSTKA)
|
|
RET1: LD A,(HL)
|
|
OR A ;CHECK FOR STACK EMPTY
|
|
JP Z,E4
|
|
CP GTYPE ;CHECK FOR GOSUB TYPE
|
|
JP Z,RET2
|
|
; REMOVE FOR TYPE ENTRY FROM STACK
|
|
LD DE,FORSZ
|
|
ADD HL,DE
|
|
JP RET1
|
|
; FOUND A GTYPE STACK ENTRY
|
|
RET2: INC HL
|
|
LD E,(HL) ;LOW ORDER TEXT ADDRESS
|
|
INC HL
|
|
LD D,(HL) ;HIGH ORDER TEXT ADDRESS
|
|
INC HL ;ADDRESS OF PREVIOUS CONTROL STACK ENTRY
|
|
LD (CSTKA),HL
|
|
EX DE,HL ;PUT TEXT ADDRESS IN HL
|
|
LD A,(HL) ;ADDRESS POINTS TO EOF IF GOSUB WAS LAST LINE
|
|
DEC A ;END OF FILE?
|
|
JP NZ,NEXT4
|
|
JP ENDX
|
|
; "DATA" AND "REM"
|
|
DATA: CALL DIRT ;DATA STATEMENT ILLEGAL AS DIRECT
|
|
REM: CALL GCI
|
|
CP CR
|
|
JP NZ,REM
|
|
DEC HL ;BACKUP POINTER SO NORMAL JOE WILL WORK
|
|
LD (TXA),HL
|
|
RET
|
|
; "DIM"
|
|
DIM: CALL NAME ;LOOK FOR VARIABLE NAME
|
|
JP C,E1
|
|
LD A,C ;PREPARE TURN ON 80H BIT TO SIGNIFY MATRIX
|
|
OR 80H
|
|
LD C,A
|
|
CALL STLK
|
|
JP NC,E6 ;ERROR IF NAME ALREADY EXISTS
|
|
PUSH HL ;SYMBOL TABLE ADDRESS
|
|
LD B,LPARRW
|
|
CALL EATC
|
|
CALL EXPRB
|
|
LD B,')'
|
|
CALL EATC
|
|
CALL PFIX ;RETURN INTEGER IN DE
|
|
LD HL,MATUB ;MAXIMUM SIZE FORM MATRIX
|
|
CALL DCMP
|
|
JP NC,E6
|
|
POP HL ;SYMBOL TABLE ADDRESS
|
|
CALL DIMS
|
|
CALL GC ;SEE IF MORE TO DO
|
|
CP ','
|
|
RET NZ
|
|
CALL GCI ;EAT THE COMMA
|
|
JP DIM
|
|
; "STOP"
|
|
STOP: CALL DIRT
|
|
STOP1: CALL CRLF2
|
|
LD (BRKCHR),A
|
|
LD HL,STOPS
|
|
JP ERM1
|
|
; "END"
|
|
ENDX EQU CMND1
|
|
; "READ"
|
|
READ: CALL DIRT
|
|
LD HL,(TXA)
|
|
PUSH HL ;SAVE TXA TEMPORARILY
|
|
LD HL,(RTXA) ;THE 'READ' TXA
|
|
READ0: LD (TXA),HL
|
|
CALL GCI
|
|
CP ','
|
|
JP Z,READ2 ;PROCESS INPUT VALUE
|
|
CP DATARW
|
|
JP Z,READ2
|
|
DEC A
|
|
JP Z,READ4
|
|
; SKIP TO NEXT LINE
|
|
CALL REM ;LEAVES ADDRESS OF LAST CR IN HL
|
|
INC HL
|
|
LD A,(HL)
|
|
DEC A
|
|
JP Z,READ4
|
|
INC HL
|
|
INC HL
|
|
INC HL ;HL NOW POINTS TO FIRST BYTE ON NEXT LINE
|
|
JP READ0
|
|
; PROCESS VALUE
|
|
READ2: CALL EXPRB
|
|
CALL GC
|
|
CP ',' ;SKIP JOE TEST IF COMMA
|
|
JP Z,READ3
|
|
; JUNK ON END TEST
|
|
CALL JOE
|
|
READ3: LD HL,(TXA)
|
|
LD (RTXA),HL ;SAVE NEW "READ" TEXT ADDRESS
|
|
POP HL ;REAL TXA
|
|
LD (TXA),HL
|
|
CALL VAR
|
|
JP C,E1
|
|
CALL POPAS ;PUT READ VALUE INTO VARIABLE
|
|
CALL GC
|
|
CP ',' ;CHECK FOR ANOTHER VARIABLE
|
|
RET NZ
|
|
CALL GCI ;EAT THE COMMA
|
|
JP READ
|
|
READ4: POP HL ;PROGRAM TXA
|
|
LD (TXA),HL
|
|
LD BC,'RD'
|
|
JP ERROR
|
|
; "RESTORE"
|
|
RESTOR: LD HL,(BOFA) ;BEGINNING OF FILE POINTER
|
|
INC HL
|
|
INC HL
|
|
INC HL
|
|
LD (RTXA),HL
|
|
RET
|
|
; "PRINT"
|
|
PRINT: CALL GC
|
|
CP CR ;CHECK FOR STAND ALONE PRINT
|
|
JP Z,CRLF
|
|
PRIN2: CP '"'
|
|
JP Z,PSTR ;PRINT THE STRING
|
|
CP TABRW
|
|
JP Z,PTAB ;TABULATION
|
|
CP '%'
|
|
JP Z,PFORM ;SET FORMAT
|
|
CP CR
|
|
RET Z
|
|
CP ';'
|
|
RET Z
|
|
CALL EXPRB ;MUST BE EXPRESSION TO PRINT
|
|
LD DE,FPSINK
|
|
CALL POPA1 ;POP VALUE TO FPSINK
|
|
LD A,(PHEAD)
|
|
CP 56
|
|
CALL NC,CRLF ;DO CRLF IF PRINT HEAD IS PAST 56
|
|
LD HL,FPSINK
|
|
CALL FPOUT
|
|
LD B,' '
|
|
CALL CHOUT
|
|
PR1: CALL GC ;GET DELIMITER
|
|
CP ','
|
|
JP NZ,CRLF
|
|
PR0: CALL GCI
|
|
CALL GC
|
|
JP PRIN2
|
|
PSTR: CALL GCI ;GOBBLE THE QUOTE
|
|
CALL PRNT ;PRINT UP TO DOUBLE QUOTE
|
|
INC HL ;MOVE POINTER PAST DOUBLE QUOTE
|
|
LD (TXA),HL
|
|
JP PR1
|
|
PFORM: LD A,2*FPNIB
|
|
LD (INFES),A
|
|
CALL GCI ;GOBBLE PREVIOUS CHAR
|
|
PFRM1: CALL GCI
|
|
LD HL,INFES
|
|
CP '%' ;DELIMITER
|
|
JP Z,PR1
|
|
LD B,80H
|
|
CP 'Z' ;TRAILING ZEROS?
|
|
JP Z,PF1
|
|
LD B,1
|
|
CP 'E' ;SCIENTIFIC NOTATION?
|
|
JP Z,PF1
|
|
CALL NMCHK
|
|
JP NC,E1
|
|
SUB '0' ;NUMBER OF DECIMAL PLACES
|
|
RLCA
|
|
LD B,A
|
|
LD A,(HL)
|
|
AND 301Q
|
|
LD (HL),A
|
|
PF1: LD A,(HL)
|
|
OR B
|
|
LD (HL),A
|
|
JP PFRM1
|
|
PTAB: CALL GCI ;GOBBLE TAB RW
|
|
LD B,LPARRW
|
|
CALL EATC
|
|
CALL EXPRB
|
|
LD B,')'
|
|
CALL EATC
|
|
CALL PFIX
|
|
PTAB1: LD A,(PHEAD)
|
|
CP E
|
|
JP NC,PR1
|
|
LD B,' '
|
|
CALL CHOUT
|
|
JP PTAB1
|
|
; "INPUT"
|
|
INPUT: CALL GC
|
|
CP ','
|
|
JP Z,NCRLF
|
|
CALL CRLF
|
|
INP0: LD B,'?'
|
|
CALL CHOUT
|
|
LINP: CALL INLINE
|
|
LD DE,IBUF
|
|
IN1: PUSH DE ;SAVE FOR FPIN
|
|
CALL VAR
|
|
JP C,E1
|
|
POP DE
|
|
LD B,0
|
|
LD A,(DE)
|
|
CP '+' ;LOOK FOR LEADING PLUS OR MINUS ON INPUT
|
|
JP Z,IN2
|
|
CP '-'
|
|
JP NZ,IN3
|
|
LD B,1
|
|
IN2: INC DE
|
|
IN3: PUSH BC
|
|
PUSH HL
|
|
CALL FPIN ;INPUT FP NUMBER
|
|
JP C,INERR
|
|
POP HL
|
|
DEC HL
|
|
POP AF
|
|
LD (HL),A
|
|
CALL GC
|
|
CP ','
|
|
RET NZ ;DONE IF NO MORE
|
|
CALL GCI ;EAT THE COMMA
|
|
LD A,B ;GET THE TERMINATOR TO A
|
|
CP ','
|
|
JP Z,IN1 ;GET THE NEXT INPUT VALUE FROM STRING
|
|
; GET NEW LINE FROM USER
|
|
LD B,'?'
|
|
CALL CHOUT
|
|
JP INP0
|
|
NCRLF: CALL GCI
|
|
JP LINP ;NOW GET LINE
|
|
INERR: LD BC,'IN'
|
|
JP ERROR
|
|
;
|
|
; EVALUATE AN EXPRESSION FROM TEXT
|
|
; HL TAKE OP TABLE ADDR OF PREVIOUS OPERATOR (NOT CHANGED)
|
|
; RESULT VALUE LEFT ON TOP OF ARG STACK, ARGF LEFT TRUE
|
|
;
|
|
EXPRB: LD B,0
|
|
EXPB1: LD HL,OPBOL
|
|
XOR A
|
|
LD (RELTYP),A
|
|
; ZERO IN B MEANS PRINCIPAL OPERATOR MAY NOT BE RELATIONAL
|
|
EXPR: PUSH BC
|
|
PUSH HL ;PUSH OPTBA
|
|
XOR A
|
|
LD (ARGF),A
|
|
EXPR1: LD A,(ARGF)
|
|
OR A
|
|
JP NZ,EXPR2
|
|
CALL VAR ;LOOK FOR VARIABLE PERHAPS SUBSCRIPTED
|
|
CALL NC,PSHAS
|
|
JP NC,EXPR2
|
|
CALL CONST
|
|
JP NC,EXPR2
|
|
CALL GC
|
|
CP LPARRW
|
|
LD HL,OPLPAR
|
|
JP Z,XLPAR
|
|
; ISN'T OR SHOULDN'T BE AN ARGUMENT
|
|
EXPR2: CALL GC
|
|
CP 340Q ;CHECK FOR RESERVED WORD OPERATOR
|
|
JP NC,XOP
|
|
CP 300Q ;CHECK FOR BUILT IN FUNCTION
|
|
JP NC,XBILT
|
|
; ILLEGAL EXPRESSION CHARACTER
|
|
POP HL ;GET OPTBA
|
|
LD A,(ARGF)
|
|
OR A
|
|
JP Z,E1
|
|
XDON1: POP AF
|
|
LD HL,RELTYP ;CHECK IF LEGAL PRINCIPAL OPERATOR
|
|
CP (HL)
|
|
RET Z
|
|
JP E1
|
|
XOP: AND 37Q ;CLEANS OFF RW BITS
|
|
LD HL,(ARGF) ;TEST FOR ARGF TRUE
|
|
DEC L
|
|
JP Z,XOP1
|
|
; ARGF WAS FALSE, UNARY OPS ONLY POSSIBILITY
|
|
CP '-'-OPBASE
|
|
JP Z,XOPM
|
|
CP '+'-OPBASE
|
|
JP NZ,E1
|
|
CALL GCI ;EAT THE '+'
|
|
JP EXPR1
|
|
XOPM: LD A,UMINUS-OPBASE
|
|
XOP1: CALL OPADR
|
|
POP DE ;PREVIOUS OPTBA
|
|
LD A,(DE)
|
|
CP (HL)
|
|
JP NC,XDON1 ;NON-INCREASING PRECEDENCE
|
|
; INCREASING PRECEDENCE CASE
|
|
PUSH DE ;SAVE PREVIOUS OPTBA
|
|
PUSH HL ;SAVE CURRENT OPTBA
|
|
CALL GCI ;TO GOBBLE OPERATOR
|
|
POP HL
|
|
PUSH HL
|
|
LD B,0 ;SPECIFY NON-RELATIONAL
|
|
CALL EXPR
|
|
POP HL
|
|
; HL HAS OPTBA ADDRESS
|
|
; SET UP ARGS AND PERFORM OPERATION ACTION
|
|
XOP2: PUSH HL
|
|
LD A,(HL)
|
|
LD HL,(ASTKA)
|
|
LD B,H
|
|
LD C,L
|
|
AND 1
|
|
JP NZ,XOP21
|
|
; DECREMENT STACK POINTER BY ONE VALUE BINARY CASE
|
|
LD DE,FPSIZ
|
|
ADD HL,DE
|
|
LD (ASTKA),HL
|
|
LD D,H
|
|
LD E,L
|
|
XOP21: LD HL,EXPR1
|
|
EX (SP),HL ;CHANGE RETURN LINK
|
|
INC HL ;SKIP OVER PRECEDENCE
|
|
CALL LHLI ;LOAD ACTION ADDRESS
|
|
JP (HL)
|
|
;
|
|
; ACTION ROUTINE CONVENTION
|
|
; DE LEFT ARG AND RESULT FOR BINARY
|
|
; BC RIGHT ARG FOR BINARY, ARG AND RESULT FOR UNARY
|
|
;
|
|
; INTRINSIC FUNCTION PROCESSING
|
|
;
|
|
XBILT: CALL GCI ;EAT TOKEN
|
|
AND 77Q ;CLEAN OFF RW BITS
|
|
LD HL,(ARGF) ;BUILT IN FUNCTION MUST COME AFTER OPERATOR
|
|
DEC L
|
|
JP Z,E1
|
|
CALL OPADR ;OPTBA TO HL
|
|
XLPAR: PUSH HL
|
|
LD B,LPARRW
|
|
CALL EATC
|
|
CALL EXPRB
|
|
LD B,')'
|
|
CALL EATC
|
|
POP HL ;CODE FOR BUILT-IN FUNCTION
|
|
JP XOP2
|
|
; COMPUTE OPTABLE ADDRESS FOR OPERATOR IN ACC
|
|
OPADR: LD C,A
|
|
LD B,0
|
|
LD HL,OPTAB
|
|
ADD HL,BC
|
|
ADD HL,BC
|
|
ADD HL,BC ;OPTAB ENTRY ADDR IS 3*OP+BASE
|
|
RET
|
|
;
|
|
; PREPROCESSOR, UN-PREPROCESSOR
|
|
; PREPROCESS LINE IN IBUF BACK INTO IBUF
|
|
; SETS CARRY IF LINE HAS NO LINE NUMBER
|
|
; LEAVES CORRECT LENGTH OF LINE AFTER PREPROCESSING IN IBCN
|
|
; IF THERE IS A LINE NUMBER, IT IS LOCATED AT IBLN=IBUF-2
|
|
; TXA IS CLOBBERED
|
|
;
|
|
PP: LD HL,IBUF ;FIRST CHARACTER OF INPUT LINE
|
|
LD (TXA),HL ;SO GCI WILL WORK
|
|
CALL INTGER ;SETS CARRY IF NO LINE NUMBER
|
|
LD (IBLN),HL ;STORE LINE NUMBER VALUE(EVEN IF NONE)
|
|
PUSH AF ;SAVE STATE OF CARRY BIT FOR RETURNING
|
|
LD HL,(TXA) ;ADDRESS OF NEXT CHARACTER IN IBUF
|
|
LD C,4 ;SET UP INITIAL VALUE FOR COUNT
|
|
LD DE,IBUF ;INITIALIZE WRITE POINTER
|
|
; COME HERE TO CONTINUE PREPROCESSING
|
|
PPL: PUSH DE
|
|
LD DE,RWT ;BASE OF RWT
|
|
PPL1: PUSH HL ;SAVE TEXT ADDRESS
|
|
LD A,(DE) ;RW VALUE FOR THIS ENTRY IN RWT
|
|
LD B,A ;SAVE IN B IN CASE OF MATCH
|
|
PPL2: INC DE ;ADVANCE ENTRY POINTER TO NEXT BYTE
|
|
LD A,(DE) ;GET NEXT CHARACTER FROM ENTRY
|
|
CP (HL) ;COMPARE WITH CHARACTER IN TEXT
|
|
JP NZ,PPL3
|
|
INC HL ;ADVANCE TEXT POINTER
|
|
JP PPL2 ;CONTINUE COMPARISON
|
|
; COME HERE WHEN COMPARISON OF BYTE FAILED
|
|
PPL3: OR A
|
|
JP M,PPL6 ;JUMP IF FOUND MATCH
|
|
; SCAN TO BEGINNING ON NEXT ENTRY
|
|
PPL4: INC DE ;ADVANCE ENTRY POINTER
|
|
LD A,(DE) ;NEXT BYTE IS EITHER CHARACTER OR RW BYTE
|
|
OR A
|
|
JP P,PPL4 ;KEEP SCANNING IF NOT RW BYTE
|
|
; NOW SEE IF AT END OF TABLE, AND FAIL OR RETURN CONDITION
|
|
POP HL ;RECOVER ORIGINAL TEXT POINTER
|
|
XOR -1 ;CHECK FOR END OF TABLE BYTE
|
|
JP NZ,PPL1 ;CONTINUE SCAN OF TABLE
|
|
; DIDN'T FIND AN ENTRY AT THE GIVER TEXT ADR
|
|
POP DE
|
|
LD A,(HL) ;GET THE TEXT CHARACTER
|
|
CP CR ;CHECK FOR END OF LINE
|
|
JP Z,PPL8 ;GO CLEAN UP AND RETURN
|
|
LD (DE),A
|
|
INC DE
|
|
INC C
|
|
INC HL ;ADVANCE TEXT POINTER
|
|
CP '"' ;CHECK FOR QUOTED STRING POSSIBILITY
|
|
JP NZ,PPL ;RESTART RWT SEARCH AT NEXT CHARACTER POSITION
|
|
; HERE WE HAVE A QUOTED STRING, SO EAT TILL ENDQUOTE
|
|
PPL5: LD A,(HL) ;NEXT CHARACTER
|
|
CP CR
|
|
JP Z,PPL8 ;NO STRING ENDQUOTE, LET INTERPRETER WORRY
|
|
LD (DE),A
|
|
INC DE
|
|
INC C
|
|
INC HL ;ADVANCE TEXT POINTER
|
|
CP '"'
|
|
JP Z,PPL ;BEGIN RWT SCAN FROM NEW CHARACTER POSITION
|
|
JP PPL5
|
|
; FOUND MATCH SO PUT RW VALUE IN TEXT
|
|
PPL6: POP AF ;REMOVE UNNEEDED TEST POINTER FROM STACK
|
|
POP DE
|
|
LD A,B
|
|
LD (DE),A
|
|
INC DE
|
|
INC C
|
|
JP PPL
|
|
; COME HERE WHEN DONE
|
|
PPL8: LD A,CR
|
|
LD (DE),A
|
|
LD HL,IBCNT ;SET UP COUNT IN CASE LINE OF LINE NUMBER
|
|
LD (HL),C
|
|
POP AF ;RESTORE CARRY CONDITION (LINE NUMBER FLAG)
|
|
RET
|
|
;
|
|
; UN-PREPROCESS LINE ADDRESSES IN HL TO DE BUFFER
|
|
; RETURN SOURCE ADDRESS OF CR IN HL ON RETURN
|
|
;
|
|
UPPL: INC HL ;SKIP OVER COUNT BYTE
|
|
PUSH HL ;SAVE SOURCE TEXT POINTER
|
|
CALL LHLI ;LOAD LINE NUMBER VALUE
|
|
CALL CNS ;CONVERT LINE NUMBER
|
|
LD A,' '
|
|
LD (DE),A ;PUT BLANK AFTER LINE NUMBER
|
|
INC DE ;INCREMENT DESTINATION POINTER
|
|
POP HL
|
|
INC HL ;INCREMENT H PAST LINE NUMBER
|
|
UPP0: INC HL
|
|
LD A,(HL) ;NEXT TOKEN IN SOURCE
|
|
OR A
|
|
JP M,UPP1 ;JUMP IF TOKEN IS RW
|
|
LD (DE),A ;PUT CHARACTER IN BUFFER
|
|
CP CR ;CHECK FOR DONE
|
|
RET Z
|
|
INC DE ;ADVANCE DESTINATION BUFFER ADDRESS
|
|
JP UPP0
|
|
; COME HERE WHEN RW BYTE DETECTED IN SOURCE
|
|
UPP1: PUSH HL ;SAVE SOURCE POINTER
|
|
LD HL,RWT ;BASE OF RWT
|
|
UPP2: CP (HL) ;SEE IF RW MATCHED RWT ENTRY
|
|
INC HL ;ADVANCE RWT POINTER
|
|
JP NZ,UPP2 ;CONTINUE LOOKING IF NOT FOUND
|
|
; FOUND MATCH, ENTRY POINTER LOCATES FIRST CHARACTER
|
|
UPP3: LD A,(HL) ;CHARACTER OF RW
|
|
OR A ;CHECK FOR DONE
|
|
JP M,UPP4
|
|
LD (DE),A
|
|
INC DE
|
|
INC HL
|
|
JP UPP3
|
|
; COME HERE IF DONE WITH RW TRANSFER
|
|
UPP4: POP HL ;SOURCE POINTER
|
|
JP UPP0
|
|
;
|
|
; CONSTANTS AND TABLES
|
|
;
|
|
RDYS: DEFM 'READY"'
|
|
PLS: DEFM 'PROGRAM LOADED? "'
|
|
ERS: DEFM ' ERROR"'
|
|
INS: DEFM ' IN LINE "'
|
|
STOPS: DEFM 'STOP"'
|
|
;
|
|
DEFB 0FFH ;FLAGS END OF SINE COEFFICIENT LIST
|
|
DEFB 0
|
|
DEFB 1*16
|
|
DEFW 0
|
|
DEFB 0
|
|
FPONE: DEFB 129 ;EXPONENT
|
|
; SINE COEFFICIENT LIST
|
|
; NOTE: THE FLOATING PNT 1 ABOVE IS A PART OF THIS TABLE
|
|
DEFB 16H
|
|
DEFB 66H
|
|
DEFB 67H
|
|
DEFB 1
|
|
DEFB 128 ;-.166667 E 0 (-1/3!)
|
|
DEFB 83H
|
|
DEFB 33H
|
|
DEFB 33H
|
|
DEFB 0
|
|
DEFB 128-2 ;.833333 E-2 (1/5!)
|
|
DEFB 19H
|
|
DEFB 84H
|
|
DEFB 13H
|
|
DEFB 1
|
|
DEFB 128-3 ;-.198413 E-3 (-1/7!)
|
|
DEFB 27H
|
|
DEFB 55H
|
|
DEFB 73H
|
|
DEFB 0
|
|
DEFB 128-5 ;.275573 E-5 (1/9!)
|
|
DEFB 25H
|
|
DEFB 5
|
|
DEFB 21H
|
|
DEFB 1
|
|
SINX: DEFB 128-7 ;-.250521 E-7 (-1/11!)
|
|
; COSINE COEFFICIENT LIST
|
|
DEFB 0FFH ;MARKS END OF LIST
|
|
DEFB 0
|
|
DEFB 10H
|
|
DEFB 0
|
|
DEFB 0
|
|
DEFB 0
|
|
DEFB 128+1 ;/100000 E 1 (1/1!)
|
|
DEFB 50H
|
|
DEFB 0
|
|
DEFB 0
|
|
DEFB 1
|
|
MATUB: DEFB 128 ;-.500000 E 0 (-1/2!)
|
|
DEFB 41H
|
|
DEFB 66H
|
|
DEFB 67H
|
|
DEFB 0
|
|
RANDS: DEFB 128-1 ;.416667 E-1 (1/4!)
|
|
DEFB 13H
|
|
DEFB 88H
|
|
DEFB 89H
|
|
DEFB 1
|
|
DEFB 128-2 ;-.138889 E-2 (-1/6!)
|
|
DEFB 24H
|
|
DEFB 80H
|
|
DEFB 16H
|
|
DEFB 0
|
|
DEFB 128-4 ;.248016 E-4 (1/8!)
|
|
DEFB 27H
|
|
DEFB 55H
|
|
DEFB 73H
|
|
DEFB 1
|
|
COSX: DEFB 128-6 ;-.275573 E-6 (-1/10!)
|
|
DEFB 20H
|
|
DEFW 0
|
|
DEFB 0
|
|
FPTWO: DEFB 129
|
|
DEFB 15H
|
|
DEFB 70H
|
|
DEFB 80H
|
|
DEFB 0
|
|
PIC2: DEFB 128+1 ;PI/2
|
|
DEFB 63H
|
|
DEFB 66H
|
|
DEFB 20H
|
|
DEFB 0
|
|
PIC1: DEFB 128 ;2/PI
|
|
LCSTKA: DEFW CSTKL
|
|
;
|
|
; COMMAND TABLE
|
|
;
|
|
CMNDD: DEFW CRUN ; 0
|
|
DEFW CLIST ; 1
|
|
DEFW CNULL ; 2
|
|
DEFW CSCR ; 3
|
|
DEFW START ; 4 SET UP MEMORY BOUNDS
|
|
DEFW TSAV ; 5 TAPE SAVE
|
|
DEFW TLOAD ; 6 TAPE LOAD
|
|
; STATEMENT TABLE
|
|
STATD: DEFW LET ; 0
|
|
DEFW NEXT ; 1
|
|
DEFW SIF ; 2
|
|
DEFW SGOTO ; 3
|
|
DEFW GOSUB ; 4
|
|
DEFW RETRN ; 5
|
|
DEFW READ ; 6
|
|
DEFW DATA ; 7
|
|
DEFW SFOR ; 10
|
|
DEFW PRINT ; 11
|
|
DEFW INPUT ; 12
|
|
DEFW DIM ; 13
|
|
DEFW STOP ; 14
|
|
DEFW ENDX ; 15
|
|
DEFW RESTOR ; 16
|
|
DEFW REM ; 17
|
|
DEFW CCLEAR ; 20
|
|
;
|
|
; R/W WORD TABLE FORMAT IS RESERVED WORD FOLLOWED BY CHR
|
|
; OF RESERVED WORD. LAST ENTRY IS FOLLOWED BY A 377Q
|
|
; RW'S THAT ARE SUBSTRINGS OF OTHER RW'S (E.G. >) MUST
|
|
; FOLLOW THE LARGER WORD.
|
|
;
|
|
RWT: DEFB 200Q
|
|
DEFM 'LET'
|
|
DEFB 201Q
|
|
DEFM 'NEXT'
|
|
DEFB 202Q
|
|
DEFM 'IF'
|
|
DEFB 203Q
|
|
DEFM 'GOTO'
|
|
DEFB 204Q
|
|
DEFM 'GOSUB'
|
|
DEFB 205Q
|
|
DEFM 'RETURN'
|
|
DEFB 206Q
|
|
DEFM 'READ'
|
|
DEFB 207Q
|
|
DEFM 'DATA'
|
|
DATARW EQU 207Q
|
|
DEFB 210Q
|
|
DEFM 'FOR'
|
|
DEFB 211Q
|
|
DEFM 'PRINT'
|
|
DEFB 211Q
|
|
DEFM ':'
|
|
DEFB 212Q
|
|
DEFM 'INPUT'
|
|
DEFB 213Q
|
|
DEFM 'DIM'
|
|
DEFB 214Q
|
|
DEFM 'STOP'
|
|
DEFB 215Q
|
|
DEFM 'END'
|
|
DEFB 216Q
|
|
DEFM 'RESTORE'
|
|
DEFB 217Q
|
|
DEFM 'REM'
|
|
DEFB 220Q
|
|
DEFM 'CLEAR'
|
|
CLRRW EQU 220Q
|
|
IRWLIM EQU 221Q ;LAST INITIAL RESERVED WORD VALUE+1
|
|
DEFB 237Q
|
|
DEFM 'STEP'
|
|
STEPRW EQU 237Q
|
|
DEFB 236Q
|
|
DEFM 'TO'
|
|
TORW EQU 236Q
|
|
DEFB 235Q
|
|
DEFM 'THEN'
|
|
THENRW EQU 235Q
|
|
DEFB 234Q
|
|
DEFM 'TAB'
|
|
TABRW EQU 234Q
|
|
DEFB 240Q
|
|
DEFM 'RUN'
|
|
RUNRW EQU 240Q
|
|
DEFB 241Q
|
|
DEFM 'LIST'
|
|
LISTRW EQU 241Q
|
|
DEFB 242Q
|
|
DEFM 'NULL'
|
|
NULLRW EQU 242Q
|
|
DEFB 243Q
|
|
DEFM 'SCR'
|
|
SCRRW EQU 243Q
|
|
DEFB 244Q
|
|
DEFM 'MEM'
|
|
MEMRW EQU 245Q ;******* WRONG CODE?*******
|
|
DEFB 245Q
|
|
DEFM 'TSAV'
|
|
DEFB 246Q
|
|
DEFM 'TLOAD'
|
|
LPARRW EQU '('-OPBASE+340Q
|
|
DEFB LPARRW
|
|
DEFB '('
|
|
DEFB '*'-OPBASE+340Q
|
|
DEFB '*'
|
|
PLSRW EQU '+'-OPBASE+340Q
|
|
DEFB PLSRW
|
|
DEFB '+'
|
|
MINRW EQU '-'-OPBASE+340Q
|
|
DEFB MINRW
|
|
DEFB '-'
|
|
DEFB '/'-OPBASE+340Q
|
|
DEFB '/'
|
|
DEFB 67Q-OPBASE+340Q
|
|
DEFM '>='
|
|
DEFB 70Q-OPBASE+340Q
|
|
DEFM '<='
|
|
DEFB 71Q-OPBASE+340Q
|
|
DEFM '<>'
|
|
DEFB 62Q-OPBASE+340Q
|
|
DEFM '=>'
|
|
DEFB 63Q-OPBASE+340Q
|
|
DEFM '=<'
|
|
DEFB '<'-OPBASE+340Q
|
|
DEFB '<'
|
|
EQRW EQU '='-OPBASE+340Q
|
|
DEFB EQRW
|
|
DEFB '='
|
|
DEFB '>'-OPBASE+340Q
|
|
DEFB '>'
|
|
DEFB 301Q
|
|
DEFM 'ABS'
|
|
DEFB 306Q
|
|
DEFM 'INT'
|
|
DEFB 314Q
|
|
DEFM 'ARG'
|
|
DEFB 315Q
|
|
DEFM 'CALL'
|
|
DEFB 316Q
|
|
DEFM 'RND'
|
|
DEFB 322Q
|
|
DEFM 'SGN'
|
|
DEFB 323Q
|
|
DEFM 'SIN'
|
|
DEFB 304Q
|
|
DEFM 'SQR'
|
|
DEFB 327Q
|
|
DEFM 'TAN'
|
|
DEFB 330Q
|
|
DEFM 'COS'
|
|
DEFB 377Q
|
|
;
|
|
; OPERATION TABLE
|
|
;
|
|
OPTAB: DEFB 15
|
|
OPLPAR EQU OPTAB
|
|
DEFW ALPAR
|
|
DEFB 15
|
|
DEFW AABS
|
|
DEFB 10
|
|
DEFW AMUL
|
|
DEFB 6
|
|
DEFW AADD
|
|
DEFB 15
|
|
DEFW ASQR
|
|
DEFB 6
|
|
DEFW ASUB
|
|
DEFB 15
|
|
DEFW AINT
|
|
DEFB 10
|
|
DEFW ADIV
|
|
OPBOL: DEFB 1
|
|
DEFW 0
|
|
DEFB 13
|
|
DEFW ANEG
|
|
DEFB 4
|
|
DEFW AGE
|
|
DEFB 4
|
|
DEFW ALE
|
|
DEFB 15
|
|
DEFW AARG
|
|
DEFB 15
|
|
DEFW ACALL
|
|
DEFB 15
|
|
DEFW ARND
|
|
DEFB 4
|
|
DEFW AGE
|
|
DEFB 4
|
|
DEFW ALE
|
|
DEFB 4
|
|
DEFW ANE
|
|
DEFB 15
|
|
DEFW ASGN
|
|
DEFB 15
|
|
DEFW ASIN
|
|
DEFB 4
|
|
DEFW ALT
|
|
DEFB 4
|
|
DEFW AEQ
|
|
DEFB 4
|
|
DEFW AGT
|
|
DEFB 15
|
|
DEFW ATAN
|
|
DEFB 15
|
|
DEFW ACOS
|
|
;
|
|
; ACTION ROUTINES FOR RELATIONAL OPERATORS
|
|
;
|
|
AGT: CALL RELOP
|
|
JP Z,RFALSE
|
|
JP M,RTRUE
|
|
RFALSE: XOR A
|
|
LD (DE),A
|
|
RET
|
|
ALT: CALL RELOP
|
|
JP Z,RFALSE
|
|
JP M,RFALSE
|
|
RTRUE: LD A,-1
|
|
LD (DE),A
|
|
RET
|
|
AEQ: CALL RELOP
|
|
JP Z,RTRUE
|
|
JP RFALSE
|
|
ANE: CALL RELOP
|
|
JP Z,RFALSE
|
|
JP RTRUE
|
|
AGE: CALL RELOP
|
|
JP Z,RTRUE
|
|
JP M,RTRUE
|
|
JP RFALSE
|
|
ALE: CALL RELOP
|
|
JP Z,RTRUE
|
|
JP M,RFALSE
|
|
JP RTRUE
|
|
;
|
|
; COMMON ROUTINE FOR RELATIONAL OPERATOR ACTION
|
|
; LEFT ARG ADDR IN DE, SAVED
|
|
; RIGHT ARG ADDR IN BC
|
|
; ON RETURN SIGN SET=GT, ZERO SET =EQUAL
|
|
;
|
|
RELOP: PUSH DE
|
|
DEC BC
|
|
DEC DE
|
|
LD H,B
|
|
LD L,C
|
|
LD A,(DE)
|
|
SUB (HL)
|
|
INC HL
|
|
INC DE
|
|
JP NZ,RLOP1 ;TEST SIGNS OF ARGS IF DIFFERENT THEN RET
|
|
LD BC,FPSINK
|
|
CALL FSUB
|
|
LD A,(FPSINK) ;CHECK FOR ZERO RESULT
|
|
OR A
|
|
JP Z,RLOP1
|
|
LD A,(FPSINK-1) ;SIGN OF FPSINK
|
|
RLCA
|
|
DEC A
|
|
RLOP1: LD A,1
|
|
LD (RELTYP),A ;SET RELTYP TRUE
|
|
POP DE
|
|
RET
|
|
;
|
|
; ACTION ROUTINES FOR ARITHMETIC OPERATORS
|
|
; (CODE WASTERS)
|
|
;
|
|
AADD: LD H,B
|
|
LD L,C
|
|
LD B,D
|
|
LD C,E
|
|
AADD1: CALL FADD
|
|
JP FPETST
|
|
ASUB: LD H,B
|
|
LD L,C
|
|
LD B,D
|
|
LD C,E
|
|
ASUB1: CALL FSUB
|
|
JP FPETST
|
|
AMUL: LD H,B
|
|
LD L,C
|
|
LD B,D
|
|
LD C,E
|
|
AMUL1: CALL FMUL
|
|
JP FPETST
|
|
ADIV: LD H,B
|
|
LD L,C
|
|
LD B,D
|
|
LD C,E
|
|
ADIV1: CALL FDIV
|
|
FPETST: XOR A
|
|
LD (RELTYP),A
|
|
LD A,(ERRI)
|
|
OR A
|
|
RET Z
|
|
LD HL,(ASTKA) ;ZERO RESULT ON UNDERFLOW
|
|
FPET1: LD (HL),0
|
|
ALPAR: RET
|
|
;
|
|
; UNARY AND BUILT IN FUNCTION ROUTINES
|
|
;
|
|
ANEG: LD A,(BC)
|
|
OR A
|
|
JP Z,ANEG1
|
|
DEC BC
|
|
LD A,(BC)
|
|
XOR 1
|
|
LD (BC),A
|
|
ANEG1: XOR A
|
|
LD (RELTYP),A
|
|
RET
|
|
AABS: DEC BC
|
|
XOR A
|
|
LD (BC),A
|
|
JP ANEG1
|
|
ASGN: CALL ANEG1
|
|
LD D,B
|
|
LD E,C
|
|
LD A,(BC) ;GET EXPONENT
|
|
OR A
|
|
JP NZ,ASGN1
|
|
LD (DE),A ;MAKE ARGUMENT ZERO
|
|
RET
|
|
ASGN1: DEC BC
|
|
LD A,(BC)
|
|
OR A
|
|
LD HL,FPONE
|
|
JP Z,VCOPY
|
|
LD HL,FPNONE
|
|
JP VCOPY
|
|
;
|
|
; COMPUTE SIN(X) X=TOP OF ARGUMENT STACK
|
|
; RETURN RESULT IN PLACE OF X
|
|
;
|
|
ASIN: CALL QUADC ;COMPUTE QUADRANT
|
|
LD HL,(ASTKA)
|
|
LD D,H
|
|
LD E,L
|
|
LD BC,FTEMP
|
|
CALL AMUL1 ;FTEMP=X*X
|
|
POP AF
|
|
PUSH AF ;A=QUADRANT
|
|
RRA
|
|
JP C,SIN10 ;QUAD. ODD, COMPUTE COSINE
|
|
; COMPUTE X*P(X*X) -- SINE
|
|
LD DE,FTEM1
|
|
LD HL,(ASTKA)
|
|
CALL VCOPY ;FTEM1=X*X
|
|
LD BC,SINX
|
|
CALL POLY ;P(X*X)
|
|
CALL PREPOP
|
|
LD HL,FTEM1
|
|
CALL AMUL1 ;X*P(X*X)
|
|
; COMPUTE SIGN OF RESULT
|
|
; POSITIVE FOR QUADRANTS 0,1. NEGATIVE FOR 2,3
|
|
; NEGATE ABOVE FOR NEGATIVE ARGUMENTS
|
|
;
|
|
SIN5: POP AF ;QUADRANT
|
|
LD B,A
|
|
POP AF ;SIGN
|
|
RLCA ;SIGN, 2 TO THE 1ST BIT
|
|
XOR B ;QUADRANT, MAYBE MODIFIED FOR NEG. ARGUMENT
|
|
LD HL,(ASTKA)
|
|
DEC HL ;PTR TO SIGN
|
|
SUB 2
|
|
RET M ;QUADRANT 0 OR 1
|
|
INC (HL) ;ELSE SET RESULT NEGATIVE
|
|
RET
|
|
; COMPUTE P(X*X) -- COSINE
|
|
SIN10: LD BC,COSX
|
|
CALL POLY ;P(X*X)
|
|
JP SIN5
|
|
;
|
|
; COMPUTE COS(X) X=TOP OF ARGUMENT STACK
|
|
; RETURN RESULT IN PLACE OF X
|
|
; COS(X) = SIN(X+PI/2)
|
|
;
|
|
ACOS: CALL PREPOP
|
|
LD HL,PIC2 ;PI/2
|
|
CALL AADD1 ;TOS=TOS+PI/2
|
|
JP ASIN
|
|
;
|
|
; COMPUTE TAN(X) X=TOP OF ARGUMENT STACK
|
|
; RETURN RESULT IN PLACE OF X
|
|
; TAN(X)=SIN(X)/COS(X)
|
|
;
|
|
ATAN: LD HL,(ASTKA)
|
|
CALL PSHAS ;PUSH COPY OF X ONTO ARG STACK
|
|
CALL ACOS ;COS(X)
|
|
LD DE,FTEM2
|
|
CALL POPA1 ;FTEM2=COS(X)
|
|
CALL ASIN
|
|
CALL PREPOP
|
|
LD HL,FTEM2
|
|
JP ADIV1 ;SIN(X)/COS(X)
|
|
;
|
|
; COMPUTE SQR(X) X=TOP OF ARGUMENT STACK
|
|
; RETURN RESULT IN PLACE OF X
|
|
;
|
|
ASQR: LD HL,(ASTKA)
|
|
LD DE,FTEMP
|
|
CALL VCOPY ;SAVE X IN FTEMP
|
|
; COMPUTE EXPONENT OF FIRST GUESS AS EXPONENT OF X/2
|
|
LD HL,(ASTKA)
|
|
LD A,(HL)
|
|
OR A
|
|
RET Z ;X=0
|
|
SUB 128
|
|
JP M,SQR5 ;NEGATIVE EXPONENT
|
|
RRCA
|
|
AND 127
|
|
JP SQR6
|
|
SQR5: CPL
|
|
INC A
|
|
RRCA
|
|
AND 127
|
|
CPL
|
|
INC A
|
|
SQR6: ADD A,128
|
|
LD (HL),A
|
|
; TEST FOR NEGATIVE ARGUMENT
|
|
DEC HL
|
|
LD A,(HL)
|
|
LD BC,'NA'
|
|
OR A
|
|
JP NZ,ERROR ;NEGATIVE ARGUMENT
|
|
;
|
|
; DO NEWTON'S METHOD
|
|
; NEWGUESS=(X/OLDGUESS + OLDGUESS)/2
|
|
LD A,6 ;DO 6 ITERATIONS
|
|
SQR20: PUSH AF ;SET NEW ITERATION COUNT
|
|
LD BC,FTEM1
|
|
LD DE,FTEMP ;FTEMP IS 'X'
|
|
LD HL,(ASTKA) ;GUESS
|
|
CALL ADIV1 ;FTEM1=X/GUESS
|
|
LD DE,FTEM1
|
|
LD HL,(ASTKA)
|
|
LD B,H
|
|
LD C,L
|
|
CALL AADD1 ;TOS=(X/GUESS)+GUESS
|
|
CALL PREPOP
|
|
LD HL,FPTWO
|
|
CALL ADIV1 ;TOS=(X/GUESS+GUESS)/2
|
|
POP AF
|
|
DEC A ;DECREMENT COUNT
|
|
JP NZ,SQR20 ;DO ANOTHER ITERATION
|
|
RET
|
|
;
|
|
; COMPUTE RND(X) X=TOP OF ARGUMENT STACK
|
|
; FRAND IS UPDATED TO NEW RANDOM VALUE
|
|
; A RANDOM NUMBER IN THE RANGE 0<RND<1 IS RETURNED IN PLACE
|
|
;
|
|
ARND: CALL PREPOP
|
|
LD DE,FRAND
|
|
LD HL,FRAND
|
|
CALL AMUL1 ;TOS=FRAND*FRAND
|
|
; SET EXPONENT = 0
|
|
LD HL,(ASTKA)
|
|
LD (HL),128 ;EXPONENT = 128 (0 IN EXTERNAL FORM)
|
|
; PERMUTE DIGITS OF X AS
|
|
; 123456 INTO 345612
|
|
LD BC,-4
|
|
ADD HL,BC
|
|
LD B,(HL) ;SAVE 12
|
|
INC HL
|
|
INC HL
|
|
CALL PERMU ;56=12
|
|
CALL PERMU ;34=56
|
|
CALL PERMU ;12=34
|
|
; NORMALIZE NUMBER
|
|
RND5: LD HL,(ASTKA) ;TOS
|
|
LD BC,-FPSIZ+1
|
|
ADD HL,BC
|
|
LD A,(HL) ;FIRST DIGIT PAIR
|
|
AND 15*16
|
|
JP NZ,RND10 ;NUMBER IS NORMALIZED
|
|
; SHIFT LEFT ONE DIGIT
|
|
LD HL,(ASTKA)
|
|
LD A,(HL) ;EXPONENT
|
|
DEC A
|
|
LD (EXP),A
|
|
CALL LOAD ;TOS INTO TEMP
|
|
LD B,4
|
|
CALL LEFT ;SHIFT LEFT
|
|
CALL PREPOP
|
|
CALL STORE
|
|
JP RND5 ;TEST IF NORMALIZED
|
|
; SAVE NEW RANDOM NUMBER IN FRAND CELL
|
|
RND10: LD DE,FRAND
|
|
LD HL,(ASTKA)
|
|
CALL VCOPY ;FRAND = TOS
|
|
RET ;*****************CALL, RET????!!!!******
|
|
; PERMUTE DIGIT PAIRS
|
|
PERMU: LD A,(HL)
|
|
LD (HL),B
|
|
LD B,A
|
|
DEC HL
|
|
RET
|
|
;
|
|
; EVALUATE P(X) USING HORNER'S METHOD (X IS IN FTEMP)
|
|
; COEFFICIENT LIST POINTER IS IN BC
|
|
; RESULT REPLACES NUMBER ON TOP OF ARGUMENT STACK (Y)
|
|
;
|
|
POLY: LD HL,(ASTKA)
|
|
EX DE,HL ;DE=PTR TO Y
|
|
LD H,B
|
|
LD L,C ;HL PTR TO COEFFICIENT LIST
|
|
CALL VCOPY ;Y=FIRST COEFFICIENT
|
|
; MULTIPLY BY X
|
|
POLY1: PUSH HL ;SAVE COEFF LIST POINTER
|
|
CALL PREPOP
|
|
LD HL,FTEMP
|
|
CALL AMUL1 ;Y=Y*X
|
|
; ADD NEXT COEFF
|
|
CALL PREPOP
|
|
POP HL
|
|
PUSH HL ;HL = COEFF LIST POINTER
|
|
CALL AADD1 ;Y=Y+COEFF
|
|
; BUMP POINTER TO NEXT COEFFICIENT
|
|
POP HL ;COEFF POINTER
|
|
LD BC,-FPSIZ-1
|
|
ADD HL,BC ;NEXT COEFF SIGN
|
|
LD A,(HL)
|
|
INC HL ;PTR TO EXPONENT
|
|
OR A
|
|
JP P,POLY1 ;PROCESS NEXT COEFFICIENT
|
|
RET ;NEGATIVE SIGN (-1) ENDS LIST
|
|
;
|
|
; PREPARE FOR OPERATION
|
|
;
|
|
PREPOP: LD HL,(ASTKA)
|
|
EX DE,HL ;DE=ASTKA
|
|
LD B,D
|
|
LD C,E
|
|
RET
|
|
;
|
|
; QUADRANT COMPUTATION
|
|
; POPS TOP OF ARGUMENT STACK
|
|
; COMPUTE/GETS SIGN OF ARGUMENT, QUADRANT OF ARGUMENT
|
|
; AND INDEX INTO QUADRANT
|
|
;
|
|
; EXITS WITH:
|
|
; SP POINTING TO QUADRANT, MOD 4
|
|
; SP+2 POINTING TO SIGN OF ARGUMENT
|
|
; TOP OF ARGUMENT STACK HAS INDEX INTO QUADRANT
|
|
;
|
|
QUADC: LD HL,(ASTKA)
|
|
DEC HL ;POINT TO SIGN
|
|
LD B,(HL)
|
|
XOR A
|
|
LD (HL),A ;ARG. SIGN=0
|
|
LD H,B
|
|
EX (SP),HL ;PUT SIGN ON STACK, POP RETURN
|
|
PUSH HL ;PUSH RETURN
|
|
; COMPUTE QUADRANT OF ABS(X)
|
|
LD HL,(ASTKA)
|
|
CALL PSHAS ;PUT COPY OF ARG ONOT STACK
|
|
CALL PREPOP
|
|
LD HL,PIC1 ;2/PI
|
|
CALL AMUL1 ;TOS=X*2/PI
|
|
CALL PREPOP
|
|
CALL AINT ;TOS=INT(X*2/PI)
|
|
LD HL,(ASTKA)
|
|
CALL PSHAS ;ANOTHER COPY
|
|
CALL PFIX ;POP TOS TO DE
|
|
LD A,E
|
|
PUSH AF ;QUADRANT
|
|
CALL PREPOP
|
|
LD HL,PIC2
|
|
CALL AMUL1 ;TOS=INT(X*2/PI)
|
|
LD DE,FTEMP
|
|
CALL POPA1 ;FTEMP=TOS
|
|
CALL PREPOP
|
|
LD HL,FTEMP
|
|
CALL ASUB1 ;TOS=TOS-FTEMP
|
|
POP AF ;A=QUADRANT, LOW ORDER BYTE
|
|
AND 3 ;MOD 4
|
|
POP HL ;POP RETURN OFF STACK
|
|
PUSH AF ;SAVE QUADRANT ON STACK
|
|
JP (HL) ;DO RETURN
|
|
; SET UP ARG FOR USER CALL
|
|
AARG: CALL PFIX
|
|
EX DE,HL
|
|
LD (CALLA),HL
|
|
LD DE,FPSINK
|
|
JP PSHA1 ;PUTS BACK THE ARG VALUE ON ARG STACK
|
|
; USED TO CALL USER ROUTINE
|
|
ACALL: CALL PFIX ;GET THE ADDRESS
|
|
LD HL,(CALLA) ;GET THE USER ARGUMENT
|
|
EX DE,HL
|
|
LD BC,ACAL1 ;RETURN LINK FOR USER ROUTINE
|
|
PUSH BC
|
|
JP (HL)
|
|
ACAL1: LD DE,CALST
|
|
CALL CNS
|
|
LD A,CR
|
|
LD (DE),A
|
|
LD DE,CALST
|
|
LD HL,FPSINK
|
|
CALL FPIN
|
|
LD DE,FPSINK
|
|
JP PSHA1 ;PUT THE RETURNED USER VALUE ON ARG STACK
|
|
;
|
|
; INT FUNCTION ACTION ROUTINE
|
|
;
|
|
AINT: LD A,(BC)
|
|
SUB 129
|
|
JP P,AINT1
|
|
; ZERO IF VALUE LESS THAN 1
|
|
XOR A
|
|
LD D,5
|
|
AINT3:
|
|
LD (BC),A
|
|
DEC BC
|
|
DEC D
|
|
JP NZ,AINT3
|
|
RET
|
|
; EXP > 0
|
|
AINT1: SUB FPNIB-1
|
|
RET NC
|
|
LD D,A ;COUNT
|
|
DEC BC
|
|
AINT2: DEC BC
|
|
LD A,(BC)
|
|
AND 360Q
|
|
LD (BC),A
|
|
INC D
|
|
RET Z
|
|
XOR A
|
|
LD (BC),A
|
|
INC D
|
|
JP NZ,AINT2
|
|
RET
|
|
;
|
|
; DIMENSION MATRIX
|
|
; SYMTAB ADDRESS IN HL, HL NOT CLOBBERED
|
|
; DE CONTAINS SIZE IN NUMBER OF ELEMENTS
|
|
;
|
|
DIMS: PUSH HL
|
|
INC DE
|
|
PUSH DE
|
|
LD HL,0
|
|
LD C,FPSIZ
|
|
CALL RADD ;MULTIPLY NELTS BY BYTES PER VALUE
|
|
EX DE,HL
|
|
LD HL,(MATA)
|
|
PUSH HL
|
|
ADD HL,DE
|
|
CALL STOV ;CHECK THAT STORAGE NOT EXHAUSTED
|
|
LD (MATA),HL ;UPDATE MATRIX FREE POINTER
|
|
POP BC ;BASE ADDR
|
|
POP DE ;NELTS (NUMBER OF ELEMENTS)
|
|
POP HL ;SYMTAB ADDR
|
|
PUSH HL
|
|
LD (HL),D
|
|
DEC HL
|
|
LD (HL),E
|
|
DEC HL
|
|
LD (HL),B
|
|
DEC HL
|
|
LD (HL),C ;SYMTAB ENTRY NOW SET UP
|
|
POP HL
|
|
RET
|
|
;
|
|
; FIND VARIABLE OPTIONALLY SUBSCRIPTED IN TEXT
|
|
; SETS CARRY IF NOT FOUND
|
|
; RETURNS ADDRESS OF VARIABLE IN HL
|
|
; UPDATES TXA IF FOUND
|
|
;
|
|
VAR: CALL ALPHA
|
|
RET C
|
|
CALL NAME2
|
|
CALL GC
|
|
CP LPARRW
|
|
JP Z,VAR1 ;TEST IF SUBSCRIPTED
|
|
; MUST BE SCALAR VARIABLE
|
|
CALL STLK ;RETURNS ENTRY ADDRESS IN HL
|
|
OR A ;CLEAR CARRY
|
|
RET
|
|
; MUST BE SUBSCRIPTED
|
|
VAR1: CALL GCI ;GOBBLE LEFT PAREN
|
|
LD A,80H
|
|
OR C
|
|
LD C,A ;SET TYPE TO MATRIX
|
|
CALL STLK
|
|
PUSH HL ;SYMBOL TABLE
|
|
LD DE,10 ;DEFAULT MATRIX SIZE
|
|
CALL C,DIMS ;DEFAULT DIMENSION MATRIX
|
|
CALL EXPRB ;EVALUATE SUBSCRIPT EXPRESSION
|
|
CALL PFIX ;DE NOW HAS INTEGER
|
|
LD B,')'
|
|
CALL EATC ;GOBBLE RIGHT PAREN
|
|
POP HL
|
|
DEC HL
|
|
CALL DCMP ;BOUNDS CHECK INDEX
|
|
JP NC,E5
|
|
DEC HL
|
|
DEC HL
|
|
CALL LHLI ;GET BASE ADDR
|
|
LD C,FPSIZ
|
|
INC DE ;BECAUSE BASE ADDR IS TO ELEMENT - 1
|
|
CALL RADD ;ADD INDEX, CLEAR CARRY
|
|
RET ;******** CALL, RET????!!!!!**********
|
|
;
|
|
; JUNK ON END OF STATEMENT, TEST IF AT END OF FILE
|
|
; DOES NOT CLOBBER DE
|
|
; EATS CHARACTER AND LINE COUNT AFTER CR
|
|
; LEAVES NEW TXA IN HL
|
|
; SETS CARRY IF END OF FILE
|
|
;
|
|
JOE: CALL GCI
|
|
CP ';'
|
|
RET Z
|
|
CP CR
|
|
JP NZ,E1
|
|
LD A,(HL)
|
|
DEC A
|
|
JP Z,JOE2
|
|
INC HL
|
|
INC HL
|
|
INC HL ;SKIP OVER COUNT AND LINE NUMBER
|
|
JOE1: LD (TXA),HL
|
|
RET
|
|
JOE2: SCF
|
|
JP JOE1
|
|
;
|
|
; GET NAME FROM TEXT
|
|
; SETS CARRY IF NAME NOT FOUND
|
|
; IF SUCCEEDS RETURNS NAME IN BC, C=0 IF NO DIGIT IN NAME
|
|
;
|
|
NAME: CALL ALPHA
|
|
RET C
|
|
NAME2: LD B,A
|
|
LD C,0
|
|
CALL DIG
|
|
CCF
|
|
RET NC
|
|
LD C,A
|
|
OR A ;CLEAR CARRY
|
|
RET
|
|
;
|
|
; SYMBOL TABLE LOOKUP
|
|
; BC CONTAIN NAME AND CLASS
|
|
; IF NOT FOUND THEN CREATE ZERO'ED ENTRY AND SET CARRY
|
|
; HL HAS ADDRESS ON RET
|
|
;
|
|
STLK: LD HL,(MEMTOP)
|
|
LD DE,-STESIZ ;SET UP BASE AND INCREMENT FOR SEARCH LOOP
|
|
STLK0: LD A,(HL)
|
|
OR A
|
|
JP Z,STLK2 ;TEST IF END OF TABLE
|
|
CP B
|
|
JP NZ,STLK1 ;TEST IF ALPHA COMPARES
|
|
DEC HL
|
|
LD A,(HL) ;LOOK FOR DIGIT
|
|
CP C
|
|
DEC HL
|
|
RET Z ;CARRY CLEAR TOO, RETURN
|
|
INC HL
|
|
INC HL
|
|
STLK1: ADD HL,DE ;DIDN'T COMPARE, DECREMENT POINTER
|
|
JP STLK0
|
|
; ADD ENTRY TO SYMTAB
|
|
STLK2: LD (HL),B
|
|
DEC HL
|
|
LD (HL),C
|
|
INC HL
|
|
EX DE,HL
|
|
ADD HL,DE
|
|
LD (STAA),HL ;STORE NEW END OF STMTAB POINTER
|
|
DEC DE
|
|
DEC DE
|
|
EX DE,HL
|
|
SCF
|
|
RET
|
|
;
|
|
; GOBBLES NEXT TEXT CHARACTER IF ALPHABETIC
|
|
; SETS CARRY IF NOT
|
|
; NEXT CHAR IN ACC ON FAILURE
|
|
;
|
|
ALPHA: CALL GC
|
|
CP 'A'
|
|
RET C
|
|
CP 'Z'+1
|
|
CCF
|
|
RET C
|
|
JP DIGT1
|
|
;
|
|
; GOBBLES NEXT TEXT CHAR IF DIGIT
|
|
; SETS CARRY IF NOT
|
|
; NEXT CHAR IN ACC ON FAILURE
|
|
;
|
|
DIG: CALL GC
|
|
CP '0'
|
|
RET C
|
|
CP '9'+1
|
|
CCF
|
|
RET C
|
|
DIGT1: INC HL
|
|
LD (TXA),HL
|
|
RET
|
|
;
|
|
; COPYS FPSIZ BYTES AT ADDR HL TO ADDR DE
|
|
; ON EXIT HL POINTS TO ADR-1 OF LAST BYTE COPIED
|
|
;
|
|
VCOPY: LD C,FPSIZ
|
|
VCOP1: LD A,(HL)
|
|
LD (DE),A
|
|
DEC HL
|
|
DEC DE
|
|
DEC C
|
|
JP NZ,VCOP1
|
|
RET
|
|
;
|
|
; PUSH VALUE ADDRESSED BY HL ONTO ARG STACK
|
|
; SETS ARGF, CLEARS CARRY
|
|
;
|
|
PSHAS: EX DE,HL
|
|
PSHA1: LD HL,(ASTKA)
|
|
LD BC,-FPSIZ
|
|
ADD HL,BC
|
|
LD (ASTKA),HL ;DECREMENT ARG STACK POINTER
|
|
EX DE,HL
|
|
CALL VCOPY
|
|
LD A,1
|
|
LD (ARGF),A ;CLEAR ARGF
|
|
OR A
|
|
RET
|
|
;
|
|
; POP ARG STACK
|
|
; HL CONTAINS ADDRESS TO PUT POPPED VALUE INTO
|
|
;
|
|
POPAS: EX DE,HL
|
|
POPA1: LD HL,(ASTKA)
|
|
PUSH HL
|
|
LD BC,FPSIZ
|
|
ADD HL,BC
|
|
LD (ASTKA),HL ;INCREMENT STACK POINTER
|
|
POP HL
|
|
JP VCOPY
|
|
;
|
|
; PUSH FRAM ONTO CONTROL STACK
|
|
; TAKES MINUS AMOUNT TO SUB FROM CSTKA IN DE
|
|
; DOES OVERFLOW TEST AND RETURNS OLD CSTKA-1
|
|
;
|
|
PSHCS: LD HL,(CSTKA)
|
|
PUSH HL
|
|
ADD HL,DE
|
|
LD (CSTKA),HL
|
|
EX DE,HL
|
|
LD HL,LCSTKA ;ADDR CONTAINS CSTKL
|
|
CALL DCMP
|
|
JP C,E4
|
|
POP HL
|
|
DEC HL
|
|
RET
|
|
;
|
|
; STORAGE OVERFLOW TEST
|
|
; TEST THAT VALUE IN HL IS BETWEEN MATA AND STA
|
|
; DOES NOT CLOBBER HL
|
|
;
|
|
STOV: EX DE,HL
|
|
LD HL,MATA
|
|
CALL DCMP
|
|
JP C,E8
|
|
LD HL,STAA
|
|
CALL DCMP
|
|
EX DE,HL
|
|
RET C
|
|
E8: LD BC,'SO'
|
|
JP ERROR
|
|
;
|
|
; INCREMENT TXA IF NEXT NON-BLANK CHAR IS EQUAL TO B
|
|
; ELSE SYNTAX ERROR
|
|
;
|
|
EATC: CALL GCI
|
|
CP B
|
|
RET Z
|
|
JP E1
|
|
;
|
|
; GET NEXT NON-BLANK CHAR INTO ACC
|
|
; INCREMENT PAST BLANKS ONLY
|
|
;
|
|
GC: CALL GCI
|
|
DEC HL
|
|
LD (TXA),HL
|
|
RET
|
|
;
|
|
; GET NEXT NON-BLANK TEXT CHAR AND INCREMENT TXA
|
|
; DOES NOT CLOBBER DE,BC
|
|
; RETURN CHAR IN ACC
|
|
;
|
|
GCI: LD HL,(TXA)
|
|
GCI0: LD A,(HL)
|
|
INC HL
|
|
CP ' '
|
|
JP Z,GCI0
|
|
LD (TXA),HL
|
|
RET
|
|
;
|
|
; REPEAT ADD
|
|
; ADDS DE TO HL C TIMES
|
|
;
|
|
RADD: ADD HL,DE
|
|
DEC C
|
|
JP NZ,RADD
|
|
RET
|
|
;
|
|
; PRINT MESSAGE ADDRESSED BY HL
|
|
; ENDS WITH CHARACTER PROVIDED IN C
|
|
; RETURN IN HL ADDRESS OF TERMINATOR
|
|
;
|
|
PRNTCR: LD C,CR
|
|
JP PRN1
|
|
PRNT: LD C,'"'
|
|
PRN1: LD A,(HL) ;GET NEXT CHAR
|
|
LD B,A ;FOR CHOUT
|
|
CP C ;END OF MESSAGE TEST
|
|
RET Z
|
|
CP CR
|
|
JP Z,E1 ;NEVER PRINT A CR IN THIS ROUTINE
|
|
CALL CHOUT
|
|
INC HL
|
|
JP PRN1
|
|
;
|
|
; 16 BIT UNSIGNED COMPARE
|
|
; COMPARE DE AGAINST VALUE ADDRESSED BY HL
|
|
; CLOBBERS A ONLY
|
|
;
|
|
DCMP: LD A,E
|
|
SUB (HL)
|
|
INC HL
|
|
LD A,D
|
|
SBC A,(HL)
|
|
DEC HL
|
|
RET NZ
|
|
LD A,E
|
|
SUB (HL)
|
|
OR A ;CLEAR CARRY
|
|
RET
|
|
;
|
|
; INDIRECT LOAD HL THRU HL
|
|
;
|
|
LHLI: PUSH AF
|
|
LD A,(HL)
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A
|
|
POP AF
|
|
RET
|
|
;
|
|
; GET FP CONSTANT FROM TEXT
|
|
; PUSHES VALUE ON ARG STACK AND SETS ARGF FLAG
|
|
; SETS CARRY IF NOT FOUND
|
|
;
|
|
CONST: LD HL,(TXA) ;PREPARE CALL FPIN
|
|
EX DE,HL
|
|
LD HL,FPSINK
|
|
CALL FPIN
|
|
RET C
|
|
DEC DE
|
|
EX DE,HL
|
|
LD (TXA),HL ;NOW POINTS TO TERMINATOR
|
|
LD DE,FPSINK
|
|
CALL PSHA1
|
|
XOR A
|
|
INC A ;SET A TO 1 AND CLEAR CARRY
|
|
LD (ARGF),A
|
|
RET
|
|
;
|
|
; DIRECT STATEMENT CHECKING ROUTINE
|
|
;
|
|
DIRT: LD A,(DIRF)
|
|
OR A
|
|
RET Z
|
|
LD BC,'DI'
|
|
JP ERROR
|
|
;
|
|
; FIND TEXT LINE WITH LINE NUMBER GIVEN IN DE
|
|
; RETURNS TEXT ADDRESS COUNT BYTE IN HL
|
|
;
|
|
FINDLN: LD HL,(BOFA)
|
|
LD B,0
|
|
FIND1: LD C,(HL)
|
|
LD A,C
|
|
CP EOF
|
|
JP Z,LERR
|
|
INC HL
|
|
CALL DCMP
|
|
DEC HL
|
|
RET Z
|
|
ADD HL,BC
|
|
JP FIND1
|
|
LERR: LD BC,'LN'
|
|
JP ERROR
|
|
;
|
|
; FIX FLOATING TO POSITIVE INTEGER
|
|
; RETURN INTEGER VALUE IN DE
|
|
; FP VALUE FROM TOP OF ARG STACK, POP ARG STACK
|
|
;
|
|
PFIX: LD HL,(ASTKA)
|
|
LD B,H
|
|
LD C,L
|
|
PUSH HL
|
|
CALL AINT
|
|
LD HL,FPSINK
|
|
CALL POPAS
|
|
POP HL
|
|
LD C,(HL) ;EXPONENT
|
|
DEC HL
|
|
LD A,(HL) ;SIGN
|
|
OR A
|
|
JP NZ,E5 ;NEGATIVE NO GOOD
|
|
LD DE,-FPSIZ+1
|
|
ADD HL,DE
|
|
LD DE,0
|
|
LD A,C
|
|
OR A
|
|
RET Z
|
|
DEC C ;SET UP FOR LOOP CLOSE TEST
|
|
PFIX1: INC HL
|
|
LD A,(HL)
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
CALL MUL10
|
|
JP C,E5
|
|
DEC C
|
|
RET P
|
|
LD A,(HL)
|
|
CALL MUL10
|
|
JP C,E5
|
|
DEC C
|
|
JP M,PFIX1
|
|
RET
|
|
;
|
|
; TAKE NEXT DIGIT IN A (MASK TO 17Q), ACCUMULATE TO DE
|
|
; PRESERVES ALL BUT A, DE
|
|
;
|
|
MUL10: PUSH HL
|
|
INC SP
|
|
INC SP
|
|
LD H,D ;GET ORIGINAL VALUE TO HL
|
|
LD L,E
|
|
ADD HL,HL ;DOUBLE IT
|
|
RET C
|
|
ADD HL,HL ;AGAIN
|
|
RET C
|
|
ADD HL,DE ;PLUS ORIGINAL MAKES 5 TIMES ORIG
|
|
RET C
|
|
ADD HL,HL ;TIMES TWO MAKES TEN
|
|
RET C
|
|
EX DE,HL
|
|
DEC SP
|
|
DEC SP
|
|
POP HL
|
|
AND 17Q
|
|
ADD A,E
|
|
LD E,A
|
|
LD A,D
|
|
ADC A,0 ;PROPAGATE THE CARRY
|
|
LD D,A
|
|
RET
|
|
;
|
|
; GET INTEGER FROM TEXT
|
|
; SET CARRY IF NOT FOUND
|
|
; RETURN INTEGER VALUE IN HL
|
|
; RETURN TERMINATOR IN ACC
|
|
;
|
|
INTGER: CALL DIG
|
|
RET C
|
|
LD DE,0
|
|
JP INTG2
|
|
INTG1: CALL DIG
|
|
LD H,D
|
|
LD L,E
|
|
CCF
|
|
RET NC
|
|
INTG2: SUB '0'
|
|
CALL MUL10
|
|
JP NC,INTG1
|
|
RET
|
|
;
|
|
; CONVERT INTEGER TO STRING
|
|
; DE CONTAINS ADDRESS OF STRING, RETURN UPDATED VALUE IN DE
|
|
; HL CONTAINS VALUE TO CONVERT
|
|
;
|
|
CNS: XOR A ;SET FOR NO LEADING ZEROES
|
|
LD BC,-10000
|
|
CALL RSUB
|
|
LD BC,-1000
|
|
CALL RSUB
|
|
LD BC,-100
|
|
CALL RSUB
|
|
LD BC,-10
|
|
CALL RSUB
|
|
LD BC,-1
|
|
CALL RSUB
|
|
RET NZ
|
|
LD A,'0'
|
|
LD (DE),A
|
|
INC DE
|
|
RET
|
|
;
|
|
; TAKE VALUE IN HL
|
|
; SUB MINUS NUMBER IN BC THE MOST POSSIBLE TIMES
|
|
; PUT VALUE ON STRING AT DE
|
|
; IF A=0 THEN DON'T PUT ZERO ON STRING
|
|
; RETURN NON-ZERO IN A IF PUT ON STRING
|
|
;
|
|
RSUB: PUSH DE
|
|
LD D,-1
|
|
RSUB1: PUSH HL
|
|
INC SP
|
|
INC SP
|
|
INC D
|
|
ADD HL,BC
|
|
JP C,RSUB1
|
|
DEC SP
|
|
DEC SP
|
|
POP HL
|
|
LD B,D
|
|
POP DE
|
|
OR B ;A GETS 0 IF A WAS 0 AND B IS 0
|
|
RET Z
|
|
LD A,'0'
|
|
ADD A,B
|
|
LD (DE),A
|
|
INC DE
|
|
RET
|
|
;
|
|
; INPUT CHARACTER FROM TERMINAL
|
|
; FORCE TO UPPER CASE.
|
|
;
|
|
INCHAR: PUSH BC ;SAVE ALL THE REGISTERS
|
|
PUSH DE ;THAT MIGHT GET WALKED OVER
|
|
PUSH HL ;BY CP/M
|
|
LD C,CONIN ;LOAD UP FUNCTION CODE AND
|
|
CALL BDOS ;CALL THE SYSTEM.
|
|
AND 07FH ;MASK OFF PARITY BIT.
|
|
CP 'a' ;CHECK IF LOWER CASE
|
|
JP C,INCH1 ;TOO LOW
|
|
CP 'z'+1 ;CHECK IF LOWER CASE
|
|
JP NC,INCH1 ;TOO HIGH
|
|
SUB 20H ;FORCE TO UPPER CASE
|
|
INCH1: POP HL ;RESTORE THE REGISTERS
|
|
POP DE ;THAT GOT PUSHED
|
|
POP BC ;GOING IN.
|
|
LD B,A ;COPY CHARACTER TO B AND
|
|
RET ;RETURN.
|
|
;
|
|
INL0: CALL CRLF
|
|
INLINE: LD HL,IBUF
|
|
LD C,LINLEN
|
|
INL1: CALL INCHAR
|
|
CP 7FH ;DELETE ?
|
|
JP Z,INL2
|
|
CP 15H ;CONTROL U ?
|
|
JP Z,INL0
|
|
LD (HL),A
|
|
LD B,LF ;IN CASE ALL DONE.
|
|
CP CR
|
|
JP Z,CHOUT ;ECHO LF AND RETURN.
|
|
INC HL
|
|
DEC C
|
|
JP NZ,INL1
|
|
LD BC,'LL'
|
|
JP ERROR
|
|
INL2: LD A,C
|
|
LD B,BELL
|
|
CP LINLEN
|
|
JP Z,INL3
|
|
DEC HL
|
|
LD B,(HL) ;ECHO DELETED CHARACTER.
|
|
INC C
|
|
INL3: CALL CHOUT
|
|
JP INL1
|
|
;
|
|
; TEST CONSOLE STATUS
|
|
;
|
|
STATUS: PUSH BC ;SAVE ALL THE
|
|
PUSH DE ;REGISTERS USED BY
|
|
PUSH HL ;CP/M.
|
|
LD C,CONSTS ;FIRE OFF THE
|
|
CALL BDOS ;CONSOLE STATUS CALL.
|
|
POP HL ;RESTORE
|
|
POP DE ;ALL
|
|
POP BC ;REGISTERS.
|
|
AND 01H ;SET FLAGS ON THE STATUS.
|
|
RET ;RETURN
|
|
;
|
|
; OUTPUT ROUTINES
|
|
;
|
|
CHOUT: PUSH BC ;PUSH THE REGISTERS
|
|
PUSH DE ;THAT GET WALKED OVER BY
|
|
PUSH HL ;OUR PAL CP/M.
|
|
LD C,CONOUT ;LOAD UP THE SYSTEM FUNCTION
|
|
LD E,B ;CODE, THEN CALL
|
|
CALL BDOS ;THE SYSTEM TO WRITE IT.
|
|
POP HL ;RESTORE
|
|
POP DE ;ALL THE REGISTERS
|
|
POP BC ;WE SAVED.
|
|
LD A,B ;GET A COPY OF THE CHARACTER.
|
|
;
|
|
CHCHK: CP CR
|
|
JP NZ,CHLF ;NOT CR, IS IT LF?
|
|
XOR A
|
|
JP PSTOR ;RETURN PHEAD TO ZERO
|
|
;
|
|
CHLF: CP LF
|
|
JP Z,NULCH ;IF LINE FEED PROCESS THE NULLS
|
|
CP 40Q ;NO PHEAD INCREMENT IF CONTROL CHAR
|
|
RET C
|
|
LD A,(PHEAD)
|
|
INC A
|
|
PSTOR: LD (PHEAD),A
|
|
RET
|
|
;
|
|
NULCH: LD A,(NULLCT) ;OUTPUT NULL CHARS
|
|
OR A
|
|
RET Z
|
|
PUSH BC
|
|
LD C,A
|
|
LD B,NULL
|
|
CH2: CALL CHOUT ;OUTPUT COUNT "C" NULLS
|
|
DEC C
|
|
JP NZ,CH2
|
|
POP BC
|
|
RET
|
|
;
|
|
CRLF2: CALL CRLF
|
|
CRLF: LD B,CR
|
|
CALL CHOUT
|
|
LD B,LF
|
|
JP CHOUT
|
|
;
|
|
; CHECK IF PANIC CHARACTER HAS BEEN HIT
|
|
;
|
|
;PCHECK:LD A,(BRKCHR)
|
|
; OR A
|
|
; CALL Z,STATUS
|
|
; RET Z
|
|
PCHECK: CALL STATUS ;ANYTHING TYPED
|
|
RET Z ;RET IF NO.
|
|
CALL INCHAR ;READ THE CHARACTER IN.
|
|
CP ESC
|
|
JP Z,STOP1
|
|
; LD (BRKCHR),A
|
|
RET
|
|
;
|
|
; GET INTEGER FROM TERMINAL
|
|
; DE CONTAINS STRING TO PRINT FIRST
|
|
; HL HAS 1 LESS THAN ACCEPTABLE LOWER BOUND
|
|
; THIS ROUTINE GOES TO START IF BAD NUMBER
|
|
; INTEGER VALUE RETURNED IN HL
|
|
;
|
|
GINT: PUSH HL
|
|
EX DE,HL
|
|
LD A,(PHEAD)
|
|
OR A
|
|
CALL NZ,CRLF
|
|
CALL PRNT
|
|
CALL INLINE
|
|
LD HL,IBUF
|
|
LD (TXA),HL
|
|
CALL INTGER
|
|
JP C,START
|
|
CP CR
|
|
JP NZ,START
|
|
POP DE
|
|
LD (IBUF),HL ;USE IBUF AS A TEMP
|
|
LD HL,IBUF
|
|
CALL DCMP
|
|
JP NC,START
|
|
LD HL,(IBUF) ;GET THE VALUE BACK TO HL
|
|
LD A,(HL)
|
|
CPL
|
|
LD (HL),A ;TRY TO STORE THERE
|
|
CP (HL)
|
|
JP NZ,START ;BAD OR MISSING MEMORY
|
|
CPL
|
|
LD (HL),A ;PUT IT BACK LIKE IT WAS
|
|
RET
|
|
;
|
|
; OUTPUT FP NUMBER ADDRESSED BY HL
|
|
;
|
|
FPOUT: LD BC,-DIGIT-1
|
|
ADD HL,BC
|
|
LD B,H
|
|
LD C,L
|
|
LD HL,ABUF ;OUTPUT BUFFER
|
|
LD A,(INFES) ;OUTPUT FORMAT
|
|
LD (FES),A ;STORE IT
|
|
LD E,DIGIT
|
|
LD (HL),0 ;CLEAR ROUND-OFF OVERFLOW BUFFER
|
|
INC HL ;ABUF+1
|
|
;
|
|
NXT: LD A,(BC) ;GET DIGIT AND UNPACK
|
|
LD D,A
|
|
RRA
|
|
RRA
|
|
RRA
|
|
RRA
|
|
AND 17Q ;REMOVE BOTTOM DIGIT
|
|
LD (HL),A ;STORE TOP DIGIT IN OUTPUT BUFFER (ABUF)
|
|
INC HL
|
|
LD A,D ;NOW GET BOTTOM DIGIT
|
|
AND 17Q
|
|
LD (HL),A ;STORE IT
|
|
INC HL
|
|
INC BC
|
|
DEC E
|
|
JP NZ,NXT
|
|
LD A,(BC)
|
|
LD (FSIGN),A ;STORE SIGN OF NUMBER
|
|
XOR A
|
|
LD (HL),A ;CLEAR ROUND-OFF BUFFER (ABUF+13) 12 DIGIT NO ROUND
|
|
LD HL,XSIGN ;EXPONENT SIGN STORE
|
|
LD (HL),A ;CLEAR XSIGN
|
|
;
|
|
FIX: INC BC ;GET EXPONENT
|
|
LD A,(BC)
|
|
OR A ;EXPONENT ZERO?
|
|
JP Z,ZERO
|
|
SUB 128 ;REMOVE EXPONENT BIAS
|
|
JP NZ,FIX2
|
|
INC (HL) ;INCREMENT XSIGN TO NEGATIVE FLAG(1) LATER ZERO
|
|
FIX2: JP P,CHK13
|
|
CPL ;IT'S A NEGATIVE EXPONENT
|
|
INC (HL) ;INCREMENT XSIGN TO NEGATIVE (1)
|
|
ZRO: INC A
|
|
CHK13: LD HL,EXPO ;EXPONENT TEMP STORE
|
|
LD (HL),A
|
|
LD E,A
|
|
CP DIGIT*2
|
|
LD HL,FES ;FORMAT TEMP BYTE
|
|
JP C,CHKXO
|
|
CHK40: LD A,1 ;FORCE EXPONENTIAL PRINTOUT
|
|
OR (HL) ;SET FORMAT FOR XOUT
|
|
LD (HL),A
|
|
;
|
|
CHKXO: LD A,(HL) ;CHECK IF EXPONENTIAL FORMAT
|
|
RRA
|
|
JP NC,CHKX3
|
|
AND 17Q
|
|
CP DIGIT*2
|
|
JP C,CHKX2
|
|
LD A,DIGIT*2-1 ;MAX DIGITS
|
|
CHKX2: LD D,A
|
|
INC A
|
|
JP ROUND
|
|
;
|
|
CHKX3: AND 17Q ;ADD EXPONENT AND DECIMAL PLACES
|
|
LD D,A
|
|
ADD A,E
|
|
CP DIGIT*2+1
|
|
LD B,A
|
|
JP C,CHKXN
|
|
LD A,(HL)
|
|
AND 100Q
|
|
JP NZ,CHK40
|
|
;
|
|
CHKXN: LD A,(XSIGN) ;CHECK EXPONENT SIGN
|
|
OR A
|
|
JP NZ,XNEG ;IT'S NEGATIVE
|
|
LD A,B
|
|
JP ROUND
|
|
;
|
|
XNEG: LD A,D ;SUBTRACT EXPONENT AND DECIMAL PLACE COUNT
|
|
SUB E
|
|
JP NC,XN2
|
|
XN1: LD A,(INFES)
|
|
OR A
|
|
JP P,ZERO
|
|
AND 16Q
|
|
JP Z,ZERO
|
|
RRCA
|
|
LD E,A
|
|
DEC E
|
|
LD C,1
|
|
LD HL,ABUF-1
|
|
JP NRND
|
|
XN2: JP Z,XN1
|
|
JP ROUND
|
|
;
|
|
CLEAN: LD B,37Q ;CLEAR FLAGS
|
|
AND B
|
|
CP DIGIT*2+1
|
|
RET C
|
|
LD A,DIGIT*2+1 ;MAX DIGITS OUT
|
|
RET
|
|
;
|
|
; THIS ROUTINE IS USED TO ROUND DATA TO THE
|
|
; SPECIFIED DECIMAL PLACE
|
|
;
|
|
ROUND: CALL CLEAN
|
|
LD C,A
|
|
LD B,0
|
|
LD HL,ABUF+1
|
|
ADD HL,BC ;GET ROUND-OFF ADDRESS
|
|
LD (ADDT),HL
|
|
LD A,(HL)
|
|
CP 5 ;ROUND IF >=5
|
|
JP C,TRL2-1
|
|
;
|
|
LESS1: DEC HL
|
|
INC (HL) ;ROUND UP
|
|
LD A,(HL)
|
|
OR A
|
|
JP Z,TRL2
|
|
CP 10 ;CHECK IF ROUNDED NUMBER >9
|
|
JP NZ,TRAIL
|
|
LD (HL),0
|
|
JP LESS1
|
|
;
|
|
; THIS ROUTINE IS USED TO ELIMINATE TRAILING ZEROES
|
|
;
|
|
TRAIL: LD HL,(ADDT)
|
|
DEC HL
|
|
TRL2: LD A,(FES) ;CHECK IF TRAILING ZEROES ARE WANTED
|
|
RLA
|
|
JP C,FPRNT ;YES- GO PRINT DATA
|
|
TRL3: LD A,(HL)
|
|
OR A ;IS IT A ZERO?
|
|
JP NZ,FPRNT ;NO - GO PRINT
|
|
DEC HL
|
|
DEC C ;YES - FIX OUTPUT DIGIT COUNT
|
|
JP M,ZERO
|
|
JP TRL3
|
|
;
|
|
; HERE START THE PRINT FORMAT ROUTINES
|
|
;
|
|
FPRNT: LD HL,ABUF
|
|
LD A,(HL) ;CHECK IF ROUNDED UP TO 1
|
|
OR A
|
|
JP Z,NRND ;JUMP IF NOT
|
|
LD B,1
|
|
LD A,(XSIGN) ;IS EXPONENT NEGATIVE?
|
|
OR A
|
|
JP Z,POSR
|
|
LD B,-1
|
|
;
|
|
POSR: LD A,(EXPO) ;GET EXPONENT
|
|
OR A
|
|
JP NZ,PO2 ;IS IT ZERO (E + 0)
|
|
LD (XSIGN),A
|
|
LD B,1
|
|
PO2: ADD A,B ;FIX EXPONENT COUNT
|
|
LD (EXPO),A
|
|
INC E
|
|
INC C
|
|
DEC HL
|
|
;
|
|
NRND: INC HL
|
|
LD A,C
|
|
CP DIGIT*2+1 ;CHECK FOR MAXIMUL DIGITS OUT
|
|
JP NZ,NRND1
|
|
DEC C
|
|
NRND1: LD A,(FSIGN) ;CHECK IN NEGATIVE NUMBER
|
|
RRA
|
|
JP NC,PRI22 ;GO OUTPUT RADIX AND NUMBER
|
|
CALL NEG ;OUTPUT (-)
|
|
JP PRI21
|
|
;
|
|
PRI22: CALL SPACE ;OUTPUT A SPACE
|
|
PRI21: LD A,(FES) ;GET OUTPUT FORMAT
|
|
RRA ;CHECK IF EXPONENTIAL FORMAT
|
|
JP C,XPRIN
|
|
LD A,(XSIGN) ;GET EXPONENT SIGN
|
|
OR A ;CHECK IF NEGATIVE EXPONENT
|
|
JP Z,POSIT
|
|
LD A,C
|
|
OR A
|
|
JP NZ,PRIN4 ;OUTPUT RADIX AND NUMBER
|
|
CALL ZERO ;NO DIGITS AFTER RADIX, OUTPUT ZERO AND DONE
|
|
RET ;****** CALL, RET????!!!********
|
|
;
|
|
PRIN4: CALL RADIX ;PRINT DECIMAL POINT
|
|
XOR A
|
|
OR E
|
|
JP Z,PRIN5 ;JUMP IF NO ZEROES TO PRINT
|
|
CALL ZERO ;FORCE PRINT A ZERO
|
|
DEC E
|
|
JP NZ,PRIN4+3
|
|
;
|
|
PRIN5: CALL NOUT ;PRINT ASCII DIGIT
|
|
JP NZ,PRIN5
|
|
RET
|
|
;
|
|
POSIT: CALL NOUT
|
|
DEC E ;BUMP EXPONENT COUNT
|
|
JP NZ,POSIT
|
|
LD A,C ;CHECK IF MORE DIGITS TO OUTPUT
|
|
OR A
|
|
RET Z ;NO, DONE
|
|
RET M
|
|
JP PRIN4 ;NOW PRINT DECIMAL POINT
|
|
;
|
|
; GET HERE FOR EXPONENTIAL OUTPUT FORMAT
|
|
;
|
|
XPRIN: CALL NOUT
|
|
JP Z,NDEC ;INTEGER?
|
|
CALL RADIX ;NO....PRINT DECIMAL POINT
|
|
XPRI2: CALL NOUT
|
|
JP NZ,XPRI2
|
|
;
|
|
NDEC: LD B,'E' ;OUTPUT 'E'
|
|
CALL CHOUT
|
|
LD A,(XSIGN)
|
|
OR A
|
|
JP Z,XPRI3
|
|
CALL NEG ;PRINT EXPONENT SIGN (-)
|
|
LD A,(EXPO)
|
|
INC A
|
|
JP XOUT2
|
|
XPRI3: LD B,'+' ;EXPONENT (+)
|
|
CALL CHOUT
|
|
;
|
|
; THIS ROUTINE IS USED TO CONVERT THE EXPONENT
|
|
; FROM BINARY TO ASCII AND PRINT THE RESULT
|
|
;
|
|
XOUT: LD A,(EXPO)
|
|
DEC A
|
|
XOUT2: LD C,100
|
|
LD D,0
|
|
CALL CONV
|
|
CP '0' ;SKIP LEADING ZEROES
|
|
JP Z,XO21
|
|
INC D
|
|
CALL CHOUT
|
|
XO21: LD A,E
|
|
LD C,10
|
|
CALL CONV
|
|
CP '0'
|
|
JP NZ,XO3
|
|
DEC D
|
|
JP NZ,XO4
|
|
XO3: CALL CHOUT
|
|
XO4: LD A,E
|
|
ADD A,'0' ;ADD ASCII BIAS
|
|
LD B,A
|
|
CALL CHOUT
|
|
RET ;****** CALL, RET?????!!!!!*****
|
|
CONV: LD B,'0'-1
|
|
INC B
|
|
SUB C
|
|
JP NC,CONV+2
|
|
ADD A,C
|
|
LD E,A
|
|
LD A,B
|
|
RET
|
|
;
|
|
; THIS ROUTINE ADD ASCII BIAS TO A BCD DIGIT
|
|
; AND CALLS THE OUTPUT ROUTINE
|
|
;
|
|
NOUT: LD A,(HL)
|
|
ADD A,'0'
|
|
LD B,A
|
|
CALL CHOUT
|
|
INC HL
|
|
DEC C ;DECREMENT TOTAL DIGITS OUT COUNT
|
|
RET
|
|
;
|
|
; COMMON SYMBOL LOADING ROUTINES
|
|
;
|
|
NEG: LD B,'-'
|
|
JP CHOUT
|
|
ZERO: LD B,'0'
|
|
JP CHOUT
|
|
SPACE: LD B,' '
|
|
JP CHOUT
|
|
RADIX: LD B,'.'
|
|
JP CHOUT
|
|
;
|
|
; CONVERTS FP STRING AT DE, UPDATE DE PAST TERMINATOR
|
|
; PUTS TERMINATOR IN B, PUTS FP NUMBER AT ADDRESS IN HL
|
|
; SETS CARRY IF NOT FOUND
|
|
;
|
|
FPIN: PUSH HL
|
|
PUSH DE
|
|
EX DE,HL
|
|
DEC HL
|
|
LD (ADDS),HL
|
|
LD HL,OPST ;CLEAR TEMPORARY STORAGE AREAS AND BC BUFFER
|
|
LD C,DIGIT+6
|
|
CALL CLEAR
|
|
;
|
|
SCANC: LD DE,0
|
|
LD HL,BCX ;BC=PACK BUFFER
|
|
SCAN0: LD (BCADD),HL ;PACK BUFFER POINTER
|
|
SCANP: LD HL,SCANP
|
|
PUSH HL ;USED FOR RETURN FROM OTHER ROUTINES
|
|
XOR A
|
|
LD (XSIGN),A ;CLEAR EXPONENT SIGN BYTE
|
|
;
|
|
SCANG: CALL IBSCN
|
|
JP C,SCANX ;FOUND A NUMBER, GO PACK IT
|
|
CP '.' ;RADIX?
|
|
JP Z,SCAN5 ;PROCESS RADIX POINTERS
|
|
CP 'E' ;EXPONENT?
|
|
JP Z,EXCON ;FOUND 'E', GO PROCESS EXPONENT
|
|
; NOT A CHARACTER LEGAL IN NUMBER
|
|
LD B,A ;MOVE TERMINATOR TO B
|
|
LD A,(OPST) ;CHECK IF ANY DIGITS YET
|
|
AND 20Q
|
|
JP NZ,ENTR2
|
|
; GET HERE IF LEGAL FP NUMBER NOT FOUND
|
|
FPIN1: POP HL ;SCANP LINK
|
|
POP DE ;TEXT POINTER
|
|
POP HL ;FP # ADDR
|
|
SCF
|
|
RET
|
|
; FOUND DECIMAL POINT
|
|
SCAN5: XOR A ;FOUND RADIX PROCESS RADIX POINTERS FOR EXP
|
|
OR D ;ANY DIGITS YET?
|
|
JP NZ,SCAN6
|
|
ADD A,300Q ;SET ECNT - STOP COUNTING DIGITS
|
|
OR E ;NO INT DIGITS, BIT 7 IS COUNT/DON'T COUNT FLAG
|
|
LD E,A ;BIT 6 IS NEGATIVE EXPONENT FLAG
|
|
RET
|
|
SCAN6: LD A,200Q ;SET ECNT TO COUNT DIGITS
|
|
OR E
|
|
LD E,A
|
|
RET
|
|
;
|
|
SCANX: AND 17Q ;FOUND NUMBER-REMOVE ASCII BIAS
|
|
LD B,A
|
|
LD HL,OPST ;SET FIRST CHARACTER FLAG
|
|
LD A,60Q
|
|
OR (HL)
|
|
LD (HL),A
|
|
XOR A
|
|
OR B ;IS CHARACTER ZERO?
|
|
JP NZ,PACK
|
|
OR D ;LEADING ZERO? IE. ANY INT DIGITS?
|
|
JP NZ,PACK
|
|
OR E
|
|
LD E,A
|
|
RET Z ;IF COUNTING YET
|
|
INC E ;ECNT+1-COUNT ZEROS FOR EXPONENT COUNT
|
|
RET
|
|
;
|
|
; THIS SUBROUTINE BCD PACKS DIGITS INTO REG BC
|
|
;
|
|
PACK: LD A,E
|
|
RLA
|
|
JP C,PACK1
|
|
INC E
|
|
PACK1: LD A,E
|
|
LD (ECNT),A ;DIGIT COUNT FOR EXPONENT COUNT
|
|
INC D ;TOTAL DIGIT COUNT (D ALSO HAS TOP/BOTM FLAG BIT 7)
|
|
LD A,D
|
|
AND 177Q ;REMOVE TOP/BOTM FLAG
|
|
CP DIGIT*2+1 ;LIMIT INPUT DIGITS
|
|
RET NC
|
|
XOR A
|
|
OR D
|
|
JP M,BOTM
|
|
;
|
|
TOP: OR 200Q ;SET MSB FOR TOP FLAG
|
|
LD D,A
|
|
LD A,B
|
|
LD HL,(BCADD) ;GET BC ADDRESS
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
LD (HL),A ;SAVE CHAR IN BC
|
|
RET
|
|
;
|
|
BOTM: AND 177Q ;STRIP MSB (BOTTOM FLAG)
|
|
LD D,A
|
|
LD A,B
|
|
LD HL,(BCADD)
|
|
OR (HL) ;OR IN TOP NUMBER
|
|
LD (HL),A ;PUT NUMBER BACK IN BC
|
|
INC HL
|
|
POP BC
|
|
JP SCAN0
|
|
IBSCN: LD HL,(ADDS) ;INPUT BUFFER POINTER
|
|
INC HL ;GET NEXT BYTE
|
|
LD A,(HL)
|
|
CP ' '
|
|
JP Z,IBSCN+3
|
|
LD (ADDS),HL ;NOTE: THIS ROUTINE FALLS THROUGH
|
|
; THIS ROUTINE CHECKS FOR ASCII NUMBERS
|
|
NMCHK: CP '9'+1
|
|
RET NC
|
|
CP '0'
|
|
CCF
|
|
RET
|
|
;
|
|
; THIS ROUTINE IS USED TO ADJUST A NUMBER IN BC BUFFER
|
|
; AND RETURNS VALUE
|
|
;
|
|
ENTR2: LD DE,0
|
|
ENT1: PUSH BC ;TERMINATOR
|
|
CALL FIXE ;NORMALIZE FLOATING POINT NUMBER
|
|
POP BC ;TERMINATOR
|
|
POP DE ;SCANP LINK
|
|
POP DE ;OLD TEXT ADDR
|
|
POP DE ;RETURN ADDR
|
|
LD C,DIGIT+2
|
|
LD HL,BCX+DIGIT+1
|
|
CALL VCOPY
|
|
LD HL,(ADDS)
|
|
EX DE,HL
|
|
INC DE
|
|
OR A
|
|
RET
|
|
;
|
|
; THIS ROUTINE IS USED TO CLEAR STORAGE AREAS
|
|
; THE STARTING ADDRESS IS IN HL AND THE COUNT
|
|
; IS IN C
|
|
;
|
|
CLEAR: XOR A
|
|
LD (HL),A
|
|
INC HL
|
|
DEC C
|
|
JP NZ,CLEAR+1
|
|
RET
|
|
;
|
|
; THIS ROUTINE CONVERTS THE ASCII EXPONENT OF
|
|
; THE NUMBER IN THE INPUT BUFFER TO BINARY, AND
|
|
; NORMALIZES THE EXPONENT ACCORDING TO THE INPUT
|
|
; FORMAT OF THE NUMBER
|
|
;
|
|
EXCON: CALL IBSCN ;GET CHARACTER
|
|
JP C,EXC3
|
|
CP PLSRW ;CHECK FOR UNARY SIGNS
|
|
JP Z,EXC4
|
|
CP '+'
|
|
JP Z,EXC4
|
|
CP '-'
|
|
JP Z,EXC2
|
|
CP MINRW
|
|
JP NZ,FPERR ;NO SIGN OR NUMBER?
|
|
EXC2: LD A,1
|
|
LD (XSIGN),A ;SAVE SIGN
|
|
EXC4: CALL IBSCN
|
|
JP NC,FPERR ;NO NUMBER?
|
|
EXC3: CALL ASCDC ;CONVERT ASCII TO BINARY
|
|
JP ENT1 ;NORMALIZE NUMBER AND RETURN
|
|
;
|
|
; THIS ROUTINE CONVERTS ASCII TO BINARY
|
|
; THREE CONSECUTIVE NUMBERS < 128 MAY BE CONVERTED
|
|
;
|
|
ASCDC: EX DE,HL
|
|
LD HL,0
|
|
ASC1: LD A,(DE) ;GET CHR FROM INPUT BUFFER-NO SPACES ALLOWED
|
|
CALL NMCHK ;CHECK IF NUMBER
|
|
JP NC,ASC2
|
|
SUB '0' ;REMOVE ASCII BIAS
|
|
LD B,H
|
|
LD C,L
|
|
ADD HL,HL
|
|
ADD HL,HL
|
|
ADD HL,BC
|
|
ADD HL,HL
|
|
LD C,A
|
|
LD B,0
|
|
ADD HL,BC
|
|
INC DE
|
|
JP ASC1
|
|
ASC2: EX DE,HL
|
|
LD B,A ;SAVE TERMINATOR
|
|
LD (ADDS),HL ;SAVE IBUF ADDRESS
|
|
LD A,D
|
|
OR A
|
|
JP NZ,FPERR ;TOO BIG >255
|
|
LD A,E
|
|
RLA
|
|
JP C,FPERR ;TOO BIG >127
|
|
RRA
|
|
RET
|
|
FPERR: POP BC ;ASCDC RET LINK
|
|
JP FPIN1
|
|
;
|
|
; THIS ROUTINE NORMALIZES THE INPUT NUMBER
|
|
;
|
|
FIXE: EX DE,HL
|
|
LD A,(BCX)
|
|
OR A ;IS IT ZERO?
|
|
JP Z,ZZ2
|
|
CALL CHKPN ;SET EXPONENT POSITIVE/NEGATIVE
|
|
ADD A,200Q ;ADD EXPONENT BIAS
|
|
ZZ2: LD (BCX+DIGIT+1),A ;STORE NORMALIZED EXPONENT IN BC
|
|
RET
|
|
;
|
|
CHKPN: LD A,(ECNT) ;GET EXPONENT COUNT-SET IN 'SCAN' ROUTINE
|
|
LD E,A
|
|
AND 77Q ;STRIP BITS 7&8
|
|
LD B,A
|
|
LD A,(XSIGN)
|
|
OR A
|
|
JP Z,LPOS ;EXPONENT IS POSITIVE
|
|
INC H ;SET SIGN IN H ** THIS SHOULD BE INR H NOT INX H
|
|
LD A,100Q ;L IS NEGATIVE
|
|
AND E ;CHECK IF E IS NEGATIVE
|
|
JP Z,EPOS
|
|
LD A,L ;BOTH E & L NEGATIVE
|
|
LD L,B
|
|
CALL BPOS+1
|
|
CPL
|
|
INC A
|
|
RET ;BACK TO FIXE
|
|
;
|
|
EPOS: LD A,L ;E&L NEGATIVE
|
|
CPL
|
|
INC A ;TWO'S COMP A
|
|
ADD A,B
|
|
RET ;TO FIXE
|
|
;
|
|
LPOS: LD A,100Q ;EXPONENT POSITIVE
|
|
AND E ;IS E NEGATIVE?
|
|
JP Z,BPOS
|
|
LD A,B
|
|
LD B,L
|
|
JP EPOS+1
|
|
;
|
|
BPOS: LD A,B ;E&L POSITIVE
|
|
ADD A,L
|
|
RET P
|
|
;
|
|
POP HL
|
|
JP FPERR
|
|
DEFB 10H
|
|
DEFW 0
|
|
DEFB 1
|
|
FPNONE: DEFB 129
|
|
;
|
|
; FLOATING POINT MATH PACKAGE
|
|
;
|
|
; EACH FUNCTION OPERATES AS FOLLOWS: (BC) = (DE) # (HL)
|
|
; WHERE BC IS ADDRESS OF RESULT
|
|
; DE IS ADDRESS OF 1ST ARGUMENT
|
|
; HL IS ADDRESS OF 2ND ARGUMENT
|
|
; AND # IS ONE OF THE OPERATORS +,-,*,/
|
|
;
|
|
; ON ENTRY ALL ADDRESS POINT TO THE EXPONENT PART OF THE
|
|
; FLOATING POINT ARGUMENT
|
|
;
|
|
; THE NUMBER ZERO IS REPRESENTED BY A ZERO EXPONENT
|
|
;
|
|
; ALL NUMBERS ARE ASSUMED TO BE NORMALIZED
|
|
;
|
|
FADD: PUSH BC
|
|
CALL EXPCK ;FETCH ARGUMENTS
|
|
LD C,0
|
|
ADSUM: DEC DE
|
|
EX DE,HL
|
|
LD A,(SIGN)
|
|
XOR (HL) ;FORM SIGN OF RESULT
|
|
LD B,A
|
|
EX DE,HL
|
|
LD A,(DE)
|
|
DEC DE
|
|
XOR C
|
|
LD (SIGN),A
|
|
LD HL,RCTRL ;ROUNDING CONTOL FLAG
|
|
LD A,(HL)
|
|
OR A
|
|
INC HL
|
|
LD A,(HL) ;GET ROUNDING DIGIT
|
|
JP Z,ADS8
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
ADS8: ADD A,0B0H ;FORCE CARRY IF DIGIT > 5
|
|
LD A,B
|
|
RRA
|
|
JP C,ADS1 ;HAVE SUBTRACTION
|
|
RLA ;RESTORE CARRY
|
|
CALL ADDX ;PERFORM ADDITION
|
|
JP NC,ADS2
|
|
LD B,4
|
|
CALL RIGHT
|
|
LD HL,EXP
|
|
INC (HL) ;INCREMENT EXPONENT
|
|
JP Z,OVER
|
|
ADS2: POP BC ;GET RESULTS ADDRESS
|
|
CALL STORE ;SAVE RESULTS
|
|
RET ;******* CALL, RET????!!!!********
|
|
ZEREX: POP HL
|
|
JP ADS2
|
|
ADDX: LD HL,BUF+DIGIT-1
|
|
LD B,DIGIT
|
|
ADD1: LD A,(DE)
|
|
ADC A,(HL)
|
|
DAA
|
|
LD (HL),A
|
|
DEC HL
|
|
DEC DE
|
|
DEC B
|
|
JP NZ,ADD1
|
|
RET NC
|
|
INC (HL)
|
|
RET
|
|
;
|
|
; FLOATING POINT SUBTRACTION
|
|
;
|
|
FSUB: PUSH BC
|
|
CALL EXPCK ;GET ARGUMENTS
|
|
LD A,(SIGN)
|
|
XOR 1 ;COMPLEMENT SIGN
|
|
LD (SIGN),A
|
|
JP ADSUM
|
|
ADS1: RLA ;RESTORE CARRY
|
|
CCF ;COMPLEMENT FOR ROUNDING
|
|
CALL SUBX ;SUBTRACT ARGUMENTS
|
|
LD HL,SIGN
|
|
JP C,ADS4
|
|
LD A,(HL) ;GET SIGN
|
|
XOR 1 ;COMPLEMENT
|
|
LD (HL),A
|
|
ADS7: DEC HL
|
|
LD B,DIGIT
|
|
ADS3: LD A,9AH
|
|
SBC A,(HL) ;COMPLEMENT RESULT
|
|
ADD A,0
|
|
DAA
|
|
LD (HL),A
|
|
DEC HL
|
|
DEC B
|
|
CCF
|
|
JP NZ,ADS3
|
|
ADS4: LD HL,BUF
|
|
LD BC,DIGIT
|
|
ADS5: LD A,(HL)
|
|
OR A
|
|
JP NZ,ADS6
|
|
INC HL
|
|
INC B
|
|
INC B
|
|
DEC C
|
|
JP NZ,ADS5
|
|
XOR A ;********* NOT NEEDED
|
|
LD (EXP),A
|
|
JP ADS2
|
|
ADS6: CP 10H
|
|
JP NC,ADS9
|
|
INC B
|
|
ADS9: LD HL,EXP
|
|
LD A,(HL)
|
|
SUB B
|
|
JP Z,UNDER
|
|
JP C,UNDER
|
|
LD (HL),A
|
|
LD A,B
|
|
RLCA
|
|
RLCA
|
|
LD B,A
|
|
CALL LEFT
|
|
JP ADS2
|
|
SUBX: LD HL,BUF+DIGIT-1
|
|
LD B,DIGIT
|
|
SUB1: LD A,99H
|
|
ADC A,0
|
|
SUB (HL)
|
|
EX DE,HL
|
|
ADD A,(HL)
|
|
DAA
|
|
EX DE,HL
|
|
LD (HL),A
|
|
DEC HL
|
|
DEC DE
|
|
DEC B
|
|
JP NZ,SUB1
|
|
RET
|
|
;
|
|
; FLOATING POINT MULTIPLY
|
|
;
|
|
FMUL: PUSH BC
|
|
LD A,(HL)
|
|
OR A ;ARGUMENT = 0?
|
|
JP Z,FMUL1+2
|
|
LD A,(DE)
|
|
OR A ;ARGUMENT =0?
|
|
JP Z,FMUL1+2
|
|
ADD A,(HL) ;FORM RESULT EXPONENT
|
|
JP C,FMOVR
|
|
JP P,UNDER
|
|
JP FMUL1
|
|
FMOVR: JP M,OVER
|
|
FMUL1: SUB 128 ;REMOVE EXCESS BIAS
|
|
LD (EXP),A ;SAVE EXPONENT
|
|
DEC DE
|
|
DEC HL
|
|
LD A,(DE)
|
|
XOR (HL) ;FORM RESULT SIGN
|
|
DEC HL
|
|
DEC DE
|
|
PUSH HL
|
|
LD HL,SIGN ;GET SIGN ADDRESS
|
|
LD (HL),A ;SAVE SIGN
|
|
DEC HL
|
|
XOR A
|
|
LD B,DIGIT+2
|
|
FMUL2: LD (HL),A ;ZERO WORKING BUFFER
|
|
DEC HL
|
|
DEC B
|
|
JP NZ,FMUL2
|
|
LD A,(EXP)
|
|
OR A
|
|
JP Z,ZEREX
|
|
LD C,DIGIT
|
|
LD HL,HOLD1+DIGIT
|
|
; GET MULTIPLIER INTO HOLDING REGISTER
|
|
FMUL3: LD A,(DE)
|
|
LD (HL),A ;PUT IN REGISTER
|
|
DEC HL
|
|
DEC DE
|
|
DEC C
|
|
JP NZ,FMUL3
|
|
LD (HL),C
|
|
DEC HL
|
|
LD B,250 ;SET LOOP COUNT
|
|
FMUL4: LD DE,DIGIT+1
|
|
LD C,E
|
|
ADD HL,DE
|
|
EX DE,HL
|
|
ADD HL,DE ;H,L=NEXT HOLDING REGISTER
|
|
INC B
|
|
JP P,FMUL8 ;FINISHED
|
|
FMUL5: LD A,(DE) ;GET DIGITS
|
|
ADC A,A ;TIMES 2
|
|
DAA
|
|
LD (HL),A ;PUT IN HOLDING REGISTER
|
|
DEC DE
|
|
DEC HL
|
|
DEC C
|
|
JP NZ,FMUL5
|
|
INC B ;INCREMENT LOOP COUNT
|
|
JP NZ,FMUL4
|
|
;
|
|
; FORM 10X BY ADDING 8X AND 2X
|
|
; FIRST GET 8X
|
|
INC HL
|
|
LD DE,HOLD5 ;NEXT HOLDING REGISTER
|
|
LD C,DIGIT+1
|
|
LD B,C
|
|
FMUL6: LD A,(HL)
|
|
LD (DE),A
|
|
INC HL
|
|
INC DE
|
|
DEC C
|
|
JP NZ,FMUL6
|
|
LD HL,HOLD2+DIGIT ;GET 2X
|
|
DEC DE
|
|
FMUL7: LD A,(DE)
|
|
ADC A,(HL) ;FORM 10X
|
|
DAA
|
|
LD (DE),A
|
|
DEC DE
|
|
DEC HL
|
|
DEC B
|
|
JP NZ,FMUL7
|
|
LD B,249
|
|
EX DE,HL
|
|
JP FMUL4
|
|
FMUL8: EX DE,HL
|
|
INC HL
|
|
LD (HL),DIGIT+1 ;SET NEXT LOOP COUNT
|
|
; PERFORM ACCUMULATION OF PRODUCT
|
|
FMUL9: POP BC ;GET MULTIPLIER
|
|
LD HL,HOLD8+DIGIT+1
|
|
DEC (HL) ;DECREMENT LOOP COUNT
|
|
JP Z,FMU14 ;FINISHED
|
|
LD A,(BC)
|
|
DEC BC
|
|
PUSH BC
|
|
DEC HL
|
|
EX DE,HL
|
|
FMU10: ADD A,A ;CHECK FOR BIT IN CARRY
|
|
JP C,FMU11 ;FOUND A BIT
|
|
JP Z,FMU12 ;ZERO - FINISHED THIS DIGIT
|
|
LD HL,-DIGIT-1
|
|
ADD HL,DE ;POINT TO NEXT HOLDING REGISTER
|
|
EX DE,HL
|
|
JP FMU10
|
|
FMU11: LD C,A
|
|
OR A ;CLEAR CARRY
|
|
CALL ADDX ;ACCUMULATE PRODUCT
|
|
LD A,(DE)
|
|
ADD A,(HL)
|
|
DAA
|
|
LD (HL),A
|
|
LD A,C
|
|
DEC DE
|
|
JP FMU10
|
|
; ROTATE RIGHT 1 BYTE
|
|
FMU12: LD B,8
|
|
CALL RIGHT
|
|
JP FMUL9
|
|
FMU14: LD A,(BUF)
|
|
AND 0F0H ;CHECK IF NORMALIZING
|
|
JP Z,FMU17
|
|
LD A,D
|
|
AND 0F0H
|
|
LD HL,SIGN-1
|
|
JP FMU18
|
|
FMU17: LD B,4
|
|
LD HL,EXP
|
|
DEC (HL)
|
|
JP Z,UNDER
|
|
CALL LEFT ;NORMALIZE
|
|
LD A,D ;GET DIGIT SHIFTED OFF
|
|
; PERFORM ROUNDING
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
FMU18: CP 50H
|
|
JP C,FMU16
|
|
INC A
|
|
AND 0FH
|
|
LD C,DIGIT
|
|
FMU15: ADC A,(HL)
|
|
DAA
|
|
LD (HL),A
|
|
LD A,0
|
|
DEC HL
|
|
DEC C
|
|
JP NZ,FMU15
|
|
; CHECK FOR ROUNDING OVERFLOW
|
|
JP NC,ADS2 ;NO OVERFLOW
|
|
INC HL
|
|
LD (HL),10H
|
|
LD HL,EXP
|
|
INC (HL)
|
|
JP NZ,ADS2
|
|
JP OVER
|
|
; ROUNDING NOT NEEDED
|
|
FMU16: AND 0FH
|
|
ADD A,(HL)
|
|
LD (HL),A
|
|
JP ADS2
|
|
;
|
|
; FLOATING POINT DIVISION
|
|
;
|
|
FDIV: PUSH BC
|
|
LD A,(HL) ;FETCH DIVISOR EXP
|
|
OR A ;DIVIDE BY ZERO?
|
|
JP Z,DIVZ
|
|
LD A,(DE)
|
|
OR A ;DIVIDEND 0?
|
|
JP Z,INSP
|
|
SUB (HL)
|
|
JP C,DIVUN
|
|
JP M,OVER
|
|
JP FDI1
|
|
DIVUN: JP P,UNDER
|
|
FDI1: ADD A,129 ;FORM QUOTIENT EXP
|
|
LD (EXPD),A
|
|
EX DE,HL
|
|
PUSH DE
|
|
CALL LOAD ;FETCH DIVIDEND
|
|
POP DE
|
|
EX DE,HL
|
|
LD A,(SIGN)
|
|
DEC HL
|
|
XOR (HL) ;FORM QUOTIENT SIGN
|
|
LD (SIGND),A
|
|
EX DE,HL
|
|
DEC DE
|
|
LD BC,HOLD1
|
|
DIV0: LD L,DIGIT+DIGIT
|
|
DIV1: PUSH BC
|
|
PUSH HL
|
|
LD C,0 ;QUOTIENT DIGIT = 0
|
|
DIV3: SCF ;SET CARRY
|
|
LD HL,BUF+DIGIT-1
|
|
LD B,DIGIT
|
|
DIV4: LD A,99H
|
|
ADC A,0
|
|
EX DE,HL
|
|
SUB (HL)
|
|
EX DE,HL
|
|
ADD A,(HL)
|
|
DAA
|
|
LD (HL),A
|
|
DEC HL
|
|
DEC DE
|
|
DEC B
|
|
JP NZ,DIV4
|
|
LD A,(HL)
|
|
CCF
|
|
SBC A,0
|
|
LD (HL),A
|
|
RRA
|
|
LD HL,DIGIT
|
|
ADD HL,DE
|
|
EX DE,HL
|
|
INC C ;INCREMENT QUOTIENT
|
|
RLA
|
|
JP NC,DIV3
|
|
OR A ;CLEAR CARRY
|
|
CALL ADDX ;RESTORE DIVIDEND
|
|
LD HL,DIGIT
|
|
ADD HL,DE
|
|
EX DE,HL
|
|
PUSH BC
|
|
LD B,4
|
|
CALL LEFT ;SHIFT DIVIDEND
|
|
POP BC
|
|
DEC C
|
|
POP HL
|
|
LD H,C
|
|
POP BC
|
|
LD A,L
|
|
JP NZ,DIV5
|
|
CP DIGIT+DIGIT
|
|
JP NZ,DIV5
|
|
LD HL,EXPD
|
|
DEC (HL)
|
|
CALL Z,UNDER
|
|
JP DIV0
|
|
DIV5: RRA
|
|
LD A,H
|
|
JP NC,DIV6
|
|
LD A,(BC)
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
ADD A,H
|
|
LD (BC),A ;STORE QUOTIENT
|
|
INC BC
|
|
JP DIV7
|
|
DIV6: LD (BC),A ;STORE QUOTIENT
|
|
DIV7: DEC L ;DECREMENT DIGIT COUNT
|
|
JP NZ,DIV1
|
|
LD HL,EXPD
|
|
POP BC
|
|
CALL STORO
|
|
RET ;***** CALL, RET????!!!!!*******
|
|
;
|
|
; FETCH AND ALIGN ARGUMENTS FOR
|
|
; ADDITION AND SUBTRACTION
|
|
;
|
|
EXPCK: LD A,(DE)
|
|
SUB (HL) ;DIFFERENCE OF EXPONENTS
|
|
LD C,0
|
|
JP NC,EXPC1
|
|
INC C
|
|
EX DE,HL
|
|
CPL
|
|
INC A
|
|
EXPC1: LD B,A
|
|
LD A,(DE)
|
|
LD (EXP),A
|
|
LD A,B
|
|
CP DIGIT+DIGIT
|
|
JP C,EXPC2
|
|
LD A,DIGIT+DIGIT
|
|
EXPC2: RLCA
|
|
RLCA
|
|
LD B,A
|
|
AND 4
|
|
LD (RCTRL),A ;SET ROUNDING CONTROL
|
|
PUSH BC
|
|
PUSH DE
|
|
CALL LOAD ;LOAD SMALLER VALUE
|
|
LD A,8*DIGIT+16
|
|
SUB B
|
|
CP 8*DIGIT+16
|
|
JP Z,EXPC3
|
|
AND 0F8H
|
|
RRA
|
|
RRA
|
|
RRA
|
|
ADD A,E
|
|
LD E,A
|
|
LD A,D
|
|
ADC A,0
|
|
LD D,A
|
|
LD A,(DE) ;GET ROUNDING DIGIT
|
|
LD (RDIGI),A ;SAVE
|
|
EXPC3: CALL RIGHT ;ALIGN VALUES
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
; LOAD ARGUMENT INTO BUFFER
|
|
LOAD: LD DE,SIGN
|
|
LD C,DIGIT+1
|
|
DEC HL
|
|
LOAD1: LD A,(HL)
|
|
LD (DE),A
|
|
DEC HL
|
|
DEC DE
|
|
DEC C
|
|
JP NZ,LOAD1
|
|
XOR A
|
|
LD (DE),A
|
|
DEC DE
|
|
LD (DE),A
|
|
LD (RDIGI),A ;ZERO ROUNDING DIGIT
|
|
RET
|
|
; STORE RESULTS IN MEMORY
|
|
STORE: LD HL,EXP
|
|
STORO: LD E,DIGIT+2
|
|
STOR1: LD A,(HL)
|
|
LD (BC),A
|
|
DEC BC
|
|
DEC HL
|
|
DEC E
|
|
JP NZ,STOR1
|
|
RET
|
|
; SHIFT RIGHT NUMBER OF DIGITS
|
|
; IN B/4
|
|
RIGHT: LD C,DIGIT+1
|
|
RIGH1: LD HL,BUF-1
|
|
LD A,B
|
|
SUB 8 ;CHECK IF BYTE CAN BE SHIFTED
|
|
JP NC,RIGH3
|
|
DEC B
|
|
RET M
|
|
OR A
|
|
RIGH2: LD A,(HL)
|
|
RRA
|
|
LD (HL),A
|
|
INC HL
|
|
DEC C
|
|
JP NZ,RIGH2
|
|
JP RIGHT
|
|
; SHIFT RIGHT ONE BYTE
|
|
RIGH3: LD B,A
|
|
XOR A
|
|
RIGH4: LD D,(HL)
|
|
LD (HL),A
|
|
LD A,D
|
|
INC HL
|
|
DEC C
|
|
JP NZ,RIGH4
|
|
JP RIGHT
|
|
; SHIFT LEFT NUMBER OF DIGITS
|
|
; IN B/4
|
|
LEFT: LD C,DIGIT+1
|
|
LD HL,SIGN-1
|
|
LEF1: LD A,B
|
|
SUB 8
|
|
JP NC,LEF3
|
|
DEC B
|
|
RET M
|
|
OR A
|
|
LEF2: LD A,(HL)
|
|
RLA
|
|
LD (HL),A
|
|
DEC HL
|
|
DEC C
|
|
JP NZ,LEF2
|
|
JP LEFT
|
|
; SHIFT LEFT ONE BYTE
|
|
LEF3: LD B,A
|
|
XOR A
|
|
LEF4: LD D,(HL)
|
|
LD (HL),A
|
|
LD A,D
|
|
DEC HL
|
|
DEC C
|
|
JP NZ,LEF4
|
|
JP LEFT
|
|
; SET FLAGS FOR OVERFLOW, UNDERFLOW,
|
|
; AND DIVIDE BY ZERO
|
|
DIVZ:
|
|
OVER: LD BC,'FP'
|
|
JP ERROR
|
|
UNDER: LD A,-1
|
|
LD (ERRI),A
|
|
INSP: INC SP
|
|
INC SP
|
|
RET
|
|
;
|
|
; FLOATING POINT RAM
|
|
;
|
|
HOLD1: DEFS DIGIT+1
|
|
HOLD2: DEFS DIGIT+1
|
|
HOLD3: DEFS DIGIT+1
|
|
HOLD4: DEFS DIGIT+1
|
|
HOLD5: DEFS DIGIT+1
|
|
HOLD6: DEFS DIGIT+1
|
|
HOLD7: DEFS DIGIT+1
|
|
HOLD8: DEFS DIGIT+1
|
|
DEFS 1
|
|
ERRI: DEFS 1 ;ERROR FLAG
|
|
DEFS 1
|
|
BUF: DEFS DIGIT ;WORKING BUFFER
|
|
SIGN: DEFS 1 ;SIGN BIT
|
|
EXP: DEFS 1 ;EXPONENT
|
|
RC |