mirror of https://github.com/FOME-Tech/openblt.git
420 lines
11 KiB
ArmAsm
420 lines
11 KiB
ArmAsm
/*****************************************************************************
|
|
* 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. *
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* Preprocessor Definitions
|
|
* ------------------------
|
|
* APP_ENTRY_POINT
|
|
*
|
|
* Defines the application entry point function, if undefined this setting
|
|
* defaults to "main".
|
|
*
|
|
* INITIALIZE_STACKS
|
|
*
|
|
* If defined, the contents of the stacks will be initialized to a the
|
|
* value 0xCC.
|
|
*
|
|
* INITIALIZE_SECONDARY_SECTIONS
|
|
*
|
|
* If defined, the .text2, .data2 and .bss2 sections will be initialized.
|
|
*
|
|
* SUPERVISOR_START
|
|
*
|
|
* If defined, the application will start up in supervisor mode. If
|
|
* undefined the application will start up in system mode.
|
|
*
|
|
* FULL_LIBRARY
|
|
*
|
|
* If defined then
|
|
* - argc, argv are setup by the debug_getargs.
|
|
* - the exit symbol is defined and executes on return from main.
|
|
* - the exit symbol calls destructors, atexit functions and then debug_exit.
|
|
*
|
|
* If not defined then
|
|
* - argc and argv are zero.
|
|
* - the exit symbol is defined, executes on return from main and loops
|
|
*
|
|
*****************************************************************************/
|
|
|
|
.section .vectors, "ax"
|
|
.code 32
|
|
.align 0
|
|
.global _vectors
|
|
.global reset_handler
|
|
|
|
/*****************************************************************************
|
|
* Exception Vectors *
|
|
*****************************************************************************/
|
|
_vectors:
|
|
ldr pc, [pc, #reset_handler_address - . - 8] /* reset */
|
|
ldr pc, [pc, #undef_handler_address - . - 8] /* undefined instruction */
|
|
ldr pc, [pc, #undef_handler_address - . - 8] /* swi handler */
|
|
ldr pc, [pc, #pabort_handler_address - . - 8] /* abort prefetch */
|
|
ldr pc, [pc, #dabort_handler_address - . - 8] /* abort data */
|
|
.word 0xB9205F88 /* boot loader checksum */
|
|
ldr pc, [pc, #-0xFF0] /* irq handler */
|
|
ldr pc, [pc, #fiq_handler_address - . - 8] /* fiq handler */
|
|
|
|
reset_handler_address:
|
|
.word Reset_Handler
|
|
undef_handler_address:
|
|
.word undef_handler
|
|
pabort_handler_address:
|
|
.word pabort_handler
|
|
dabort_handler_address:
|
|
.word dabort_handler
|
|
fiq_handler_address:
|
|
.word fiq_handler
|
|
|
|
|
|
.section .init, "ax"
|
|
.code 32
|
|
.align 4
|
|
|
|
#ifndef APP_ENTRY_POINT
|
|
#define APP_ENTRY_POINT main
|
|
#endif
|
|
|
|
#ifndef ARGSSPACE
|
|
#define ARGSSPACE 128
|
|
#endif
|
|
|
|
.weak Reset_Handler
|
|
.global __start
|
|
.global __gccmain
|
|
.extern APP_ENTRY_POINT
|
|
.global exit
|
|
|
|
/************************************************************************************//**
|
|
** \brief Reset interrupt service routine. Configures the stack for each mode,
|
|
** disables the IRQ and FIQ interrupts, initializes RAM and jumps to
|
|
** function main.
|
|
** \return none.
|
|
**
|
|
****************************************************************************************/
|
|
Reset_Handler:
|
|
__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__
|
|
#ifdef __ARM_EABI__
|
|
bic sp, sp, #0x7
|
|
#endif
|
|
|
|
orr r1, r0, #0x17 /* Abort mode */
|
|
msr cpsr_cxsf, r1
|
|
ldr sp, =__stack_abt_end__
|
|
#ifdef __ARM_EABI__
|
|
bic sp, sp, #0x7
|
|
#endif
|
|
|
|
orr r1, r0, #0x12 /* IRQ mode */
|
|
msr cpsr_cxsf, r1
|
|
ldr sp, =__stack_irq_end__
|
|
#ifdef __ARM_EABI__
|
|
bic sp, sp, #0x7
|
|
#endif
|
|
|
|
orr r1, r0, #0x11 /* FIQ mode */
|
|
msr cpsr_cxsf, r1
|
|
ldr sp, =__stack_fiq_end__
|
|
#ifdef __ARM_EABI__
|
|
bic sp, sp, #0x7
|
|
#endif
|
|
|
|
orr r1, r0, #0x13 /* Supervisor mode */
|
|
msr cpsr_cxsf, r1
|
|
ldr sp, =__stack_svc_end__
|
|
#ifdef __ARM_EABI__
|
|
bic sp, sp, #0x7
|
|
#endif
|
|
|
|
#ifdef SUPERVISOR_START
|
|
/* Start application in supervisor mode */
|
|
ldr r1, =__stack_end__ /* Setup user/system mode stack */
|
|
#ifdef __ARM_EABI__
|
|
bic r1, r1, #0x7
|
|
#endif
|
|
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__
|
|
#ifdef __ARM_EABI__
|
|
bic sp, sp, #0x7
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef INITIALIZE_STACKS
|
|
mov r2, #0xCC
|
|
ldr r0, =__stack_und_start__
|
|
ldr r1, =__stack_und_end__
|
|
bl memory_set
|
|
ldr r0, =__stack_abt_start__
|
|
ldr r1, =__stack_abt_end__
|
|
bl memory_set
|
|
ldr r0, =__stack_irq_start__
|
|
ldr r1, =__stack_irq_end__
|
|
bl memory_set
|
|
ldr r0, =__stack_fiq_start__
|
|
ldr r1, =__stack_fiq_end__
|
|
bl memory_set
|
|
ldr r0, =__stack_svc_start__
|
|
ldr r1, =__stack_svc_end__
|
|
bl memory_set
|
|
ldr r0, =__stack_start__
|
|
ldr r1, =__stack_end__
|
|
bl memory_set
|
|
#endif
|
|
|
|
/* Copy initialised memory sections into RAM (if necessary). */
|
|
ldr r0, =__data_load_start__
|
|
ldr r1, =__data_start__
|
|
ldr r2, =__data_end__
|
|
bl memory_copy
|
|
ldr r0, =__text_load_start__
|
|
ldr r1, =__text_start__
|
|
ldr r2, =__text_end__
|
|
bl memory_copy
|
|
ldr r0, =__fast_load_start__
|
|
ldr r1, =__fast_start__
|
|
ldr r2, =__fast_end__
|
|
bl memory_copy
|
|
ldr r0, =__ctors_load_start__
|
|
ldr r1, =__ctors_start__
|
|
ldr r2, =__ctors_end__
|
|
bl memory_copy
|
|
ldr r0, =__dtors_load_start__
|
|
ldr r1, =__dtors_start__
|
|
ldr r2, =__dtors_end__
|
|
bl memory_copy
|
|
ldr r0, =__rodata_load_start__
|
|
ldr r1, =__rodata_start__
|
|
ldr r2, =__rodata_end__
|
|
bl memory_copy
|
|
#ifdef INITIALIZE_SECONDARY_SECTIONS
|
|
ldr r0, =__data2_load_start__
|
|
ldr r1, =__data2_start__
|
|
ldr r2, =__data2_end__
|
|
bl memory_copy
|
|
ldr r0, =__text2_load_start__
|
|
ldr r1, =__text2_start__
|
|
ldr r2, =__text2_end__
|
|
bl memory_copy
|
|
ldr r0, =__rodata2_load_start__
|
|
ldr r1, =__rodata2_start__
|
|
ldr r2, =__rodata2_end__
|
|
bl memory_copy
|
|
#endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */
|
|
|
|
/* Zero the bss. */
|
|
ldr r0, =__bss_start__
|
|
ldr r1, =__bss_end__
|
|
mov r2, #0
|
|
bl memory_set
|
|
#ifdef INITIALIZE_SECONDARY_SECTIONS
|
|
ldr r0, =__bss2_start__
|
|
ldr r1, =__bss2_end__
|
|
mov r2, #0
|
|
bl memory_set
|
|
#endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */
|
|
|
|
/* Initialise the heap */
|
|
ldr r0, = __heap_start__
|
|
ldr r1, = __heap_end__
|
|
sub r1, r1, r0
|
|
cmp r1, #8
|
|
movge r2, #0
|
|
strge r2, [r0], #+4
|
|
strge r1, [r0]
|
|
|
|
/* 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
|
|
#ifdef __ARM_ARCH_3__
|
|
mov pc, r2
|
|
#else
|
|
bx r2
|
|
#endif
|
|
ldmfd sp!, {r0-r1}
|
|
b ctor_loop
|
|
ctor_end:
|
|
|
|
.type start, function
|
|
start:
|
|
/* Jump to application entry point */
|
|
#ifdef FULL_LIBRARY
|
|
mov r0, #ARGSSPACE
|
|
ldr r1, =args
|
|
ldr r2, =debug_getargs
|
|
mov lr, pc
|
|
#ifdef __ARM_ARCH_3__
|
|
mov pc, r2
|
|
#else
|
|
bx r2
|
|
#endif
|
|
ldr r1, =args
|
|
#else
|
|
mov r0, #0
|
|
mov r1, #0
|
|
#endif
|
|
ldr r2, =APP_ENTRY_POINT
|
|
mov lr, pc
|
|
#ifdef __ARM_ARCH_3__
|
|
mov pc, r2
|
|
#else
|
|
bx r2
|
|
#endif
|
|
|
|
exit:
|
|
#ifdef FULL_LIBRARY
|
|
mov r5, r0 // save the exit parameter/return result
|
|
|
|
/* 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
|
|
#ifdef __ARM_ARCH_3__
|
|
mov pc, r2
|
|
#else
|
|
bx r2
|
|
#endif
|
|
ldmfd sp!, {r0-r1}
|
|
b dtor_loop
|
|
dtor_end:
|
|
|
|
/* Call atexit functions */
|
|
ldr r2, =_execute_at_exit_fns
|
|
mov lr, pc
|
|
#ifdef __ARM_ARCH_3__
|
|
mov pc, r2
|
|
#else
|
|
bx r2
|
|
#endif
|
|
|
|
/* Call debug_exit with return result/exit parameter */
|
|
mov r0, r5
|
|
ldr r2, =debug_exit
|
|
mov lr, pc
|
|
#ifdef __ARM_ARCH_3__
|
|
mov pc, r2
|
|
#else
|
|
bx r2
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/* Returned from application entry point/debug_exit, loop forever. */
|
|
exit_loop:
|
|
b exit_loop
|
|
|
|
|
|
|
|
|
|
memory_copy:
|
|
cmp r0, r1
|
|
moveq pc, lr
|
|
subs r2, r2, r1
|
|
moveq pc, lr
|
|
|
|
/* if either pointer or length is not word aligned then byte copy */
|
|
orr r3, r0, r1
|
|
orr r3, r3, r2
|
|
tst r3, #0x3
|
|
bne 2f
|
|
/* word copy */
|
|
1:
|
|
ldr r3, [r0], #+4
|
|
str r3, [r1], #+4
|
|
subs r2, r2, #4
|
|
bne 1b
|
|
mov pc, lr
|
|
/* byte copy */
|
|
2:
|
|
ldrb r3, [r0], #+1
|
|
strb r3, [r1], #+1
|
|
subs r2, r2, #1
|
|
bne 2b
|
|
mov pc, lr
|
|
|
|
memory_set:
|
|
cmp r0, r1
|
|
moveq pc, lr
|
|
strb r2, [r0], #1
|
|
b memory_set
|
|
|
|
|
|
.section .init, "ax"
|
|
.code 32
|
|
.align 0
|
|
|
|
/******************************************************************************
|
|
* *
|
|
* Default exception handlers *
|
|
* *
|
|
******************************************************************************/
|
|
/******************************************************************************
|
|
* *
|
|
* Default exception handlers *
|
|
* These are declared weak symbols so they can be redefined in user code. *
|
|
* *
|
|
******************************************************************************/
|
|
undef_handler:
|
|
b undef_handler
|
|
|
|
pabort_handler:
|
|
b pabort_handler
|
|
|
|
dabort_handler:
|
|
b dabort_handler
|
|
|
|
fiq_handler:
|
|
b fiq_handler
|
|
|
|
irq_handler:
|
|
b irq_handler
|
|
|
|
.weak undef_handler, pabort_handler, dabort_handler, fiq_handler, irq_handler
|
|
|
|
|
|
#ifdef FULL_LIBRARY
|
|
.bss
|
|
args:
|
|
.space ARGSSPACE
|
|
#endif
|
|
|
|
/* Setup attibutes of stack and heap sections so they don't take up unnecessary room in the elf file */
|
|
.section .stack, "wa", %nobits
|
|
.section .stack_abt, "wa", %nobits
|
|
.section .stack_irq, "wa", %nobits
|
|
.section .stack_fiq, "wa", %nobits
|
|
.section .stack_svc, "wa", %nobits
|
|
.section .stack_und, "wa", %nobits
|
|
.section .heap, "wa", %nobits
|
|
|