gint/src/core/exch.c

139 lines
3.9 KiB
C

#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_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;
uint32_t PC;
__asm__("stc spc, %0" : "=r"(PC));
dfont(NULL);
dclear(C_WHITE);
#ifdef FX9860G
dtext(1, 0, "Exception! (SysERROR)");
for(int i = 0; i < 32; i++) gint_vram[i] = ~gint_vram[i];
char const *name = "";
if(code == 0x040) name = "TLB miss read";
if(code == 0x060) name = "TLB miss write";
if(code == 0x0e0) name = "Read address error";
if(code == 0x100) name = "Write address error";
if(code == 0x160) name = "Unconditional trap";
if(code == 0x180) name = "Illegal instruction";
if(code == 0x1a0) name = "Illegal delay slot";
/* Custom gint codes for convenience */
if(code == 0x1020) name = "DMA address error";
if(code == 0x1040) name = "Add-in too large";
if(name[0]) dtext(1, 9, name);
else dprint(1, 9, "%03x", code);
dprint(1, 17, " PC :%08x", PC);
dprint(1, 25, "TEA :%08x", TEA);
dprint(1, 33, "TRA :%08x", TRA);
dtext(1, 49, "The add-in crashed.");
dtext(1, 57, "Please reset the calc");
#endif
#ifdef FXCG50
dtext(6, 3, "An exception occured! (System ERROR)");
uint32_t *long_vram = (void *)gint_vram;
for(int i = 0; i < 198 * 16; i++) long_vram[i] = ~long_vram[i];
char const *name = "";
if(code == 0x040) name = "TLB miss (nonexisting address) on read";
if(code == 0x060) name = "TLB miss (nonexisting address) on write";
if(code == 0x0e0) name = "Read address error (probably alignment)";
if(code == 0x100) name = "Write address error (probably alignment)";
if(code == 0x160) name = "Unconditional trap";
if(code == 0x180) name = "Illegal instruction";
if(code == 0x1a0) name = "Illegal delay slot instruction";
/* Custom gint codes for convenience */
if(code == 0x1020) name = "DMA address error";
if(code == 0x1040) name = "Add-in not fully mapped (too large)";
dprint(6, 25, "%03x %s", code, name);
dtext(6, 45, "PC");
dprint(38, 45, "= %08x", PC);
dtext(261, 45, "(Error location)");
dtext(6, 60, "TEA");
dprint(38, 60, "= %08x", TEA);
dtext(234, 60, "(Offending address)");
dtext(6, 75, "TRA");
dprint(38, 75, "= %#x", TRA);
dtext(281, 75, "(Trap number)");
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();
while(1) sleep();
}
/* 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)
{
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 ? panic : gint_default_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));
}