having a multi-byte Instruction like COP split at the edge of a bank seems like a pretty rare scenario. unless the program is specifically written to make use of the PC wrapping... but even then it seems easier to just avoid split instructions like that.
anyways, my SBC's BIOS also uses COP for system calls because it's very convient and much easier to expand/move around in the ROM compared to jump tables accessed with JSL or Indirect Jumps.
but the way i get the signature byte is a bit different, as it loads the whole 24-bit address into a temporary DP location, subtracts 1 from it, and then uses the 24-bit Indirect Addressing mode to get the byte.
that way the code doesn't need to touch the data bank register.
The signature byte is then multiplied by 2 and put into X to be used as an index to a jump table. giving me 256 possible functions.
Code:
COP_HANDLER:
ai16 ; 16-bit A/X/Y
PHA
PHX
PHY
TDC
PHA ; Save all Registers (A, X, Y, DP)
LDA #SYS_DP
TCD ; Set the Driect Page
accu8
; Get the Return Address, subtract 1 from it, and store it into a Temp Pointer
LDA 10,S ; Low Byte
CLC
SBC #0
STA T_PTR
LDA 11,S ; Middle Byte
SBC #0
STA T_PTR+1
LDA 12,S ; High Byte
SBC #0
STA T_PTR+2
LDA #0
XBA ; Clear the High Byte of A
LDA [T_PTR] ; Get the Signature Byte
ASL A ; Multiply it by 2
TAX ; And put it into X
PEA .LOWORD(COP_RET - 1)
JMP (COP_TABLE,X) ; Then use it as an index for the Jump Table
COP_RET:
ai16 ; 16-bit A/X/Y
PLA
TCD
PLY
PLX
PLA ; Restore all Registers
RTI
the PEA infront of the Indirect JMP pushes the address of (COP_RET - 1) to the stack, basically just emulating an Indirect JSR instruction.
so all the COP functions can jump to that code by using RTS instead of a regular JMP.