xref: /openbsd-src/gnu/llvm/compiler-rt/lib/builtins/trampoline_setup.c (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===----- trampoline_setup.c - Implement __trampoline_setup -------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick 
93cab2bb3Spatrick #include "int_lib.h"
103cab2bb3Spatrick 
113cab2bb3Spatrick extern void __clear_cache(void *start, void *end);
123cab2bb3Spatrick 
133cab2bb3Spatrick // The ppc compiler generates calls to __trampoline_setup() when creating
143cab2bb3Spatrick // trampoline functions on the stack for use with nested functions.
153cab2bb3Spatrick // This function creates a custom 40-byte trampoline function on the stack
163cab2bb3Spatrick // which loads r11 with a pointer to the outer function's locals
173cab2bb3Spatrick // and then jumps to the target nested function.
183cab2bb3Spatrick 
19*810390e3Srobert #if __powerpc__ && !defined(__powerpc64__)
__trampoline_setup(uint32_t * trampOnStack,int trampSizeAllocated,const void * realFunc,void * localsPtr)203cab2bb3Spatrick COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack,
213cab2bb3Spatrick                                         int trampSizeAllocated,
223cab2bb3Spatrick                                         const void *realFunc, void *localsPtr) {
233cab2bb3Spatrick   // should never happen, but if compiler did not allocate
243cab2bb3Spatrick   // enough space on stack for the trampoline, abort
253cab2bb3Spatrick   if (trampSizeAllocated < 40)
263cab2bb3Spatrick     compilerrt_abort();
273cab2bb3Spatrick 
283cab2bb3Spatrick   // create trampoline
293cab2bb3Spatrick   trampOnStack[0] = 0x7c0802a6; // mflr r0
303cab2bb3Spatrick   trampOnStack[1] = 0x4800000d; // bl Lbase
313cab2bb3Spatrick   trampOnStack[2] = (uint32_t)realFunc;
323cab2bb3Spatrick   trampOnStack[3] = (uint32_t)localsPtr;
333cab2bb3Spatrick   trampOnStack[4] = 0x7d6802a6; // Lbase: mflr r11
343cab2bb3Spatrick   trampOnStack[5] = 0x818b0000; // lwz    r12,0(r11)
353cab2bb3Spatrick   trampOnStack[6] = 0x7c0803a6; // mtlr r0
363cab2bb3Spatrick   trampOnStack[7] = 0x7d8903a6; // mtctr r12
373cab2bb3Spatrick   trampOnStack[8] = 0x816b0004; // lwz    r11,4(r11)
383cab2bb3Spatrick   trampOnStack[9] = 0x4e800420; // bctr
393cab2bb3Spatrick 
403cab2bb3Spatrick   // clear instruction cache
413cab2bb3Spatrick   __clear_cache(trampOnStack, &trampOnStack[10]);
423cab2bb3Spatrick }
43*810390e3Srobert #endif // __powerpc__ && !defined(__powerpc64__)
44