;* ;* 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