mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
kernel: compact VBR even more on SH3
This change moves interrupt handler from VBR + 0x640 to VBR + 0x200, in the gap between the exception and TLB miss handlers. This new scheme is not limited to VBR+0x200 .. VBR+0x400 as new large block numbers can be used to jump over the TLB miss handler and the interrupt handler entry points.
This commit is contained in:
parent
2b1f408cb4
commit
0aceb6f93e
4 changed files with 35 additions and 23 deletions
1
TODO
1
TODO
|
@ -6,6 +6,7 @@ Issues:
|
||||||
* #10 support fx-CG 20
|
* #10 support fx-CG 20
|
||||||
|
|
||||||
Extensions on existing code:
|
Extensions on existing code:
|
||||||
|
* tmu: make interrupt handlers more elegant
|
||||||
* bopti: try to display fullscreen images with TLB access + DMA on fxcg50
|
* bopti: try to display fullscreen images with TLB access + DMA on fxcg50
|
||||||
* gray: double-buffer gray settings and unify d* with g*
|
* gray: double-buffer gray settings and unify d* with g*
|
||||||
* topti: support unicode fonts
|
* topti: support unicode fonts
|
||||||
|
|
|
@ -20,9 +20,12 @@
|
||||||
|
|
||||||
The .gint.blocks section consists of blocks of 32 bytes intended for mapping
|
The .gint.blocks section consists of blocks of 32 bytes intended for mapping
|
||||||
into the VBR space (exception, TLB miss, and interrupt handlers). Each event
|
into the VBR space (exception, TLB miss, and interrupt handlers). Each event
|
||||||
gate is linearly associated with a block number:
|
gate is linearly associated with a block number on SH4:
|
||||||
|
|
||||||
block_id = (event_code - 0x380) / 0x20
|
block_id = (event_code - 0x3c0) / 0x20
|
||||||
|
|
||||||
|
and associated with a compact block number on SH3 through a table (to ensure
|
||||||
|
that blocks are consecutive in memory).
|
||||||
|
|
||||||
This file provides entry points; drivers may provide their own interrupt
|
This file provides entry points; drivers may provide their own interrupt
|
||||||
handlers, and store them in the .gint.blocks section for consistency. They
|
handlers, and store them in the .gint.blocks section for consistency. They
|
||||||
|
@ -32,8 +35,8 @@
|
||||||
- It is possible to map MPU-specific blocks at runtime, to avoid checking
|
- It is possible to map MPU-specific blocks at runtime, to avoid checking
|
||||||
the MPU each time an interrupt is handled;
|
the MPU each time an interrupt is handled;
|
||||||
- However, the blocks can only rely on relative displacements or cross-
|
- However, the blocks can only rely on relative displacements or cross-
|
||||||
references if their relative order is known and heeded for. A good example
|
references if their relative order is known and heeded for both on SH4 and
|
||||||
of this is the timer driver. Please be careful. */
|
SH3. A good example of this is the timer driver. Please be careful. */
|
||||||
|
|
||||||
/* SH7305-TYPE DEBUG INTERRUPT HANDLER - 26 BYTES */
|
/* SH7305-TYPE DEBUG INTERRUPT HANDLER - 26 BYTES */
|
||||||
|
|
||||||
|
@ -76,10 +79,11 @@ _gint_inth_7305:
|
||||||
sub r1, r0
|
sub r1, r0
|
||||||
|
|
||||||
/* Add the distance to the first entry and jump as a subroutine */
|
/* Add the distance to the first entry and jump as a subroutine */
|
||||||
add #40, r0
|
add #(.first_entry - .jump_over), r0
|
||||||
bsrf r0
|
bsrf r0
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
.jump_over:
|
||||||
/* Restore caller-saved registers */
|
/* Restore caller-saved registers */
|
||||||
lds.l @r15+, macl
|
lds.l @r15+, macl
|
||||||
lds.l @r15+, mach
|
lds.l @r15+, mach
|
||||||
|
@ -91,10 +95,11 @@ _gint_inth_7305:
|
||||||
|
|
||||||
.zero 24
|
.zero 24
|
||||||
1: .long 0xff000028
|
1: .long 0xff000028
|
||||||
|
.first_entry:
|
||||||
|
|
||||||
#ifdef FX9860G
|
#ifdef FX9860G
|
||||||
|
|
||||||
/* SH7705-TYPE INTERRUT HANDLER ENTRY - 52 BYTES */
|
/* SH7705-TYPE INTERRUT HANDLER ENTRY - 56 BYTES */
|
||||||
|
|
||||||
_gint_inth_7705:
|
_gint_inth_7705:
|
||||||
/* Save caller-saved registers as before */
|
/* Save caller-saved registers as before */
|
||||||
|
@ -107,18 +112,22 @@ _gint_inth_7705:
|
||||||
mov.l 1f, r0
|
mov.l 1f, r0
|
||||||
mov.l @r0, r0 /* r0 = old_code */
|
mov.l @r0, r0 /* r0 = old_code */
|
||||||
|
|
||||||
/* Translate the event code to SH4 format */
|
/* Translate the event code to compact format. The compact format is
|
||||||
|
laid out in a way that leaves no gap in the VBR space. Additionally,
|
||||||
|
gates are installed starting at VBR + 0x200 to save space. */
|
||||||
mov.l 2f, r2
|
mov.l 2f, r2
|
||||||
mov #-5, r3
|
mov #-5, r3
|
||||||
shld r3, r0 /* r0 = old_code >> 5 */
|
shld r3, r0 /* r0 = old_code >> 5 */
|
||||||
add #-32, r0 /* r0 = (old_code - 0x400) >> 5 */
|
add #-32, r0 /* r0 = (old_code - 0x400) >> 5 */
|
||||||
mov.b @(r0, r2), r0 /* r0 = (new_code - 0x400) >> 5 */
|
mov.b @(r0, r2), r0 /* r0 = gate_number */
|
||||||
|
add #16, r0 /* r0 = (0x200 + gate_number * 0x20) >> 5 */
|
||||||
mov #5, r3
|
mov #5, r3
|
||||||
shld r3, r0 /* r0 = new_code - 0x400 */
|
shld r3, r0 /* r0 = 0x200 + gate_number * 0x20 */
|
||||||
|
|
||||||
/* Add the distance between nop and the first entry, and jump */
|
/* Start at VBR + 0x200 and jump! */
|
||||||
add #32, r0
|
stc vbr, r1
|
||||||
bsrf r0
|
add r1, r0
|
||||||
|
jsr @r0
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* Restore saved registers */
|
/* Restore saved registers */
|
||||||
|
@ -130,7 +139,7 @@ _gint_inth_7705:
|
||||||
rte
|
rte
|
||||||
nop
|
nop
|
||||||
|
|
||||||
.zero 12
|
.zero 8
|
||||||
1: .long 0xa4000000 /* INTEVT2 register */
|
1: .long 0xa4000000 /* INTEVT2 register */
|
||||||
2: .long _inth_remap
|
2: .long _inth_remap
|
||||||
|
|
||||||
|
@ -148,13 +157,15 @@ _gint_inth_7705:
|
||||||
|
|
||||||
VBR offset SH3 events Description
|
VBR offset SH3 events Description
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
0x200 400 420 440 --- TMU0, TMU1, TMU2 and a helper
|
||||||
|
0x280 f00 --- --- --- ETMU0, ETMU1, ETMU2 and a helper
|
||||||
|
0x300 4a0 --- RTC Periodic Interrupt and a helper
|
||||||
|
----------------------------------------------------------------
|
||||||
0x600 --- --- Entry gate
|
0x600 --- --- Entry gate
|
||||||
0x640 400 420 440 --- TMU0, TMU1, TMU2 and a helper
|
|
||||||
0x6c0 f00 --- --- --- ETMU0, ETMU1, ETMU2 and a helper
|
|
||||||
0x740 4a0 --- RTC Periodic Interrupt and a helper
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
This represents 12 gates so the VBR space ends at VBR + 0x780. */
|
There is space for 16 gates at VBR + 0x200 so the VBR currently ends after
|
||||||
|
the interrupt entry gate at VBR + 0x640. */
|
||||||
|
|
||||||
_inth_remap:
|
_inth_remap:
|
||||||
.byte 0, 1, 2, 0xff, 0xff, 8, 0xff, 0xff
|
.byte 0, 1, 2, 0xff, 0xff, 8, 0xff, 0xff
|
||||||
|
|
|
@ -162,7 +162,7 @@ static const uint16_t sh3_vbr_map[] = {
|
||||||
/* gint_inthandler(): Install interrupt handlers */
|
/* gint_inthandler(): Install interrupt handlers */
|
||||||
void *gint_inthandler(int event_code, const void *handler, size_t size)
|
void *gint_inthandler(int event_code, const void *handler, size_t size)
|
||||||
{
|
{
|
||||||
int offset;
|
void *dest;
|
||||||
|
|
||||||
/* Normalize the event code */
|
/* Normalize the event code */
|
||||||
if(event_code < 0x400) return NULL;
|
if(event_code < 0x400) return NULL;
|
||||||
|
@ -183,16 +183,16 @@ void *gint_inthandler(int event_code, const void *handler, size_t size)
|
||||||
ie. the compact VBR scheme does not support this code */
|
ie. the compact VBR scheme does not support this code */
|
||||||
if(!sh3_vbr_map[index]) return NULL;
|
if(!sh3_vbr_map[index]) return NULL;
|
||||||
|
|
||||||
offset = index * 0x20;
|
/* Gates are placed starting at VBR + 0x200 to save space */
|
||||||
|
dest = (void *)gint_ctx.VBR + 0x200 + index * 0x20;
|
||||||
}
|
}
|
||||||
/* On SH4, just use the code as offset */
|
/* On SH4, just use the code as offset */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offset = event_code - 0x400;
|
/* 0x40 is the size of the entry gate */
|
||||||
|
dest = (void *)gint_ctx.VBR + 0x640 + (event_code - 0x400);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0x40 is the size of the entry gate */
|
|
||||||
void *dest = (void *)gint_ctx.VBR + 0x600 + 0x40 + offset;
|
|
||||||
return memcpy(dest, handler, size);
|
return memcpy(dest, handler, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -378,7 +378,7 @@ static void init(void)
|
||||||
/* On SH3, the ETMU handler is not at an offset of 0x840 (event
|
/* On SH3, the ETMU handler is not at an offset of 0x840 (event
|
||||||
code 0xc40) but at an offset of 0xc0 */
|
code 0xc40) but at an offset of 0xc0 */
|
||||||
uint32_t *etmu_offset = h + 16;
|
uint32_t *etmu_offset = h + 16;
|
||||||
if(isSH3()) *etmu_offset = *etmu_offset - 0x840 + 0xc0;
|
if(isSH3()) *etmu_offset = *etmu_offset - 0xe80 + 0x2c0;
|
||||||
|
|
||||||
uint32_t *data_id = h + 20;
|
uint32_t *data_id = h + 20;
|
||||||
*data_id = i;
|
*data_id = i;
|
||||||
|
|
Loading…
Reference in a new issue