From 8eb69bb16e0ec39d7a6f736cbcdbe413384233d6 Mon Sep 17 00:00:00 2001 From: Kyle Cardoza Date: Thu, 28 Mar 2024 01:32:57 -0400 Subject: [PATCH] Added custom cstartup for W65C265S --- config/memory.scm | 20 ++---- config/sdk-config.mk | 19 +++--- config/sdk-targets.mk | 10 +-- include/drivers/vera.h | 12 ++-- include/interrupts.h | 26 ++++---- include/macros.h | 86 ++++++++++++++++++++++++ src/cstartup.s | 146 +++++++++++++++++++++++++++++++++++++++++ src/drivers/vera.c | 8 +-- src/interrupts.c | 26 ++++---- src/{init.c => main.c} | 4 +- 10 files changed, 290 insertions(+), 67 deletions(-) create mode 100644 include/macros.h create mode 100644 src/cstartup.s rename src/{init.c => main.c} (89%) diff --git a/config/memory.scm b/config/memory.scm index 1fab83c..3a5ef6e 100644 --- a/config/memory.scm +++ b/config/memory.scm @@ -1,27 +1,14 @@ (define memories '( - - (memory HighCode - (address (#xC00000 . #xC7FFFF)) - (section farcode) - (section ifar) - (section ihuge) - (type rom) - ) - - (memory HighData - (address (#x010000 . #x07FFFF)) - (section heap) - (type ram) - ) - (memory LowCode - (address (#x008800 . #x00FFFF)) + (address (#x008000 . #x00FFFF)) (section code) (section cdata) (section idata) (section inear) (section switch) (section data_init_table) + (section reset) + (section (boot #x008000)) (type rom) ) @@ -36,6 +23,7 @@ (section data) (section znear) (section zdata) + (section heap) ) (memory stack diff --git a/config/sdk-config.mk b/config/sdk-config.mk index 179b508..5d5def4 100644 --- a/config/sdk-config.mk +++ b/config/sdk-config.mk @@ -11,16 +11,15 @@ MEMORY_MAP := config/memory.scm CFLAGS := --include-system=include/libc \ -I include \ - --code-model=large \ - --data-model=huge \ + --code-model=small \ + --data-model=small \ --64bit-doubles \ --strong-inline \ --force-switch jump-table -ASFLAGS := --include-system=include/libc \ - -I include \ - --code-model=large \ - --data-model=huge +ASFLAGS := -I include \ + --code-model=small \ + --data-model=small ifeq ($(RELEASE), "true") CFLAGS += -DNDEBUG \ @@ -42,10 +41,12 @@ ASFLAGS += --debug endif LDFLAGS := $(MEMORY_MAP) \ - --no-data-init-table-section \ - --rtattr cstartup=turaco \ --list-file build.lst \ - --verbose + --rom-code \ + --output-format raw \ + --raw-multiple-memories \ + --verbose \ + --cstartup=sentinel65x ifeq ($(ENABLE_RELEASE_BUILD), "true") CFLAGS += -DRELEASE_BUILD diff --git a/config/sdk-targets.mk b/config/sdk-targets.mk index 9ab35e5..35d649b 100644 --- a/config/sdk-targets.mk +++ b/config/sdk-targets.mk @@ -1,5 +1,5 @@ .PHONY: all -all: build/sentinel-kernel.a +all: build/sentinel-kernel.bin .PHONY: clean clean: @@ -29,8 +29,10 @@ clean: @printf '%s' "$(dir $@)" > $@ @$(CC) $(CFLAGS) --dependencies $< >> $@ -build/sentinel-kernel.a: $(KERNEL_OBJ) +build/sentinel-kernel.bin: $(KERNEL_OBJ) @echo "Linking $@..." - @$(AR) $@ $^ - +# @$(AR) $@ $^ + $(LD) $(LDFLAGS) -o $@ $^ + @rm -f $@ + @mv build/sentinel-kernel.raw $@ -include $(KERNEL_DEP) diff --git a/include/drivers/vera.h b/include/drivers/vera.h index 4948e50..29ede9c 100644 --- a/include/drivers/vera.h +++ b/include/drivers/vera.h @@ -8,16 +8,16 @@ #include -far void vera_init(void); +void vera_init(void); -far uint8_t vera_peek(uint32_t addr); +uint8_t vera_peek(uint32_t addr); -far uint16_t vera_peek16(uint32_t addr); +uint16_t vera_peek16(uint32_t addr); -far void vera_poke(uint32_t addr, uint8_t value); +void vera_poke(uint32_t addr, uint8_t value); -far void vera_poke16(uint32_t addr, uint16_t value); +void vera_poke16(uint32_t addr, uint16_t value); -far void _vera_set_bgcolor(uint8_t color); +void _vera_set_bgcolor(uint8_t color); #define vera_set_bgcolor(X) _vera_set_bgcolor((X)) #define vera_set_bgcolour(X) _vera_set_bgcolor((X)) diff --git a/include/interrupts.h b/include/interrupts.h index 4a539c4..a3632ab 100644 --- a/include/interrupts.h +++ b/include/interrupts.h @@ -8,28 +8,28 @@ #include "config.h" -far void set_user_nmi_handler(void (*f)(void)); +void set_user_nmi_handler(void (*f)(void)); -far void set_user_brk_handler(void (*f)(void)); +void set_user_brk_handler(void (*f)(void)); -far void set_user_cop_handler(void (*f)(void)); +void set_user_cop_handler(void (*f)(void)); -far void set_user_irq_handler(void (*f)(void)); +void set_user_irq_handler(void (*f)(void)); -far void set_user_vera_irq_handler(void (*f)(void)); +void set_user_vera_irq_handler(void (*f)(void)); -far void set_user_t7_handler(void (*f)(void)); +void set_user_t7_handler(void (*f)(void)); -far void set_user_t6_handler(void (*f)(void)); +void set_user_t6_handler(void (*f)(void)); -far void set_user_t5_handler(void (*f)(void)); +void set_user_t5_handler(void (*f)(void)); -far void set_user_t4_handler(void (*f)(void)); +void set_user_t4_handler(void (*f)(void)); -far void set_user_t3_handler(void (*f)(void)); +void set_user_t3_handler(void (*f)(void)); -far void set_user_t2_handler(void (*f)(void)); +void set_user_t2_handler(void (*f)(void)); -far void set_user_t1_handler(void (*f)(void)); +void set_user_t1_handler(void (*f)(void)); -far void set_user_t0_handler(void (*f)(void)); +void set_user_t0_handler(void (*f)(void)); diff --git a/include/macros.h b/include/macros.h new file mode 100644 index 0000000..5f1cd4f --- /dev/null +++ b/include/macros.h @@ -0,0 +1,86 @@ +#ifndef __MACROS_H +#define __MACROS_H + +#ifdef __CALYPSI_ASSEMBLER__ + +#ifdef __CALYPSI_CODE_MODEL_SMALL__ + +#define libcode code + +call .macro dest + jsr \dest + .endm + +return .macro + rts + .endm + +jump .macro dest + jmp \dest + .endm + +#elif defined(__CALYPSI_CODE_MODEL_COMPACT__) + +#define libcode compactcode + +call .macro dest + jsr .kbank \dest + .endm + +return .macro + rts + .endm + +jump .macro dest + jmp .kbank \dest + .endm + +#else + +#define libcode farcode + +call .macro dest + jsl \dest + .endm + +return .macro + rtl + .endm + +jump .macro dest + jmp long:\dest + .endm + +#endif // __CALYPSI_CODE_MODEL_SMALL__ + +// ---------------------------------------------------------------------- +// +// Define code and data model used. This is to add a bit of safety in +// case the way a file is assembled is combined with the wrong run-time. +// +// ---------------------------------------------------------------------- + +#if defined(__CALYPSI_DATA_MODEL_SMALL__) + .rtmodel dataModel,"small" +#elif defined (__CALYPSI_DATA_MODEL_MEDIUM__) + .rtmodel dataModel,"medium" +#elif defined(__CALYPSI_DATA_MODEL_LARGE__) + .rtmodel dataModel,"large" +#elif defined(__CALYPSI_DATA_MODEL_HUGE__) + .rtmodel dataModel,"huge" +#else +#pragma GCC error "unexpected data model" +#endif + +#if defined(__CALYPSI_CODE_MODEL_SMALL__) + .rtmodel codeModel,"small" +#elif defined(__CALYPSI_CODE_MODEL_COMPACT__) + .rtmodel codeModel,"compact" +#elif defined(__CALYPSI_CODE_MODEL_LARGE__) + .rtmodel codeModel,"large" +#else +#pragma GCC error "unexpected code model" +#endif + +#endif // __CALYPSI_ASSEMBLER__ +#endif // __MACROS_H diff --git a/src/cstartup.s b/src/cstartup.s new file mode 100644 index 0000000..49a98cc --- /dev/null +++ b/src/cstartup.s @@ -0,0 +1,146 @@ +;;; Startup variant, change attribute value if you make your own + .rtmodel cstartup,"sentinel65x" + + .rtmodel version, "1" + .rtmodel core, "*" + + .section stack + .section cstack + .section heap + .section data_init_table + + .extern main, exit + .extern _Dp, _Vfp + .extern _DirectPageStart + +#ifndef __CALYPSI_DATA_MODEL_SMALL__ + .extern _NearBaseAddress +#endif + +#include "macros.h" + +;;; *************************************************************************** +;;; +;;; The reset vector. This uses the entry point label __program_root_section +;;; which by default is what the linker will pull in first. +;;; +;;; *************************************************************************** + + .section reset + .pubweak __program_root_section +__program_root_section: + .word __program_start + +;;; *************************************************************************** +;;; +;;; __program_start - actual start point of the program +;;; +;;; Set up CPU stack, initialize sections and call main(). +;;; You can override this with your own routine, or tailor it as needed. +;;; The easiest way to make custom initialization is to provide your own +;;; __low_level_init which gets called after stacks have been initialized. +;;; +;;; *************************************************************************** + +#ifdef __CALYPSI_CODE_MODEL_COMPACT__ + .section boot +#else + .section boot, noreorder +#endif + + .asciz "WDC" + .pubweak __program_start +__program_start: + clc + xce ; native 16-bit mode + rep #0x38 ; 16-bit registers, no decimal mode + ldx ##.sectionEnd stack + txs ; set stack + lda ##_DirectPageStart + tcd ; set direct page +#ifdef __CALYPSI_DATA_MODEL_SMALL__ + lda ##0 +#else + lda ##.word2 _NearBaseAddress +#endif + stz dp:.tiny(_Vfp+2) + xba ; A upper half = data bank + pha + plb ; pop 8 dummy + plb ; set data bank + +#ifdef __CALYPSI_CODE_MODEL_COMPACT__ + jmp long:_Trampoline_program_start + .section compactcode, noreorder +_Trampoline_program_start: +#define CODE compactcode +#else +#define CODE code +#endif + call __low_level_init + +;;; **** Initialize data sections if needed. + .section CODE, noroot, noreorder + .pubweak __data_initialization_needed + .extern __initialize_sections +__data_initialization_needed: + lda ##.word2 (.sectionEnd data_init_table) + sta dp:.tiny(_Dp+6) + lda ##.word0 (.sectionEnd data_init_table) + sta dp:.tiny(_Dp+4) + lda ##.word2 (.sectionStart data_init_table) + sta dp:.tiny(_Dp+2) + lda ##.word0 (.sectionStart data_init_table) + sta dp:.tiny(_Dp+0) + call __initialize_sections + +;;; **** Initialize streams if needed. + .section CODE, noroot, noreorder + .pubweak __call_initialize_global_streams + .extern __initialize_global_streams +__call_initialize_global_streams: + call __initialize_global_streams + +;;; **** Initialize heap if needed. + .section CODE, noroot, noreorder + .pubweak __call_heap_initialize + .extern __heap_initialize, __default_heap +__call_heap_initialize: +#ifdef __CALYPSI_DATA_MODEL_SMALL__ + lda ##.sectionSize heap + sta dp:.tiny(_Dp+2) + lda ##.sectionStart heap + sta dp:.tiny(_Dp+0) + lda ##__default_heap +#else + lda ##.word2 (.sectionStart heap) + sta dp:.tiny(_Dp+6) + lda ##.word0 (.sectionStart heap) + sta dp:.tiny(_Dp+4) + lda ##.word2 __default_heap + sta dp:.tiny(_Dp+2) + lda ##.word0 __default_heap + sta dp:.tiny(_Dp+0) + ldx ##.word2 (.sectionSize heap) + lda ##.word0 (.sectionSize heap) +#endif + call __heap_initialize + + .section CODE, root, noreorder + lda ##0 ; argc = 0 + call main + jump exit + +;;; *************************************************************************** +;;; +;;; __low_level_init - custom low level initialization +;;; +;;; This default routine just returns doing nothing. You can provide your own +;;; routine, either in C or assembly for doing custom low leve initialization. +;;; +;;; *************************************************************************** + + .section libcode + .pubweak __low_level_init +__low_level_init: + return diff --git a/src/drivers/vera.c b/src/drivers/vera.c index 3db2f31..d969289 100644 --- a/src/drivers/vera.c +++ b/src/drivers/vera.c @@ -30,13 +30,13 @@ struct vera_s { VERA vera = (VERA)(0x00df00); -far void +void vera_init(void) { } -far uint8_t +uint8_t vera_peek(uint32_t addr) { (void) addr; @@ -56,7 +56,7 @@ vera_peek(uint32_t addr) return vera->data[0]; } -far void +void vera_poke(uint32_t addr, uint8_t value) { (void) addr; @@ -77,7 +77,7 @@ vera_poke(uint32_t addr, uint8_t value) return; } -far void +void _vera_set_bgcolor(uint8_t color) { (void) color; diff --git a/src/interrupts.c b/src/interrupts.c index 219cffb..5f8781e 100644 --- a/src/interrupts.c +++ b/src/interrupts.c @@ -34,79 +34,79 @@ static void (*user_t1_handler)(void) = NULL; static void (*user_t0_handler)(void) = NULL; -far void +void set_user_nmi_handler(void (*f)(void)) { user_nmi_handler = f; } -far void +void set_user_brk_handler(void (*f)(void)) { user_brk_handler = f; } -far void +void set_user_cop_handler(void (*f)(void)) { user_cop_handler = f; } -far void +void set_user_irq_handler(void (*f)(void)) { user_irq_handler = f; } -far void +void set_user_vera_irq_handler(void (*f)(void)) { user_vera_irq_handler = f; } -far void +void set_user_t7_handler(void (*f)(void)) { user_t7_handler = f; } -far void +void set_user_t6_handler(void (*f)(void)) { user_t6_handler = f; } -far void +void set_user_t5_handler(void (*f)(void)) { user_t5_handler = f; } -far void +void set_user_t4_handler(void (*f)(void)) { user_t4_handler = f; } -far void +void set_user_t3_handler(void (*f)(void)) { user_t3_handler = f; } -far void +void set_user_t2_handler(void (*f)(void)) { user_t2_handler = f; } -far void +void set_user_t1_handler(void (*f)(void)) { user_t1_handler = f; } -far void +void set_user_t0_handler(void (*f)(void)) { user_t0_handler = f; diff --git a/src/init.c b/src/main.c similarity index 89% rename from src/init.c rename to src/main.c index 493abfc..03941f4 100644 --- a/src/init.c +++ b/src/main.c @@ -1,7 +1,7 @@ //***************************************************************************** // Sentinel 65X Kernel // -// src/init.c +// src/main.c //***************************************************************************** #include "config.h" @@ -9,7 +9,7 @@ #include "drivers/vera.h" void -kernel_init(void) +main(void) { vera_init();