twl_wrapsdk/build/libraries/init/ARM7/crt0.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)
{
}