diff --git a/README.md b/README.md index 74e305d..f2e3a96 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Currently, this includes: * A stripped-down version of the [Grisu2b floating-point representation algorithm](https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf) with α=-59 and γ=-56, by Florian Loitsch. See `src/3rdparty/grisu2b_59_56/README` - for details [the original code here](https://drive.google.com/open?id=0BwvYOx00EwKmejFIMjRORTFLcTA). + for details, and [the original code here](https://drive.google.com/open?id=0BwvYOx00EwKmejFIMjRORTFLcTA). ## Programming interface diff --git a/TODO b/TODO index 744e586..d904b9b 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,8 @@ Extensions on existing code: +* kernel: better restore to userspace before panic (ensure BL=0 IMASK=0) * kernel: check if cpu_setVBR() really needs to be perma-mapped -* stdio: support %f in printf * project: add license file * kernel: group linker script symbols in a single header file -* kernel: be consistent about *tlb_mapped_memory() in hw_detect() * bopti: try to display fullscreen images with TLB access + DMA on fxcg50 * dma: fx9860g support (need to switch it on and update the Makefile) * core: try to leave add-in without reset in case of panic @@ -12,7 +11,6 @@ Extensions on existing code: * core: review forgotten globals and MPU addresses not in * core: run destructors when a task-switch results in leaving the app * core rtc: use qdiv10 to massively improve division performance -* topti: let the font specify letter and word spacing Future directions. * A complete file system abstraction diff --git a/fx9860g.ld b/fx9860g.ld index 9a37ef7..4e65efd 100644 --- a/fx9860g.ld +++ b/fx9860g.ld @@ -16,12 +16,15 @@ MEMORY /* Userspace mapping of the add-in (G1A header takes 0x200 bytes) */ rom (rx): o = 0x00300200, l = 500k - /* User RAM is mapped at 0x08100000 through MMU; 8k on SH3, 32k on SH4. - Currently gint provides access to 8k, with three blocks: + /* User RAM is mapped at 0x08100000 through MMU; usually 8k on SH3, 32k + on SH4. This script exposes only 6k to the user, reserving: * 0x200 bytes for text accessed without the TLB when SR.BL=1, linked into the rram region below, then loaded dynamically - * 6k for user content - * 0x600 bytes for the VBR space, also without MMU */ + * 0x600 bytes for the VBR space, also without MMU + On SH3, the VBR space consumes these 0x600 bytes. On SH4, it spans + 0x1100 bytes near the end of the user RAM, which is larger; the 6k + left for the user are honored in both cases. Unused memory from the + exposed 6k and non-exposed memory is available through malloc(). */ ram (rw): o = 0x08100200, l = 6k /* This region represents the first block of user RAM. Linker arranges @@ -172,6 +175,9 @@ SECTIONS *(.gint.bss .gint.bss.sh3) . = ALIGN(16); + + /* End of user RAM */ + _euram = . ; } > ram :NONE _sgbss = SIZEOF(.gint.bss); diff --git a/fxcg50.ld b/fxcg50.ld index 5ce4b1e..459f124 100644 --- a/fxcg50.ld +++ b/fxcg50.ld @@ -179,6 +179,9 @@ SECTIONS .gint.bss (NOLOAD) : { *(.gint.bss) . = ALIGN(16); + + /* End of user RAM */ + _euram = . ; } > ram :NONE _sgbss = SIZEOF(.gint.bss); diff --git a/src/kernel/cpu.h b/src/kernel/cpu.h index 2e94e1f..f138110 100644 --- a/src/kernel/cpu.h +++ b/src/kernel/cpu.h @@ -24,6 +24,9 @@ extern uint32_t (*cpu_setVBR)(uint32_t vbr, void (*conf_intc)(int arg), int arg); +/* cpu_getVBR(): Query the current VBR address */ +uint32_t cpu_getVBR(void); + /* cpu_setCPUOPM(): Change the CPU Operation Mode register Updates the CPU Operation Mode with the specified settings, then performs a diff --git a/src/kernel/cpu.s b/src/kernel/cpu.s index 54d06fc..7e63ad4 100644 --- a/src/kernel/cpu.s +++ b/src/kernel/cpu.s @@ -2,7 +2,8 @@ ** gint:core:vbr - Assembler-level VBR management */ -.global _cpu_setVBR +.global _cpu_getVBR +.global _cpu_setVBR .global _cpu_setCPUOPM .global _cpu_getCPUOPM .global _cpu_getSR @@ -52,6 +53,12 @@ _cpu_setVBR: .text +/* cpu_getVBR(): Query the current VBR address */ +_cpu_getVBR: + stc vbr, r0 + rts + nop + /* cpu_setCPUOPM(): Change the CPU Operation Mode register */ _cpu_setCPUOPM: /* Set CPUOPM as requested */ diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 14f9b7b..fc0b1fd 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -127,9 +127,17 @@ static void kinit_cpu(void) void kinit(void) { #ifdef FX9860G - /* VBR is loaded 0x600 bytes before end of the user RAM (0x100 bytes at - the start of the VBR space are unused) */ - gint_ctx.VBR = (uint32_t)mmu_uram() + 0x1a00 - 0x100; + /* VBR is loaded at the end of the user RAM. */ + uint32_t uram_end = (uint32_t)mmu_uram() + mmu_uram_size(); + /* On SH4, stack is at the end of the region, leave 8k */ + if(isSH4()) uram_end -= 0x2000; + /* VBR size differs with models. On SH3, only 0x600 bytes are used due + to the compact scheme. On SH4, 0x1100 bytes are needed to cover the + expanded region. */ + uram_end -= (isSH3() ? 0x600 : 0x1100); + + /* There are 0x100 unused bytes at the start of the VBR area */ + gint_ctx.VBR = uram_end - 0x100; #endif #ifdef FXCG50 @@ -191,6 +199,12 @@ void *gint_inthandler(int event_code, const void *handler, size_t size) if(event_code < 0x400) return NULL; event_code &= ~0x1f; + /* Prevent writing beyond the end of the VBR space on SH4. Using code + 0xfc0 into the interrupt handler space (which starts 0x540 bytes + into VBR-reserved memory) would reach byte 0x540 + 0xfc0 - 0x400 = + 0x1100, which is out of gint's reserved VBR area. */ + if(isSH4() && event_code + size > 0xfc0) return NULL; + /* On SH3, make VBR compact. Use this offset specified in the VBR map above to avoid gaps */ if(isSH3())