source: rtems/c/src/lib/libbsp/arm/gdbarmsim/start/start.S @ 32b8506

4.104.11
Last change on this file since 32b8506 was 32b8506, checked in by Ralf Corsepius <ralf.corsepius@…>, on Nov 29, 2009 at 2:53:02 PM

Whitespace removal.

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 *  Copied from libgloss 1 Oct 2009.
3 *  Minor modifications to work with RTEMS.
4 *
5 *  $Id$
6 */
7
8#include <newlib.h>
9#include <bsp/swi.h>
10
11/* ANSI concatenation macros.  */
12#define CONCAT(a, b) CONCAT2(a, b)
13#define CONCAT2(a, b) a ## b
14
15#ifdef __USER_LABEL_PREFIX__
16#define FUNCTION( name ) CONCAT (__USER_LABEL_PREFIX__, name)
17#else
18#error __USER_LABEL_PREFIX is not defined
19#endif
20
21#ifdef HAVE_INITFINI_ARRAY
22#define _init   __libc_init_array
23#define _fini   __libc_fini_array
24#endif
25
26/* .text is used instead of .section .text so it works with arm-aout too.  */
27        .text
28#if defined(__thumb2__)
29        .syntax unified
30        .thumb
31.macro FUNC_START name
32        .global \name
33        .thumb_func
34\name:
35.endm
36#else
37        .code 32
38.macro FUNC_START name
39        .global \name
40\name:
41.endm
42#endif
43        .align  0
44
45        FUNC_START      _mainCRTStartup
46        FUNC_START      _start
47        FUNC_START      start
48#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
49        /* Annotation for EABI unwinding tables.  */
50        .fnstart
51#endif
52
53/* Start by setting up a stack */
54#ifdef ARM_RDP_MONITOR
55        /*  Issue Demon SWI to read stack info */
56        swi     SWI_GetEnv      /*  Returns command line in r0 */
57        mov     sp,r1           /*  and the highest memory address in r1 */
58        ldr     sl, .LC2        /*  stack limit is at end of data */
59        add     sl, sl, #256    /*  allow slop for stack overflow handling */
60                                /*  and small frames */
61#else
62#ifdef ARM_RDI_MONITOR
63        /*  Issue Angel SWI to read stack info */
64        mov     r0, #AngelSWI_Reason_HeapInfo
65        adr     r1, .LC0        /*  point at ptr to 4 words to receive data */
66#if defined(__thumb2__)
67        bkpt    AngelSWI
68#else
69        /*  We are always in ARM mode for startup */
70        AngelSWIAsm     AngelSWI_ARM
71#endif
72        ldr     r0, .LC0        /*  point at values read */
73        ldr     sp, [r0, #8]
74        ldr     sl, [r0, #12]
75        add     sl, sl, #256    /*  allow slop for stack overflow handling */
76                                /*  and small frames */
77#else
78        /*  Set up the stack pointer to a fixed value */
79        /*  Changes by toralf:
80            - Allow linker script to provide stack via __stack symbol - see
81              defintion of .Lstack
82            - Provide "hooks" that may be used by the application to add
83              custom init code - see .Lhwinit and .Lswinit
84            - Go through all execution modes and set up stack for each of them.
85              Loosely based on init.s from ARM/Motorola example code.
86              Note: Mode switch via CPSR is not allowed once in non-privileged
87                    mode, so we take care not to enter "User" to set up its sp,
88                    and also skip most operations if already in that mode. */
89
90        ldr     r3, .Lstack
91        cmp     r3, #0
92#ifdef __thumb2__
93        it      eq
94#endif
95        ldreq   r3, .LC0
96        /* Note: This 'mov' is essential when starting in User, and ensures we
97                 always get *some* sp value for the initial mode, even if we
98                 have somehow missed it below (in which case it gets the same
99                 value as FIQ - not ideal, but better than nothing.) */
100        mov     sp, r3
101#ifdef __thumb2__
102        /* XXX Fill in stack assignments for interrupt modes.  */
103#else
104        mrs     r2, CPSR
105        tst     r2, #0x0F       /* Test mode bits - in User of all are 0 */
106        beq     .LC23           /* "eq" means r2 AND #0x0F is 0 */
107        msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled */
108        mov     sp, r3
109        sub     sl, sp, #0x1000 /* This mode also has its own sl (see below) */
110
111        mov     r3, sl
112        msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled */
113        mov     sp, r3
114        sub     r3, r3, #0x1000
115
116        msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled */
117        mov     sp, r3
118        sub     r3, r3, #0x1000
119
120        msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled */
121        mov     sp, r3
122        sub     r3, r3, #0x2000
123
124        msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled */
125
126        mov     sp, r3
127        sub     r3, r3, #0x8000 /* Min size 32k */
128        bic     r3, r3, #0x00FF /* Align with current 64k block */
129        bic     r3, r3, #0xFF00
130
131        str     r3, [r3, #-4]   /* Move value into user mode sp without */
132        ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm */
133        orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
134        msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1 */
135#endif
136.LC23:
137        /* Setup a default stack-limit in-case the code has been
138           compiled with "-mapcs-stack-check".  Hard-wiring this value
139           is not ideal, since there is currently no support for
140           checking that the heap and stack have not collided, or that
141           this default 64k is enough for the program being executed.
142           However, it ensures that this simple crt0 world will not
143           immediately cause an overflow event:  */
144        sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl */
145#endif
146#endif
147        /* Zero the memory in the .bss section.  */
148        mov     a2, #0                  /* Second arg: fill value */
149        mov     fp, a2                  /* Null frame pointer */
150        mov     r7, a2                  /* Null frame pointer for Thumb */
151
152        ldr     a1, .LC1                /* First arg: start of memory block */
153        ldr     a3, .LC2
154        sub     a3, a3, a1              /* Third arg: length of block */
155
156
157#if defined(__thumb__) && !defined(__thumb2__)
158        /* Enter Thumb mode.... */
159        add     a4, pc, #1      /* Get the address of the Thumb block */
160        bx      a4              /* Go there and start Thumb decoding  */
161
162        .code 16
163        .global __change_mode
164        .thumb_func
165__change_mode:
166#endif
167
168        bl      FUNCTION (memset)
169#if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
170/* Changes by toralf: Taken from libgloss/m68k/crt0.S
171 * initialize target specific stuff. Only execute these
172 * functions it they exist.
173 */
174        ldr     r3, .Lhwinit
175        cmp     r3, #0
176        beq     .LC24
177#if defined(__thumb__) || defined(__thumb2__)
178        blx   r3
179#else
180        mov     lr, pc
181        mov     pc, r3
182#endif
183.LC24:
184        ldr     r3, .Lswinit
185        cmp     r3, #0
186        beq     .LC25
187#if defined(__thumb__) || defined(__thumb2__)
188        blx   r3
189#else
190        mov     lr, pc
191        mov     pc, r3
192#endif
193
194.LC25:
195        mov     r0, #0          /*  no arguments  */
196        mov     r1, #0          /*  no argv either */
197#else
198        /* Need to set up standard file handles */
199        bl      FUNCTION (initialise_monitor_handles)
200
201#ifdef ARM_RDP_MONITOR
202        swi     SWI_GetEnv      /*  sets r0 to point to the command line */
203        mov     r1, r0
204#else
205        mov     r0, #AngelSWI_Reason_GetCmdLine
206        adr     r1, .LC30       /*  Space for command line */
207        AngelSWIAsm     AngelSWI
208        ldr     r1, .LC30
209#endif
210        /*  Parse string at r1 */
211        mov     r0, #0          /*  count of arguments so far */
212        /* Push a NULL argument onto the end of the list.  */
213#ifdef __thumb__
214        push    {r0}
215#else
216        stmfd   sp!, {r0}
217#endif
218.LC10:
219/*  Skip leading blanks */
220#ifdef __thumb__
221        ldrb    r3, [r1]
222        add     r1, #1
223#else
224        ldrb    r3, [r1], #1
225#endif
226        cmp     r3, #0
227        beq     .LC12
228        cmp     r3, #' '
229        beq     .LC10
230
231/*  See whether we are scanning a string */
232        cmp     r3, #'"'
233#ifdef __thumb__
234        beq     .LC20
235        cmp     r3, #'\''
236        bne     .LC21
237.LC20:
238        mov     r2, r3
239        b       .LC22
240
241.LC21:
242        mov     r2, #' '        /*  terminator type */
243        sub     r1, r1, #1      /*  adjust back to point at start char */
244.LC22:
245#else
246        cmpne   r3, #'\''
247        moveq   r2, r3
248        movne   r2, #' '        /*  terminator type */
249        subne   r1, r1, #1      /*  adjust back to point at start char */
250#endif
251
252/*  Stack a pointer to the current argument */
253#ifdef __thumb__
254        push    {r1}
255#else
256        stmfd   sp!, {r1}
257#endif
258        add     r0, r0, #1
259.LC11:
260#ifdef __thumb__
261        ldrb    r3, [r1]
262        add     r1, #1
263#else
264        ldrb    r3, [r1], #1
265#endif
266        cmp     r3, #0
267        beq     .LC12
268        cmp     r2, r3          /*  reached terminator? */
269        bne     .LC11
270        mov     r2, #0
271        sub     r3, r1, #1
272        strb    r2, [r3]        /*  terminate the arg string */
273        b       .LC10
274
275.LC12:
276        mov     r1, sp          /*  point at stacked arg pointers */
277        /* We've now got the stacked args in order reverse the */
278#ifdef __thumb__
279        mov     r2, r0
280        lsl     r2, #2
281        add     r2, sp
282        mov     r3, sp
283.LC15:  cmp     r2, r3
284        bls     .LC14
285        sub     r2, #4
286        ldr     r4, [r2]
287        ldr     r5, [r3]
288        str     r5, [r2]
289        str     r4, [r3]
290        add     r3, #4
291        b       .LC15
292.LC14:
293        /* Ensure doubleword stack alignment.  */
294        mov     r4, sp
295        mov     r5, #7
296        bic     r4, r5
297        mov     sp, r4
298#else
299        add     r2, sp, r0, LSL #2      /* End of args */
300        mov     r3, sp                  /* Start of args */
301.LC13:  cmp     r2, r3
302        ldrhi   r4,[r2, #-4]            /* Reverse ends of list */
303        ldrhi   r5, [r3]
304        strhi   r5, [r2, #-4]!
305        strhi   r4, [r3], #4
306        bhi     .LC13
307        /* Ensure doubleword stack alignment.  */
308        bic     sp, sp, #7
309#endif
310#endif
311
312        bl      FUNCTION (boot_card)
313
314        bl      FUNCTION (bsp_cleanup)          /* Should not return.  */
315
316#if defined(__thumb__) && !defined(__thumb2__)
317        /* Come out of Thumb mode.  This code should be redundant.  */
318
319        mov     a4, pc
320        bx      a4
321
322        .code 32
323        .global change_back
324change_back:
325        /* Halt the execution.  This code should never be executed.  */
326        /* With no debug monitor, this probably aborts (eventually).
327           With a Demon debug monitor, this halts cleanly.
328           With an Angel debug monitor, this will report 'Unknown SWI'.  */
329        swi     SWI_Exit
330#endif
331
332        /* For Thumb, constants must be after the code since only
333           positive offsets are supported for PC relative addresses.  */
334
335        .align 0
336.LC0:
337#ifdef ARM_RDI_MONITOR
338        .word   HeapBase
339#else
340#ifndef ARM_RDP_MONITOR
341        /* Changes by toralf: Provide alternative "stack" variable whose value
342           may be defined externally; .Lstack will be used instead of .LC0 if
343           it points to a non-0 value. Also set up references to "hooks" that
344           may be used by the application to provide additional init code. */
345
346#ifdef __pe__
347        .word   0x800000
348#else
349        .word   0x80000                 /* Top of RAM on the PIE board.  */
350#endif
351.Lstack:
352        .word   __stack
353.Lhwinit:
354        .word   FUNCTION (hardware_init_hook)
355.Lswinit:
356        .word   FUNCTION (software_init_hook)
357
358        /* Set up defaults for the above variables in the form of weak symbols
359           - so that application will link correctly, and get value 0 in
360           runtime (meaning "ignore setting") for the variables, when the user
361           does not provide the symbols. (The linker uses a weak symbol if,
362           and only if, a normal version of the same symbol isn't provided
363           e.g. by a linker script or another object file.) */
364
365        .weak __stack
366        .weak FUNCTION (hardware_init_hook)
367        .weak FUNCTION (software_init_hook)
368#endif
369
370#endif
371#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
372        /* Protect against unhandled exceptions.  */
373        .cantunwind
374        .fnend
375#endif
376.LC1:
377        .word   __bss_start__
378.LC2:
379        .word   __clear_end__ /* __bss_end__ */
380#ifdef __USES_INITFINI__
381.Lfini:
382        .word   FUNCTION(_fini)
383#endif
384#ifdef ARM_RDI_MONITOR
385.LC30:
386        .word   CommandLine
387        .word   255
388
389/*  Workspace for Angel calls.  */
390        .data
391/*  Data returned by monitor SWI.  */
392.global __stack_base__
393HeapBase:       .word   0
394HeapLimit:      .word   0
395__stack_base__: .word   0
396StackLimit:     .word   0
397CommandLine:    .space  256,0   /*  Maximum length of 255 chars handled.  */
398#endif
399
400#ifdef __pe__
401        .section .idata$3
402        .long   0,0,0,0,0,0,0,0
403#endif
Note: See TracBrowser for help on using the repository browser.