OSDN Git Service

* configure.in (spu-*-*): Don't skip target-libiberty.
[pf3gnuchains/gcc-fork.git] / gcc / config / spu / crt0.c
1 /* Copyright (C) 2006 Free Software Foundation, Inc.
2   
3    This file is free software; you can redistribute it and/or modify it under
4    the terms of the GNU General Public License as published by the Free
5    Software Foundation; either version 2 of the License, or (at your option)
6    any later version.
7   
8    This file is distributed in the hope that it will be useful, but WITHOUT
9    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11    for more details.
12   
13    You should have received a copy of the GNU General Public License
14    along with this file; see the file COPYING.  If not, write to the Free
15    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
16    02110-1301, USA.  */
17
18 /* As a special exception, if you link this library with files compiled with
19    GCC to produce an executable, this does not cause the resulting executable
20    to be covered by the GNU General Public License.  The exception does not
21    however invalidate any other reasons why the executable file might be covered
22    by the GNU General Public License. */
23
24 extern int main(int, unsigned long long, unsigned long long);
25 void _start(int, unsigned long long, unsigned long long) __attribute__((__naked__));
26
27 extern void exit(int);
28
29 void _exit(int) __attribute__((__naked__));
30
31 typedef void (*func_ptr) (void);
32 typedef __attribute__ ((__vector_size__(16))) unsigned int vec_uint4;
33
34 extern vec_uint4 __stack[];
35 register vec_uint4 si_sp __asm__("$sp");
36 register unsigned int si_r2 __asm__("$2");
37
38 extern char _end[];
39
40 /* If we want these aligned we need to do it in the linker script. */
41 func_ptr __CTOR_LIST__[1]
42   __attribute__ ((__section__(".ctors"), __aligned__(4)))
43   = { (func_ptr) (-1) };
44
45 static func_ptr __DTOR_LIST__[1]
46   __attribute__((__section__(".dtors"), __aligned__(4)))
47   = { (func_ptr) (-1) };
48
49 void *__dso_handle = 0;
50
51 /* According to the BE Linux ABI an SPU module is called with these
52  * parameters.  Also, $2 is set to the Available Stack Size.  */
53 void
54 _start(int spu_id,
55        unsigned long long param,
56        unsigned long long env)
57 {
58   unsigned int stack_size;
59   unsigned int sp = (unsigned int)(__stack - 2);
60
61   /* Initialize the stack.  __stack has been set to point to the top
62      quadword of the stack.  The ABI requires at least a NULL terminated
63      back chain and lr save area.  For example:
64          +----------------+
65          | 0              |
66          +----------------+  <-  __stack (e.g., 0x3fff0)
67          | space for $lr  |
68          +----------------+
69          | back chain     |
70          +----------------+  <-  $sp  (e.g., __stack - 32, 0x3ffd0)
71   */
72   __stack[0] = (vec_uint4){0, 0, 0, 0};
73   __stack[-1] = (vec_uint4){0, 0, 0, 0};
74
75   /* Initialize the Available Stack Size word of the Stack Pointer
76    * information register.  The BE Linux ABI passes the stack size in
77    * $2, or use everything up to _end if $2 == 0. */
78   stack_size = si_r2 == 0 ? sp - (unsigned int)_end : si_r2;
79
80   __stack[-2] = (vec_uint4){(unsigned int)__stack, stack_size, 0, 0};
81
82   si_sp = (vec_uint4){sp, stack_size, 0, 0};
83
84
85   {
86     extern func_ptr __CTOR_END__[];
87     func_ptr *p;
88
89     /* The compiler assumes all symbols are 16 byte aligned, which is
90      * not the case for __CTOR_END__.  This inline assembly makes sure
91      * the address is loaded into a register for which the compiler does
92      * not assume anything about alignment. */
93     __asm__ ("\n" : "=r" (p) : "0" (__CTOR_END__ - 1));
94
95     for (; *p != (func_ptr) -1; p--)
96       (*p) ();
97   }
98
99   exit(main(spu_id, param, env));
100   __asm__ volatile ( "  stop    0x20ff");
101 }
102
103 /* C99 requires _Exit */
104 void _Exit(int) __attribute__((__weak__, __alias__("_exit")));
105
106 void
107 _exit(int rc)
108 {
109   {
110     static func_ptr *p = 0;
111     if (!p)
112       {
113         /* See comment for __CTOR_END__ above. */
114         __asm__ ("" : "=r" (p) : "0" (__DTOR_LIST__ + 1));
115         for (; *p; p++)
116           (*p) ();
117       }
118   }
119   /* Some self modifying code to return 'rc' in the 'stop' insn. */
120   __asm__ volatile (
121     "   ori     $3, %0,0\n"
122     "   lqr     $4, 1f\n"
123     "   cbd     $5, 1f+3($sp)\n"
124     "   shufb   $0, %0, $4, $5\n"
125     "   stqr    $0, 1f\n"
126     "   sync\n"
127     "1:\n"
128     "   stop    0x2000\n"
129     : : "r" (rc) );
130 }
131