PAGE SBTTL "--- OPCODE SUPPORT SUBROUTINES ---" ; ----------------------- ; FETCH A SHORT IMMEDIATE ; ----------------------- GETSHT: LDA #0 ; CLEAR MSB OF [VALUE] BEQ GLG ; AND GRAB LSB ; ---------------------- ; FETCH A LONG IMMEDIATE ; ---------------------- GETLNG: JSR NEXTPC ; GRAB MSB GLG: STA VALUE+HI ; STORE IT JSR NEXTPC ; GRAB LSB STA VALUE+LO ; STORE THAT TOO RTS ; ---------------- ; FETCH A VARIABLE ; ---------------- ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) VARGET: TAX ; IF NON-ZERO, BNE GETVR1 ; ACCESS A VARIABLE JSR POPVAL ; ELSE PULL VAR OFF Z-STACK JMP PSHVAL ; WITHOUT ALTERING STACK ; FROM THE MAIN LOOP (ID BYTE IN Z-CODE) GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE BEQ POPVAL ; VALUE IS ON Z-STACK ; IS VARIABLE LOCAL OR GLOBAL? GETVR1: CMP #$10 ; IF >= 16, BCS GETVRG ; IT'S GLOBAL ; HANDLE A LOCAL VARIABLE GETVRL: SEC SBC #1 ; FORM A ZERO-ALIGNED ASL A ; WORD INDEX TAX ; INTO THE [LOCALS] LDA LOCALS+LO,X ; GRAB LSB STA VALUE+LO LDA LOCALS+HI,X ; AND MSB STA VALUE+HI RTS ; HANDLE A GLOBAL VARIABLE GETVRG: JSR GVCALC ; GET ADDRESS OF GLOBAL INTO [I] LDA (I),Y ; MSB OF GLOBAL ([Y] = 0) STA VALUE+HI INY ; = 1 LDA (I),Y ; LSB OF GLOBAL STA VALUE+LO ; SAVE IT RTS ; AND WE'RE DONE ; ---------------------------------- ; POP G-STACK INTO [VALUE] AND [X/A] ; ---------------------------------- POPVAL: DEC GSP BEQ UNDER ; UNDERFLOW IF ZERO! LDY GSP ; READ STACK POINTER LDX GSTAKL,Y ; GRAB LSB OF STACK VALUE STX VALUE+LO ; GIVE TO [VALUE] LDA GSTAKH,Y ; ALSO GRAB MSB STA VALUE+HI ; A SIMILAR FATE RTS ; *** ERROR #6: G-STACK UNDERFLOW *** UNDER: LDA #6 JMP GERROR ; ----------------------- ; PUSH [VALUE] TO G-STACK ; ----------------------- PSHVAL: LDX VALUE+LO LDA VALUE+HI ; FALL THROUGH ... ; --------------------- ; PUSH [X/A] TO G-STACK ; --------------------- PSHXA: LDY GSP STA GSTAKH,Y TXA STA GSTAKL,Y INC GSP BEQ OVER ; OVERFLOW IF ZEROED! RTS ; *** ERROR #7: G-STACK OVERFLOW *** OVER: LDA #7 JMP GERROR ; -------------- ; RETURN A VALUE ; -------------- ; FROM WITHIN AN OPCODE (VARIABLE ID IN [A]) VARPUT: TAX ; IF ZERO, BNE PUTVR1 DEC GSP ; FLUSH TOP WORD OFF STACK BNE PSHVAL ; AND REPLACE WITH [VALUE] BEQ UNDER ; ERROR IF ZSP BECAME ZERO! ; RETURN A ZERO RET0: LDA #0 ; RETURN BYTE IN [A] PUTBYT: STA VALUE+LO LDA #0 STA VALUE+HI ; CLEAR MSB ; RETURN [VALUE]; VARIABLE ID IN NEXT Z-BYTE PUTVAL: JSR NEXTPC ; GET VAR-TYPE BYTE BEQ PSHVAL ; VALUE GOES TO STACK IF ZERO ; LOCAL OR GLOBAL VARIABLE? PUTVR1: CMP #$10 ; IF >= 16, BCS PUTVLG ; IT'S GLOBAL ; PUT A LOCAL VARIABLE PUTVLL: SEC SBC #1 ; FORM A ZERO-ALIGNED ASL A ; WORD INDEX TAX ; INTO [LOCALS] LDA VALUE+LO ; GRAB LSB STA LOCALS+LO,X ; SAVE IN LOCAL TABLE LDA VALUE+HI ; DO SAME TO STA LOCALS+HI,X ; MSB RTS ; PUT A GLOBAL VARIABLE PUTVLG: JSR GVCALC ; GET ADDR OF GLOBAL INTO [I] LDA VALUE+HI ; GET MSB STA (I),Y ; STORE AS 1ST BYTE ([Y] = 0) INY ; [Y] = 1 LDA VALUE+LO ; NOW GET LSB STA (I),Y ; STORE AS 2ND BYTE RTS ; ----------------------- ; CALC GLOBAL WORD OFFSET ; ----------------------- ; ENTRY: VAR-ID BYTE (16-255) IN [A] ; EXIT: ADDRESS OF GLOBAL VAR IN [VAL] ; [Y] = 0 FOR INDEXING GVCALC: SEC SBC #$10 ; FORM A ZERO-ALIGNED INDEX LDY #0 ; MAKE SURE MSB OF OFFSET AND [Y] STY I+HI ; ARE CLEARED ASL A ; MULTIPLY OFFSET BY 2 ROL I+HI ; TO WORD-ALIGN IT CLC ; TO ADDRESS OF GLOBAL TABLE ADC GLOBAL+LO ; TO FORM THE ABSOLUTE STA I+LO ; ADDRESS OF THE LDA I+HI ; DESIRED GLOBAL VARIABLE ADC GLOBAL+HI ; STORE ADDRESS BACK IN [I] STA I+HI ; AS A POINTER WCEX: RTS ; --------------- ; PREDICATE FAILS ; --------------- PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE BPL PREDB ; BRANCH IF BIT 7 CLEAR ; ----------------------- ; IGNORE PREDICATE BRANCH ; ----------------------- ; ENTRY: 1ST BRANCH BYTE IN [A] PREDNB: AND #%01000000 ; TEST BIT 6 BNE WCEX ; SHORT BRANCH IF SET JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE ; ------------------ ; PREDICATE SUCCEEDS ; ------------------ PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR ; -------------------------- ; PERFORM A PREDICATE BRANCH ; -------------------------- ; ENTRY: 1ST PRED BYTE IN [A] PREDB: TAX ; COPY FOR LATER AND #%01000000 ; LONG OR SHORT BRANCH? BEQ PREDLB ; LONG IF BIT 6 IS CLEAR ; HANDLE A SHORT BRANCH TXA ; RESTORE PRED BYTE AND #%00111111 ; FORM SHORT OFFSET STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET LDA #0 STA VALUE+HI ; MSB OF OFFSET IS ZERO BEQ PREDB1 ; DO THE BRANCH ; HANDLE A LONG BRANCH PREDLB: TXA ; RESTORE 1ST PRED BYTE AND #%00111111 ; FORM MSB OF OFFSET TAX ; SAVE HERE FOR REFERENCE AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE BEQ DOB2 ; POSITIVE IF ZERO, USE [X] FOR MSB TXA ; ELSE RESTORE BYTE ORA #%11100000 ; EXTEND SIGN BIT TAX ; BACK HERE FOR STORAGE DOB2: STX VALUE+HI JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET STA VALUE+LO ; BRANCH TO Z-ADDRESS IN [VALUE] PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET BNE PREDB3 ; DO BRANCH IF NZ LDA VALUE+LO ; IF LSB IS NON-ZERO, BNE PREDB2 ; MAKE SURE IT ISN'T 1 JMP GRFALS ; ELSE DO AN "RFALSE" IF [VALUE] = 0 PREDB2: CMP #1 ; IF OFFSET = 1 BNE PREDB3 JMP GRTRUE ; DO AN "RTRUE" ; ENTRY POINT FOR "JUMP" PREDB3: JSR DECVAL ; CALC [VALUE]-2 JSR DECVAL ;*** LDA VALUE+HI LDX VALUE+LO JSR ADDGPC LDA VALUE+HI ; EXTEND SIGN AND #$80 CLC ADC GPCH STA GPCH ;*** ; LDA VALUE+LO ; GET LSB OF OFFSET ; CLC ; ADC GPCL ; ADD LSB OF GPC ; BCC PREDB5 ; IF OVERFLOWED, ; INC VALUE+HI ; UPDATE MSB OF OFFSET ;PREDB5: STA GPCL ; UPDATE ZPCL ; LDA VALUE+HI ; IF MSB IS ZERO, ; BEQ GNOOP ; PAGE IS STILL VALID ; CLC ; ADC GPCH ; STA GPCH ; ELSE SWITCH PAGES ; LDA #0 ; INVALIDATE [GPC] ; STA GPCFLG ; FALL THROUGH ... ; ---- ; NOOP ; ---- GNOOP: RTS ; ----------------- ; INCREMENT [VALUE] ; ----------------- INCVAL: INC VALUE+LO BNE IVX INC VALUE+HI IVX: RTS ; ----------------- ; DECREMENT [VALUE] ; ----------------- DECVAL: LDA VALUE+LO SEC SBC #1 STA VALUE+LO BCS DVX DEC VALUE+HI DVX: RTS ; ---------------------- ; MOVE [ARG1] TO [VALUE] ; ---------------------- A12VAL: LDA ARG1+LO STA VALUE+LO LDA ARG1+HI STA VALUE+HI RTS END