Compare commits
2 Commits
4a8ba82fab
...
5630814897
Author | SHA1 | Date |
---|---|---|
Lephe | 5630814897 | |
Lephe | 9a4ae4c80a |
3
TODO
3
TODO
|
@ -10,8 +10,7 @@ Tests to run.
|
|||
* topti: all charsets
|
||||
|
||||
Complementary elements on existing code.
|
||||
* core: make it possiblé to catch exceptions (gintctl's memory browser)
|
||||
* core: check if -DX still works in GCC 9 and if not, put spaces
|
||||
* topti: support unicode fonts
|
||||
* gray: find good values for more models than the Graph 35+E II
|
||||
* render: get rid of GINT_NEED_VRAM and #define vram gint_vram if you need
|
||||
* dma: dma_memcpy() and dma_memset(), possibly requiring alignment
|
||||
|
|
|
@ -34,4 +34,7 @@
|
|||
#define GCONSTRUCTOR __attribute__((constructor))
|
||||
#define GDESTRUCTOR __attribute__((destructor))
|
||||
|
||||
/* Functions that do not return */
|
||||
#define GNORETURN __attribute__((noreturn))
|
||||
|
||||
#endif /* GINT_DEFS_ATTRIBUTES */
|
||||
|
|
|
@ -38,6 +38,11 @@ enum {
|
|||
C_DARK = 0x5555,
|
||||
C_BLACK = 0x0000,
|
||||
|
||||
/* Other colors */
|
||||
C_RED = 0xf800,
|
||||
C_GREEN = 0x07e0,
|
||||
C_BLUE = 0x001f,
|
||||
|
||||
C_NONE = -1,
|
||||
};
|
||||
|
||||
|
|
|
@ -9,13 +9,58 @@
|
|||
#ifndef GINT_EXC
|
||||
#define GINT_EXC
|
||||
|
||||
/* gint_exc(): Exception handler fatal error message
|
||||
Displays a full-screen fatal error message from an exception event code.
|
||||
Some custom event codes are also used for library failure. This function is
|
||||
typically called by exception handlers and returns after a dupdate_noint().
|
||||
You probably want to soft-lock or quit the add-in after calling it. */
|
||||
void gint_exc(uint32_t code);
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* TODO: Add functions to disable fatal errors for some exceptions */
|
||||
/* 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 in 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 causes an exception, such as logging the exception or any other useful
|
||||
mechanism.
|
||||
|
||||
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 if 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.
|
||||
|
||||
@instructions Number of instructions to skip (usually only one) */
|
||||
void gint_exc_skip(int instructions);
|
||||
|
||||
#endif /* GINT_EXC */
|
||||
|
|
|
@ -64,7 +64,7 @@ void gray_stop(void);
|
|||
1325 1607 heavy light excellent
|
||||
--------------------------------------------------
|
||||
|
||||
Here are values for this version of gint:
|
||||
Here are values for this version of gint (for the Graph 35+E II only):
|
||||
|
||||
LIGHT DARK BLINKING STRIPES COLORS
|
||||
--------------------------------------------------
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
#define GINT_NEED_VRAM
|
||||
#include <gint/display.h>
|
||||
#include <gint/exc.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/clock.h>
|
||||
#include <gint/mpu/dma.h>
|
||||
#include <gint/defs/attributes.h>
|
||||
|
||||
#define dprint(x, y, ...) dprint(x, y, C_BLACK, C_NONE, __VA_ARGS__)
|
||||
#define dtext(x, y, str) dtext (x, y, str, C_BLACK, C_NONE)
|
||||
|
||||
/* gint_exc(): Exception handler fatal error message */
|
||||
void gint_exc(GUNUSED uint32_t code)
|
||||
/* gint_panic_default(): Default panic handler */
|
||||
GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
|
||||
{
|
||||
uint32_t TEA = *(volatile uint32_t *)0xff00000c;
|
||||
uint32_t TRA = *(volatile uint32_t *)0xff000020 >> 2;
|
||||
|
@ -82,17 +84,56 @@ void gint_exc(GUNUSED uint32_t code)
|
|||
dtext(6, 95, "An unrecoverable error ocurred in the add-in.");
|
||||
dtext(6, 108, "Please press the RESET button to restart the");
|
||||
dtext(6, 121, "calculator.");
|
||||
|
||||
/* DMA address error handler */
|
||||
if(code == 0x1020)
|
||||
{
|
||||
#define DMA SH7305_DMA
|
||||
dprint(6, 141, "SAR0: %08x DAR0: %08x TCR0: %08x",
|
||||
DMA.DMA0.SAR, DMA.DMA0.DAR, DMA.DMA0.TCR);
|
||||
dprint(6, 154, "CHCR0: %08x", DMA.DMA0.CHCR);
|
||||
dprint(6, 167, "SAR1: %08x DAR1: %08x TCR1: %08x",
|
||||
DMA.DMA1.SAR, DMA.DMA1.DAR, DMA.DMA1.TCR);
|
||||
dprint(6, 180, "CHCR1: %08x", DMA.DMA1.CHCR);
|
||||
dprint(6, 193, "DMAOR: %04x", DMA.OR);
|
||||
#undef DMA
|
||||
}
|
||||
#endif
|
||||
|
||||
dupdate_noint();
|
||||
dupdate();
|
||||
while(1) sleep();
|
||||
}
|
||||
|
||||
/* gint_exch_tlbh(): Exception and TLB miss handler */
|
||||
__attribute__((interrupt_handler)) GSECTION(".gint.exch_tlbh") GALIGNED(4)
|
||||
void gint_exch_tlbh(void)
|
||||
/* Panic handler */
|
||||
GDATA GNORETURN void (*gint_exc_panic)(uint32_t code) = gint_default_panic;
|
||||
/* Exception catcher */
|
||||
GDATA int (*gint_exc_catcher)(uint32_t code) = NULL;
|
||||
|
||||
/* gint_panic(): Panic handler function */
|
||||
void gint_panic(uint32_t code)
|
||||
{
|
||||
uint32_t EXPEVT = *(volatile uint32_t *)0xff000024;
|
||||
|
||||
gint_exc(EXPEVT);
|
||||
while(1);
|
||||
gint_exc_panic(code);
|
||||
}
|
||||
|
||||
/* gint_panic_set(): Change the panic handler function */
|
||||
void gint_panic_set(GNORETURN void (*panic)(uint32_t code))
|
||||
{
|
||||
gint_exc_panic = panic;
|
||||
}
|
||||
|
||||
/* gint_exc_catch(): Set a function to catch exceptions */
|
||||
void gint_exc_catch(int (*handler)(uint32_t code))
|
||||
{
|
||||
gint_exc_catcher = handler;
|
||||
}
|
||||
|
||||
/* gint_exc_skip(): Skip pending exception instructions */
|
||||
void gint_exc_skip(int instructions)
|
||||
{
|
||||
uint32_t spc;
|
||||
|
||||
/* Increase SPC by 2 bytes per instruction */
|
||||
__asm__("stc spc, %0" : "=r"(spc));
|
||||
spc += 2 * instructions;
|
||||
__asm__("ldc %0, spc" :: "r"(spc));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
.global _gint_exch_tlbh
|
||||
.section .gint.exch_tlbh
|
||||
.align 4
|
||||
|
||||
_gint_exch_tlbh:
|
||||
sts.l pr, @-r15
|
||||
mov.l r8, @-r15
|
||||
|
||||
mov.l .expevt, r8
|
||||
|
||||
/* Panic if the catcher is NULL */
|
||||
mov.l .catcher, r0
|
||||
mov.l @r0, r0
|
||||
tst r0, r0
|
||||
bt panic
|
||||
|
||||
/* Leave if the catcher returns zero */
|
||||
jsr @r0
|
||||
mov.l @r8, r4
|
||||
tst r0, r0
|
||||
bt end
|
||||
|
||||
panic:
|
||||
/* RTE to the panic function, but manually, so that SPC is preserved */
|
||||
mov.l @r8, r4
|
||||
ldc r4, r4_bank
|
||||
|
||||
mov.l @r15+, r8
|
||||
lds.l @r15+, pr
|
||||
|
||||
/* Here we switch banks so r0..r7 change meaning! */
|
||||
stc ssr, r0
|
||||
ldc r0, sr
|
||||
|
||||
mov.l .panic, r0
|
||||
mov.l @r0, r0
|
||||
jmp @r0
|
||||
nop
|
||||
|
||||
end:
|
||||
mov.l @r15+, r8
|
||||
lds.l @r15+, pr
|
||||
rte
|
||||
nop
|
||||
|
||||
.align 4
|
||||
|
||||
.expevt:
|
||||
.long 0xff000024
|
||||
.catcher:
|
||||
.long _gint_exc_catcher
|
||||
.panic:
|
||||
.long _gint_exc_panic
|
|
@ -134,12 +134,7 @@ int start(int isappli, int optnum)
|
|||
bootlog_mapped(rom, ram);
|
||||
|
||||
/* Cancel add-in execution if not all pages are mapped */
|
||||
if(rom < (uint32_t)&srom)
|
||||
{
|
||||
gint_exc(0x1040);
|
||||
while(1);
|
||||
return 1;
|
||||
}
|
||||
if(rom < (uint32_t)&srom) gint_panic(0x1040);
|
||||
|
||||
/* Install gint and switch VBR */
|
||||
gint_install();
|
||||
|
|
|
@ -152,34 +152,6 @@ void dma_transfer_noint(int channel, dma_size_t size, uint blocks,
|
|||
DMA.OR.NMIF = 0;
|
||||
}
|
||||
|
||||
//---
|
||||
// Address error handler
|
||||
//---
|
||||
|
||||
/* gint_dma_ae(): DMA Address Error handler */
|
||||
void gint_dma_ae(void)
|
||||
{
|
||||
gint_exc(0x1020);
|
||||
|
||||
#ifdef FXCG50
|
||||
dprint(6, 141, C_BLACK, C_NONE,
|
||||
"SAR0: %08x DAR0: %08x TCR0: %08x",
|
||||
DMA.DMA0.SAR, DMA.DMA0.DAR, DMA.DMA0.TCR);
|
||||
dprint(6, 154, C_BLACK, C_NONE,
|
||||
"CHCR0: %08x", DMA.DMA0.CHCR);
|
||||
dprint(6, 167, C_BLACK, C_NONE,
|
||||
"SAR1: %08x DAR1: %08x TCR1: %08x",
|
||||
DMA.DMA1.SAR, DMA.DMA1.DAR, DMA.DMA1.TCR);
|
||||
dprint(6, 180, C_BLACK, C_NONE,
|
||||
"CHCR1: %08x", DMA.DMA1.CHCR);
|
||||
dprint(6, 193, C_BLACK, C_NONE,
|
||||
"DMAOR: %04x", DMA.OR);
|
||||
dupdate_noint();
|
||||
#endif
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
//---
|
||||
// Initialization
|
||||
//---
|
||||
|
|
|
@ -34,16 +34,19 @@ _inth_dma_te:
|
|||
/* DMA ADDRESS ERROR INTERRUPT HANDLER - 18 BYTES */
|
||||
|
||||
_inth_dma_ae:
|
||||
/* Call a fixed function */
|
||||
sts.l pr, @-r15
|
||||
mov.l 1f, r1
|
||||
jsr @r1
|
||||
nop
|
||||
lds.l @r15+, pr
|
||||
/* Manually RTE into the panic routine, preserving SPC */
|
||||
mov.l 2f, r4
|
||||
ldc r4, r4_bank
|
||||
|
||||
rte
|
||||
/* This instruction changes register bank! */
|
||||
stc ssr, r1
|
||||
ldc r1, sr
|
||||
|
||||
mov.l 1f, r0
|
||||
jmp @r0
|
||||
nop
|
||||
|
||||
.zero 14
|
||||
.zero 10
|
||||
|
||||
1: .long _gint_dma_ae
|
||||
1: .long _gint_panic
|
||||
2: .long 0x1020
|
||||
|
|
Loading…
Reference in New Issue