From 5138223a23241abd05a61de004c4ed7446d168d3 Mon Sep 17 00:00:00 2001 From: Mikael Lund Date: Thu, 19 Sep 2024 05:30:25 +0200 Subject: [PATCH] [commodore] Implement KERNAL LOAD function as inline assembly (#373) * Rewrite cbm_k_load w. inline asm * Add doxygen documentation * Remove empty line * Update doxygen documentation --- mos-platform/commodore/CMakeLists.txt | 2 +- mos-platform/commodore/cbm.h | 24 ++++++++++++++++++++- mos-platform/commodore/cbm_k_load.c | 31 +++++++++++++++++++++++++++ mos-platform/commodore/cbm_k_load.s | 23 -------------------- 4 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 mos-platform/commodore/cbm_k_load.c delete mode 100644 mos-platform/commodore/cbm_k_load.s diff --git a/mos-platform/commodore/CMakeLists.txt b/mos-platform/commodore/CMakeLists.txt index cd3ba7375..b97111086 100644 --- a/mos-platform/commodore/CMakeLists.txt +++ b/mos-platform/commodore/CMakeLists.txt @@ -38,7 +38,7 @@ add_platform_library(commodore-c cbm_k_getin.c cbm_k_iobase.s cbm_k_listen.c - cbm_k_load.s + cbm_k_load.c cbm_k_open.s cbm_k_readst.c cbm_k_save.s diff --git a/mos-platform/commodore/cbm.h b/mos-platform/commodore/cbm.h index 605e2324f..c0146905c 100644 --- a/mos-platform/commodore/cbm.h +++ b/mos-platform/commodore/cbm.h @@ -231,7 +231,29 @@ void cbm_k_clrch (void); unsigned char cbm_k_getin (void); unsigned cbm_k_iobase (void) __attribute__((leaf)); void cbm_k_listen (unsigned char dev); -void *cbm_k_load(unsigned char flag, void *startaddr) __attribute__((leaf)); + +/** + * @brief CBM KERNAL function to load or verify file + * + * Should be called after `cbm_k_setlfs()` and `cbm_k_setnam()`. + * On Commander X16, the `flag` argument takes the following + * values: + * + * `flag` | Description + * ------ | --------------- + * 0 | Load at address + * 1 | Verify + * 2 | Loads into VRAM $00000 + address (cx16) + * 3 | Loads into VRAM $10000 + address (cx16) + * + * On other Commodore targets, a non-zero `flag` value triggers verify. + * + * @param flag Load or verify + * @param load_addr Load address pointer (if not verifying). + * @return Address of last byte loaded/verified or KERNAL error code + */ +void *cbm_k_load(unsigned char flag, void *load_addr); + unsigned char cbm_k_open (void) __attribute__((leaf)); unsigned char cbm_k_readst (void); unsigned char cbm_k_save(void *startaddr, void *endaddr_plusone) __attribute__((leaf)); diff --git a/mos-platform/commodore/cbm_k_load.c b/mos-platform/commodore/cbm_k_load.c new file mode 100644 index 000000000..2c3723ec8 --- /dev/null +++ b/mos-platform/commodore/cbm_k_load.c @@ -0,0 +1,31 @@ +// Copyright 2024 LLVM-MOS Project +// Licensed under the Apache License, Version 2.0 with LLVM Exceptions. +// See https://github.com/llvm-mos/llvm-mos-sdk/blob/main/LICENSE for license +// information. + +#include + +// Helper to (dis)assemble a 16-bit integer +typedef union { + uint16_t value; + struct { + uint8_t lo, hi; + }; +} Word; + +void *cbm_k_load(const unsigned char flag, void *load_addr) { + Word result; + const Word addr = {.value = (uint16_t)(load_addr)}; + + __attribute__((leaf)) __asm__ volatile( + " jsr __LOAD \n" + " bcc 1f \n" // no error if carry clear + " tax \n" // else get error code from A + " ldy #0 \n" + "1: \n" // no error + : "=x"(result.lo), "=y"(result.hi) + : "a"(flag), "x"(addr.lo), "y"(addr.hi) + : "p"); + + return (void *)(result.value); +} diff --git a/mos-platform/commodore/cbm_k_load.s b/mos-platform/commodore/cbm_k_load.s deleted file mode 100644 index 739728886..000000000 --- a/mos-platform/commodore/cbm_k_load.s +++ /dev/null @@ -1,23 +0,0 @@ -.include "imag.inc" - -.text - -; -; void *cbm_k_load(unsigned char verifyflag, void *startaddr); // if result address < 256, likely an error code -; a rc2/3 -; -.global cbm_k_load -cbm_k_load: - ldx __rc2 - ldy __rc2+1 - jsr __LOAD - bcc noerror - ; store error code in A - sta __rc2 - ldx #0 - stx __rc2+1 - rts -noerror: - stx __rc2 ; store end+1 low - sty __rc2+1 ; store end+1 high - rts