From b60181a5290b08ac630f73cfc8f378c0912ed2c6 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Fri, 8 Mar 2024 11:31:01 -0700 Subject: [PATCH] [KERNAL] implement native-capable jsrfar (#283) * [KERNAL] implement native-capable jsrfar * native jsrfar falls back to old code if in emulated mode * fix off-by-one error * fix up some logic, jmpfr need only be in one place * Save a couple cycles here * save a few more cycles w/ carry assumptions * add assert for jsrfar3n * saved one more cycle * trivial changes * trivial changes * updates to comments * updates to comments * no need to preserve X in the native jsrfar * fix stack misalignment issue in a 16-bit jsrfar call * requested changes --- cfg/audio-x16.cfgtpl | 4 +- cfg/bannex-x16.cfgtpl | 4 +- cfg/codex-x16.cfgtpl | 6 +-- cfg/kernal-x16.cfgtpl | 1 + cfg/monitor-x16.cfgtpl | 4 +- cfg/util-x16.cfgtpl | 4 +- cfg/x16.cfginc | 3 +- inc/banks.inc | 1 + inc/jsrfar.inc | 85 +++++++++++++++++++++++++++++++++++-- kernal/drivers/x16/memory.s | 35 +++++++++++++++ 10 files changed, 131 insertions(+), 16 deletions(-) diff --git a/cfg/audio-x16.cfgtpl b/cfg/audio-x16.cfgtpl index 833c9a6d..dff54393 100644 --- a/cfg/audio-x16.cfgtpl +++ b/cfg/audio-x16.cfgtpl @@ -1,8 +1,8 @@ MEMORY { #include "x16.cfginc" - ROM: start = $C000, size = $3B00, fill=yes, fillval=$AA; - KSUP_CODE10: start = $FB00, size = $03A8, fill=yes, fillval=$AA; + ROM: start = $C000, size = $3A80, fill=yes, fillval=$AA; + KSUP_CODE10: start = $FA80, size = $0428, fill=yes, fillval=$AA; KSUP_VEC10: start = $FEA8, size = $0158, fill=yes, fillval=$AA; } diff --git a/cfg/bannex-x16.cfgtpl b/cfg/bannex-x16.cfgtpl index 21e6f02b..db3db408 100644 --- a/cfg/bannex-x16.cfgtpl +++ b/cfg/bannex-x16.cfgtpl @@ -1,8 +1,8 @@ MEMORY { #include "x16.cfginc" - ANNEX: start = $C000, size = $3B00, fill=yes, fillval=$AA; - KSUP_CODE12: start = $FB00, size = $03A8, fill=yes, fillval=$AA; + ANNEX: start = $C000, size = $3A80, fill=yes, fillval=$AA; + KSUP_CODE12: start = $FA80, size = $0428, fill=yes, fillval=$AA; KSUP_VEC12: start = $FEA8, size = $0158, fill=yes, fillval=$AA; } diff --git a/cfg/codex-x16.cfgtpl b/cfg/codex-x16.cfgtpl index dea8706b..252683fa 100644 --- a/cfg/codex-x16.cfgtpl +++ b/cfg/codex-x16.cfgtpl @@ -1,11 +1,11 @@ MEMORY { #include "x16.cfginc" - MAIN: file = %O, define = yes, start = $C000, size = $3AE2, fill=yes fillval=$A3; + MAIN: file = %O, define = yes, start = $C000, size = $3A72, fill=yes fillval=$A3; RWRAM: file = "", start = $0400, size = $3FF; BANK: file = "", start = $A000, size = $2000; - CODEX_VECS: start = $FAE2, size = $001E, fill=yes, fillval=$A0; - KSUP_CODE2: start = $FB00, size = $03A8, fill=yes, fillval=$A1; + CODEX_VECS: start = $FA72, size = $001E, fill=yes, fillval=$A0; + KSUP_CODE2: start = $FA80, size = $0418, fill=yes, fillval=$A1; KSUP_VEC2: start = $FEA8, size = $0158, fill=yes, fillval=$A2; } diff --git a/cfg/kernal-x16.cfgtpl b/cfg/kernal-x16.cfgtpl index bce76755..7b5beba1 100644 --- a/cfg/kernal-x16.cfgtpl +++ b/cfg/kernal-x16.cfgtpl @@ -68,6 +68,7 @@ SEGMENTS { VERA_DRV: load = KERNAL, type = ro; PALETTE: load = KERNAL, type = ro, align = $100; KRAMJFAR: load = KERNAL, run = KRAMJFAR, type = ro, define = yes; + KJFAR816: load = KERNAL, run = KJFAR816, type = ro, define = yes; KERNRAM2: load = KERNAL, run = KERNRAM2, type = ro, define = yes; KRAM816: load = KERNAL, run = KRAM816, type = ro, define = yes; KRAM02B: load = KERNAL, run = KRAM02B, type = ro, define = yes; diff --git a/cfg/monitor-x16.cfgtpl b/cfg/monitor-x16.cfgtpl index 65ffca39..b3199ef6 100644 --- a/cfg/monitor-x16.cfgtpl +++ b/cfg/monitor-x16.cfgtpl @@ -3,8 +3,8 @@ MEMORY { L0220: start = $0220, size = $0019; # overlaps with top end of BASIC input line only - BANK5: start = $C000, size = $3B00, fill=yes, fillval=$AA; - KSUP_CODE2: start = $FB00, size = $03A8, fill=yes, fillval=$AA; + BANK5: start = $C000, size = $3A80, fill=yes, fillval=$AA; + KSUP_CODE2: start = $FA80, size = $0428, fill=yes, fillval=$AA; KSUP_VEC2: start = $FEA8, size = $0158, fill=yes, fillval=$AA; } diff --git a/cfg/util-x16.cfgtpl b/cfg/util-x16.cfgtpl index 303b6913..d89f48d1 100644 --- a/cfg/util-x16.cfgtpl +++ b/cfg/util-x16.cfgtpl @@ -4,8 +4,8 @@ MEMORY { HEXEDITZP: start = $0022, size = $005E, fill=no; HEXEDITBSS: start = $0200, size = $0050, fill=no; MENUBSS: start = $0200, size = $0050, fill=no; - ROM: start = $C000, size = $3B00, fill=yes, fillval=$AA; - KSUP_CODE11: start = $FB00, size = $03A8, fill=yes, fillval=$AA; + ROM: start = $C000, size = $3A80, fill=yes, fillval=$AA; + KSUP_CODE11: start = $FA80, size = $0428, fill=yes, fillval=$AA; KSUP_VEC11: start = $FEA8, size = $0158, fill=yes, fillval=$AA; } diff --git a/cfg/x16.cfginc b/cfg/x16.cfginc index 3a7d2924..3c216b82 100644 --- a/cfg/x16.cfginc +++ b/cfg/x16.cfginc @@ -23,7 +23,8 @@ ZPBASIC: start = $00D4, size = $002B; # BASIC (last byte used: $FE) /* $0200-$02FF: always-available variables and RAM code */ KVAR: start = $0200, size = $0095; # KERNAL KRAM816S: start = $0295, size = $0003; # KERNAL: 65C816: old stack pointer -/* start = $0298, size = $0028; # reserved for KERNAL growth */ +KJFAR816: start = $0298, size = $0019; # KERNAL: jsrfar3n +/* start = $02B1, size = $000F; # reserved for KERNAL growth */ I2CMUTEX: start = $02C0, size = $0001; # I2C MUTEX FLAG GRAPHVAR: start = $02C1, size = $0003; # GRAPH BANK VARS KRAMJFAR: start = $02C4, size = $001E; # KERNAL: jsrfar3 diff --git a/inc/banks.inc b/inc/banks.inc index c4118558..fde273d3 100644 --- a/inc/banks.inc +++ b/inc/banks.inc @@ -19,6 +19,7 @@ BANK_BASLOAD = $0F ; XXX implementation details and need to go away! cbdos_flags= $0268 status = $0287 ; channel: status byte +jsrfar3n = $0298 ; jsrfar: RAM part, 65C816 native jsrfar3 = $02c4 ; jsrfar: RAM part jmpfr = $02df ; jsrfar: core jmp instruction imparm = $82 ; jsrfar: temporary byte diff --git a/inc/jsrfar.inc b/inc/jsrfar.inc index 86a1bf73..05759585 100644 --- a/inc/jsrfar.inc +++ b/inc/jsrfar.inc @@ -4,16 +4,23 @@ ; .word address ; .byte bank - pha ;reserve 1 byte on the stack + php ;reserve 1 byte on the stack php ;save registers & status + + sec + .byte $c2, $03 ; rep #$03, clear carry/z if 65c816 + bcc jsrfarn + + clc +jsrfare: pha phx phy - tsx + tsx lda $106,x ;return address lo sta imparm - clc + ; carry is clear adc #3 sta $106,x ;and write back with 3 added lda $107,x ;return address hi @@ -63,4 +70,74 @@ jsrfar2: pla plp plp - rts \ No newline at end of file + rts + +.pushcpu + +.setcpu "65816" + +jsrfarn: + ; carry is clear + php + sei + xce + bcc :+ + xce + plp + bra jsrfare ; with carry cleared +: plp + rep #$31 ; force 16 bit memory/index, clear carry + .A16 + .I16 + pha + phy + + lda $07,S ; fetch return address + sta imparm + ; carry is clear + adc #3 + sta $07,S ; write back return address+3 + ldy #1 + lda (imparm),y + sta jmpfr+1 + cmp #$c000 + bcc jsrfar1n +; target is in ROM + sep #$20 ; 8 bit accumulator + .A8 + lda rom_bank + sta $06,S ; save original bank onto reserved byte + ldy #3 + lda (imparm),y + ply + jmp jsrfar3n + +; target is in RAM +jsrfar1n: + sep #$20 ; 8 bit accumulator + .A8 + lda ram_bank + sta $06,S ; save original bank onto reserved byte + lda #3 + lda (imparm),y + sta ram_bank + rep #$20 ; 16 bit accumulator + .A16 + ply + pla + plp ; original register widths popped immediately before call + jsr jmpfr + php ; preserve flags immediately after return from call + sep #$20 ; 8 bit accumulator + .A8 + pha + lda $03,S + sta ram_bank + lda $02,S ; overwrite reserved byte + sta $03,S ; with copy of .P + pla + plp ; restore flags to state immediately after call + plp + rts + +.popcpu diff --git a/kernal/drivers/x16/memory.s b/kernal/drivers/x16/memory.s index 2e1b7938..a40b2224 100644 --- a/kernal/drivers/x16/memory.s +++ b/kernal/drivers/x16/memory.s @@ -8,6 +8,7 @@ .include "io.inc" .import __KRAMJFAR_LOAD__, __KRAMJFAR_RUN__, __KRAMJFAR_SIZE__ +.import __KJFAR816_LOAD__, __KJFAR816_RUN__, __KJFAR816_SIZE__ .import __KERNRAM2_LOAD__, __KERNRAM2_RUN__, __KERNRAM2_SIZE__ .import __KRAM816_LOAD__, __KRAM816_RUN__, __KRAM816_SIZE__ .import __KRAM02B_LOAD__, __KRAM02B_RUN__, __KRAM02B_SIZE__ @@ -139,6 +140,11 @@ ramtas: .A16 .I16 + ldx #__KJFAR816_LOAD__ + ldy #__KJFAR816_RUN__ + lda #(__KJFAR816_SIZE__ - 1) + mvn #00,#00 + ldx #__KRAM816_LOAD__ ldy #__KRAM816_RUN__ lda #(__KRAM816_SIZE__ - 1) @@ -271,6 +277,35 @@ jsrfar: __jmpfr: jmp $ffff +.pushcpu +.setcpu "65816" + +.segment "KJFAR816" +.assert * = jsrfar3n, error, "jsrfar3n must be at specific address" + +;jsrfar3n: + .A8 + .I16 + sta rom_bank ;set ROM bank + rep #$20 + .A16 + pla + plp ; restore all flags immediately before call + jsr jmpfr + php + sep #$20 ; 8 bit accumulator + .A8 + pha ; Push lower byte of accumulator + lda $03,S + sta rom_bank ;restore ROM bank + lda $02,S ;overwrite reserved byte... + sta $03,S ;...with copy of .P + pla ; .B remains unchanged and is thus preserved + plp ; restore flags from state immediately after call + plp + rts + +.popcpu .segment "KERNRAM2"