Arlet wrote:
A disadvantage of using BRK for kernel calls is that it will disable interrupts even when it's not necessary, increasing latency for real interrupts.
That's certainly true and the programmer who is writing the kernel can't afford to forget it. However, at the most, a handful of microseconds will elapse from when the
BRK (or
COP) is executed to where IRQs are re-enabled, assuming the software ISR front end promptly does a
CLI or equivalent.
Quote:
The disadvantage of having direct JSR to absolute addresses is not very limiting for the (single user) hobby systems we're talking about here. It's easy enough to rebuild the whole project when something changes.
I guess it would depend on how much software has been written to use the jump table. I rearranged POC's BIOS jump table once to reduce the footprint and had to reassemble nine other programs so they would continue to work following the change. Also, I had to rebuild the boot block on the hard disk because the BIOS API calls in the MBR were no longer valid.
These gyrations caused me to cogitate on how to avoid such work in the future, leading to the decision to call POC V2's BIOS APIs via software interrupts, rather than via
JSR. Also, as POC V2 will have much more RAM than POC V1—the latter has 52KB addressable, all in bank $00—there was the consideration of being able to access the BIOS from any bank, which is not possible with
JSR/RTS. Yes, I could use
JSL/RTL to circumvent the cross-bank issue, but that wouldn't address portability. Hence the code to call an API in POC V2 will be something along the lines of:
Code:
lda #parm1 ;parameter if needed
ldx #parm2 ;parameter if needed
ldy #parm3 ;parameter if needed
pea #api_num ;API index (16 bit push)
cop $00 ;call API
bcs excep ;if exception is returned
No API in POC's existing BIOS requires more than three parameters, which means they can be passed via the registers. Only the API index would be pushed before the call, the index being defined in an INCLUDE file. This method of calling BIOS APIs will work from any bank, as any interrupt automatically forces
$00 into the MPU's
PB register. Also, if a new function is added to the BIOS the corresponding API index will be the highest current index plus one—existing applications will not be affected, as the previous API index numbers will be immutable.
The front end of the API handler would look something like the following:
Code:
icop rep #%00110100 ;16 bit registers & enabled IRQs
pha ;save .A for return access
phx ;preserve .X, as it will be used
phy ;preserve .Y if necessary
;
;———————————————————————————————————————————————
;Stack Frame Definitions
;
.reg_y =1 ;.Y
.reg_x =.reg_y+2 ;.X
.reg_c =.reg_x+2 ;.C
.reg_sr =.reg_c+2 ;SR
.reg_pc =.reg_sr+1 ;PC
.reg_pb =.reg_pc+2 ;PB
.api_num =.reg_pb+1 ;API index
.s_frame =.api_num+2 ;stack frame size
;———————————————————————————————————————————————
;
lda .api_num,S ;get API index
cmp #maxapi ;index in range (16 bit comparison)?
bcs icop01 ;no, error
;
asl a ;double API index for...
tax ;jump table index
jmp (apidptab,x) ;run appropriate code
;
;
; invalid API index error processing...
;
icop01 ...handle invalid API index...
The above front end consumes 34 clock cycles on the 65C816, amounting to 1.7 microseconds if operating at 20 MHz. The
COP $00 instruction needed to call the API consumes 8 clock cycles, equal to 400 nanoseconds at 20 MHz. The
RTI at the back end that returns control to the caller consumes 7 cycles or 350 nanoseconds at 20 MHz. I daresay most of the execution time will be in the internal API code, not the front and back ends of the API calling process.
The above is trivial code for the '816, but would require some rework to accommodate the 65C02, as it lacks the
,S addressing mode, as well as 16 bit registers (the latter only matters if more than 128 API functions exist). Also,
BRK would have to be used, which is slightly complicated by the fact that that instruction is often used to assist in debugging programs. Fortunately, the 65C02 does have
JMP (<addr>,X), so that method of accessing the internal API jump table can be retained.