newlib/libgloss/arm/redboot-crt0.S

134 lines
2.5 KiB
ArmAsm
Raw Normal View History

#include "arm.h"
2002-01-07 19:12:32 +01:00
.file "crt0.S"
#define XGLUE(a,b) a##b
#define GLUE(a,b) XGLUE(a,b)
#ifdef __USER_LABEL_PREFIX__
#define SYM_NAME( name ) GLUE (__USER_LABEL_PREFIX__, name)
#else
#error __USER_LABEL_PREFIX is not defined
#endif
.text
.syntax unified
/* Setup the assembly entry point. */
#ifdef THUMB_V7_V6M
.macro FUNC_START name
.global \name
.thumb_func
\name:
.endm
.thumb
#else
.macro FUNC_START name
.global \name
\name:
.endm
.code 32
#endif
FUNC_START SYM_NAME(start)
FUNC_START SYM_NAME(_start)
/* Unnecessary to set fp for v6-m/v7-m, which don't support
ARM state. */
#ifndef THUMB_V7M_V6M
mov fp, #0 /* Null frame pointer. */
#endif
movs r7, #0 /* Null frame pointer for Thumb. */
2002-01-07 19:12:32 +01:00
/* Enable interrupts for gdb debugging. */
#ifdef THUMB_V7_V6M
cpsie if
#else
2002-01-07 19:12:32 +01:00
mrs r0, cpsr
bic r0, r0, #0xC0
msr cpsr, r0
#endif
2002-01-07 19:12:32 +01:00
movs a2, #0 /* Second arg: fill value. */
ldr a1, .LC1 /* First arg: start of memory block. */
2002-01-07 19:12:32 +01:00
ldr a3, .LC2
subs a3, a3, a1 /* Third arg: length of block. */
#ifdef GCRT0
/* Zero out the bss without using memset.
Using memset is bad because it may be instrumented for
profiling, but at this point, the profiling data structures
have not been set up.
FIXME: This loop could be a lot more efficient. */
subs a3, a3, #0
beq 2f
1: strb a2, [a1]
subs a3, a3, #1
add a1, a1, #1
bne 1b
2:
/* Nothing to left to clear. */
#endif
2002-01-07 19:12:32 +01:00
#if defined(__thumb__) && !defined(THUMB_V7_V6M)
/* Enter Thumb mode. */
add a4, pc, #1 /* Get the address of the Thumb block. */
bx a4 /* Go there and start Thumb decoding. */
2002-01-07 19:12:32 +01:00
.code 16
.global __change_mode
.thumb_func
__change_mode:
#endif
#ifndef GCRT0
2002-01-07 19:12:32 +01:00
bl SYM_NAME(memset)
#endif
bl SYM_NAME(__get_memtop)
subs r0, r0, #32
mov sp, r0
2002-02-05 19:09:18 +01:00
#ifdef __USES_INITFINI__
/* Some arm/elf targets use the .init and .fini sections
to create constructors and destructors, and for these
targets we need to call the _init function and arrange
for _fini to be called at program exit. */
ldr r0, .Lfini
bl SYM_NAME (atexit)
bl SYM_NAME (_init)
#endif
movs a1, #0
2002-01-07 19:12:32 +01:00
ldr a2, .LC3
mov a3, a2
bl SYM_NAME(main)
1: bl SYM_NAME(exit)
b 1b
2002-02-05 19:09:18 +01:00
.align 2
2002-01-07 19:12:32 +01:00
.LC1:
.word __bss_start__
.LC2:
.word __bss_end__
.LC3:
.word 0
2002-02-05 19:09:18 +01:00
#ifdef __USES_INITFINI__
.Lfini:
.word SYM_NAME(_fini)
#endif
2002-01-07 19:12:32 +01:00
#if 0
#ifdef __thumb__
.code 16
#endif
.global SYM_NAME(__syscall)
#ifdef __thumb__
.thumb_func
#else
.align 4
#endif
SYM_NAME(__syscall):
mov r12, lr
#ifdef __thumb__
swi 0x18
#else
swi 0x180001
#endif
mov pc, r12
#endif