mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
core: backport TLB handling to fx9860g, fix return-to-menu (UNSTABLE)
This change ports the TLB management system to fx9860g through %003. This raises the size limit for add-ins to about 500k. Because SH3 fx9860g does not have ILRAM, the GMAPPED attribute has been made to generate content to a .gint.mapped section which is sent to the P1 RAM section historically dubbed "real ram" in which gint's data and VBR are installed. (Now that I think about it, gint's data should try to go to normal RAM instead to reduce pressure on this invasion.) Return-to-menu was also fixed on both platforms by narrowing down the need for code to remain mapped to the chance of running it with interrupts disabled. The natural distribution of GMAPPED under this criterion showed that _gint_setvbr had been left under TLB control; moving it to the proper RAM area fixed gint switches. Finally, an omission in the bound checks for mappable TEA addresses (TEA >= 0x00300000) prevented the appearance of a non-interactible System ERROR popup when some unmapped addresses are accessed. This version still does not enable interrupts in timer callbacks, exposing any application to a crash if a timer underflows while its callback is not mapped. It is not suitable for any stable application!
This commit is contained in:
parent
fbfcdd7664
commit
8148d89c88
10 changed files with 54 additions and 48 deletions
20
fx9860g.ld
20
fx9860g.ld
|
@ -13,9 +13,8 @@ ENTRY(_start)
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
/* Userspace mapping of the add-in (0x200 B are for the G1A header).
|
/* Userspace mapping of the add-in (G1A header takes 0x200 bytes) */
|
||||||
220k is the maximum amount of simultaneously-mappable code */
|
rom (rx): o = 0x00300200, l = 500k
|
||||||
rom (rx): o = 0x00300200, l = 220k
|
|
||||||
/* This is mapped to RAM; 8k on SH3, apparently 32k on SH4 */
|
/* This is mapped to RAM; 8k on SH3, apparently 32k on SH4 */
|
||||||
ram (rw): o = 0x08100000, l = 8k
|
ram (rw): o = 0x08100000, l = 8k
|
||||||
/* gint's VBR space, mentioned here for completeness */
|
/* gint's VBR space, mentioned here for completeness */
|
||||||
|
@ -60,9 +59,13 @@ SECTIONS
|
||||||
} > rom
|
} > rom
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
_gint_exch_tlbh_start = . ;
|
_gint_exch_start = . ;
|
||||||
*(.gint.exch_tlbh);
|
*(.gint.exch)
|
||||||
_gint_exch_tlbh_size = ABSOLUTE(. - _gint_exch_tlbh_start);
|
_gint_exch_size = ABSOLUTE(. - _gint_exch_start);
|
||||||
|
|
||||||
|
_gint_tlbh_start = . ;
|
||||||
|
*(.gint.tlbh)
|
||||||
|
_gint_tlbh_size = ABSOLUTE(. - _gint_tlbh_start);
|
||||||
|
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
*(C P)
|
*(C P)
|
||||||
|
@ -210,6 +213,9 @@ SECTIONS
|
||||||
|
|
||||||
*(.gint.data .gint.data.*)
|
*(.gint.data .gint.data.*)
|
||||||
|
|
||||||
|
/* Also code that must remain permanently mapped! */
|
||||||
|
*(.gint.mapped)
|
||||||
|
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
} > rram AT> rom
|
} > rram AT> rom
|
||||||
|
|
||||||
|
@ -234,7 +240,7 @@ SECTIONS
|
||||||
|
|
||||||
/* Unwanted sections going to meet Dave Null:
|
/* Unwanted sections going to meet Dave Null:
|
||||||
- Debug sections, often come out of libgcc
|
- Debug sections, often come out of libgcc
|
||||||
- Java classes registration (why are there even here?)
|
- Java classes registration (why is there any of this here?)
|
||||||
- Asynchronous unwind tables: no C++ exception handling for now ^^
|
- Asynchronous unwind tables: no C++ exception handling for now ^^
|
||||||
- Comments or anything the compiler might put in its assembler
|
- Comments or anything the compiler might put in its assembler
|
||||||
- A stack section sometimes generated for build/version.o */
|
- A stack section sometimes generated for build/version.o */
|
||||||
|
|
|
@ -147,6 +147,8 @@ SECTIONS
|
||||||
_rilram = . ;
|
_rilram = . ;
|
||||||
|
|
||||||
*(.ilram)
|
*(.ilram)
|
||||||
|
/* Code that must remain mapped is placed here */
|
||||||
|
*(.gint.mapped)
|
||||||
|
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
} > ilram AT> rom
|
} > ilram AT> rom
|
||||||
|
@ -224,7 +226,7 @@ SECTIONS
|
||||||
/* Unwanted sections going to meet Dave Null:
|
/* Unwanted sections going to meet Dave Null:
|
||||||
- SH3-only data sections
|
- SH3-only data sections
|
||||||
- Debug sections, often come out of libgcc
|
- Debug sections, often come out of libgcc
|
||||||
- Java classes registration (why are there even here?)
|
- Java classes registration (why is there any of this here?)
|
||||||
- Asynchronous unwind tables: no C++ exception handling for now ^^
|
- Asynchronous unwind tables: no C++ exception handling for now ^^
|
||||||
- Comments or anything the compiler might put in its assembler */
|
- Comments or anything the compiler might put in its assembler */
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
|
|
|
@ -17,8 +17,9 @@
|
||||||
#define GILRAM __attribute__((section(".ilram")))
|
#define GILRAM __attribute__((section(".ilram")))
|
||||||
#define GXRAM __attribute__((section(".xram")))
|
#define GXRAM __attribute__((section(".xram")))
|
||||||
#define GYRAM __attribute__((section(".yram")))
|
#define GYRAM __attribute__((section(".yram")))
|
||||||
/* Objects that must remain mapped */
|
/* Objects that must remain mapped; placed in "real RAM" (some P1 area) on
|
||||||
#define GMAPPED GILRAM
|
fx9860g, and ILRAM on fxcg50 */
|
||||||
|
#define GMAPPED __attribute__((section(".gint.mapped")))
|
||||||
|
|
||||||
/* Unused parameters or variables */
|
/* Unused parameters or variables */
|
||||||
#define GUNUSED __attribute__((unused))
|
#define GUNUSED __attribute__((unused))
|
||||||
|
|
|
@ -27,13 +27,17 @@ void gint_panic_set(GNORETURN void (*panic)(uint32_t code));
|
||||||
/* gint_exc_catch(): Set a function to catch exceptions
|
/* gint_exc_catch(): Set a function to catch exceptions
|
||||||
|
|
||||||
Sets up an exception-catching function. If an exception occurs, before a
|
Sets up an exception-catching function. If an exception occurs, before a
|
||||||
panic is raised, the exception-catching function is executed in interrupt
|
panic is raised, the exception-catching function is executed with interrupt
|
||||||
mode and is given a chance to handle the exception. Passing NULL disables
|
mode and is given a chance to handle the exception. Passing NULL disables
|
||||||
this feature.
|
this feature.
|
||||||
|
|
||||||
The exception-catching function can do anything that does not use interrupts
|
The exception-catching function can do anything that does not use interrupts
|
||||||
or causes an exception, such as logging the exception or any other useful
|
or cause an exception, such as logging the exception or any other useful
|
||||||
mechanism.
|
mechanism. TLB misses count as exceptions and are disabled, so this function
|
||||||
|
must absolutely be mapped *before* it runs! The only real way to ensure this
|
||||||
|
is to have it mapped at all times using the GMAPPED attribute. Note that
|
||||||
|
GMAPPED puts the function in a generally small memory region so you should
|
||||||
|
defer as much handling as possible until after the exception is caught.
|
||||||
|
|
||||||
What happens next depends on the return value:
|
What happens next depends on the return value:
|
||||||
* If it returns 0, the exception is considered handled and execution
|
* If it returns 0, the exception is considered handled and execution
|
||||||
|
@ -58,7 +62,7 @@ void gint_exc_catch(int (*handler)(uint32_t code));
|
||||||
When an exception-catching function records an exception without solving it,
|
When an exception-catching function records an exception without solving it,
|
||||||
this re-execution will fail again and the exception handling process will
|
this re-execution will fail again and the exception handling process will
|
||||||
loop. In such a situation, gint_exc_skip() can be used to manually skip the
|
loop. In such a situation, gint_exc_skip() can be used to manually skip the
|
||||||
offending instruction.
|
offending instruction, if this is an acceptable resolution.
|
||||||
|
|
||||||
@instructions Number of instructions to skip (usually only one) */
|
@instructions Number of instructions to skip (usually only one) */
|
||||||
void gint_exc_skip(int instructions);
|
void gint_exc_skip(int instructions);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#define dtext(x, y, str) dtext (x, y, str, C_BLACK, C_NONE)
|
#define dtext(x, y, str) dtext (x, y, str, C_BLACK, C_NONE)
|
||||||
|
|
||||||
/* gint_panic_default(): Default panic handler */
|
/* gint_panic_default(): Default panic handler */
|
||||||
GNORETURN GMAPPED static void gint_default_panic(GUNUSED uint32_t code)
|
GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
||||||
{
|
{
|
||||||
uint32_t TEA, TRA;
|
uint32_t TEA, TRA;
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ GNORETURN GMAPPED static void gint_default_panic(GUNUSED uint32_t code)
|
||||||
dprint(38, 75, "= %#x", TRA);
|
dprint(38, 75, "= %#x", TRA);
|
||||||
dtext(281, 75, "(Trap number)");
|
dtext(281, 75, "(Trap number)");
|
||||||
|
|
||||||
dtext(6, 95, "An unrecoverable error ocurred in the add-in.");
|
dtext(6, 95, "An unrecoverable error occurred in the add-in.");
|
||||||
dtext(6, 108, "Please press the RESET button to restart the");
|
dtext(6, 108, "Please press the RESET button to restart the");
|
||||||
dtext(6, 121, "calculator.");
|
dtext(6, 121, "calculator.");
|
||||||
|
|
||||||
|
@ -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;
|
GDATA int (*gint_exc_catcher)(uint32_t code) = NULL;
|
||||||
|
|
||||||
/* gint_panic(): Panic handler function */
|
/* gint_panic(): Panic handler function */
|
||||||
GMAPPED void gint_panic(uint32_t code)
|
void gint_panic(uint32_t code)
|
||||||
{
|
{
|
||||||
gint_exc_panic(code);
|
gint_exc_panic(code);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
/* VBR address, from the linker script */
|
/* VBR address, from the linker script */
|
||||||
extern char gint_vbr[];
|
extern char gint_vbr[];
|
||||||
/* System's VBR address */
|
/* System's VBR address */
|
||||||
GBSS uint32_t system_vbr;
|
GBSS static uint32_t system_vbr;
|
||||||
/* Size of exception and TLB handler */
|
/* Size of exception and TLB handler */
|
||||||
extern char gint_exch_size;
|
extern char gint_exch_size;
|
||||||
extern char gint_tlbh_size;
|
extern char gint_tlbh_size;
|
||||||
|
@ -95,7 +95,7 @@ GMAPPED static void lock(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gint_install() - install and start gint */
|
/* gint_install() - install and start gint */
|
||||||
GMAPPED void gint_install(void)
|
void gint_install(void)
|
||||||
{
|
{
|
||||||
/* VBR address, provided by the linker script */
|
/* VBR address, provided by the linker script */
|
||||||
void *vbr = (void *)&gint_vbr;
|
void *vbr = (void *)&gint_vbr;
|
||||||
|
@ -135,7 +135,7 @@ GMAPPED static void unlock(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gint_unload() - unload gint and give back control to the system */
|
/* gint_unload() - unload gint and give back control to the system */
|
||||||
GMAPPED void gint_unload(void)
|
void gint_unload(void)
|
||||||
{
|
{
|
||||||
/* First wait for all the drivers to finish their current jobs */
|
/* First wait for all the drivers to finish their current jobs */
|
||||||
for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;)
|
for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;)
|
||||||
|
@ -192,7 +192,7 @@ GMAPPED static void gint_switch_in(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gint_switch() - temporarily switch out of gint */
|
/* gint_switch() - temporarily switch out of gint */
|
||||||
GMAPPED void gint_switch(void (*function)(void))
|
void gint_switch(void (*function)(void))
|
||||||
{
|
{
|
||||||
/* Wait for all the drivers to finish their current jobs */
|
/* Wait for all the drivers to finish their current jobs */
|
||||||
for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;)
|
for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;)
|
||||||
|
@ -203,18 +203,6 @@ GMAPPED void gint_switch(void (*function)(void))
|
||||||
gint_setvbr(system_vbr, gint_switch_out);
|
gint_setvbr(system_vbr, gint_switch_out);
|
||||||
if(function) function();
|
if(function) function();
|
||||||
|
|
||||||
/* Remap all of the ROM */
|
|
||||||
extern uint32_t brom, srom;
|
|
||||||
volatile void *b = &brom;
|
|
||||||
int32_t s = (int32_t)&srom;
|
|
||||||
GUNUSED uint8_t x;
|
|
||||||
while(s > 0)
|
|
||||||
{
|
|
||||||
x = *(volatile uint8_t *)b;
|
|
||||||
b += 1024;
|
|
||||||
s -= 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for the OS to finish working */
|
/* Wait for the OS to finish working */
|
||||||
for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;)
|
for(gint_driver_t *drv = &edrv; (--drv) >= &bdrv;)
|
||||||
{
|
{
|
||||||
|
@ -235,7 +223,7 @@ void __ConfigureStatusArea(int mode);
|
||||||
|
|
||||||
static int __osmenu_id;
|
static int __osmenu_id;
|
||||||
|
|
||||||
GMAPPED static void __osmenu_handler(void)
|
static void __osmenu_handler(void)
|
||||||
{
|
{
|
||||||
__PutKeyCode(0x04, 0x09, 0);
|
__PutKeyCode(0x04, 0x09, 0);
|
||||||
|
|
||||||
|
@ -243,7 +231,7 @@ GMAPPED static void __osmenu_handler(void)
|
||||||
__Timer_Deinstall(__osmenu_id);
|
__Timer_Deinstall(__osmenu_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GMAPPED static void __osmenu(void)
|
static void __osmenu(void)
|
||||||
{
|
{
|
||||||
__ClearKeyBuffer();
|
__ClearKeyBuffer();
|
||||||
|
|
||||||
|
@ -288,7 +276,7 @@ GMAPPED static void __osmenu(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gint_osmenu() - switch out of gint and call the calculator's main menu */
|
/* gint_osmenu() - switch out of gint and call the calculator's main menu */
|
||||||
GMAPPED void gint_osmenu(void)
|
void gint_osmenu(void)
|
||||||
{
|
{
|
||||||
gint_switch(__osmenu);
|
gint_switch(__osmenu);
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,10 +93,11 @@ int start(int isappli, int optnum)
|
||||||
redirecting interrupts and reimplementing drivers, so we can't rely
|
redirecting interrupts and reimplementing drivers, so we can't rely
|
||||||
too much on the system. Ladies and gentlemen, let's have fun! ;D */
|
too much on the system. Ladies and gentlemen, let's have fun! ;D */
|
||||||
|
|
||||||
/* For now, we use the system's memory mapper for ROM. RAM is always
|
/* For now, we use the system's memory mapper for ROM. We'll still do
|
||||||
|
it from our TLB miss handler once we're installed. RAM is always
|
||||||
fully mapped, but we need to initialize it. We also need to do some
|
fully mapped, but we need to initialize it. We also need to do some
|
||||||
hardware detection because old fx9860g models have a different
|
hardware detection because old fx9860g models have a different
|
||||||
processor with some incompatible features */
|
processor with some incompatible features. */
|
||||||
|
|
||||||
/* Detect architecture - this will tell SH3 from SH4 on fx9860g */
|
/* Detect architecture - this will tell SH3 from SH4 on fx9860g */
|
||||||
hw_detect();
|
hw_detect();
|
||||||
|
@ -118,7 +119,7 @@ int start(int isappli, int optnum)
|
||||||
/* We are now running on our own in kernel mode. Since we have taken
|
/* We are now running on our own in kernel mode. Since we have taken
|
||||||
control of interrupts, pretty much any interaction with the system
|
control of interrupts, pretty much any interaction with the system
|
||||||
will break it. We'll limit our use of syscalls and do device driving
|
will break it. We'll limit our use of syscalls and do device driving
|
||||||
ourselves. (Hopefully we can add cool features in the process.) */
|
ourselves. (Hopefully we can add cool features in the process!) */
|
||||||
|
|
||||||
gint_driver_t *drv;
|
gint_driver_t *drv;
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,9 @@
|
||||||
|
|
||||||
#define syscall(id) syscall_(id, syscall_table)
|
#define syscall(id) syscall_(id, syscall_table)
|
||||||
|
|
||||||
/*** Special syscalls in ILRAM ***/
|
/*** Special syscalls that must remain mapped ***/
|
||||||
|
|
||||||
.section .ilram
|
.section .gint.mapped
|
||||||
|
|
||||||
#ifdef FX9860G
|
#ifdef FX9860G
|
||||||
___TLB_LoadPTEH:
|
___TLB_LoadPTEH:
|
||||||
|
|
|
@ -17,14 +17,17 @@ _gint_tlbh:
|
||||||
mov.l .tea_sh3, r0
|
mov.l .tea_sh3, r0
|
||||||
|
|
||||||
test_tea:
|
test_tea:
|
||||||
# Check TEA to see if we want to map a page or raise a SysERROR
|
/* Check TEA to see if we want to map a page or raise a SysERROR */
|
||||||
mov.l @r0, r0
|
mov.l @r0, r0
|
||||||
mov.l .max_mapped_rom, r1
|
mov.l .max_mapped_rom, r1
|
||||||
cmp/ge r1, r0
|
cmp/ge r1, r0
|
||||||
bt panic
|
bt panic
|
||||||
|
mov.l .min_mapped_rom, r1
|
||||||
|
cmp/ge r1, r0
|
||||||
|
bf panic
|
||||||
|
|
||||||
map:
|
map:
|
||||||
# If TEA is mappable, map a page and return
|
/* If TEA is mappable, map a page and return */
|
||||||
mov.l .TLB_LoadPTEH, r0
|
mov.l .TLB_LoadPTEH, r0
|
||||||
jsr @r0
|
jsr @r0
|
||||||
nop
|
nop
|
||||||
|
@ -37,8 +40,8 @@ map:
|
||||||
nop
|
nop
|
||||||
|
|
||||||
panic:
|
panic:
|
||||||
# Otherwise, panic by defaulting to the exception handler (the TLB miss
|
/* Otherwise, panic by defaulting to the exception handler (the TLB
|
||||||
# may still be resolved by a panic handler)
|
miss may still be resolved by a panic handler) */
|
||||||
lds.l @r15+, macl
|
lds.l @r15+, macl
|
||||||
lds.l @r15+, mach
|
lds.l @r15+, mach
|
||||||
ldc.l @r15+, gbr
|
ldc.l @r15+, gbr
|
||||||
|
@ -59,6 +62,8 @@ panic:
|
||||||
.long 0xff00000c
|
.long 0xff00000c
|
||||||
.tea_sh3:
|
.tea_sh3:
|
||||||
.long 0xfffffffc
|
.long 0xfffffffc
|
||||||
|
.min_mapped_rom:
|
||||||
|
.long 0x00300000
|
||||||
.max_mapped_rom:
|
.max_mapped_rom:
|
||||||
.long 0x00300000 + _srom
|
.long 0x00300000 + _srom
|
||||||
.TLB_LoadPTEH:
|
.TLB_LoadPTEH:
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
** gint:core:vbr - Assembler-level VBR management
|
** gint:core:vbr - Assembler-level VBR management
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.global _gint_setvbr
|
.global _gint_setvbr
|
||||||
.text
|
.section .gint.mapped
|
||||||
.align 2
|
|
||||||
|
|
||||||
/* gint_setvbr()
|
/* gint_setvbr()
|
||||||
Changes the VBR address and the calls the configuration function while
|
Changes the VBR address and the calls the configuration function while
|
||||||
|
|
Loading…
Reference in a new issue