summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/arm/crt0.S
blob: 49d4bedfec2e16edbe99785fa6f50e4713976498 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* When we enter this piece of code, the program stack looks like this:
        argc            argument counter (integer)
        argv[0]         program name (pointer)
        argv[1...N]     program args (pointers)
        argv[argc-1]    end of args (integer)
        env[0...N]      environment variables (pointers)
        NULL
	
   When we are done here, we want
	a1=argc
	a2=argv[0]
	a3=argv[argc+1]

This file now uses the register naming from the ARM Procedure Calling Standard

    Name    Number      APCS Role

    a1      0           argument 1 / integer result / scratch register / argc
    a2      1           argument 2 / scratch register / argv
    a3      2           argument 3 / scratch register / envp
    a4      3           argument 4 / scratch register
    v1      4           register variable
    v2      5           register variable
    v3      6           register variable
    v4      7           register variable
    v5      8           register variable
    sb/v6   9           static base / register variable
    sl/v7   10          stack limit / stack chunk handle / reg. variable
    fp      11          frame pointer
    ip      12          scratch register / new-sb in inter-link-unit calls
    sp      13          lower end of current stack frame
    lr      14          link address / scratch register
    pc      15          program counter
*/


.text
	.align 2
	.global __environ
	.global _start
	.global exit
	.global main
	.global __libc_init
	.global __init_stdio
	.global __stdio_close_all
	.global _void_void_null_func

	.type   _start,%function
	.type   exit,%function
	.type   main,%function
	.type   __libc_init,%function
	.type   __init_stdio,%function
	.type   __stdio_close_all,%function
	.type   _void_void_null_func,%function

.text
_start:

	/* clear the frame pointer */
	mov     fp, #0

	/* Load register a1 (argc) from the stack to its final resting place */
	ldr     a1, [sp], #4

	/* Copy argv pointer into a2 -- which its final resting place */
	mov     a2, sp

	/* Set up environ,  skip to the end of argv, and put 
	 * a pointer to whatever we find there (hopefully the
	 environment) in a3 */
	ldr     a4, .L3
	add     a3, a2, a1, lsl #2
	add     a3, a3, #4
	str     a3, [a4, #0]

	/* Tell libc to initialize whatever it needs */
        bl __libc_init		    
        bl __init_stdio
	bl      main
	bl      exit

_void_void_null_func:
	nop

.weak __libc_init
__libc_init = _void_void_null_func

.weak __init_stdio
__init_stdio = _void_void_null_func

.weak __stdio_close_all
__stdio_close_all = _void_void_null_func

.align 2
.L3:
	.word environ


.data
	.align 2
	.global __environ
	
__environ:  
	.long 0

.weak environ
environ = __environ