2023-11-16 18:19:54 -05:00

617 lines
9.6 KiB
Plaintext

PAGE
SBTTL "--- 2-OPS ---"
; -----
; LESS?
; -----
; [ARG1] < [ARG2]?
ZLESS: JSR A12VAL ; MOVE [ARG1] TO [VALUE]
JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE
; ------
; DLESS?
; ------
; DECREMENT [ARG1]; SUCCEED IF < [ARG2]
ZDLESS: JSR ZDEC ; MOVES ([ARG1]-1) TO [VALUE]
DLS0: LDA ARG2+LO ; MOVE [ARG2] TO [I]
STA I+LO
LDA ARG2+HI
STA I+HI
JMP COMPAR ; COMPARE & RETURN
; -----
; GRTR?
; -----
; [ARG1] > [ARG2]?
ZGRTR: LDA ARG1+LO ; MOVE [ARG1] TO [I]
STA I+LO
LDA ARG1+HI
STA I+HI
JMP A2VAL ; MOVE [ARG2] TO [VALUE] & COMPARE
; ------
; IGRTR?
; ------
; INCREMENT [ARG1]; SUCCEED IF GREATER THAN [ARG2]
ZIGRTR: JSR ZINC ; GET ([ARG1]+1) INTO [VALUE]
LDA VALUE+LO ; MOVE [VALUE] TO [I]
STA I+LO
LDA VALUE+HI
STA I+HI
A2VAL: LDA ARG2+LO ; MOVE [ARG2] TO [VALUE]
STA VALUE+LO
LDA ARG2+HI
STA VALUE+HI
COMPAR: JSR SCOMP ; COMPARE [VALUE] AND [I]
BCC PGOOD
BCS PBAD
; -----------------
; SIGNED COMPARISON
; -----------------
; ENTRY: VALUES IN [VALUE] AND [I]
SCOMP: LDA I+HI
EOR VALUE+HI
BPL SCMP
LDA I+HI
CMP VALUE+HI
RTS
SCMP: LDA VALUE+HI
CMP I+HI
BNE SCEX
LDA VALUE+LO
CMP I+LO
SCEX: RTS
; ---
; IN?
; ---
; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]?
ZIN: LDA ARG1+LO
JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I]
LDY #4 ; POINT TO "LOC" SLOT
LDA (I),Y ; GET DATA
CMP ARG2+LO ; IS IT THERE?
BEQ PGOOD ; YES, SUCCEED
PBAD: JMP PREDF ; TOO BAD, CHUM ...
; ----
; BTST
; ----
; IS EVERY "ON" BIT IN [ARG1]
; ALSO "ON" IN [ARG2]?
ZBTST: LDA ARG2+LO ; FIRST CHECK LSBS
AND ARG1+LO
CMP ARG2+LO ; LSBS MATCH?
BNE PBAD ; NO, EXIT NOW
LDA ARG2+HI ; ELSE CHECK MSBS
AND ARG1+HI
CMP ARG2+HI ; MATCHED?
BNE PBAD ; SORRY ...
PGOOD: JMP PREDS
; ---
; BOR
; ---
; RETURN [ARG1] "OR" [ARG2]
ZBOR: LDA ARG1+LO
ORA ARG2+LO
TAX
LDA ARG1+HI
ORA ARG2+HI
JMP VEXIT
; ----
; BAND
; ----
; RETURN [ARG1] "AND" [ARG2]
ZBAND: LDA ARG1+LO
AND ARG2+LO
TAX
LDA ARG1+HI
AND ARG2+HI
JMP VEXIT
; -----
; FSET?
; -----
; IS FLAG [ARG1] SET IN OBJECT [ARG2]?
ZFSETP: JSR FLAGSU ; GET BITS INTO [K] AND [J]
LDA K+HI ; DO MSBS
AND J+HI
STA K+HI
LDA K+LO ; DO LSBS
AND J+LO
ORA K+HI ; ANY BITS ON?
BNE PGOOD ; TARGET BIT MUST BE ON
JMP PREDF
; ----
; FSET
; ----
; SET FLAG [ARG2] IN OBJECT [ARG1]
ZFSET: JSR FLAGSU ; GET BITS INTO [K] & [J], ADDR IN [I]
LDY #0
LDA K+HI ; FIRST DO MSBS
ORA J+HI
STA (I),Y
INY
LDA K+LO ; THEN LSBS
ORA J+LO
STA (I),Y
RTS
; ------
; FCLEAR
; ------
; CLEAR FLAG [ARG2] IN OBJECT [ARG1]
ZFCLR: JSR FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [I]
LDY #0
LDA J+HI ; FETCH MSB
EOR #$FF ; COMPLEMENT IT
AND K+HI ; RUB OUT FLAG
STA (I),Y
INY
LDA J+LO ; SAME FOR LSB
EOR #$FF
AND K+LO
STA (I),Y
RTS
; ---
; SET
; ---
; SET VARIABLE [ARG1] EQUAL TO [ARG2]
ZSET: LDA ARG2+LO ; MOVE THE VALUE
STA VALUE+LO ; INTO [VALUE]
LDA ARG2+HI
STA VALUE+HI
LDA ARG1+LO ; GET VARIABLE ID
JMP VARPUT ; AND CHANGE THE VARIABLE
; ----
; MOVE
; ----
; MOVE OBJECT [ARG1] INTO OBJECT [ARG2]
ZMOVE: JSR ZREMOV ; REMOVE FIRST
LDA ARG1+LO
JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I]
LDA I+LO ; COPY SOURCE ADDRESS
STA J+LO ; INTO [J]
LDA I+HI
STA J+HI
LDA ARG2+LO ; GET DEST OBJECT ID
LDY #4 ; POINT TO "LOC" SLOT OF SOURCE
STA (I),Y ; AND MOVE IT IN
JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I]
LDY #6 ; POINT TO "FIRST" SLOT
LDA (I),Y ; GET "FIRST" OF DEST
TAX ; SAVE HERE FOR A MOMENT
LDA ARG1+LO ; GET SOURCE OBJECT ID
STA (I),Y ; MAKE IT "FIRST" OF DEST
TXA ; RESTORE "FIRST" OF DEST
BEQ ZMVEX ; SCRAM IF ZERO
LDY #5 ; MAKE "FIRST" OF DEST
STA (J),Y ; THE "NEXT" OF SOURCE
ZMVEX: RTS
; ---
; GET
; ---
; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1]
ZGET: JSR WCALC ; CALC ADDRESS
JSR GETBYT ; GET 1ST BYTE (MSB)
DOGET: STA VALUE+HI ; SAVE MSB
JSR GETBYT ; GET LSB
STA VALUE+LO ; SAVE AND
JMP PUTVAL ; HAND IT OVER
; ----
; GETB
; ----
; RETURN ITEM [ARG2] IN BYTE-TABLE AT [ARG1]
ZGETB: JSR BCALC
BEQ DOGET ; [A] = 0, SO CLEAR MSB OF [VALUE]
; --------------------
; CALC TABLE ADDRESSES
; --------------------
; WORD-ALIGNED ENTRY
WCALC: ASL ARG2+LO ; WORD-ALIGN FOR
ROL ARG2+HI ; WORD ACCESS
; BYTE-ALIGNED ENTRY
BCALC: LDA ARG2+LO ; ADD BASE ADDR OF TABLE
CLC ; TO ITEM
ADC ARG1+LO ; INDEX
STA MPCL
LDA ARG2+HI ; SAME FOR MSBS
ADC ARG1+HI
STA MPCM
LDA #0
STA MPCH ; CLEAR TOP BIT
STA MPCFLG ; & INVALIDATE [MPC]
RTS
; ----
; GETP
; ----
; RETURN PROPERTY [ARG2] OF OBJECT [ARG1];
; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0
ZGETP: JSR PROPB
GETP1: JSR PROPN
CMP ARG2+LO
BEQ GETP3
BCC GETP2
JSR PROPNX
JMP GETP1 ; TRY AGAIN WITH NEXT PROP
GETP2: LDA ARG2+LO ; GET PROPERTY #
SEC ; ZERO-ALIGN IT
SBC #1
ASL A ; WORD-ALIGN IT
TAY ; USE AS AN INDEX
LDA (OBJTAB),Y ; GET MSB OF PROPERTY
STA VALUE+HI
INY
LDA (OBJTAB),Y ; DO SAME WITH LSB
STA VALUE+LO
JMP PUTVAL ; RETURN DEFAULT IN [VALUE]
GETP3: JSR PROPL
INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP
TAX ; (SET FLAGS) IF LENGTH IN [A] = 0
BEQ GETPB ; GET A BYTE PROPERTY
CMP #1 ; IF LENGTH = 1
BEQ GETPW ; GET A WORD PROPERTY
; *** ERROR #7: PROPERTY LENGTH ***
LDA #7
JMP ZERROR
; GET A 1-BYTE PROPERTY
GETPB: LDA (I),Y ; GET LSB INTO [A]
LDX #0 ; CLEAR MSB IN [X]
BEQ ETPEX
; GET A 2-BYTE PROPERTY
GETPW: LDA (I),Y ; GET MSB
TAX ; INTO [X]
INY ; POINT TO LSB
LDA (I),Y ; GET IT INTO [A]
ETPEX: STA VALUE+LO ; STORE LSB
STX VALUE+HI ; AND MSB
JMP PUTVAL
; -----
; GETPT
; -----
; RETURN POINTER TO PROP TABLE [ARG2]
; IN OBJECT [ARG1]
ZGETPT: JSR PROPB
GETPT1: JSR PROPN ; RETURNS OFFSET IN [Y]
CMP ARG2+LO
BEQ GETPT2
BCC DORET
JSR PROPNX ; TRY NEXT PROPERTY
JMP GETPT1
GETPT2: INC I+LO
BNE GETPT3
INC I+HI
GETPT3: TYA ; FETCH OFFSET
CLC
ADC I+LO ; ADD LSB OF TABLE ADDRESS
STA VALUE+LO
LDA I+HI ; AND MSB
ADC #0
SEC ; STRIP OFF
SBC ZCODE ; RELATIVE POINTER
STA VALUE+HI
JMP PUTVAL ; AND RETURN
DORET: JMP RET0 ; ELSE RETURN A ZERO
; -----
; NEXTP
; -----
; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [ARG1];
; RETURN ZERO IF LAST; RETURN FIRST IF [ARG2]=0; ERROR IF NONE
ZNEXTP: JSR PROPB
LDA ARG2+LO ; IF [ARG2]=0
BEQ NXTP3 ; RETURN "FIRST" SLOT
NXTP1: JSR PROPN ; FETCH PROPERTY #
CMP ARG2+LO ; COMPARE TO TARGET #
BEQ NXTP2 ; FOUND IT!
BCC DORET ; LAST PROP, SO RETURN ZERO
JSR PROPNX ; ELSE TRY NEXT PROPERTY
JMP NXTP1
NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY
NXTP3: JSR PROPN ; GET THE PROPERTY #
JMP PUTBYT ; AND RETURN IT
; ---
; ADD
; ---
; RETURN [ARG1] + [ARG2]
ZADD: LDA ARG1+LO ; ADD LSBS
CLC
ADC ARG2+LO
TAX ; SAVE LSB HERE
LDA ARG1+HI ; ADD MSBS
ADC ARG2+HI
JMP VEXIT
; ---
; SUB
; ---
; RETURN [ARG1] - [ARG2]
ZSUB: LDA ARG1+LO ; SUBTRACT LSBS
SEC
SBC ARG2+LO
TAX ; SAVE LSB HERE
LDA ARG1+HI ; SUBTRACT MSBS
SBC ARG2+HI
JMP VEXIT ; EXIT WITH [X]=LSB, [A]=MSB
; ---
; MUL
; ---
; RETURN [ARG1] * [ARG2]
ZMUL: JSR MINIT ; INIT THINGS
ZMLOOP: ROR MTEMP+HI
ROR MTEMP+LO
ROR ARG2+HI
ROR ARG2+LO
BCC ZMNEXT
LDA ARG1+LO
CLC
ADC MTEMP+LO
STA MTEMP+LO
LDA ARG1+HI
ADC MTEMP+HI
STA MTEMP+HI
ZMNEXT: DEX
BPL ZMLOOP
LDX ARG2+LO ; PUT LSB OF PRODUCT
LDA ARG2+HI ; AND MSB
JMP VEXIT ; WHERE "VEXIT" EXPECTS THEM
; ---
; DIV
; ---
; RETURN QUOTIENT OF [ARG1] / [ARG2]
ZDIV: JSR DIVIDE
LDX QUOT+LO
LDA QUOT+HI
JMP VEXIT
; ---
; MOD
; ---
; RETURN REMAINDER OF [ARG1] / [ARG2]
ZMOD: JSR DIVIDE
LDX REMAIN+LO ; FETCH THE REMAINDER
LDA REMAIN+HI ; IN [REMAIN]
JMP VEXIT ; AND RETURN IT
; ---------------
; SIGNED DIVISION
; ---------------
; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2]
; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN]
DIVIDE: LDA ARG1+HI ; SIGN OF REMAINDER
STA RSIGN ; IS THE SIGN OF THE DIVIDEND
EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE
STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME
LDA ARG1+LO ; MOVE [ARG1] TO [QUOT]
STA QUOT+LO
LDA ARG1+HI
STA QUOT+HI ; IF DIVIDEND IS POSITIVE
BPL ABSDIV ; MOVE DIVISOR
JSR ABQUOT ; ELSE CALC ABS(DIVIDEND) FIRST
ABSDIV: LDA ARG2+LO
STA REMAIN+LO
LDA ARG2+HI
STA REMAIN+HI ; IF REMAINDER IS POSITIVE
BPL GODIV ; WE'RE READY TO DIVIDE
JSR ABREM ; ELSE CALC ABS(DIVISOR)
GODIV: JSR UDIV ; DO UNSIGNED DIVIDE
LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED?
BPL RFLIP ; NO, TEST REMAINDER
JSR ABQUOT ; ELSE GET ABSOLUTE VALUE
RFLIP: LDA RSIGN ; SHOULD EMAINDER BE FLIPPED?
BPL DIVEX ; NO, WE'RE DONE
; ELSE FALL THROUGH ...
; ----------------
; CALC ABS(REMAIN)
; ----------------
ABREM: LDA #0
SEC
SBC REMAIN+LO
STA REMAIN+LO
LDA #0
SBC REMAIN+HI
STA REMAIN+HI
DIVEX: RTS
; --------------
; CALC ABS(QUOT)
; --------------
ABQUOT: LDA #0
SEC
SBC QUOT+LO
STA QUOT+LO
LDA #0
SBC QUOT+HI
STA QUOT+HI
RTS
; -----------------
; UNSIGNED DIVISION
; -----------------
; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN]
; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN]
UDIV: LDA REMAIN+LO ; CHECK [REMAIN]
ORA REMAIN+HI ; BEFORE PROCEEDING
BEQ DIVERR ; CAN'T DIVIDE BY ZERO!
JSR MINIT ; SET IT ALL UP
UDLOOP: ROL QUOT+LO
ROL QUOT+HI
ROL MTEMP+LO
ROL MTEMP+HI
LDA MTEMP+LO
SEC
SBC REMAIN+LO
TAY ; SAVE HERE
LDA MTEMP+HI
SBC REMAIN+HI
BCC UDNEXT
STY MTEMP+LO
STA MTEMP+HI
UDNEXT: DEX
BNE UDLOOP
ROL QUOT+LO ; SHIFT LAST CARRY FOR QUOTIENT
ROL QUOT+HI
LDA MTEMP+LO ; MOVE REMAINDER
STA REMAIN+LO ; INTO [REMAIN]
LDA MTEMP+HI
STA REMAIN+HI
RTS
; *** ERROR #8: DIVISION BY ZERO ***
DIVERR: LDA #8
JMP ZERROR
; ---------
; MATH INIT
; ---------
MINIT: LDX #16 ; INIT LOOPING INDEX
LDA #0
STA MTEMP+LO ; CLEAR TEMP
STA MTEMP+HI ; REGISTER
CLC ; AND CARRY
RTS
END