1 | #include "arm.h" |
---|
2 | |
---|
3 | .file "crt0.S" |
---|
4 | |
---|
5 | #define XGLUE(a,b) a##b |
---|
6 | #define GLUE(a,b) XGLUE(a,b) |
---|
7 | |
---|
8 | #ifdef __USER_LABEL_PREFIX__ |
---|
9 | #define SYM_NAME( name ) GLUE (__USER_LABEL_PREFIX__, name) |
---|
10 | #else |
---|
11 | #error __USER_LABEL_PREFIX is not defined |
---|
12 | #endif |
---|
13 | |
---|
14 | .text |
---|
15 | .syntax unified |
---|
16 | /* Setup the assembly entry point. */ |
---|
17 | #ifdef PREFER_THUMB |
---|
18 | .macro FUNC_START name |
---|
19 | .global \name |
---|
20 | .thumb_func |
---|
21 | \name: |
---|
22 | .endm |
---|
23 | .thumb |
---|
24 | #else |
---|
25 | .macro FUNC_START name |
---|
26 | .global \name |
---|
27 | \name: |
---|
28 | .endm |
---|
29 | .code 32 |
---|
30 | #endif |
---|
31 | FUNC_START SYM_NAME(_start) |
---|
32 | /* Unnecessary to set fp for v6-m/v7-m, which don't support |
---|
33 | ARM state. */ |
---|
34 | #if __ARM_ARCH_ISA_ARM |
---|
35 | mov fp, #0 /* Null frame pointer. */ |
---|
36 | #endif |
---|
37 | movs r7, #0 /* Null frame pointer for Thumb. */ |
---|
38 | |
---|
39 | /* Enable interrupts for gdb debugging. */ |
---|
40 | #ifdef PREFER_THUMB |
---|
41 | cpsie if |
---|
42 | #else |
---|
43 | mrs r0, cpsr |
---|
44 | bic r0, r0, #0xC0 |
---|
45 | msr cpsr, r0 |
---|
46 | #endif |
---|
47 | |
---|
48 | movs a2, #0 /* Second arg: fill value. */ |
---|
49 | ldr a1, .LC1 /* First arg: start of memory block. */ |
---|
50 | ldr a3, .LC2 |
---|
51 | subs a3, a3, a1 /* Third arg: length of block. */ |
---|
52 | |
---|
53 | #ifdef GCRT0 |
---|
54 | /* Zero out the bss without using memset. |
---|
55 | Using memset is bad because it may be instrumented for |
---|
56 | profiling, but at this point, the profiling data structures |
---|
57 | have not been set up. |
---|
58 | FIXME: This loop could be a lot more efficient. */ |
---|
59 | subs a3, a3, #0 |
---|
60 | beq 2f |
---|
61 | 1: strb a2, [a1] |
---|
62 | subs a3, a3, #1 |
---|
63 | add a1, a1, #1 |
---|
64 | bne 1b |
---|
65 | 2: |
---|
66 | /* Nothing to left to clear. */ |
---|
67 | #endif |
---|
68 | |
---|
69 | #if __thumb__ && !defined(PREFER_THUMB) |
---|
70 | /* Enter Thumb mode. */ |
---|
71 | add a4, pc, #1 /* Get the address of the Thumb block. */ |
---|
72 | bx a4 /* Go there and start Thumb decoding. */ |
---|
73 | |
---|
74 | .code 16 |
---|
75 | .global __change_mode |
---|
76 | .thumb_func |
---|
77 | __change_mode: |
---|
78 | #endif |
---|
79 | |
---|
80 | #ifndef GCRT0 |
---|
81 | bl SYM_NAME(memset) |
---|
82 | #endif |
---|
83 | bl SYM_NAME(__get_memtop) |
---|
84 | subs r0, r0, #32 |
---|
85 | mov sp, r0 |
---|
86 | |
---|
87 | #ifdef __USES_INITFINI__ |
---|
88 | /* Some arm/elf targets use the .init and .fini sections |
---|
89 | to create constructors and destructors, and for these |
---|
90 | targets we need to call the _init function and arrange |
---|
91 | for _fini to be called at program exit. */ |
---|
92 | ldr r0, .Lfini |
---|
93 | bl SYM_NAME (atexit) |
---|
94 | bl SYM_NAME (_init) |
---|
95 | #endif |
---|
96 | |
---|
97 | movs a1, #0 |
---|
98 | ldr a2, .LC3 |
---|
99 | movs a3, a2 |
---|
100 | bl SYM_NAME(main) |
---|
101 | 1: bl SYM_NAME(exit) |
---|
102 | b 1b |
---|
103 | .align 2 |
---|
104 | .LC1: |
---|
105 | .word __bss_start__ |
---|
106 | .LC2: |
---|
107 | .word __bss_end__ |
---|
108 | .LC3: |
---|
109 | .word 0 |
---|
110 | #ifdef __USES_INITFINI__ |
---|
111 | .Lfini: |
---|
112 | .word SYM_NAME(_fini) |
---|
113 | #endif |
---|
114 | #if 0 |
---|
115 | #ifdef __thumb__ |
---|
116 | .code 16 |
---|
117 | #endif |
---|
118 | .global SYM_NAME(__syscall) |
---|
119 | #ifdef __thumb__ |
---|
120 | .thumb_func |
---|
121 | #else |
---|
122 | .align 4 |
---|
123 | #endif |
---|
124 | SYM_NAME(__syscall): |
---|
125 | mov r12, lr |
---|
126 | #ifdef __thumb__ |
---|
127 | swi 0x18 |
---|
128 | #else |
---|
129 | swi 0x180001 |
---|
130 | #endif |
---|
131 | mov pc, r12 |
---|
132 | #endif |
---|