mirror of
https://github.com/rvtr/twl_wrapsdk.git
synced 2025-06-18 14:25:43 -04:00
275 lines
9.1 KiB
C
275 lines
9.1 KiB
C
/*---------------------------------------------------------------------------*
|
|
Project: TwlSDK - library - init
|
|
File: crt0.c
|
|
|
|
Copyright 2007 Nintendo. All rights reserved.
|
|
|
|
These coded instructions, statements, and computer programs contain
|
|
proprietary information of Nintendo of America Inc. and/or Nintendo
|
|
Company Ltd., and are protected by Federal copyright law. They may
|
|
not be disclosed to third parties or copied or duplicated in any form,
|
|
in whole or in part, without the prior written consent of Nintendo.
|
|
|
|
$Log: $
|
|
$NoKeywords: $
|
|
*---------------------------------------------------------------------------*/
|
|
#include <nitro/code32.h>
|
|
#include <twl.h>
|
|
|
|
extern void NitroSpMain(void);
|
|
extern void OS_IrqHandler(void);
|
|
extern void *const _start_ModuleParams[];
|
|
static void do_autoload(void);
|
|
static void detect_main_memory_size(void);
|
|
void _start(void);
|
|
void _start_AutoloadDoneCallback(void *argv[]);
|
|
|
|
extern void __call_static_initializers(void);
|
|
extern void _fp_init(void);
|
|
|
|
// from LCF
|
|
extern void SDK_IRQ_STACKSIZE(void);
|
|
extern void SDK_STATIC_BSS_START(void); // static bss start address
|
|
extern void SDK_STATIC_BSS_END(void); // static bss start address
|
|
extern void SDK_AUTOLOAD_START(void); // autoload data will start from here
|
|
extern void SDK_AUTOLOAD_LIST(void); // start pointer to autoload information
|
|
extern void SDK_AUTOLOAD_LIST_END(void); // end pointer to autoload information
|
|
|
|
// volatile parameters in IPL's work memory
|
|
#define IPL_PARAM_CARD_ROM_HEADER 0x023FE940
|
|
#define IPL_PARAM_DOWNLOAD_PARAMETER 0x023FE904
|
|
|
|
//---- IRQ+SVC stack size in boot (this area is not cleared)
|
|
#define INITi_Initial_Stack 0x100
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: _start
|
|
|
|
Description: Start up
|
|
|
|
Arguments: None
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
SDK_WEAK_SYMBOL asm void _start( void )
|
|
{
|
|
//---- set IME = 0
|
|
// ( use that LSB of HW_REG_BASE equal to 0 )
|
|
mov r12, #HW_REG_BASE
|
|
str r12, [r12, #REG_IME_OFFSET]
|
|
|
|
//---- clear memory
|
|
// private-WRAM (except program area)
|
|
ldr r1, =SDK_STATIC_BSS_END // r1= max(__bss_end__, #HW_PRV_WRAM)
|
|
mov r0, #HW_PRV_WRAM
|
|
cmp r0, r1
|
|
movpl r1, r0
|
|
ldr r2, =HW_PRV_WRAM_END - INITi_Initial_Stack
|
|
// r2= WRAM_END - r1 - svc+irq stack in boot
|
|
mov r0, #0 // r0= clear value
|
|
@1:
|
|
cmp r1, r2
|
|
stmltia r1!, {r0}
|
|
blt @1
|
|
|
|
//---- initialize stack pointer
|
|
// SVC mode
|
|
mov r0, #HW_PSR_SVC_MODE
|
|
msr cpsr_c, r0
|
|
ldr sp, =HW_PRV_WRAM_SVC_STACK_END
|
|
|
|
// IRQ mode
|
|
mov r0, #HW_PSR_IRQ_MODE
|
|
msr cpsr_c, r0
|
|
ldr r0, =HW_PRV_WRAM_IRQ_STACK_END
|
|
mov sp, r0
|
|
|
|
// System mode
|
|
ldr r1, =SDK_IRQ_STACKSIZE
|
|
sub r1, r0, r1
|
|
mov r0, #HW_PSR_SYS_MODE
|
|
msr cpsr_csfx, r0
|
|
sub sp, r1, #4 // 4byte for stack check code
|
|
|
|
// move parameters from IPL's work memory to shared area
|
|
ldr r0, =IPL_PARAM_CARD_ROM_HEADER
|
|
ldr r1, =HW_CARD_ROM_HEADER
|
|
add r2, r1, #HW_CARD_ROM_HEADER_SIZE
|
|
@1_1:
|
|
ldr r3, [r0], #4
|
|
str r3, [r1], #4
|
|
cmp r1, r2
|
|
bmi @1_1
|
|
ldr r0, =IPL_PARAM_DOWNLOAD_PARAMETER
|
|
add r2, r1, #HW_DOWNLOAD_PARAMETER_SIZE
|
|
@1_2:
|
|
ldr r3, [r0], #4
|
|
str r3, [r1], #4
|
|
cmp r1, r2
|
|
bmi @1_2
|
|
|
|
//---- load autoload block and initialize bss
|
|
// bl do_autoload
|
|
|
|
//---- fill static static bss with 0
|
|
ldr r0, =_start_ModuleParams
|
|
ldr r1, [r0, #12] // BSS segment start
|
|
ldr r2, [r0, #16] // BSS segment end
|
|
mov r0, #0
|
|
@2: cmp r1, r2
|
|
strcc r0, [r1], #4
|
|
bcc @2
|
|
|
|
//---- detect main memory size
|
|
bl detect_main_memory_size
|
|
|
|
//---- set interrupt vector
|
|
ldr r1, =HW_INTR_VECTOR_BUF
|
|
ldr r0, =OS_IrqHandler
|
|
str r0, [r1, #0]
|
|
|
|
#ifndef SDK_NOINIT
|
|
//---- for C++
|
|
bl _fp_init
|
|
bl NitroSpStartUp
|
|
bl __call_static_initializers
|
|
#endif
|
|
|
|
//---- start (to 16bit code)
|
|
ldr r1, =NitroSpMain
|
|
ldr lr, =HW_RESET_VECTOR
|
|
|
|
bx r1
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: do_autoload
|
|
|
|
Description: put autoload data block according to autoload information,
|
|
and clear static bss by filling with 0.
|
|
|
|
Arguments: None.
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
void *const _start_ModuleParams[] = {
|
|
(void *)SDK_AUTOLOAD_LIST,
|
|
(void *)SDK_AUTOLOAD_LIST_END,
|
|
(void *)SDK_AUTOLOAD_START,
|
|
(void *)SDK_STATIC_BSS_START,
|
|
(void *)SDK_STATIC_BSS_END,
|
|
};
|
|
|
|
static asm void do_autoload( void )
|
|
{
|
|
#define ptable r0
|
|
#define infop r1
|
|
#define infop_end r2
|
|
#define src r3
|
|
#define dest r4
|
|
#define dest_size r5
|
|
#define dest_end r6
|
|
#define tmp r7
|
|
|
|
ldr ptable, =_start_ModuleParams
|
|
ldr infop, [ptable, #0] // r1 = start pointer to autoload_info
|
|
ldr infop_end, [ptable, #4] // r2 = end pointer to autoload_info
|
|
ldr src, [ptable, #8] // r3 = autoload block
|
|
|
|
//---- put each blocks according to autoload information
|
|
@2:
|
|
cmp infop, infop_end // reach to end?
|
|
beq @skipout
|
|
|
|
ldr dest, [infop], #4 // dest
|
|
ldr dest_size, [infop], #4 // size
|
|
add dest_end, dest, dest_size // dest_end
|
|
@1:
|
|
cmp dest, dest_end
|
|
ldrmi tmp, [src], #4 // [dest++] <- [src++]
|
|
strmi tmp, [dest], #4
|
|
bmi @1
|
|
|
|
//---- fill bss with 0
|
|
ldr dest_size, [infop], #4 // size
|
|
add dest_end, dest, dest_size // bss end
|
|
mov tmp, #0
|
|
@4:
|
|
cmp dest, dest_end
|
|
strcc tmp, [dest], #4
|
|
bcc @4
|
|
beq @2
|
|
|
|
@skipout:
|
|
// r0 = autoload_params
|
|
b _start_AutoloadDoneCallback // Jump into the callback
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: _start_AutoloadDoneCallback
|
|
|
|
Description: hook for end of autoload (This is dummy target for DEBUGGER)
|
|
|
|
Arguments: argv: pointer for autoload parameters
|
|
argv[0] = SDK_AUTOLOAD_LIST
|
|
argv[1] = SDK_AUTOLOAD_LIST_END
|
|
argv[2] = SDK_AUTOLOAD_START
|
|
argv[3] = SDK_STATIC_BSS_START
|
|
argv[4] = SDK_STATIC_BSS_END
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
SDK_WEAK_SYMBOL asm void _start_AutoloadDoneCallback( void* argv[] )
|
|
{
|
|
bx lr
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: detect_main_memory_size
|
|
|
|
Description: detect main memory size.
|
|
result is written into (u32*)HW_MMEMCHECKER_SUB.
|
|
value is [OS_CONSOLE_SIZE_4MB|OS_CONSOLE_SIZE_8MB]
|
|
|
|
Arguments: None.
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
#define OSi_IMAGE_DIFFERENCE 0x400000
|
|
|
|
static asm void detect_main_memory_size( void )
|
|
{
|
|
mov r0, #OS_CONSOLE_SIZE_4MB
|
|
mov r1, #0
|
|
|
|
ldr r2, =HW_MMEMCHECKER_SUB
|
|
sub r3, r2, #OSi_IMAGE_DIFFERENCE
|
|
@1:
|
|
strh r1, [r2]
|
|
ldrh r12, [r3]
|
|
cmp r1, r12
|
|
|
|
movne r0, #OS_CONSOLE_SIZE_8MB
|
|
bne @2
|
|
|
|
add r1, r1, #1
|
|
cmp r1, #2 // check 2 loop
|
|
bne @1
|
|
@2:
|
|
strh r0, [r2]
|
|
bx lr
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
Name: NitroSpStartUp
|
|
|
|
Description: hook for user start up
|
|
|
|
Arguments: None
|
|
|
|
Returns: None.
|
|
*---------------------------------------------------------------------------*/
|
|
SDK_WEAK_SYMBOL void NitroSpStartUp(void)
|
|
{
|
|
}
|