Rev 1906 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1906 | Rev 3065 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * crt1.c |
2 | * crt1.c |
3 | * This file has no copyright assigned and is placed in the Public Domain. |
3 | * This file has no copyright assigned and is placed in the Public Domain. |
4 | * This file is a part of the mingw-runtime package. |
4 | * This file is a part of the mingw-runtime package. |
5 | * No warranty is given; refer to the file DISCLAIMER within the package. |
5 | * No warranty is given; refer to the file DISCLAIMER within the package. |
6 | * |
6 | * |
7 | * Source code for the startup proceedures used by all programs. This code |
7 | * Source code for the startup proceedures used by all programs. This code |
8 | * is compiled to make crt1.o, which should be located in the library path. |
8 | * is compiled to make crt1.o, which should be located in the library path. |
9 | * |
9 | * |
10 | */ |
10 | */ |
11 | 11 | ||
12 | /* Hide the declaration of _fmode with dllimport attribute in stdlib.h to |
12 | /* Hide the declaration of _fmode with dllimport attribute in stdlib.h to |
13 | avoid problems with older GCC. */ |
13 | avoid problems with older GCC. */ |
14 | 14 | ||
15 | #include |
15 | #include |
16 | #include |
16 | #include |
17 | #include |
17 | #include |
18 | #include |
18 | #include |
19 | #include |
19 | #include |
20 | #include |
20 | #include |
21 | 21 | ||
22 | #include "cpu_features.h" |
22 | #include "cpu_features.h" |
23 | 23 | ||
24 | 24 | ||
25 | /* NOTE: The code for initializing the _argv, _argc, and environ variables |
25 | /* NOTE: The code for initializing the _argv, _argc, and environ variables |
26 | * has been moved to a separate .c file which is included in both |
26 | * has been moved to a separate .c file which is included in both |
27 | * crt1.c and dllcrt1.c. This means changes in the code don't have to |
27 | * crt1.c and dllcrt1.c. This means changes in the code don't have to |
28 | * be manually synchronized, but it does lead to this not-generally- |
28 | * be manually synchronized, but it does lead to this not-generally- |
29 | * a-good-idea use of include. */ |
29 | * a-good-idea use of include. */ |
30 | 30 | ||
31 | 31 | ||
32 | extern char __cmdline; |
32 | extern char __cmdline; |
33 | extern char __pgmname; |
33 | extern char __pgmname; |
34 | 34 | ||
35 | extern int main (int, char **, char **); |
35 | extern int main (int, char **, char **); |
36 | 36 | ||
37 | int _errno; |
37 | int _errno; |
38 | int _fmode; |
38 | int _fmode; |
39 | 39 | ||
40 | char __appcwd[1024]; |
40 | char __appcwd[1024]; |
41 | int __appcwdlen; |
41 | int __appcwdlen; |
42 | 42 | ||
43 | int _argc; |
43 | int _argc; |
44 | char **_argv; |
44 | char **_argv; |
45 | 45 | ||
46 | static char *arg[2]; |
46 | static char *arg[2]; |
47 | 47 | ||
48 | void _exit(int __status) __attribute__((noreturn)); |
48 | void _exit(int __status) __attribute__((noreturn)); |
49 | 49 | ||
50 | 50 | ||
51 | char * __libc_getenv(const char *name) |
51 | char * __libc_getenv(const char *name) |
52 | { |
52 | { |
53 | return NULL; |
53 | return NULL; |
54 | } |
54 | } |
55 | 55 | ||
56 | void __main (){}; |
56 | void __main (){}; |
57 | void init_reent(); |
57 | void init_reent(); |
58 | 58 | ||
59 | void __attribute__((noreturn)) |
59 | void __attribute__((noreturn)) |
60 | __thread_startup (int (*entry)(void*), void *param, |
60 | __thread_startup (int (*entry)(void*), void *param, |
61 | void *stacklow, void *stackhigh) |
61 | void *stacklow, void *stackhigh) |
62 | { |
62 | { |
63 | int retval; |
63 | int retval; |
64 | 64 | ||
65 | __asm__ __volatile__( // save stack limits |
65 | __asm__ __volatile__( // save stack limits |
66 | "movl %0, %%fs:4 \n\t" // use TLS |
66 | "movl %0, %%fs:4 \n\t" // use TLS |
67 | "movl %1, %%fs:8 \n\t" |
67 | "movl %1, %%fs:8 \n\t" |
68 | ::"r"(stacklow), "r"(stackhigh)); |
68 | ::"r"(stacklow), "r"(stackhigh)); |
69 | 69 | ||
70 | init_reent(); // initialize thread reentry structure |
70 | init_reent(); // initialize thread reentry structure |
71 | 71 | ||
72 | retval = entry(param); // call user thread function |
72 | retval = entry(param); // call user thread function |
73 | 73 | ||
74 | _exit(retval); |
74 | _exit(retval); |
75 | }; |
75 | }; |
76 | 76 | ||
77 | struct app_hdr |
77 | struct app_hdr |
78 | { |
78 | { |
79 | char banner[8]; |
79 | char banner[8]; |
80 | int version; |
80 | int version; |
81 | int start; |
81 | int start; |
82 | int iend; |
82 | int iend; |
83 | int memsize; |
83 | int memsize; |
84 | int stacktop; |
84 | int stacktop; |
85 | char *cmdline; |
85 | char *cmdline; |
86 | char *path; |
86 | char *path; |
87 | }; |
87 | }; |
88 | 88 | ||
89 | 89 | ||
90 | void __attribute__((noreturn)) |
90 | void __attribute__((noreturn)) |
91 | __crt_startup (void) |
91 | __crt_startup (void) |
92 | { |
92 | { |
93 | int nRet; |
93 | int nRet; |
94 | struct app_hdr *header; |
94 | struct app_hdr *header; |
95 | 95 | ||
96 | 96 | ||
97 | init_reent(); |
97 | init_global_reent(); |
98 | 98 | ||
99 | /* |
99 | /* |
100 | * Initialize floating point unit. |
100 | * Initialize floating point unit. |
101 | */ |
101 | */ |
102 | __cpu_features_init (); /* Do we have SSE, etc.*/ |
102 | __cpu_features_init (); /* Do we have SSE, etc.*/ |
103 | // _fpreset (); /* Supplied by the runtime library. */ |
103 | // _fpreset (); /* Supplied by the runtime library. */ |
104 | 104 | ||
105 | __initPOSIXHandles(); |
105 | __initPOSIXHandles(); |
106 | 106 | ||
107 | __appcwdlen = strrchr(&__pgmname, '/') - &__pgmname + 1; |
107 | __appcwdlen = strrchr(&__pgmname, '/') - &__pgmname + 1; |
108 | __appcwdlen = __appcwdlen > 1023 ? 1023 : __appcwdlen; |
108 | __appcwdlen = __appcwdlen > 1023 ? 1023 : __appcwdlen; |
109 | memcpy(__appcwd, &__pgmname, __appcwdlen); |
109 | memcpy(__appcwd, &__pgmname, __appcwdlen); |
110 | __appcwd[__appcwdlen] = 0; |
110 | __appcwd[__appcwdlen] = 0; |
111 | 111 | ||
112 | set_cwd(__appcwd); |
112 | set_cwd(__appcwd); |
113 | 113 | ||
114 | arg[0] = &__pgmname; |
114 | arg[0] = &__pgmname; |
115 | 115 | ||
116 | if( __cmdline != 0) |
116 | if( __cmdline != 0) |
117 | { |
117 | { |
118 | _argc = 2; |
118 | _argc = 2; |
119 | arg[1] = &__cmdline; |
119 | arg[1] = &__cmdline; |
120 | } else _argc = 1; |
120 | } else _argc = 1; |
121 | 121 | ||
122 | _argv = arg; |
122 | _argv = arg; |
123 | 123 | ||
124 | /* |
124 | /* |
125 | * Sets the default file mode. |
125 | * Sets the default file mode. |
126 | * If _CRT_fmode is set, also set mode for stdin, stdout |
126 | * If _CRT_fmode is set, also set mode for stdin, stdout |
127 | * and stderr, as well |
127 | * and stderr, as well |
128 | * NOTE: DLLs don't do this because that would be rude! |
128 | * NOTE: DLLs don't do this because that would be rude! |
129 | */ |
129 | */ |
130 | // _mingw32_init_fmode (); |
130 | // _mingw32_init_fmode (); |
131 | 131 | ||
132 | 132 | ||
133 | nRet = main (_argc, _argv, NULL); |
133 | nRet = main (_argc, _argv, NULL); |
134 | 134 | ||
135 | /* |
135 | /* |
136 | * Perform exit processing for the C library. This means |
136 | * Perform exit processing for the C library. This means |
137 | * flushing output and calling 'atexit' registered functions. |
137 | * flushing output and calling 'atexit' registered functions. |
138 | */ |
138 | */ |
139 | exit (nRet); |
139 | exit (nRet); |
140 | } |
140 | } |