/***************************************************************************** | |
* Copyright (c) 2001, 2002 Rowley Associates Limited. * | |
* * | |
* This file may be distributed under the terms of the License Agreement * | |
* provided with this software. * | |
* * | |
* THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE * | |
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * | |
*****************************************************************************/ | |
.section .init, "ax" | |
.code 32 | |
.align 0 | |
.weak _start | |
.global __start | |
.global __gccmain | |
.extern main | |
.extern exit | |
/***************************************************************************** | |
* Function : _start * | |
* Description : Main entry point and startup code for C system. * | |
*****************************************************************************/ | |
_start: | |
__start: | |
mrs r0, cpsr | |
bic r0, r0, #0x1F | |
/* Setup stacks */ | |
orr r1, r0, #0x1B /* Undefined mode */ | |
msr cpsr_cxsf, r1 | |
ldr sp, =__stack_und_end__ | |
orr r1, r0, #0x17 /* Abort mode */ | |
msr cpsr_cxsf, r1 | |
ldr sp, =__stack_abt_end__ | |
orr r1, r0, #0x12 /* IRQ mode */ | |
msr cpsr_cxsf, r1 | |
ldr sp, =__stack_irq_end__ | |
orr r1, r0, #0x11 /* FIQ mode */ | |
msr cpsr_cxsf, r1 | |
ldr sp, =__stack_fiq_end__ | |
orr r1, r0, #0x13 /* Supervisor mode */ | |
msr cpsr_cxsf, r1 | |
ldr sp, =__stack_svc_end__ | |
#ifdef SUPERVISOR_START | |
/* Start application in supervisor mode */ | |
ldr r1, =__stack_end__ /* Setup user/system mode stack */ | |
mov r2, sp | |
stmfd r2!, {r1} | |
ldmfd r2, {sp}^ | |
#else | |
/* Start application in system mode */ | |
orr r1, r0, #0x1F /* System mode */ | |
msr cpsr_cxsf, r1 | |
ldr sp, =__stack_end__ | |
#endif | |
/* Copy from initialised data section to data section (if necessary). */ | |
ldr r0, =__data_load_start__ | |
ldr r1, =__data_start__ | |
cmp r0, r1 | |
beq copy_data_end | |
ldr r2, =__data_end__ | |
subs r2, r2, r1 | |
beq copy_data_end | |
copy_data_loop: | |
ldrb r3, [r0], #+1 | |
strb r3, [r1], #+1 | |
subs r2, r2, #1 | |
bne copy_data_loop | |
copy_data_end: | |
/* Copy from initialised text section to text section (if necessary). */ | |
ldr r0, =__text_load_start__ | |
ldr r1, =__text_start__ | |
cmp r0, r1 | |
beq copy_text_end | |
ldr r2, =__text_end__ | |
subs r2, r2, r1 | |
beq copy_text_end | |
copy_text_loop: | |
ldrb r3, [r0], #+1 | |
strb r3, [r1], #+1 | |
subs r2, r2, #1 | |
bne copy_text_loop | |
copy_text_end: | |
/* Copy from initialised fast_text section to fast_text section (if necessary). */ | |
ldr r0, =__fast_load_start__ | |
ldr r1, =__fast_start__ | |
cmp r0, r1 | |
beq copy_fast_end | |
ldr r2, =__fast_end__ | |
subs r2, r2, r1 | |
beq copy_fast_end | |
copy_fast_loop: | |
ldrb r3, [r0], #+1 | |
strb r3, [r1], #+1 | |
subs r2, r2, #1 | |
bne copy_fast_loop | |
copy_fast_end: | |
/* Zero the bss. */ | |
ldr r0, =__bss_start__ | |
ldr r1, =__bss_end__ | |
mov r2, #0 | |
zero_bss_loop: | |
cmp r0, r1 | |
beq zero_bss_end | |
strb r2, [r0], #+1 | |
b zero_bss_loop | |
zero_bss_end: | |
#ifdef CHECK | |
/* Check data */ | |
ldr r0, =__data_load_start__ | |
ldr r1, =__data_start__ | |
cmp r0, r1 | |
beq check_data_end | |
ldr r2, =__data_end__ | |
subs r2, r2, r1 | |
beq check_data_end | |
check_data_loop: | |
ldrb r3, [r0], #+1 | |
ldrb r4, [r1], #+1 | |
cmp r3, r4 | |
bne data_error_loop | |
subs r2, r2, #1 | |
bne check_data_loop | |
check_data_end: | |
/* Check text */ | |
ldr r0, =__text_load_start__ | |
ldr r1, =__text_start__ | |
cmp r0, r1 | |
beq check_text_end | |
ldr r2, =__text_end__ | |
subs r2, r2, r1 | |
beq check_text_end | |
check_text_loop: | |
ldrb r3, [r0], #+1 | |
ldrb r4, [r1], #+1 | |
cmp r3, r4 | |
bne text_error_loop | |
subs r2, r2, #1 | |
bne check_text_loop | |
check_text_end: | |
/* Check fast */ | |
ldr r0, =__fast_load_start__ | |
ldr r1, =__fast_start__ | |
cmp r0, r1 | |
beq check_fast_end | |
ldr r2, =__fast_end__ | |
subs r2, r2, r1 | |
beq check_fast_end | |
check_fast_loop: | |
ldrb r3, [r0], #+1 | |
ldrb r4, [r1], #+1 | |
cmp r3, r4 | |
bne fast_error_loop | |
subs r2, r2, #1 | |
bne check_fast_loop | |
check_fast_end: | |
/* Check bss */ | |
ldr r0, =__bss_start__ | |
ldr r1, =__bss_end__ | |
mov r2, #0 | |
check_bss_loop: | |
cmp r0, r1 | |
beq check_bss_end | |
ldrb r2, [r0], #+1 | |
cmp r2, #0 | |
bne bss_error_loop | |
b check_bss_loop | |
check_bss_end: | |
#endif | |
/* Initialise the heap */ | |
ldr r0, = __heap_start__ | |
ldr r1, = __heap_end__ | |
sub r1, r1, r0 /* r1 = r1-r0 */ | |
mov r2, #0 | |
str r2, [r0], #+4 /* *r0++ = 0 */ | |
str r1, [r0] /* *r0 = __heap_end__ - __heap_start__ */ | |
/* Call constructors */ | |
ldr r0, =__ctors_start__ | |
ldr r1, =__ctors_end__ | |
ctor_loop: | |
cmp r0, r1 | |
beq ctor_end | |
ldr r2, [r0], #+4 | |
stmfd sp!, {r0-r1} | |
mov lr, pc | |
mov pc, r2 | |
ldmfd sp!, {r0-r1} | |
b ctor_loop | |
ctor_end: | |
/* Setup initial call frame */ | |
mov lr, #4 | |
mov r12, sp | |
stmfd sp!, {r11-r12, lr-pc} | |
sub r11, r12, #0x00000004 | |
start: | |
/* Jump to main entry point */ | |
mov r0, #0 | |
mov r1, #0 | |
ldr r2, =main | |
mov lr, pc | |
#ifdef __ARM_ARCH_3__ | |
mov pc, r2 | |
#else | |
bx r2 | |
#endif | |
/* Call destructors */ | |
ldr r0, =__dtors_start__ | |
ldr r1, =__dtors_end__ | |
dtor_loop: | |
cmp r0, r1 | |
beq dtor_end | |
ldr r2, [r0], #+4 | |
stmfd sp!, {r0-r1} | |
mov lr, pc | |
mov pc, r2 | |
ldmfd sp!, {r0-r1} | |
b dtor_loop | |
dtor_end: | |
/* Return from main, loop forever. */ | |
exit_loop: | |
b exit_loop | |
#ifdef CHECK | |
data_error_loop: | |
b data_error_loop | |
text_error_loop: | |
b text_error_loop | |
fast_error_loop: | |
b fast_error_loop | |
bss_error_loop: | |
b bss_error_loop | |
#endif | |