Catching errors
Normally, if you call a routine, such as an MOS entry point, if an error occurs, the error handler on BRKV is jumped to. ARM, 32016 and PDP11 systems allow you to call a routine and have an error status returned to the calling program instead of an error being generated, for instance:
; ARM ; 32016 ; PDP-11 SWI "XOS_CLI" SVC OS_CLI EMT OS_CLI BVS error_occured BFS error_occured BVS error_occured
The following code allows you to do exactly the same on the 6502.
brkv=&202:zp=&A8 \ xos_call - call inline address, catching any returned error \ =========================================================== \ Called with \ JSR xos_call \ EQUW dest \ On entry, A,X,Y hold entry parameters \ On exit, V clear - no error, A,X,Y,P hold return parameters \ V set - error, A=ERR, &FD=>error block \ .xos_call PHA:TXA:PHA :\ Stack holds X, A, main LDA brkv+1:PHA:LDA brkv+0:PHA LDA oldSP:PHA:TSX:STX oldSP :\ Stack holds oldSP, oldbrkv, X, A, main LDA #error DIV 256:STA brkv+1 :\ Redirect BRKV LDA #error AND 255:STA brkv+0 LDA #(return-1)DIV 256:PHA LDA #(return-1)AND 255:PHA :\ Stack return address PHA:PHA:PHA:PHA :\ Make space to hold dest and X, A LDA zp+1:PHA:LDA zp:PHA:CLC :\ Save zp workspace LDA &106,X:STA zp:ADC #2:STA &106,X :\ Get mainline address and step LDA &107,X:STA zp+1:ADC #0:STA &107,X :\ past inline dest address TYA:PHA:TSX :\ Save Y, get new SP LDY #2:LDA (zp),Y:STA &107,X DEY:LDA (zp),Y:STA &106,X :\ Copy inline address to stack LDA &10E,X:STA &105,X :\ Copy A to top of stack LDA &10D,X:STA &104,X :\ Copy X to top of stack : \ Stack holds Y, zp, X, A, dest, return, oldSP, oldbrkv, X, A, main : PLA:TAY:PLA:STA zp:PLA:STA zp+1 :\ Restore Y and zp workspace PLA:TAX:PLA:PHP:RTI :\ Restore X, A, jump to stacked dest addr : .return :\ Stack holds oldSP, oldbrkv, X, A, main PHA:TXA:TSX :\ Stack A STA &105,X:PLA:STA &105,X :\ Copy X, A to top of stack PLA:STA oldSP :\ Restore oldSP PLA:STA brkv+0:PLA:STA brkv+1 :\ Restore BRKV PLA:TAX:PLA:RTS :\ Get returned X, A and return to main : .error LDX oldSP:TXS:PLA:STA oldSP :\ Restore oldSP PLA:STA brkv+0:PLA:STA brkv+1 :\ Restore BRKV PLA:PLA:LDY #0:LDA (&FD),Y :\ Drop X, A, get error number BIT P%-1:RTS :\ Set V from inline &FD byte and return : .oldSP EQUB 0 :\ Saved stack pointer
As an example, the following call tries to do BGET#0 which raises a "Channel" error. Catching the error returns the error with V set, A=222 and &FD pointing to the error block.
LDY #0 JSR xos_call EQUW OSBGET
Calls to xos_call can recursively call xos_call again. Each call takes 8 bytes on the stack, and initially needs 16 bytes free.