diff --git a/fxcg50.ld b/fxcg50.ld index 9c0cc47..a2d4989 100644 --- a/fxcg50.ld +++ b/fxcg50.ld @@ -54,9 +54,13 @@ SECTIONS *(.dtors .dtors.*) _etors = . ; - _gint_exch_tlbh_start = . ; - *(.gint.exch_tlbh); - _gint_exch_tlbh_size = ABSOLUTE(. - _gint_exch_tlbh_start); + _gint_exch_start = . ; + *(.gint.exch) + _gint_exch_size = ABSOLUTE(. - _gint_exch_start); + + _gint_tlbh_start = . ; + *(.gint.tlbh) + _gint_tlbh_size = ABSOLUTE(. - _gint_tlbh_start); *(.text .text.*) } > rom diff --git a/include/core/setup.h b/include/core/setup.h index 4118968..7e13026 100644 --- a/include/core/setup.h +++ b/include/core/setup.h @@ -20,8 +20,10 @@ Returns the previous VBR address. */ uint32_t gint_setvbr(uint32_t vbr, void (*configure)(void)); -/* gint_exch_tlbh(): Exception and TLB miss handler */ -void gint_exch_tlbh(void); +/* gint_exch(): Exception handler */ +void gint_exch(void); +/* gint_tlbh(): TLB miss handler */ +void gint_tlbh(void); /* gint_inth_7705(): SH7705 exception handler */ void gint_inth_7705(void); diff --git a/include/gint/defs/attributes.h b/include/gint/defs/attributes.h index c5f19d1..fac700c 100644 --- a/include/gint/defs/attributes.h +++ b/include/gint/defs/attributes.h @@ -17,6 +17,8 @@ #define GILRAM __attribute__((section(".ilram"))) #define GXRAM __attribute__((section(".xram"))) #define GYRAM __attribute__((section(".yram"))) +/* Objects that must remain mapped */ +#define GMAPPED GILRAM /* Unused parameters or variables */ #define GUNUSED __attribute__((unused)) diff --git a/include/gint/mpu/mmu.h b/include/gint/mpu/mmu.h index b81aa9b..9b60333 100644 --- a/include/gint/mpu/mmu.h +++ b/include/gint/mpu/mmu.h @@ -14,7 +14,7 @@ //--- // SH7705 TLB. Refer to: // "Renesas SH7705 Group Hardware Manual" -// Section 3: "Memory Manaegement Unit (MMU)" +// Section 3: "Memory Management Unit (MMU)" //--- /* tlb_addr_t - address part of a TLB entry */ diff --git a/src/core/exch.c b/src/core/exch.c index a1e9871..536fd3c 100644 --- a/src/core/exch.c +++ b/src/core/exch.c @@ -9,7 +9,7 @@ #define dtext(x, y, str) dtext (x, y, str, C_BLACK, C_NONE) /* gint_panic_default(): Default panic handler */ -GNORETURN static void gint_default_panic(GUNUSED uint32_t code) +GNORETURN GMAPPED static void gint_default_panic(GUNUSED uint32_t code) { uint32_t TEA, TRA; @@ -124,7 +124,7 @@ GDATA GNORETURN void (*gint_exc_panic)(uint32_t code) = gint_default_panic; GDATA int (*gint_exc_catcher)(uint32_t code) = NULL; /* gint_panic(): Panic handler function */ -void gint_panic(uint32_t code) +GMAPPED void gint_panic(uint32_t code) { gint_exc_panic(code); } @@ -142,7 +142,7 @@ void gint_exc_catch(int (*handler)(uint32_t code)) } /* gint_exc_skip(): Skip pending exception instructions */ -void gint_exc_skip(int instructions) +GMAPPED void gint_exc_skip(int instructions) { uint32_t spc; diff --git a/src/core/exch.s b/src/core/exch.s index c5539db..d7937ee 100644 --- a/src/core/exch.s +++ b/src/core/exch.s @@ -1,8 +1,8 @@ -.global _gint_exch_tlbh -.section .gint.exch_tlbh +.global _gint_exch +.section .gint.exch .align 4 -_gint_exch_tlbh: +_gint_exch: sts.l pr, @-r15 stc.l gbr, @-r15 sts.l mach, @-r15 diff --git a/src/core/setup.c b/src/core/setup.c index dadc3af..edd61a8 100644 --- a/src/core/setup.c +++ b/src/core/setup.c @@ -16,7 +16,8 @@ extern char gint_vbr[]; /* System's VBR address */ GBSS uint32_t system_vbr; /* Size of exception and TLB handler */ -extern char gint_exch_tlbh_size; +extern char gint_exch_size; +extern char gint_tlbh_size; /* Driver table */ extern gint_driver_t bdrv, edrv; @@ -33,7 +34,7 @@ typedef struct /* gint_ctx_save() - save interrupt controller configuration @arg ctx gint core context object */ -static void gint_ctx_save(gint_core_ctx *ctx) +GMAPPED static void gint_ctx_save(gint_core_ctx *ctx) { if(isSH3()) { @@ -53,7 +54,7 @@ static void gint_ctx_save(gint_core_ctx *ctx) /* gint_ctx_restore() - restore interrupt controller configuration @arg ctx gint core context object */ -static void gint_ctx_restore(gint_core_ctx *ctx) +GMAPPED static void gint_ctx_restore(gint_core_ctx *ctx) { if(isSH3()) { @@ -84,7 +85,7 @@ static void gint_ctx_restore(gint_core_ctx *ctx) GBSS static gint_core_ctx sys_ctx; /* lock() - lock interrupts to avoid receiving unsupported signals */ -static void lock(void) +GMAPPED static void lock(void) { /* Just disable everything, drivers will enable what they support */ if(isSH3()) for(int i = 0; i < 8; i++) @@ -94,7 +95,7 @@ static void lock(void) } /* gint_install() - install and start gint */ -void gint_install(void) +GMAPPED void gint_install(void) { /* VBR address, provided by the linker script */ void *vbr = (void *)&gint_vbr; @@ -103,7 +104,8 @@ void gint_install(void) void *inth_entry = isSH3() ? gint_inth_7705 : gint_inth_7305; /* Size of the exception and TLB handlers */ - uint32_t exch_tlbh_size = (uint32_t)&gint_exch_tlbh_size; + uint32_t exch_size = (uint32_t)&gint_exch_size; + uint32_t tlbh_size = (uint32_t)&gint_tlbh_size; /* First save the hardware configuration. This step is crucial because we don't want the system to find out about us directly manipulating @@ -111,8 +113,8 @@ void gint_install(void) gint_ctx_save(&sys_ctx); /* Load the event handler entry points into memory */ - memcpy(vbr + 0x100, gint_exch_tlbh, exch_tlbh_size); - memcpy(vbr + 0x400, gint_exch_tlbh, exch_tlbh_size); + memcpy(vbr + 0x100, gint_exch, exch_size); + memcpy(vbr + 0x400, gint_tlbh, tlbh_size); memcpy(vbr + 0x600, inth_entry, 64); /* Time to switch VBR and roll! */ @@ -120,7 +122,7 @@ void gint_install(void) } /* unlock() - unlock interrupts, restoring system settings */ -static void unlock(void) +GMAPPED static void unlock(void) { /* Restore all driver settings, but do it in reverse order of loading to honor the dependency system */ @@ -133,7 +135,7 @@ static void unlock(void) } /* gint_unload() - unload gint and give back control to the system */ -void gint_unload(void) +GMAPPED void gint_unload(void) { /* First wait for all the drivers to finish their current jobs */ for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;) @@ -151,7 +153,7 @@ void gint_unload(void) static gint_core_ctx gint_ctx; extern gint_driver_t bdrv, edrv; -static void gint_switch_out(void) +GMAPPED static void gint_switch_out(void) { /* Save all drivers in reverse order */ for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;) @@ -170,7 +172,7 @@ static void gint_switch_out(void) } } -static void gint_switch_in(void) +GMAPPED static void gint_switch_in(void) { /* Save system state again */ for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;) @@ -190,7 +192,7 @@ static void gint_switch_in(void) } /* gint_switch() - temporarily switch out of gint */ -void gint_switch(void (*function)(void)) +GMAPPED void gint_switch(void (*function)(void)) { /* Wait for all the drivers to finish their current jobs */ for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;) @@ -233,7 +235,7 @@ void __ConfigureStatusArea(int mode); static int __osmenu_id; -static void __osmenu_handler(void) +GMAPPED static void __osmenu_handler(void) { __PutKeyCode(0x04, 0x09, 0); @@ -241,7 +243,7 @@ static void __osmenu_handler(void) __Timer_Deinstall(__osmenu_id); } -static void __osmenu(void) +GMAPPED static void __osmenu(void) { __ClearKeyBuffer(); @@ -286,7 +288,7 @@ static void __osmenu(void) } /* gint_osmenu() - switch out of gint and call the calculator's main menu */ -void gint_osmenu(void) +GMAPPED void gint_osmenu(void) { gint_switch(__osmenu); } diff --git a/src/core/start.c b/src/core/start.c index 0f9cf21..ed14906 100644 --- a/src/core/start.c +++ b/src/core/start.c @@ -66,25 +66,6 @@ static void regclr(uint32_t *r, int32_t s) } #define regclr(r, s) regclr(&r, (int32_t)&s) -/* explore() - read data from a memory region to get it mapped by the system - This function accesses all the 1k-blocks between b and b+s. This corresponds - to the region [b; b+s) when b and s are 1k-aligned. - @b Base pointer (first address checked) - @s Size of region */ -GSECTION(".pretext") -static void explore(volatile void *b, int32_t s) -{ - GUNUSED uint8_t x; - - while(s > 0) - { - x = *(volatile uint8_t *)b; - b += 1024; - s -= 1024; - } -} -#define explore(b, s) explore(&b, (int32_t)&s) - /* acall() - call an array of functions (constructors or destructors) @f First element of array @l First element outside of the array */ @@ -130,18 +111,6 @@ int start(int isappli, int optnum) regclr(rbss, sbss); bootlog_loaded(); - /* Traverse all ROM pages */ - explore(brom, srom); - - /* Count how much memory got mapped from this process */ - uint32_t rom, ram; - isSH3() ? tlb_mapped_memory(&rom, &ram) - : utlb_mapped_memory(&rom, &ram); - bootlog_mapped(rom, ram); - - /* Cancel add-in execution if not all pages are mapped */ -// if(rom < (uint32_t)&srom) gint_panic(0x1040); - /* Install gint and switch VBR */ gint_install(); bootlog_kernel(); diff --git a/src/core/syscalls.S b/src/core/syscalls.S index 0efb627..18f71c8 100644 --- a/src/core/syscalls.S +++ b/src/core/syscalls.S @@ -41,9 +41,7 @@ .global ___GetVRAMAddress .global ___ConfigureStatusArea -.section ".pretext" - -#define syscall(id) \ +#define syscall_(id, syscall_table) \ mov.l syscall_table, r2 ;\ mov.l 1f, r0 ;\ jmp @r2 ;\ @@ -51,12 +49,29 @@ .align 4 ;\ 1: .long id +#define syscall(id) syscall_(id, syscall_table) + +/*** Special syscalls in ILRAM ***/ + +.section .ilram + #ifdef FX9860G - -/* TLB Management */ - ___TLB_LoadPTEH: - syscall(0x0003) + syscall_(0x0003, 2f) +2: .long 0x80010070 +#endif + +#ifdef FXCG50 +___TLB_LoadPTEH: + syscall_(0x000c, 2f) +2: .long 0x80020070 +#endif + +/*** Normal syscalls in ROM ***/ + +.section .pretext + +#ifdef FX9860G /* Dynamic allocation */ @@ -118,13 +133,10 @@ syscall_table: #ifdef FXCG50 -/* TLB Management */ - -___TLB_LoadPTEH: - syscall(0x000c) - /* Dynamic allocation */ +.section .pretext + _malloc: syscall(0x1f44) _free: diff --git a/src/core/tlbh.S b/src/core/tlbh.S new file mode 100644 index 0000000..4f60cd8 --- /dev/null +++ b/src/core/tlbh.S @@ -0,0 +1,65 @@ +.global _gint_tlbh +.section .gint.tlbh +.align 4 + +_gint_tlbh: + sts.l pr, @-r15 + stc.l gbr, @-r15 + sts.l mach, @-r15 + sts.l macl, @-r15 + + /* Get HWMPU in gint's hardware info. If last bit is set, we're SH3 */ + mov.l .gint, r0 + mov.l @r0, r0 + tst #1, r0 + mov.l .tea_sh4, r0 + bt test_tea + mov.l .tea_sh3, r0 + +test_tea: + # Check TEA to see if we want to map a page or raise a SysERROR + mov.l @r0, r0 + mov.l .max_mapped_rom, r1 + cmp/ge r1, r0 + bt panic + +map: + # If TEA is mappable, map a page and return + mov.l .TLB_LoadPTEH, r0 + jsr @r0 + nop + + lds.l @r15+, macl + lds.l @r15+, mach + ldc.l @r15+, gbr + lds.l @r15+, pr + rte + nop + +panic: + # Otherwise, panic by defaulting to the exception handler (the TLB miss + # may still be resolved by a panic handler) + lds.l @r15+, macl + lds.l @r15+, mach + ldc.l @r15+, gbr + lds.l @r15+, pr + + stc vbr, r0 + mov #1, r1 + shll8 r1 + add r1, r0 + jmp @r0 + nop + +.align 4 + +.gint: + .long _gint +.tea_sh4: + .long 0xff00000c +.tea_sh3: + .long 0xfffffffc +.max_mapped_rom: + .long 0x00300000 + _srom +.TLB_LoadPTEH: + .long ___TLB_LoadPTEH diff --git a/src/keysc/keysc.c b/src/keysc/keysc.c index 695f0ff..4117463 100644 --- a/src/keysc/keysc.c +++ b/src/keysc/keysc.c @@ -57,7 +57,7 @@ GDATA static uint time = 0; /* buffer_push(): Add an event in the keyboard buffer Returns non-zero if the event cannot be pushed. */ -static int buffer_push(driver_event_t ev) +GMAPPED static int buffer_push(driver_event_t ev) { int next = (buffer_end + 1) % KEYBOARD_QUEUE_SIZE; if(next == buffer_start) return 1; @@ -79,7 +79,7 @@ static int buffer_poll(driver_event_t *ev) } /* keysc_frame(): Generate driver events from KEYSC state */ -static void keysc_frame(void) +GMAPPED static void keysc_frame(void) { GALIGNED(2) uint8_t scan[12] = { 0 }; @@ -94,9 +94,9 @@ static void keysc_frame(void) } /* Compare new data with the internal state. Push releases before - presses so that a key change occuring within a single analysis frame - can be performed. This happens all the time when going back to the - main MENU via gint_osmenu() on a keybind. */ + presses so that a key change occurring within a single analysis + frame can be performed. This happens all the time when going back to + the main MENU via gint_osmenu() on a keybind. */ for(int row = 0; row < 12; row++) { int diff = ~scan[row] & state[row]; @@ -248,7 +248,7 @@ int keydown_any(int key, ...) // Driver initialization and status //--- -static int callback(GUNUSED volatile void *arg) +GMAPPED static int callback(GUNUSED volatile void *arg) { keysc_frame(); time++; diff --git a/src/render-cg/topti-asm.s b/src/render-cg/topti-asm.s index ac3247e..94d3091 100644 --- a/src/render-cg/topti-asm.s +++ b/src/render-cg/topti-asm.s @@ -1,7 +1,7 @@ .global _topti_glyph_fg_bg .global _topti_glyph_fg .global _topti_glyph_bg -.section .pretext +.text # Glyph rendering functions. # These are pretty naive, using only word accesses to index the VRAM and diff --git a/src/render-cg/topti.c b/src/render-cg/topti.c index 39a9a3d..95d8c8f 100644 --- a/src/render-cg/topti.c +++ b/src/render-cg/topti.c @@ -25,7 +25,6 @@ font_t const * topti_font = &gint_font8x9; @height Subglyph height @dataw Glyph width @fg @bg Foreground and background colors */ -GSECTION(".pretext") static void topti_glyph(uint16_t *vram, uint32_t const * data, int left, int top, int width, int height, int dataw, int fg, int bg) { @@ -42,7 +41,6 @@ static void topti_glyph(uint16_t *vram, uint32_t const * data, int left, dataw - width, index); } -GSECTION(".pretext") void topti_render(int x, int y, char const *str, size_t size, font_t const *f, int fg, int bg) { @@ -119,7 +117,6 @@ void topti_render(int x, int y, char const *str, size_t size, font_t const *f, } /* dtext() - display a string of text */ -GSECTION(".pretext") void dtext(int x, int y, char const *str, int fg, int bg) { topti_render(x, y, str, strlen(str), topti_font, fg, bg); diff --git a/src/render-fx/dtext.c b/src/render-fx/dtext.c index e85b64b..e388b52 100644 --- a/src/render-fx/dtext.c +++ b/src/render-fx/dtext.c @@ -3,7 +3,6 @@ #include "topti-asm.h" /* dtext(): Display a string of text */ -GSECTION(".pretext") void dtext(int x, int y, char const *str, int fg, int bg) { if((uint)fg >= 8 || (uint)bg >= 8) return; diff --git a/src/render-fx/topti-asm.s b/src/render-fx/topti-asm.s index ffa0efa..fa89079 100644 --- a/src/render-fx/topti-asm.s +++ b/src/render-fx/topti-asm.s @@ -1,6 +1,5 @@ .global _topti_asm_text -.section .pretext # REGISTER ALLOCATION: # r0: x or ~x @@ -12,7 +11,7 @@ # r6: operators # r7: number of rows (r7>0, otherwise the font is clearly ill-formed) -# Mind that there are pipeline optimisation efforts in this file: +# Mind that there are pipeline optimization efforts in this file: # * Doing memory accesses on 4-aligned instructions to avoid contention between # IF and MA (1 cycle); # * Avoid using an operand just after it is fetched from memory because of the diff --git a/src/render-fx/topti.c b/src/render-fx/topti.c index f30874d..7ffdf3e 100644 --- a/src/render-fx/topti.c +++ b/src/render-fx/topti.c @@ -24,7 +24,6 @@ font_t const * topti_font = &gint_font5x7; 0, call topti_draw() and reset the operators. If it's negative, call topti_draw() then do another pass of topti_split() to recover the missing information. */ -GSECTION(".pretext") static int topti_split(uint32_t const * glyph, int width, int height, int free, uint32_t *operators) { @@ -81,7 +80,6 @@ static int topti_split(uint32_t const * glyph, int width, int height, int free, } /* topti_render(): Render a string on the VRAM */ -GSECTION(".pretext") void topti_render(int x, int y, char const *str, font_t const *f, asm_text_t *asm_fg, asm_text_t *asm_bg, uint32_t *v1, uint32_t *v2) { diff --git a/src/render/topti.c b/src/render/topti.c index a087eb0..6d7b869 100644 --- a/src/render/topti.c +++ b/src/render/topti.c @@ -7,7 +7,6 @@ #define PROP_SPACING 5 /* dfont(): Set the default font for text rendering */ -GSECTION(".pretext") font_t const *dfont(font_t const * font) { font_t const *old_font = topti_font; @@ -17,7 +16,6 @@ font_t const *dfont(font_t const * font) } /* charset_size(): Number of elements in each character set */ -GSECTION(".pretext") int charset_size(enum topti_charset set) { int size[] = { 10, 26, 52, 62, 95, 128 }; @@ -25,7 +23,6 @@ int charset_size(enum topti_charset set) } /* charset_decode(): Translate ASCII into reduced character sets */ -GSECTION(".pretext") int charset_decode(enum topti_charset set, uint c) { int x, y; @@ -59,7 +56,6 @@ int charset_decode(enum topti_charset set, uint c) } /* topti_offset(): Use a font index to find the location of a glyph */ -GSECTION(".pretext") int topti_offset(font_t const *f, uint glyph) { /* Non-proportional fonts don't need an index */ diff --git a/src/tmu/tmu.c b/src/tmu/tmu.c index d94bb7e..3dd56b4 100644 --- a/src/tmu/tmu.c +++ b/src/tmu/tmu.c @@ -134,7 +134,7 @@ void timer_pause(int id) } /* timer_stop() - stop and free a timer */ -void timer_stop(int id) +GMAPPED void timer_stop(int id) { /* Stop the timer and disable UNIE to indicate that it's free */ timer_pause(id); @@ -167,7 +167,7 @@ void timer_stop(int id) //--- /* timer_timeout() - callback that sets a flag and halts the timer */ -int timer_timeout(volatile void *arg) +GMAPPED int timer_timeout(volatile void *arg) { volatile int *x = arg; (*x)++; @@ -181,7 +181,7 @@ int timer_timeout(volatile void *arg) /* timer_clear() - clear an ETMU flag and possibly stop the timer @timer Timer ID, must be an ETMU @stop Non-zero to stop the timer */ -void timer_clear(int id, int stop) +GMAPPED void timer_clear(int id, int stop) { do ETMU[id-3].TCR.UNF = 0; while(ETMU[id-3].TCR.UNF);