From 3973ce57dfe399357e702cd76d02adc05f605b35 Mon Sep 17 00:00:00 2001 From: Wolfvak Date: Thu, 23 Jul 2020 20:33:46 -0300 Subject: [PATCH] revert back to using Thumb code for the ARM9 binary leads to better density and therefore much smaller FIRM sizes --- arm11/Makefile | 2 +- arm9/Makefile | 2 +- arm9/source/system/xrq.c | 20 ++- common/arm.c | 230 ++++++++++++++++++++++++++++++++++ common/arm.h | 259 ++++++--------------------------------- common/common.h | 5 +- 6 files changed, 281 insertions(+), 237 deletions(-) create mode 100644 common/arm.c diff --git a/arm11/Makefile b/arm11/Makefile index 2f321a1..3528587 100644 --- a/arm11/Makefile +++ b/arm11/Makefile @@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR)) SOURCE := source BUILD := build -SUBARCH := -D$(PROCESSOR) -marm -march=armv6k -mtune=mpcore -mfloat-abi=hard -mfpu=vfpv2 -mtp=soft +SUBARCH := -D$(PROCESSOR) -march=armv6k -mtune=mpcore -marm -mfloat-abi=hard -mfpu=vfpv2 -mtp=soft INCDIRS := source INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)") diff --git a/arm9/Makefile b/arm9/Makefile index e9487f0..0a5e2c5 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR)) SOURCE := source BUILD := build -SUBARCH := -D$(PROCESSOR) -marm -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mno-thumb-interwork +SUBARCH := -D$(PROCESSOR) -march=armv5te -mtune=arm946e-s -mthumb -mfloat-abi=soft INCDIRS := source source/common source/filesys source/crypto source/fatfs source/nand source/virtual source/game source/gamecart source/lodepng source/qrcodegen source/system source/utils INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)") diff --git a/arm9/source/system/xrq.c b/arm9/source/system/xrq.c index 18a3f55..f224be0 100644 --- a/arm9/source/system/xrq.c +++ b/arm9/source/system/xrq.c @@ -60,7 +60,7 @@ XRQ_DUMPDATAFUNC(u16, 4) XRQ_DUMPDATAFUNC(u32, 8) -const char *XRQ_Name[] = { +static const char *XRQ_Name[] = { "Reset", "Undefined", "SWI", "Prefetch Abort", "Data Abort", "Reserved", "IRQ", "FIQ" }; @@ -80,10 +80,9 @@ void XRQ_DumpRegisters(u32 xrq, u32 *regs) wstr += sprintf(wstr, "20%02lX-%02lX-%02lX %02lX:%02lX:%02lX\n \n", (u32) dstime.bcd_Y, (u32) dstime.bcd_M, (u32) dstime.bcd_D, (u32) dstime.bcd_h, (u32) dstime.bcd_m, (u32) dstime.bcd_s); - for (int i = 0; i < 8; i++) { - int i_ = i*2; + for (int i = 0; i < 16; i += 2) { wstr += sprintf(wstr, - "R%02d: %08lX | R%02d: %08lX\n", i_, regs[i_], i_+1, regs[i_+1]); + "R%02d: %08lX | R%02d: %08lX\n", i, regs[i], i+1, regs[i+1]); } wstr += sprintf(wstr, "CPSR: %08lX\n\n", regs[16]); @@ -93,7 +92,7 @@ void XRQ_DumpRegisters(u32 xrq, u32 *regs) u32 draw_x = (SCREEN_WIDTH_MAIN - draw_width) / 2; u32 draw_y = (SCREEN_HEIGHT - draw_height) / 2; u32 draw_y_upd = draw_y + draw_height - 10; - + ClearScreen(MAIN_SCREEN, COLOR_STD_BG); DrawStringF(MAIN_SCREEN, draw_x, draw_y, COLOR_STD_FONT, COLOR_STD_BG, dumpstr); @@ -110,11 +109,11 @@ void XRQ_DumpRegisters(u32 xrq, u32 *regs) if (pc_dumpable(pc, &pc_lower, &pc_upper)) { wstr += sprintf(wstr, "Code:\n"); wstr += XRQ_DumpData_u32(wstr, pc_lower, pc_upper); - /*if (regs[16] & SR_THUMB) { // no need to take Thumb code into account + if (regs[16] & SR_THUMB) { // need to take Thumb code into account wstr += XRQ_DumpData_u16(wstr, pc-PC_DUMPRAD, pc+PC_DUMPRAD); } else { wstr += XRQ_DumpData_u32(wstr, pc-PC_DUMPRAD, pc+PC_DUMPRAD); - }*/ + } } /* Draw QR Code */ @@ -127,7 +126,6 @@ void XRQ_DumpRegisters(u32 xrq, u32 *regs) DrawQrCode(ALT_SCREEN, qrcode); } - /* Reinitialize SD */ DrawStringF(MAIN_SCREEN, draw_x, draw_y_upd, COLOR_STD_FONT, COLOR_STD_BG, "%-29.29s", "Reinitializing SD card..."); @@ -145,18 +143,16 @@ void XRQ_DumpRegisters(u32 xrq, u32 *regs) DrawStringF(MAIN_SCREEN, draw_x, draw_y_upd, COLOR_STD_FONT, COLOR_STD_BG, "%-29.29s", "Dumping state to SD card..."); FileSetData(path, dumpstr, wstr - dumpstr, 0, true); - - + /* Deinit SD */ DeinitSDCardFS(); - + /* Done, wait for user power off */ DrawStringF(MAIN_SCREEN, draw_x, draw_y_upd, COLOR_STD_FONT, COLOR_STD_BG, "%-29.29s", "Press POWER to turn off"); while (!(InputWait(0) & BUTTON_POWER)); PowerOff(); - /* We will not return */ return; } diff --git a/common/arm.c b/common/arm.c new file mode 100644 index 0000000..37013a9 --- /dev/null +++ b/common/arm.c @@ -0,0 +1,230 @@ +#include + +#define ARM_TARGET __attribute__((noinline, target("arm"))) + +#ifdef ARM11 + #define ARM_CPS(m) asm_v("CPS " #m) + #define ARM_CPSID(m) asm_v("CPSID " #m) + #define ARM_CPSIE(m) asm_v("CPSIE " #m) + + /* + * An Instruction Synchronization Barrier (ISB) flushes the pipeline in the processor + * so that all instructions following the ISB are fetched from cache or memory + * after the ISB has been completed. + */ + void ARM_TARGET ARM_ISB(void) { + ARM_MCR(p15, 0, 0, c7, c5, 4); + } + + /* + * A Data Memory Barrier (DMB) ensures that all explicit memory accesses before + * the DMB instruction complete before any explicit memory accesses after the DMB instruction start. + */ + void ARM_TARGET ARM_DMB(void) { + ARM_MCR(p15, 0, 0, c7, c10, 5); + } + + /* Wait For Interrupt */ + void ARM_TARGET ARM_WFI(void) { + asm_v("wfi\n\t"); + } + + /* Wait For Event */ + void ARM_TARGET ARM_WFE(void) { + asm_v("wfe\n\t"); + } + + /* Send Event */ + void ARM_TARGET ARM_SEV(void) { + asm_v("sev\n\t"); + } + + /* Auxiliary Control Registers */ + u32 ARM_TARGET ARM_GetACR(void) { + u32 acr; + ARM_MRC(p15, 0, acr, c1, c0, 1); + return acr; + } + + void ARM_TARGET ARM_SetACR(u32 acr) { + ARM_MCR(p15, 0, acr, c1, c0, 1); + } +#endif + + +/* + * A Data Synchronization Barrier (DSB) completes when all + * instructions before this instruction complete. + */ +void ARM_TARGET ARM_DSB(void) { + ARM_MCR(p15, 0, 0, c7, c10, 4); +} + + +/* Control Registers */ +u32 ARM_TARGET ARM_GetCR(void) { + u32 cr; + ARM_MRC(p15, 0, cr, c1, c0, 0); + return cr; +} + +void ARM_TARGET ARM_SetCR(u32 cr) { + ARM_MCR(p15, 0, cr, c1, c0, 0); +} + +/* Thread ID Registers */ +u32 ARM_TARGET ARM_GetTID(void) { + u32 tid; + #ifdef ARM9 + ARM_MRC(p15, 0, tid, c13, c0, 1); + #else + ARM_MRC(p15, 0, tid, c13, c0, 4); + #endif + return tid; +} + +void ARM_TARGET ARM_SetTID(u32 tid) { + #ifdef ARM9 + ARM_MCR(p15, 0, tid, c13, c0, 1); + #else + ARM_MCR(p15, 0, tid, c13, c0, 4); + #endif +} + +/* CPU ID */ +u32 ARM_TARGET ARM_CoreID(void) { + u32 id; + #ifdef ARM9 + id = 0; + #else + ARM_MRC(p15, 0, id, c0, c0, 5); + #endif + return id & 3; +} + +/* Status Register */ +u32 ARM_TARGET ARM_GetCPSR(void) { + u32 sr; + ARM_MRS(sr, cpsr); + return sr; +} + +void ARM_TARGET ARM_SetCPSR_c(u32 sr) { + ARM_MSR(cpsr_c, sr); +} + +void ARM_TARGET ARM_DisableInterrupts(void) { + #ifdef ARM9 + ARM_SetCPSR_c(ARM_GetCPSR() | SR_NOINT); + #else + ARM_CPSID(if); + #endif +} + +void ARM_TARGET ARM_EnableInterrupts(void) { + #ifdef ARM9 + ARM_SetCPSR_c(ARM_GetCPSR() & ~SR_NOINT); + #else + ARM_CPSIE(if); + #endif +} + +u32 ARM_TARGET ARM_EnterCritical(void) { + u32 stat = ARM_GetCPSR(); + ARM_DisableInterrupts(); + return stat & SR_NOINT; +} + +void ARM_TARGET ARM_LeaveCritical(u32 stat) { + ARM_SetCPSR_c((ARM_GetCPSR() & ~SR_NOINT) | stat); +} + + +/* Cache functions */ +void ARM_TARGET ARM_InvIC(void) { + #ifdef ARM9 + ARM_MCR(p15, 0, 0, c7, c5, 0); + #else + ARM_MCR(p15, 0, 0, c7, c7, 0); + #endif +} + +void ARM_TARGET ARM_InvIC_Range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + #ifdef ARM9 + ARM_MCR(p15, 0, addr, c7, c5, 1); + #else + ARM_MCR(p15, 0, addr, c7, c7, 1); + #endif + addr += 0x20; + } while(len--); +} + +void ARM_TARGET ARM_InvDC(void) { + ARM_MCR(p15, 0, 0, c7, c6, 0); +} + +void ARM_TARGET ARM_InvDC_Range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + ARM_MCR(p15, 0, addr, c7, c6, 1); + addr += 0x20; + } while(len--); +} + +void ARM_TARGET ARM_WbDC(void) { + #ifdef ARM9 + u32 seg = 0, ind; + do { + ind = 0; + do { + ARM_MCR(p15, 0, seg | ind, c7, c10, 2); + ind += 0x20; + } while(ind < 0x400); + seg += 0x40000000; + } while(seg != 0); + #else + ARM_MCR(p15, 0, 0, c7, c10, 0); + #endif +} + +void ARM_TARGET ARM_WbDC_Range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + ARM_MCR(p15, 0, addr, c7, c10, 1); + addr += 0x20; + } while(len--); +} + +void ARM_TARGET ARM_WbInvDC(void) { + #ifdef ARM9 + u32 seg = 0, ind; + do { + ind = 0; + do { + ARM_MCR(p15, 0, seg | ind, c7, c14, 2); + ind += 0x20; + } while(ind < 0x400); + seg += 0x40000000; + } while(seg != 0); + #else + ARM_MCR(p15, 0, 0, c7, c14, 0); + #endif +} + +void ARM_TARGET ARM_WbInvDC_Range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + ARM_MCR(p15, 0, addr, c7, c14, 1); + addr += 0x20; + } while(len--); +} diff --git a/common/arm.h b/common/arm.h index 53843ed..778e6a0 100644 --- a/common/arm.h +++ b/common/arm.h @@ -69,12 +69,7 @@ #ifndef __ASSEMBLER__ -/* ARM Private Memory Region */ -#ifdef ARM11 - #define REG_ARM_PMR(off, type) ((volatile type*)(0x17E00000 + (off))) -#endif - - +// only accessible from ARM mode #define ARM_MCR(cp, op1, reg, crn, crm, op2) asm_v( \ "MCR " #cp ", " #op1 ", %[R], " #crn ", " #crm ", " #op2 "\n\t" \ :: [R] "r"(reg) : "memory","cc") @@ -91,232 +86,52 @@ "MRS %[R], " #cp "\n\t" \ : [R] "=r"(reg) :: "memory","cc") + +/* ARM Private Memory Region */ #ifdef ARM11 - #define ARM_CPS(m) asm_v("CPS " #m) - #define ARM_CPSID(m) asm_v("CPSID " #m) - #define ARM_CPSIE(m) asm_v("CPSIE " #m) + #define REG_ARM_PMR(off, type) ((volatile type*)(0x17E00000 + (off))) - /* - * An Instruction Synchronization Barrier (ISB) flushes the pipeline in the processor - * so that all instructions following the ISB are fetched from cache or memory - * after the ISB has been completed. - */ - static inline void ARM_ISB(void) { - ARM_MCR(p15, 0, 0, c7, c5, 4); - } - - /* - * A Data Memory Barrier (DMB) ensures that all explicit memory accesses before - * the DMB instruction complete before any explicit memory accesses after the DMB instruction start. - */ - static inline void ARM_DMB(void) { - ARM_MCR(p15, 0, 0, c7, c10, 5); - } - - /* Wait For Interrupt */ - static inline void ARM_WFI(void) { - asm_v("wfi\n\t"); - } - - /* Wait For Event */ - static inline void ARM_WFE(void) { - asm_v("wfe\n\t"); - } - - /* Send Event */ - static inline void ARM_SEV(void) { - asm_v("sev\n\t"); - } - - /* Auxiliary Control Registers */ - static inline u32 ARM_GetACR(void) { - u32 acr; - ARM_MRC(p15, 0, acr, c1, c0, 1); - return acr; - } - - static inline void ARM_SetACR(u32 acr) { - ARM_MCR(p15, 0, acr, c1, c0, 1); - } + void ARM_ISB(void); + void ARM_DMB(void); + void ARM_WFI(void); + void ARM_WFE(void); + void ARM_SEV(void); + u32 ARM_GetACR(void); + void ARM_SetACR(u32 acr); #endif +// Data Synchronization Barrier +void ARM_DSB(void); -/* - * A Data Synchronization Barrier (DSB) completes when all - * instructions before this instruction complete. - */ -static inline void ARM_DSB(void) { - ARM_MCR(p15, 0, 0, c7, c10, 4); -} +// Get and set Control Register +u32 ARM_GetCR(void); +void ARM_SetCR(u32 cr); +// Get and set Thread ID +u32 ARM_GetTID(void); +void ARM_SetTID(u32 tid); -/* Control Registers */ -static inline u32 ARM_GetCR(void) { - u32 cr; - ARM_MRC(p15, 0, cr, c1, c0, 0); - return cr; -} +// Core ID (not CPU ID) +u32 ARM_CoreID(void); -static inline void ARM_SetCR(u32 cr) { - ARM_MCR(p15, 0, cr, c1, c0, 0); -} +// Get and set CPSR +u32 ARM_GetCPSR(void); +void ARM_SetCPSR_c(u32 sr); -/* Thread ID Registers */ -static inline u32 ARM_GetTID(void) { - u32 pid; - #ifdef ARM9 - ARM_MRC(p15, 0, pid, c13, c0, 1); - #else - ARM_MRC(p15, 0, pid, c13, c0, 4); - #endif - return pid; -} +// Manage interrupts +void ARM_DisableInterrupts(void); +void ARM_EnableInterrupts(void); +u32 ARM_EnterCritical(void); +void ARM_LeaveCritical(u32 stat); -static inline void ARM_SetTID(u32 pid) { - #ifdef ARM9 - ARM_MCR(p15, 0, pid, c13, c0, 1); - #else - ARM_MCR(p15, 0, pid, c13, c0, 4); - #endif -} - -/* CPU ID */ -static inline u32 ARM_CoreID(void) { - u32 id; - #ifdef ARM9 - id = 0; - #else - ARM_MRC(p15, 0, id, c0, c0, 5); - #endif - return id & 3; -} - -/* Status Register */ -static inline u32 ARM_GetCPSR(void) { - u32 sr; - ARM_MRS(sr, cpsr); - return sr; -} - -static inline void ARM_SetCPSR_c(u32 sr) { - ARM_MSR(cpsr_c, sr); -} - -static inline void ARM_DisableInterrupts(void) { - #ifdef ARM9 - ARM_SetCPSR_c(ARM_GetCPSR() | SR_NOINT); - #else - ARM_CPSID(if); - #endif -} - -static inline void ARM_EnableInterrupts(void) { - #ifdef ARM9 - ARM_SetCPSR_c(ARM_GetCPSR() & ~SR_NOINT); - #else - ARM_CPSIE(if); - #endif -} - -static inline u32 ARM_EnterCritical(void) { - u32 stat = ARM_GetCPSR(); - ARM_DisableInterrupts(); - return stat & SR_NOINT; -} - -static inline void ARM_LeaveCritical(u32 stat) { - ARM_SetCPSR_c((ARM_GetCPSR() & ~SR_NOINT) | stat); -} - - -/* Cache functions */ -static inline void ARM_InvIC(void) { - #ifdef ARM9 - ARM_MCR(p15, 0, 0, c7, c5, 0); - #else - ARM_MCR(p15, 0, 0, c7, c7, 0); - #endif -} - -static inline void ARM_InvIC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - #ifdef ARM9 - ARM_MCR(p15, 0, addr, c7, c5, 1); - #else - ARM_MCR(p15, 0, addr, c7, c7, 1); - #endif - addr += 0x20; - } while(len--); -} - -static inline void ARM_InvDC(void) { - ARM_MCR(p15, 0, 0, c7, c6, 0); -} - -static inline void ARM_InvDC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - ARM_MCR(p15, 0, addr, c7, c6, 1); - addr += 0x20; - } while(len--); -} - -static inline void ARM_WbDC(void) { - #ifdef ARM9 - u32 seg = 0, ind; - do { - ind = 0; - do { - ARM_MCR(p15, 0, seg | ind, c7, c10, 2); - ind += 0x20; - } while(ind < 0x400); - seg += 0x40000000; - } while(seg != 0); - #else - ARM_MCR(p15, 0, 0, c7, c10, 0); - #endif -} - -static inline void ARM_WbDC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - ARM_MCR(p15, 0, addr, c7, c10, 1); - addr += 0x20; - } while(len--); -} - -static inline void ARM_WbInvDC(void) { - #ifdef ARM9 - u32 seg = 0, ind; - do { - ind = 0; - do { - ARM_MCR(p15, 0, seg | ind, c7, c14, 2); - ind += 0x20; - } while(ind < 0x400); - seg += 0x40000000; - } while(seg != 0); - #else - ARM_MCR(p15, 0, 0, c7, c14, 0); - #endif -} - -static inline void ARM_WbInvDC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - ARM_MCR(p15, 0, addr, c7, c14, 1); - addr += 0x20; - } while(len--); -} +void ARM_InvIC(void); +void ARM_InvIC_Range(void *base, u32 len); +void ARM_InvDC(void); +void ARM_InvDC_Range(void *base, u32 len); +void ARM_WbDC(void); +void ARM_WbDC_Range(void *base, u32 len); +void ARM_WbInvDC(void); +void ARM_WbInvDC_Range(void *base, u32 len); static inline void ARM_BKPT(void) { __builtin_trap(); diff --git a/common/common.h b/common/common.h index 66fd697..9d02ddf 100755 --- a/common/common.h +++ b/common/common.h @@ -59,7 +59,10 @@ (!!(x) ? (void)0 : __builtin_trap()) static inline void waitClks(unsigned clk) { - asm_v("1: subs %0, %0, #2\n\tbne 1b\n\t":"=r"(clk)::"memory","cc"); + clk >>= 1; + while(clk--) { + asm_v("nop":::"memory", "cc"); + } } #define STATIC_ASSERT(...) \