1 /* Copyright (C) 2006 Free Software Foundation, Inc.
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)
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
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
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. */
24 extern int main(int, unsigned long long, unsigned long long);
25 void _start(int, unsigned long long, unsigned long long) __attribute__((__naked__));
27 extern void exit(int);
29 void _exit(int) __attribute__((__naked__));
31 typedef void (*func_ptr) (void);
32 typedef __attribute__ ((__vector_size__(16))) unsigned int vec_uint4;
34 extern vec_uint4 __stack[];
35 register vec_uint4 si_sp __asm__("$sp");
36 register unsigned int si_r2 __asm__("$2");
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) };
45 static func_ptr __DTOR_LIST__[1]
46 __attribute__((__section__(".dtors"), __aligned__(4)))
47 = { (func_ptr) (-1) };
49 void *__dso_handle = 0;
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. */
55 unsigned long long param,
56 unsigned long long env)
58 unsigned int stack_size;
59 unsigned int sp = (unsigned int)(__stack - 2);
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:
66 +----------------+ <- __stack (e.g., 0x3fff0)
70 +----------------+ <- $sp (e.g., __stack - 32, 0x3ffd0)
72 __stack[0] = (vec_uint4){0, 0, 0, 0};
73 __stack[-1] = (vec_uint4){0, 0, 0, 0};
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;
80 __stack[-2] = (vec_uint4){(unsigned int)__stack, stack_size, 0, 0};
82 si_sp = (vec_uint4){sp, stack_size, 0, 0};
86 extern func_ptr __CTOR_END__[];
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));
95 for (; *p != (func_ptr) -1; p--)
99 exit(main(spu_id, param, env));
100 __asm__ volatile ( " stop 0x20ff");
103 /* C99 requires _Exit */
104 void _Exit(int) __attribute__((__weak__, __alias__("_exit")));
110 static func_ptr *p = 0;
113 /* See comment for __CTOR_END__ above. */
114 __asm__ ("" : "=r" (p) : "0" (__DTOR_LIST__ + 1));
119 /* Some self modifying code to return 'rc' in the 'stop' insn. */
123 " cbd $5, 1f+3($sp)\n"
124 " shufb $0, %0, $4, $5\n"