1276789Sdim/* ===----- trampoline_setup.c - Implement __trampoline_setup -------------===
2276789Sdim *
3276789Sdim *                     The LLVM Compiler Infrastructure
4276789Sdim *
5276789Sdim * This file is dual licensed under the MIT and the University of Illinois Open
6276789Sdim * Source Licenses. See LICENSE.TXT for details.
7276789Sdim *
8276789Sdim * ===----------------------------------------------------------------------===
9276789Sdim */
10276789Sdim
11276789Sdim#include "int_lib.h"
12276789Sdim
13276789Sdimextern void __clear_cache(void* start, void* end);
14276789Sdim
15276789Sdim/*
16276789Sdim * The ppc compiler generates calls to __trampoline_setup() when creating
17276789Sdim * trampoline functions on the stack for use with nested functions.
18276789Sdim * This function creates a custom 40-byte trampoline function on the stack
19276789Sdim * which loads r11 with a pointer to the outer function's locals
20276789Sdim * and then jumps to the target nested function.
21276789Sdim */
22276789Sdim
23276789Sdim#if __ppc__ && !defined(__powerpc64__)
24276789SdimCOMPILER_RT_ABI void
25276789Sdim__trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
26276789Sdim                   const void* realFunc, void* localsPtr)
27276789Sdim{
28276789Sdim    /* should never happen, but if compiler did not allocate */
29276789Sdim    /* enough space on stack for the trampoline, abort */
30276789Sdim    if ( trampSizeAllocated < 40 )
31276789Sdim        compilerrt_abort();
32276789Sdim
33276789Sdim    /* create trampoline */
34276789Sdim    trampOnStack[0] = 0x7c0802a6;    /* mflr r0 */
35276789Sdim    trampOnStack[1] = 0x4800000d;    /* bl Lbase */
36276789Sdim    trampOnStack[2] = (uint32_t)realFunc;
37276789Sdim    trampOnStack[3] = (uint32_t)localsPtr;
38276789Sdim    trampOnStack[4] = 0x7d6802a6;    /* Lbase: mflr r11 */
39276789Sdim    trampOnStack[5] = 0x818b0000;    /* lwz    r12,0(r11) */
40276789Sdim    trampOnStack[6] = 0x7c0803a6;    /* mtlr r0 */
41276789Sdim    trampOnStack[7] = 0x7d8903a6;    /* mtctr r12 */
42276789Sdim    trampOnStack[8] = 0x816b0004;    /* lwz    r11,4(r11) */
43276789Sdim    trampOnStack[9] = 0x4e800420;    /* bctr */
44276789Sdim
45276789Sdim    /* clear instruction cache */
46276789Sdim    __clear_cache(trampOnStack, &trampOnStack[10]);
47276789Sdim}
48276789Sdim#endif /* __ppc__ && !defined(__powerpc64__) */
49