Lephe
8148d89c88
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!
71 lines
3.1 KiB
C
71 lines
3.1 KiB
C
//---
|
|
// gint:exc - Exception handling
|
|
//
|
|
// This small module is used to display exceptions and configure when the
|
|
// exception handler displays these messages. This is for advanced users
|
|
// only!
|
|
//---
|
|
|
|
#ifndef GINT_EXC
|
|
#define GINT_EXC
|
|
|
|
#include <gint/defs/attributes.h>
|
|
#include <stdint.h>
|
|
|
|
/* gint_panic(): Panic handler function
|
|
This function is called when an uncaught CPU exception is generated. By
|
|
default, it displays a full-screen error message with the event code and
|
|
basic debugging information. Some custom event codes may be used for kernel
|
|
failure scenarios. This function never returns. */
|
|
GNORETURN void gint_panic(uint32_t code);
|
|
|
|
/* gint_panic_set(): Change the panic handler function
|
|
Sets up a different panic function instead of the default. It the argument
|
|
is NULL, restores the default. */
|
|
void gint_panic_set(GNORETURN void (*panic)(uint32_t code));
|
|
|
|
/* gint_exc_catch(): Set a function to catch exceptions
|
|
|
|
Sets up an exception-catching function. If an exception occurs, before a
|
|
panic is raised, the exception-catching function is executed with interrupt
|
|
mode and is given a chance to handle the exception. Passing NULL disables
|
|
this feature.
|
|
|
|
The exception-catching function can do anything that does not use interrupts
|
|
or cause an exception, such as logging the exception or any other useful
|
|
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:
|
|
* If it returns 0, the exception is considered handled and execution
|
|
continues normally at or after the offending instruction.
|
|
* If it returns nonzero, a panic is raised.
|
|
|
|
Please be aware that many exceptions are of re-execution type. When
|
|
execution restarts after such an exception is handled, the offending
|
|
instruction is re-executed. This can cause the exception handling mechanism
|
|
to loop. Use gint_exc_skip() to skip over the offending instruction when
|
|
needed. Whether an exception is of re-execution type depends on the
|
|
exception code. */
|
|
void gint_exc_catch(int (*handler)(uint32_t code));
|
|
|
|
/* gint_exc_skip(): Skip pending exception instructions
|
|
|
|
Many exceptions re-execute the offending instruction after the exception is
|
|
handled. For instance the TLB miss handler is supposed to load the required
|
|
page into memory, so that the instruction that accessed unmapped memory can
|
|
be successfully re-executed.
|
|
|
|
When an exception-catching function records an exception without solving it,
|
|
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
|
|
offending instruction, if this is an acceptable resolution.
|
|
|
|
@instructions Number of instructions to skip (usually only one) */
|
|
void gint_exc_skip(int instructions);
|
|
|
|
#endif /* GINT_EXC */
|