VM02/src/frame.s

886 lines
17 KiB
ArmAsm
Executable File

;*
;* JAVA VIRTUAL MACHINE FRAME/STACK SUPPORT FOR 6502
;*
;*
;* FRAME BLOCKS ARE LINKED LIST OF PREDEFINED SIZES TO HOLD LOCAL VARIABLES AND A STACK
;* FOR EACH METHOD INVOCATION. A FRAME BLOCK CONTAINS AS MANY FRAMES AS WILL FIT. WHEN
;* SPANNING BLOCKS, THE FIRST FIELDS IN THE BLOCK IS THE PREVIOUS BLOCK AND STACK_PTR.
;* THE FRAME BLOCK IS ORGANIZED AS:
;* FRAME_PTR -> PREV HFRAME
;* FRAME 0
;* ...
;* FRAME N
;* IF PREV HFRAME IS 0, THEN FRAME LIST IS EMPTY, THREAD IS FINISHED.
;*
;* A METHOD FRAME IS ORGANIZED AS:
;* VAR_BASE -> PARAMETERS/LOCAL VARIABLES
;* (BP),Y -> LOCAL VARIABLE POINTERS
;* RETURN ADDRESS = HMETHOD, PC
;* STACK_BASE -> STACK
;* ...
;* (SP),Y-> TOP OF STACK
;*
;* IF NEW FRAME WON'T FIT IN CURRENT FRAME BLOCK, ALLOCATE A NEW ONE AND LINK TO PREVIOUS
;*
.INCLUDE "global.inc"
.INCLUDE "class.inc"
.INCLUDE "frame.inc"
.IMPORT CROUT,COUT,PRSTR,KBWAIT,PRHSTR,PRHSTRLN
.IMPORT HMEM_ALLOC,HMEM_ALLOC_FIXED,HMEM_FREE,HMEM_LOCK,HMEM_UNLOCK,HMEM_UNLOCK_CODE
.IMPORT HMEM_PTR,HMEM_REF_INC,HMEM_REF_DEC
.IMPORT HSTR_HASH,STR_HASH,HSTRPL_ADD,HSTRPL_DEL
.IMPORT HCLASS_NAME,HCLASS_HNDL,HCLASS_ADD,HCLASS_INDEX,CLASS_STRING,CLASS_OF,CLASS_LOCK,CLASS_UNLOCK
.IMPORT CLASS_METHODPTR,CLASS_VIRTCODE,CLASS_LOCKMETHOD,CLASS_UNLOCKMETHOD
.IMPORT THREAD_PUSH_TLS,THREAD_POP_TLS,THREAD_LOCK,THREAD_UNLOCK,CURRENT_THREAD
.IMPORT HCODE_ACCESS,HCODE_UNACCESS,HCODE_LOCK,HCODE_UNLOCK,HCODE_ISBYTECODE
.IMPORT HCODE_GETLOCALS,HCODE_GETCLASS,HCODE_FLAGS,HCODE_GETHEXCEPT,HCODE_GETEXCEPTLEN
.IMPORT EXECBYTECODES,LOOKUPCLASSIDX
.IMPORT UNREF_OBJECT,SYSTHROW,THROW_INTERNALERR,CURRENTEXCEPTN
.EXPORT ASYNC_VIRTUAL,ASYNC_STATIC,INVOKE_VIRTUAL,INVOKE_SPECIAL,INVOKE_STATIC,EXIT_METHOD,CATCH_EXCEPTN
.CODE
;*
;* INVOKE AN ASYNCHRONOUS METHOD. JSR HERE.
;* ENTRY: AX = METHOD OFFSET
;* Y = CLASS INDEX
;*
ASYNC_VIRTUAL: STY LOCKCLASS
.IFDEF DEBUG
STA METHDOFST
STX METHDOFST+1
.ENDIF
JSR CLASS_LOCKMETHOD ; GET POINTER TO LOCKED METHOD
STA METHODPTR
STX METHODPTR+1
LDY #METHODVINDEX+1 ; GET INDEX FOR VIRTUAL TABLE
LDA (METHODPTR),Y
DEY
STA TMP+1
LDA (METHODPTR),Y
DEY
STA TMP
TSX
TXA
CLC
ADC (METHODPTR),Y ; SKIP METHOD PARAM SIZE
TAX
LDA $0105,X ; GET ICLASS FROM *THIS* REF
AND #$7F
.IFDEF DEBUG_INVOKE
BNE :+
JMP NULL_THIS
:
.ELSE
BEQ NULL_THIS
.ENDIF
TAY
LDA TMP
LDX TMP+1
JSR CLASS_VIRTCODE
JMP ASYNC_METHOD
ASYNC_STATIC: STY LOCKCLASS
.IFDEF DEBUG
STA METHDOFST
STX METHDOFST+1
.ENDIF
JSR CLASS_LOCKMETHOD ; GET POINTER TO LOCKED METHOD
STA METHODPTR
STX METHODPTR+1
LDY #METHODSTATICODE+1 ; GET STATIC CODE HANDLE
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
ASYNC_METHOD: STA HMETHODCODE
STX HMETHODCODE+1
.IFDEF DEBUG_INVOKE
PSTR "INVOKING ASYNC METHOD:"
LDY LOCKCLASS
JSR CLASS_STRING
JSR HMEM_PTR
JSR PRSTR
LDA #'.'
JSR COUT
LDY #METHODNAME+1
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
JSR HMEM_PTR
JSR PRSTR
LDY #METHODDESC+1
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
JSR HMEM_PTR
JSR PRSTR
JSR CROUT
; JSR KBWAIT
.ENDIF
LDA HMETHODCODE
LDX HMETHODCODE+1
JSR HCODE_ISBYTECODE ; CHECK FOR NATIVE METHOD
BEQ ASYNCBYTECODE
LDY LOCKCLASS
JSR CLASS_UNLOCKMETHOD ; UNLOCK METHOD STRUCTURE
LDA HMETHODCODE
LDX HMETHODCODE+1
JSR HMEM_PTR
STA NATIVECODEPTR ; CALL NATIVE METHOD
STX NATIVECODEPTR+1
CLC ; CLEAR CARRY
JMP (NATIVECODEPTR)
ASYNCBYTECODE: JSR SAVEPC_RELFRM ; SAVE EXECPC AND RELEASE FRAME
PLA ; SAVE RETURN ADDRESS
TAX ; IN TLS
PLA
JSR THREAD_PUSH_TLS
LDA HEXECFRAME
LDX HEXECFRAME+1
JSR THREAD_PUSH_TLS
LDA #$00 ; ZERO OUT CURRENT FRAME
STA HEXECFRAME
STA HEXECFRAME+1
JMP BUILD_FRAME
NULL_THIS: LDA #17 ; NULL *THIS* REF
JMP SYSTHROW
;*
;* INVOKE A METHOD. DON'T JSR HERE, JMP HERE.
;* ENTRY: AX = METHOD OFFSET
;* Y = CLASS INDEX
;*
INVOKE_VIRTUAL: STY LOCKCLASS
.IFDEF DEBUG
STA METHDOFST
STX METHDOFST+1
.ENDIF
JSR CLASS_LOCKMETHOD ; GET POINTER TO LOCKED METHOD
STA METHODPTR
STX METHODPTR+1
LDY #METHODVINDEX+1 ; GET INDEX FOR VIRTUAL TABLE
LDA (METHODPTR),Y
DEY
STA TMP+1
LDA (METHODPTR),Y
DEY
STA TMP
TSX
TXA
CLC
ADC (METHODPTR),Y ; SKIP METHOD PARAM SIZE
TAX
LDA $0103,X ; GET ICLASS FROM *THIS* REF
AND #$7F
BEQ NULL_THIS
TAY
LDA TMP
LDX TMP+1
JSR CLASS_VIRTCODE
JMP INVOKE_METHOD
INVOKE_SPECIAL: STY LOCKCLASS
.IFDEF DEBUG
STA METHDOFST
STX METHDOFST+1
.ENDIF
JSR CLASS_LOCKMETHOD ; GET POINTER TO LOCKED METHOD
STA METHODPTR
STX METHODPTR+1
LDY #METHODVINDEX+1 ; GET INDEX FOR VIRTUAL TABLE
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
LDY LOCKCLASS
JSR CLASS_VIRTCODE
JMP INVOKE_METHOD
INVOKE_STATIC: STY LOCKCLASS
.IFDEF DEBUG
STA METHDOFST
STX METHDOFST+1
.ENDIF
JSR CLASS_LOCKMETHOD ; GET POINTER TO LOCKED METHOD
STA METHODPTR
STX METHODPTR+1
LDY #METHODSTATICODE+1 ; GET STATIC CODE HANDLE
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
;*
;* INVOKE METHOD
;* ENTRY: AX = CODE HANDLE
;*
INVOKE_METHOD: STA HMETHODCODE
STX HMETHODCODE+1
.IFDEF DEBUG_INVOKE
PSTR "INVOKING METHOD:"
LDY LOCKCLASS
JSR CLASS_STRING
JSR HMEM_PTR
JSR PRSTR
LDA #'.'
JSR COUT
LDY #METHODNAME+1
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
JSR HMEM_PTR
JSR PRSTR
LDY #METHODDESC+1
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
JSR HMEM_PTR
JSR PRSTR
JSR CROUT
; JSR KBWAIT
.ENDIF
LDA EXECPC ; INCREMENT EXECPC
CLC
ADC #$03
STA EXECPC
BCC :+
INC EXECPC+1
: LDA HMETHODCODE
LDX HMETHODCODE+1
JSR HCODE_ISBYTECODE ; CHECK FOR NATIVE METHOD
BEQ BUILD_FRAME
LDY LOCKCLASS
JSR CLASS_UNLOCKMETHOD ; UNLOCK METHOD STRUCTURE
LDA HMETHODCODE
LDX HMETHODCODE+1
JSR HMEM_PTR
STA NATIVECODEPTR ; CALL NATIVE METHOD
STX NATIVECODEPTR+1
CLC ; CLEAR CARRY
JSR :+
SEI ; MAKE A SANE ENVIRONMENT ON RETURN
BIT LCBNK2
BIT LCBNK2
CLI
JMP EXECBYTECODES ; RETURN TO EXECUTING BYTECODES
: JMP (NATIVECODEPTR)
;*
;* BUILD A NEW FRAME FOR METHOD INVOCATION
;* A NEW FRAME BLOCK WILL BE ALLOCATED IF THE CURRENT
;* BLOCK CAN'T FIT THE NEW FRAME
;* ENTRY: METHODPTR = POINTER TO METHOD BEING CALLED
;*
BUILD_FRAME:
.IFDEF DEBUG
LDA $0101 ; CHECK FOR STACK OVERFLOW
CMP #$69
BEQ :++
: PERR "STACK OVERFLOW IN METHOD INVOKE"
BRK
JMP THROW_INTERNALERR
: LDA $0100
CMP #$69
BNE :--
.ENDIF
JSR SAVEPC_RELFRM ; SAVE EXECPC AND RELEASE FRAME
LDA HMETHODCODE
LDX HMETHODCODE+1
JSR HCODE_ACCESS ; ACCESS THIS CODE BLOCK
JSR HCODE_GETCLASS
STA CALLCLASS
JSR HCODE_GETLOCALS ; GET LOCAL VAR COUNT & SIZE IN BYTES
STY FRMVARS ; (INCLUDES PARAMETERS)
CLC
ADC #FRAMEBASESZ
BCC :+
INX
: LDY #$00
JSR HMEM_ALLOC ; ALLOCATE NEW FRAME
STA HLINKFRAME
STX HLINKFRAME+1
JSR HMEM_LOCK
STA FRAMEPTR
STX FRAMEPTR+1
.IFDEF DEBUG
LDY #FRAMEMETHOD
LDA METHDOFST
STA (FRAMEPTR),Y
INY
LDA METHDOFST+1
STA (FRAMEPTR),Y
INY
.ELSE
LDY #FRAMEICLASS ; SAVE CLASS IN FRAME
.ENDIF
LDA CALLCLASS
STA (FRAMEPTR),Y
INY ; LDY #FRAMELOCALCNT
LDA FRMVARS ; SAVE LOCAL VAR COUNT
STA (FRAMEPTR),Y
INY ; LDY #FRAMEHCODE
LDA HMETHODCODE ; SAVE CODE HANDLE IN FRAME
STA (FRAMEPTR),Y
INY
LDA HMETHODCODE+1
STA (FRAMEPTR),Y
INY ; LDY #FRAMEPC
LDA #$00 ; SET PC TO ENTRYPOINT
STA (FRAMEPTR),Y
INY
STA (FRAMEPTR),Y
INY ; LDY #FRAMEHPREV
LDA HEXECFRAME ; LINK TO PREVIOUS FRAME HANDLE
STA (FRAMEPTR),Y
INY
LDA HEXECFRAME+1
STA (FRAMEPTR),Y
LDA HLINKFRAME
LDX HLINKFRAME+1
JSR SETUP_FRAME
LDY #METHODDESC+1
LDA (METHODPTR),Y ; GET POINTER TO DESC STRING
DEY
TAX
LDA (METHODPTR),Y
JSR HMEM_LOCK ; LOCK STRING IN PLACE
STA SCANPTR
STX SCANPTR+1
LDY #$01 ; SKIP SIZE BYTE
STY SCANPOS
DEY
STY VARCNT
TSX ; COPY PARAMETERS INTO NEW LOCALS
TXA
LDY #METHODPARAMS
CLC
ADC (METHODPTR),Y ; ADD PARAM BYTE COUNT
TAX
STX STACKPOPPED
LDY #METHODACCESS ; CHECK FOR STATIC METHOD, Y = 0
LDA (METHODPTR),Y
AND #$08
BNE SCANPARAMTYPES
TXA
CLC
ADC #$04
STA STACKPOPPED
TAX
BNE COPYREF ; COPY THIS REF PARAMETER
SCANPARAMTYPES: LDY SCANPOS ; SCAN PARAMETERS FOR REF TYPE
INY
LDA (SCANPTR),Y
CMP #')' ; END OF PARAM LIST
BNE SCANPTYPECHK
JMP ZEROLOCALTYPES
SCANPTYPECHK: CMP #'L' ; CHECK FOR REFERENCE
BEQ SCANTYPEREF
CMP #'[' ; CHECK FOR ARRAY
BEQ SCANTYPEARRAY
CMP #'J'
BEQ SCANLONG
STY SCANPOS ; PULL 32 BIT VALUE OFF STACK
LDY VARCNT
: LDA #$00 ; NON-REF TYPE
STA (BPT),Y
LDA $0100,X
DEX
STA (BP3),Y
LDA $0100,X
DEX
STA (BP2),Y
LDA $0100,X
DEX
STA (BP1),Y
LDA $0100,X
DEX
STA (BP0),Y
INC VARCNT
BNE SCANPARAMTYPES
SCANLONG: STY SCANPOS
LDY VARCNT
INY
LDA #$00
STA (BPT),Y ; ZERO OUT HIWORD TYPE
DEY
INC VARCNT ; ADD TWO TO VARCNT TO MATCH UP LOCALS
BNE :-
SCANTYPEARRAY: INY ; EAT ARRAY
LDA (SCANPTR),Y
CMP #'['
BEQ SCANTYPEARRAY
CMP #'L' ; FALL THRU FOR ARRAY OBJS
BNE INCREFCNT
SCANTYPEREF: INY
LDA (SCANPTR),Y
CMP #';' ; CHECK FOR END OF REFERENCE
BNE SCANTYPEREF
INCREFCNT: STY SCANPOS
COPYREF: LDY VARCNT
LDA #T_REF|$80 ; PULL REF VALUE OFF STACK
STA (BPT),Y
LDA $0100,X
DEX
STA (BP3),Y
LDA $0100,X
DEX
AND #$7F ; MASK OFF NOINC FLAG
STA (BP2),Y
LDA $0100,X
DEX
STA (BP1),Y
LDA $0100,X
DEX
STA (BP0),Y
LDA $0103,X ; CHECK NOINC FLAG
BMI SKIPREFINC
LDA (BP1),Y ; CHECK NULL REF
BEQ SKIPREFINC
STX STACKPOS
TAX
LDA (BP0),Y
JSR HMEM_REF_INC ; INCREMENT REF CNT
LDX STACKPOS
SKIPREFINC: INC VARCNT
JMP SCANPARAMTYPES
ZEROLOCALTYPES: LDX STACKPOPPED ; UPDATE STACK POINTER
TXS
LDY #FRAMESP ; SAVE SP FOR EXCEPTION
TXA
STA (FRAMEPTR),Y
LDY #FRAMELOCALCNT ; ZERO OUT REMAINING LOCALS
LDA (FRAMEPTR),Y
SEC
SBC VARCNT
BEQ EXECFRAME
TAX
LDA #$00
LDY VARCNT
ZEROLOCALSLP: STA (BPT),Y
INY
DEX
BNE ZEROLOCALSLP
EXECFRAME: LDY #METHODDESC+1
LDA (METHODPTR),Y ; UNLOCK DESC STRING
DEY
TAX
LDA (METHODPTR),Y
JSR HMEM_UNLOCK
JSR HCODE_UNACCESS ; DONE ACCESSING CODE PARAMTERS
LDY LOCKCLASS
JSR CLASS_UNLOCKMETHOD ; UNLOCK METHOD STRUCTURE
LDA HMETHODCODE
LDX HMETHODCODE+1
JSR HCODE_FLAGS
AND #$20 ; CHECK FOR SYNCHRONIZED METHODS
BNE :+
JMP EXECBYTECODES
: LDY #METHODACCESS ; CHECK FOR STATIC METHOD
LDA (METHODPTR),Y
AND #$08
BEQ :+
LDY CALLCLASS
JSR HCLASS_INDEX
BCC LOCKNLOAD ; SHOULD ALWAYS BE TAKEN
PERR "BAD SYNCH CLASS"
: LDA (BP1),Y ; Y = 0
TAX
LDA (BP0),Y
LOCKNLOAD: PHA
LDY #FRAMESYNCHOBJ ; SAVE HCLASS IN FRAME FOR SYNCHRONIZATION
STA (FRAMEPTR),Y
INY
TXA
STA (FRAMEPTR),Y
PLA
JSR THREAD_LOCK ; LOCK OBJECT
JMP EXECBYTECODES
;*
;* SETUP FRAME POINTERS
;* ENTRY: AX = FRAME HANDLE
;*
SETUP_FRAME: STA HEXECFRAME ; SET NEW FRAME
STX HEXECFRAME+1
JSR HMEM_LOCK ; LOCK FRAME IN PLACE, RETURN POINTER
STA FRAMEPTR
STX FRAMEPTR+1
LDY #FRAMEHCODE+1 ; GET CODE SEGMENT
LDA (FRAMEPTR),Y
DEY
TAX
LDA (FRAMEPTR),Y
JSR HCODE_LOCK
STA EXECCODEBASE
STX EXECCODEBASE+1
LDY #FRAMEPC ; SET PC POINTER
CLC ; ADD EXECPC OFFSET
ADC (FRAMEPTR),Y
INY
STA EXECPC
TXA
ADC (FRAMEPTR),Y
STA EXECPC+1
LDY #FRAMEICLASS ; SET CLASS INDEX
LDA (FRAMEPTR),Y
STA IEXECCLASS
TAY
JSR CLASS_LOCK
CLC
ADC #(CLASSCONSTPL-CONSTPLRECSZ) ; INDEX IS 1 BASED
BCC :+
INX
: STA EXECCONSTPL
STX EXECCONSTPL+1
LDY #FRAMELOCALCNT
LDA (FRAMEPTR),Y ; SETUP BASE POINTERS
STA TMP
LDA FRAMEPTR
LDX FRAMEPTR+1
CLC
ADC #FRAMEBASESZ
BCC :+
INX
CLC
: STA BPT ; BASE POINTER - TYPE
STX BPT+1
ADC TMP
BCC :+
INX
CLC
: STA BP0 ; BASE POINTER - BYTE0
STX BP0+1
ADC TMP
BCC :+
INX
CLC
: STA BP1 ; BASE POINTER - BYTE1
STX BP1+1
ADC TMP
BCC :+
INX
CLC
: STA BP2 ; BASE POINTER - BYTE2
STX BP2+1
ADC TMP
BCC :+
INX
CLC
: STA BP3 ; BASE POINTER - BYTE3
STX BP3+1
: RTS
;*
;* SAVE EXECPC AND FALL INTO RELEASE_FRAME
;*
SAVEPC_RELFRM: LDX HEXECFRAME+1
BEQ :-
LDA HEXECFRAME
JSR HMEM_PTR
STA FRAMEPTR
STX FRAMEPTR+1
LDY #FRAMEPC
LDA EXECPC ; SAVE INSTRUCTION PTR IN CURRENT FRAME
SEC ; SAVE AS OFFSET FROM CODEPTR
SBC EXECCODEBASE
STA (FRAMEPTR),Y
INY
LDA EXECPC+1
SBC EXECCODEBASE+1
STA (FRAMEPTR),Y
;*
;* RELEASE CURRENT FRAME'S MEMORY RESOURCES
;*
RELEASE_FRAME: LDY #FRAMEHCODE+1 ; EXIT CODE BLOCK
LDA (FRAMEPTR),Y
DEY
TAX
LDA (FRAMEPTR),Y
JSR HCODE_UNLOCK
LDA HEXECFRAME ; UNLOCK CURRENT FRAME
LDX HEXECFRAME+1
JSR HMEM_UNLOCK
LDY IEXECCLASS
JMP CLASS_UNLOCK
;*
;* EXIT A METHOD, BREAK DOWN FRAME.
;* ENTRY: AX = REFERENCE NOT TO DELETE
;*
EXIT_METHOD: STA RETURN_REF
STX RETURN_REF+1
.IFDEF DEBUG_INVOKE
PERR "EXITING METHOD"
; JSR KBWAIT
.ENDIF
.IFDEF DEBUG
LDA $0101 ; CHECK FOR STACK OVERFLOW
CMP #$69
BEQ :++
: PERR "STACK OVERFLOW IN EXIT METHOD"
BRK
JMP THROW_INTERNALERR
: LDA $0100
CMP #$69
BNE :--
.ENDIF
LDA HEXECFRAME ; SET FRAME POINTER
LDX HEXECFRAME+1
JSR HMEM_PTR
STA FRAMEPTR
STX FRAMEPTR+1
LDY #FRAMELOCALCNT
LDA (FRAMEPTR),Y
TAY
BEQ CHECKSYNC
DEREFLOCALS: DEY
LDA (BPT),Y ; CHECK FOR LOCAL REF VAR
BPL NEXTLOCAL
LDA (BP1),Y
BEQ NEXTLOCAL ; CHECK FOR NULL REFERENCE
TAX
LDA (BP0),Y
CMP RETURN_REF
BNE UNREFLOCAL
CPX RETURN_REF+1
BNE UNREFLOCAL ; MATCHES RETURN REF, DON'T DELETE
STY VARCNT
JSR HMEM_REF_DEC ; JUST DEC REF COUNT
LDY VARCNT
JMP NEXTLOCAL
UNREFLOCAL: TYA
PHA
LDA RETURN_REF
PHA
LDA RETURN_REF+1
PHA
LDA (BP3),Y
PHA
LDA (BP2),Y
PHA
TXA
PHA
LDA (BP0),Y
PHA
JSR UNREF_OBJECT
PLA
STA RETURN_REF+1
PLA
STA RETURN_REF
PLA
TAY
NEXTLOCAL: CPY #$00
BNE DEREFLOCALS
LDA HEXECFRAME ; RE-SET FRAME POINTER
LDX HEXECFRAME+1
JSR HMEM_PTR
STA FRAMEPTR
STX FRAMEPTR+1
CHECKSYNC: LDY #FRAMEHCODE+1
LDA (FRAMEPTR),Y
DEY
TAX
LDA (FRAMEPTR),Y
JSR HCODE_FLAGS
AND #$20 ; CHECK FOR SYNCHRONIZED METHODS
BEQ UNLINKFRAME
LDY #FRAMESYNCHOBJ+1
LDA (FRAMEPTR),Y
DEY
TAX
LDA (FRAMEPTR),Y
JSR THREAD_UNLOCK ; UNLOCK OBJECT
UNLINKFRAME: LDY #FRAMELINKPREV ; GET PREVIOUS FRAME
LDA (FRAMEPTR),Y
INY
STA HLINKFRAME
LDA (FRAMEPTR),Y
STA HLINKFRAME+1
JSR RELEASE_FRAME ; RELEASE CURRENT FRAME
LDA HEXECFRAME
LDX HEXECFRAME+1
JSR HMEM_FREE ; FREE UP ITS MEMORY
LDA HLINKFRAME
LDX HLINKFRAME+1
BEQ ASYNC_EXIT
JSR SETUP_FRAME
.IFDEF DEBUG_INVOKE
PSTR "RETURNING TO METHOD:"
LDY #FRAMEICLASS ; GET METHOD CLASS
LDA (FRAMEPTR),Y
TAY
STY CALLCLASS
JSR CLASS_STRING
JSR PRHSTR
LDA #'.'
JSR COUT
LDY #FRAMEMETHOD+1
LDA (FRAMEPTR),Y
DEY
TAX
LDA (FRAMEPTR),Y
STA METHDOFST
STX METHDOFST+1
LDY CALLCLASS
JSR CLASS_LOCKMETHOD ; GET POINTER TO LOCKED METHOD
STA METHODPTR
STX METHODPTR+1
LDY #METHODNAME+1
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
JSR PRHSTR
LDY #METHODDESC+1
LDA (METHODPTR),Y
DEY
TAX
LDA (METHODPTR),Y
JSR PRHSTR
JSR CROUT
LDY CALLCLASS
JSR CLASS_UNLOCKMETHOD
; JSR KBWAIT
.ENDIF
LDA EXECFLAGS ; CHECK FOR EXCEPTION
BMI CATCH_EXCEPTN
JMP EXECBYTECODES
ASYNC_EXIT: JSR THREAD_POP_TLS ; RETURN FROM ASYNC METHOD
STA HEXECFRAME
STX HEXECFRAME+1
CPX #$00
BEQ :+
JSR SETUP_FRAME
:
.IFDEF DEBUG_INVOKE
PERR "ASYNC RETURN"
; JSR KBWAIT
.ENDIF
JSR THREAD_POP_TLS
PHA
TXA
PHA
ASL EXECFLAGS ; MOVE EXCEPTION FLAG INTO CARRY
RTS
;*
;* AN EXCEPTION IS IN PROGRESS - SEARCH FOR MATCHING CATCH CLAUSE
;*
CATCH_EXCEPTN:
.IFDEF DEBUG_EXCEPT
; .IMPORT THREAD_TRACE
; JSR THREAD_TRACE
PERR "CATCH EXCEPTION"
JSR KBWAIT
.ENDIF
PLA ; POP EXCEPTION
STA CURRENTEXCEPTN
PLA
STA CURRENTEXCEPTN+1
PLA
STA CURRENTEXCEPTN+2
PLA
STA CURRENTEXCEPTN+3
LDY #FRAMESP ; RESTORE SP TO CALLING DEPTH
LDA (FRAMEPTR),Y ; PUSH EXCEPTION BACK ON STACK
TAX
TXS
LDA CURRENTEXCEPTN+3
PHA
LDA CURRENTEXCEPTN+2
PHA
LDA CURRENTEXCEPTN+1
PHA
LDA CURRENTEXCEPTN
PHA
LDY #FRAMEPC+1 ; RECOVER PC POINTER
LDA (FRAMEPTR),Y
DEY
STA EXCEPTPC+1
LDA (FRAMEPTR),Y
STA EXCEPTPC
LDY #FRAMEHCODE+1 ; GET CODE SEGMENT
LDA (FRAMEPTR),Y
DEY
TAX
LDA (FRAMEPTR),Y
JSR HCODE_ACCESS ; ACCESS THIS CODE BLOCK
JSR HCODE_GETHEXCEPT
STA HEXCEPTTBL
STX HEXCEPTTBL+1
CPX #$00
BEQ NOTCAUGHT
JSR HMEM_LOCK
STA EXCEPTPTR
STX EXCEPTPTR+1
JSR HCODE_GETEXCEPTLEN
STX EXCEPTCNT+1
SEARCHEXCEPT: STA EXCEPTCNT
ORA EXCEPTCNT+1
BNE CHKRANGE
NOTCAUGHT: JSR HCODE_UNACCESS
LDA HEXCEPTTBL
LDX HEXCEPTTBL+1
BEQ :+
JSR HMEM_UNLOCK
: LDA RETURN_REF
LDX RETURN_REF+1
JMP EXIT_METHOD ; BACKTRACE FRAMES
CHKRANGE: LDY #$03 ; CHECK HANDLER END RANGE
LDA EXCEPTPC
CMP (EXCEPTPTR),Y
DEY
LDA EXCEPTPC+1
SBC (EXCEPTPTR),Y
BCS NEXTEXCEPT
DEY ; CHECK HANDLER START RANGE
LDA EXCEPTPC
CMP (EXCEPTPTR),Y
DEY
LDA EXCEPTPC+1
SBC (EXCEPTPTR),Y
BCC NEXTEXCEPT
LDY #$06 ; CHECK HANDLER EXCEPTION
LDA (EXCEPTPTR),Y
INY
TAX
LDA (EXCEPTPTR),Y
CMP #$00
BNE :+
CPX #$00
BEQ CAUGHTEXCEPT
: JSR LOOKUPCLASSIDX
LDA CURRENTEXCEPTN+2
AND #$7F
JSR CLASS_OF ; IS EXCEPTION A CLASS OF HANDLER
BCS NEXTEXCEPT
CAUGHTEXCEPT: LDY #$05 ; GET HANDLER PC
LDA (EXCEPTPTR),Y
DEY
CLC
ADC EXECCODEBASE ; SET PC PTR
STA EXECPC
LDA (EXCEPTPTR),Y
ADC EXECCODEBASE+1
STA EXECPC+1
JSR HCODE_UNACCESS
LDA HEXCEPTTBL
LDX HEXCEPTTBL+1
JSR HMEM_UNLOCK
ASL EXECFLAGS ; CLEAR EXCEPTION FLAG
JMP EXECBYTECODES ; EXECUTE HANDLER
NEXTEXCEPT: LDA EXCEPTPTR
CLC
ADC #$08
BCC :+
INC EXCEPTPTR+1
: STA EXCEPTPTR
LDA EXCEPTCNT
SEC
SBC #$01
BCS :+
DEC EXCEPTCNT+1
: JMP SEARCHEXCEPT
.DATA
HEXCEPTTBL:
HLINKFRAME: .RES 2
EXCEPTPC:
METHDOFST: .RES 2