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

217 lines
4.2 KiB
Plaintext

PAGE
SBTTL "--- MAIN LOOP ---"
MLOOP: LDX #$FF ; RESET THE
TXS ; HARDWARE STACK
INX ; = 0
STX NARGS ; CLEAR # ARGS
JSR NEXTPC ; GET Z-BYTE INTO [A]
STA OPCODE ; FLAGS ARE SET
IF DEBUG
LDA #0 ; BREAKPOINT #0
JSR DOBUG
LDA OPCODE
ENDIF
; DECODE AN OPCODE
TAX ; SET FLAGS
BMI DC0 ; IF POSITIVE,
JMP OP2 ; IT'S A 2-OP
DC0: CMP #$E0 ; IS IT "CALL"?
BNE DC1
JMP GCALL
DC1: CMP #$B0
BCS DC2
JMP OP1 ; OR MAYBE A 1-OP
DC2: CMP #$C0
BCS OPEXT
JMP OP0 ; PERHAPS A 0-OP
; --------------
; HANDLE AN X-OP
; --------------
OPEXT: JSR NEXTPC ; GRAB ARGUMENT BYTE
STA ABYTE ; HOLD IT HERE
LDX #0
STX ADEX ; INIT LOOP INDEX
BEQ OPX1 ; JUMP INTO LOOP
TOPX: LDA ABYTE ; GET ARG BYTE
ASL A ; SHIFT NEXT 2 ARG BITS
ASL A ; INTO BITS 7 & 6
STA ABYTE ; HOLD FOR LATER
OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS
BNE OPX2
JSR GETLNG ; 00 = LONG IMMEDIATE
JMP OPXNXT
OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE?
BNE OPX3 ; NO, KEEP GUESSING
JSR GETSHT ; 01 = SHORT IMMEDIATE
JMP OPXNXT
OPX3: CMP #%10000000 ; LAST TEST
BNE OPX4 ; 11 = NO MORE ARGUMENTS
JSR GETVAR ; 10 = VARIABLE
OPXNXT: LDX ADEX ; ARGUMENT INDEX
LDA VALUE+LO ; GRAB LSB OF VALUE
STA ARG1+LO,X ; STORE IN ARGUMENT TABLE
LDA VALUE+HI ; GRAB MSB OF VALUE
STA ARG1+HI,X ; STORE THAT, TOO
INC NARGS ; UPDATE ARGUMENT COUNTER
INX
INX
STX ADEX ; UPDATE INDEX
CPX #8 ; DONE 4 ARGUMENTS YET?
BCC TOPX ; NO, GET SOME MORE
; ALL X-OP ARGUMENTS READY
OPX4: LDA OPCODE ; IS THIS
CMP #$E0 ; AN EXTENDED 2-OP?
BCS DOXOP ; NO, IT'S A REAL X-OP
JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP
DOXOP: LDX #LOW OPTX ; GET ADDR OF X-OP TABLE
LDY #HIGH OPTX ; INTO [X/Y]
AND #%00011111 ; ISOLATE OP ID BITS
CMP #NOPSX ; IS IT A LEGAL X-OP?
BCC DODIS ; YUP; TIME TO DISPATCH IT
; *** ERROR #2: UNDEFINED X-OP ***
LDA #2
JMP GERROR
; ---------------
; OPCODE DISPATCH
; ---------------
; ENTRY: MASKED OPCODE INDEX IN [A]
; OP-TABLE ADDR IN X/Y (LSB/MSB)
DODIS: STX I+LO ; SAVE TABLE ADDRESS
STY I+HI ; IN A POINTER
ASL A ; WORD-ALIGN THE OP INDEX
TAY
LDA (I),Y ; GET LSB OF DISPATCH ADDRESS
STA GO+LO ; INSTALL AS JSR OPERAND
INY
LDA (I),Y ; SAME WITH MSB
STA GO+HI
DB $20 ; 6502 "JSR" OPCODE
GO: DW $0000 ; DUMMY OPERAND BYTES
JMP MLOOP ; GO BACK FOR ANOTHER OPCODE
; -------------
; HANDLE A 0-OP
; -------------
OP0: LDX #LOW OPT0 ; GET ADDR OF 0-OP TABLE
LDY #HIGH OPT0 ; INTO [X/Y]
AND #%00001111 ; ISOLATE OP ID BITS
CMP #NOPS0 ; OUT OF RANGE?
BCC DODIS ; NO, DISPATCH
; *** ERROR #3: UNDEFINED 0-OP ***
LDA #3
JMP GERROR
; -------------
; HANDLE A 1-OP
; -------------
OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS
BNE OP1A
JSR GETLNG ; 00 = LONG IMMEDIATE
JMP OP1EX
OP1A: CMP #%00010000 ; TEST AGAIN
BNE OP1B
JSR GETSHT ; 01 = SHORT IMMEDIATE
JMP OP1EX
OP1B: CMP #%00100000 ; ONE MORE TEST
BNE BADOP1 ; UNDEFINED STATE!
JSR GETVAR ; 10 = VARIABLE
OP1EX: JSR V2A1 ; VALUE TO [ARG1], UPDATE COUNT
LDX #LOW OPT1 ; LSB OF DISPATCH TABLE
LDY #HIGH OPT1 ; MSB
LDA OPCODE ; RESTORE OPCODE
AND #%00001111 ; ISOLATE OP ID BITS
CMP #NOPS1 ; IF WITHIN RANGE,
BCC DODIS ; EXECUTE THE 1-OP
; *** ERROR #4: UNDEFINED 1-OP ***
BADOP1: LDA #4
JMP GERROR
; -------------
; HANDLE A 2-OP
; -------------
OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT
BNE OP2A
JSR GETSHT ; 0 = SHORT IMMEDIATE
JMP OP2B
OP2A: JSR GETVAR ; 1 = VARIABLE
OP2B: JSR V2A1 ; VALUE TO [ARG1], UPDATE COUNT
LDA OPCODE ; RESTORE OPCODE BYTE
AND #%00100000 ; ISOLATE 2ND ARG BIT
BNE OP2C
JSR GETSHT ; 0 = SHORT IMMEDIATE
JMP OP2D
OP2C: JSR GETVAR ; 1 = VARIABLE
OP2D: LDA VALUE+LO ; MOVE VALUE TO [ARG2]
STA ARG2+LO
LDA VALUE+HI
STA ARG2+HI
INC NARGS ; UPDATE COUNT
; ENTRY FOR EXTENDED 2-OPS
OP2EX: LDX #LOW OPT2 ; LSB OF DISPATCH TABLE
LDY #HIGH OPT2 ; MSB
LDA OPCODE ; RESTORE OPCODE BYTE
AND #%00011111 ; ISOLATE OP ID BITS
CMP #NOPS2
BCS BADOP2 ; ERROR IF OUT OF RANGE
JMP DODIS ; ELSE DISPATCH
; *** ERROR #5: UNDEFINED 2-OP ****
BADOP2: LDA #5
JMP GERROR
; --------------------------------------
; MOVE [VALUE] TO [ARG1], UPDATE [NARGS]
; --------------------------------------
V2A1: LDA VALUE+LO
STA ARG1+LO
LDA VALUE+HI
STA ARG1+HI
INC NARGS
RTS
END