1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ----------------------------------------------------------------------- 2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org> 3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (c) 2008 Red Hat, Inc. 4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project HPPA Foreign Function Interface 6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc. 7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Permission is hereby granted, free of charge, to any person obtaining 9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a copy of this software and associated documentation files (the 10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ``Software''), to deal in the Software without restriction, including 11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project without limitation the rights to use, copy, modify, merge, publish, 12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project distribute, sublicense, and/or sell copies of the Software, and to 13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project permit persons to whom the Software is furnished to do so, subject to 14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the following conditions: 15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The above copyright notice and this permission notice shall be included 17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in all copies or substantial portions of the Software. 18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project DEALINGS IN THE SOFTWARE. 27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ----------------------------------------------------------------------- */ 28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h> 30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h> 31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h> 33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdio.h> 34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) 36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define MIN_STACK_SIZE 64 38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FIRST_ARG_SLOT 9 39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define DEBUG_LEVEL 0 40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fldw(addr, fpreg) \ 42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg) 43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fstw(fpreg, addr) \ 44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr)) 45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fldd(addr, fpreg) \ 46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg) 47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fstd(fpreg, addr) \ 48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr)) 49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0) 51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic inline int ffi_struct_type(ffi_type *t) 53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t sz = t->size; 55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Small structure results are passed in registers, 57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project larger ones are passed by pointer. Note that 58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project small structures of size 2, 4 and 8 differ from 59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the corresponding integer types in that they have 60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project different alignment requirements. */ 61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (sz <= 1) 63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_UINT8; 64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (sz == 2) 65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_SMALL_STRUCT2; 66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (sz == 3) 67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_SMALL_STRUCT3; 68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (sz == 4) 69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_SMALL_STRUCT4; 70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (sz == 5) 71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_SMALL_STRUCT5; 72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (sz == 6) 73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_SMALL_STRUCT6; 74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (sz == 7) 75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_SMALL_STRUCT7; 76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (sz <= 8) 77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_SMALL_STRUCT8; 78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */ 80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* PA has a downward growing stack, which looks like this: 83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Offset 85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project [ Variable args ] 86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP = (4*(n+9)) arg word N 87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ... 88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP-52 arg word 4 89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project [ Fixed args ] 90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP-48 arg word 3 91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP-44 arg word 2 92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP-40 arg word 1 93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP-36 arg word 0 94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project [ Frame marker ] 95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ... 96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP-20 RP 97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project SP-4 previous SP 98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The first four argument words on the stack are reserved for use by 100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the callee. Instead, the general and floating registers replace 101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the first four argument slots. Non FP arguments are passed solely 102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in the general registers. FP arguments are passed in both general 103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project and floating registers when using libffi. 104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23. 106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Non-FP 64-bit args are passed in register pairs, starting 107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project on an odd numbered register (i.e. r25+r26 and r23+r24). 108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L. 109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FP 64-bit arguments are passed in fr5 and fr7. 110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The registers are allocated in the same manner as stack slots. 112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project This allows the callee to save its arguments on the stack if 113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project necessary: 114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg word 3 -> gr23 or fr7L 116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg word 2 -> gr24 or fr6L or fr7R 117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg word 1 -> gr25 or fr5L 118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg word 0 -> gr26 or fr4L or fr5R 119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Note that fr4R and fr6R are never used for arguments (i.e., 121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project doubles are not passed in fr4 or fr6). 122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The rest of the arguments are passed on the stack starting at SP-52, 124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project but 64-bit arguments need to be aligned to an 8-byte boundary 125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project This means we can have holes either in the register allocation, 127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project or in the stack. */ 128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space 130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project has been allocated for the function's arguments 131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The following code will put everything into the stack frame 133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (which was allocated by the asm routine), and on return 134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the asm routine will load the arguments that should be 135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project passed by register into the appropriate registers 136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project NOTE: We load floating point args in this function... that means we 138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project assume gcc will not mess with fp regs in here. */ 139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes) 141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register unsigned int i; 143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register ffi_type **p_arg; 144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register void **p_argv; 145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int slot = FIRST_ARG_SLOT; 146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *dest_cpy; 147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t len; 148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, 150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif, bytes); 151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_arg = ecif->cif->arg_types; 153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv = ecif->avalue; 154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (i = 0; i < ecif->cif->nargs; i++) 156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int type = (*p_arg)->type; 158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (type) 160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv); 163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv); 167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv); 171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv); 175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT32: 178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT32: 179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_POINTER: 180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), 181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot); 182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv); 183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Align slot for 64-bit type. */ 188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot += (slot & 1) ? 1 : 2; 189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv); 190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* First 4 args go in fr4L - fr7L. */ 194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(3, "Storing UINT32(float) in slot %u\n", slot); 195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv); 196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (slot - FIRST_ARG_SLOT) 197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* First 4 args go in fr4L - fr7L. */ 199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 0: fldw(stack - slot, fr4); break; 200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 1: fldw(stack - slot, fr5); break; 201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 2: fldw(stack - slot, fr6); break; 202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 3: fldw(stack - slot, fr7); break; 203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Align slot for 64-bit type. */ 208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot += (slot & 1) ? 1 : 2; 209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(3, "Storing UINT64(double) at slot %u\n", slot); 210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv); 211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (slot - FIRST_ARG_SLOT) 212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* First 2 args go in fr5, fr7. */ 214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 1: fldd(stack - slot, fr5); break; 215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 3: fldd(stack - slot, fr7); break; 216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX 220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_LONGDOUBLE: 221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Long doubles are passed in the same manner as structures 222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project larger than 8 bytes. */ 223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT32 *)(stack - slot) = (UINT32)(*p_argv); 224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Structs smaller or equal than 4 bytes are passed in one 230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register. Structs smaller or equal 8 bytes are passed in two 231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project registers. Larger structures are passed by pointer. */ 232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project len = (*p_arg)->size; 234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (len <= 4) 235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project dest_cpy = (char *)(stack - slot) + 4 - len; 237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(dest_cpy, (char *)*p_argv, len); 238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (len <= 8) 240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot += (slot & 1) ? 1 : 2; 242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project dest_cpy = (char *)(stack - slot) + 8 - len; 243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(dest_cpy, (char *)*p_argv, len); 244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT32 *)(stack - slot) = (UINT32)(*p_argv); 247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot++; 254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_arg++; 255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv++; 256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Make sure we didn't mess up and scribble on the stack. */ 259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int n; 261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(5, "Stack setup:\n"); 263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (n = 0; n < (bytes + 3) / 4; n++) 264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); } 266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(5, "%08x ", *(stack - n)); 267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(5, "\n"); 269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(slot * 4 <= bytes); 272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return; 274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void ffi_size_stack_pa32(ffi_cif *cif) 277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **ptr; 279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int i; 280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int z = 0; /* # stack slots */ 281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++) 283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int type = (*ptr)->type; 285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (type) 287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z += 2 + (z & 1); /* must start on even regs, so we may waste one */ 292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX 295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_LONGDOUBLE: 296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z += 1; /* pass by ptr, callee will copy */ 299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: /* <= 32-bit values */ 302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z++; 303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* We can fit up to 6 args in the default 64-byte stack frame, 307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if we need more, we need more stack. */ 308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (z <= 6) 309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->bytes = MIN_STACK_SIZE; /* min stack size */ 310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE); 312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(3, "Calculated stack size is %u bytes\n", cif->bytes); 314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing. */ 317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif) 318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Set the return type flag */ 320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->rtype->type) 321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_VOID: 323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = (unsigned) cif->rtype->type; 326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX 329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_LONGDOUBLE: 330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Long doubles are treated like a structure. */ 331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = FFI_TYPE_STRUCT; 332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* For the return type we have to check the size of the structures. 337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project If the size is smaller or equal 4 bytes, the result is given back 338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in one register. If the size is smaller or equal 8 bytes than we 339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return the result in two registers. But if the size is bigger than 340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 8 bytes, we work with pointers. */ 341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = ffi_struct_type(cif->rtype); 342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = FFI_TYPE_UINT64; 347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = FFI_TYPE_INT; 351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Lucky us, because of the unique PA ABI we get to do our 355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project own stack sizing. */ 356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->abi) 357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_PA32: 359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_size_stack_pa32(cif); 360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned), 371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif *, unsigned, unsigned, unsigned *, 372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void (*fn)(void)); 373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif ecif; 377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.cif = cif; 379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.avalue = avalue; 380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* If the return value is a struct and we don't have a return 382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project value address then we need to make one. */ 383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (rvalue == NULL 385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX 386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && (cif->rtype->type == FFI_TYPE_STRUCT 387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project || cif->rtype->type == FFI_TYPE_LONGDOUBLE)) 388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && cif->rtype->type == FFI_TYPE_STRUCT) 390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = alloca(cif->rtype->size); 393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = rvalue; 396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->abi) 399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_PA32: 401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn); 402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes, 403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags, ecif.rvalue, fn); 404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURES 413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This is more-or-less an inverse of ffi_call -- we have arguments on 414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the stack, and we need to fill them into a cif structure and invoke 415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the user function. This really ought to be in asm to make sure 416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the compiler doesn't do things we don't expect. */ 417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) 418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif *cif; 420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **avalue; 421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *rvalue; 422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project UINT32 ret[2]; /* function can return up to 64-bits in registers */ 423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **p_arg; 424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *tmp; 425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int i, avn; 426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int slot = FIRST_ARG_SLOT; 427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register UINT32 r28 asm("r28"); 428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif = closure->cif; 430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* If returning via structure, callee will write to our pointer. */ 432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->flags == FFI_TYPE_STRUCT) 433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project rvalue = (void *)r28; 434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project rvalue = &ret[0]; 436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG); 438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avn = cif->nargs; 439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_arg = cif->arg_types; 440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (i = 0; i < avn; i++) 442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int type = (*p_arg)->type; 444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (type) 446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT32: 452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT32: 453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_POINTER: 454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size; 455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot += (slot & 1) ? 1 : 2; 460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = (void *)(stack - slot); 461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_LINUX 465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* The closure call is indirect. In Linux, floating point 466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arguments in indirect calls with a prototype are passed 467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in the floating point registers instead of the general 468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project registers. So, we need to replace what was previously 469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project stored in the current slot with the value in the 470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project corresponding floating point register. */ 471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (slot - FIRST_ARG_SLOT) 472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 0: fstw(fr4, (void *)(stack - slot)); break; 474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 1: fstw(fr5, (void *)(stack - slot)); break; 475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 2: fstw(fr6, (void *)(stack - slot)); break; 476a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 3: fstw(fr7, (void *)(stack - slot)); break; 477a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 478a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 479a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = (void *)(stack - slot); 480a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 481a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 482a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 483a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot += (slot & 1) ? 1 : 2; 484a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_LINUX 485a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* See previous comment for FFI_TYPE_FLOAT. */ 486a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (slot - FIRST_ARG_SLOT) 487a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 488a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 1: fstd(fr5, (void *)(stack - slot)); break; 489a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case 3: fstd(fr7, (void *)(stack - slot)); break; 490a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 491a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 492a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = (void *)(stack - slot); 493a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 494a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 495a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 496a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Structs smaller or equal than 4 bytes are passed in one 497a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register. Structs smaller or equal 8 bytes are passed in two 498a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project registers. Larger structures are passed by pointer. */ 499a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if((*p_arg)->size <= 4) 500a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 501a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = (void *)(stack - slot) + sizeof(UINT32) - 502a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (*p_arg)->size; 503a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 504a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if ((*p_arg)->size <= 8) 505a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 506a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot += (slot & 1) ? 1 : 2; 507a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = (void *)(stack - slot) + sizeof(UINT64) - 508a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (*p_arg)->size; 509a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 510a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 511a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = (void *) *(stack - slot); 512a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 513a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 514a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 515a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 516a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 517a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 518a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project slot++; 519a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_arg++; 520a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 521a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 522a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Invoke the closure. */ 523a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (closure->fun) (cif, rvalue, avalue, closure->user_data); 524a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 525a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], 526a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ret[1]); 527a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 528a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Store the result using the lower 2 bytes of the flags. */ 529a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->flags) 530a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 531a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 532a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24); 533a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 534a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 535a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24); 536a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 537a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 538a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16); 539a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 540a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 541a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16); 542a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 543a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_INT: 544a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT32: 545a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT32: 546a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT) = ret[0]; 547a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 548a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 549a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 550a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT) = ret[0]; 551a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT - 1) = ret[1]; 552a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 553a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 554a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 555a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fldd(rvalue, fr4); 556a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 557a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 558a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 559a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fldw(rvalue, fr4); 560a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 561a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 562a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 563a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Don't need a return value, done by caller. */ 564a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 565a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 566a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT2: 567a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT3: 568a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT4: 569a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tmp = (void*)(stack - FIRST_ARG_SLOT); 570a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tmp += 4 - cif->rtype->size; 571a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy((void*)tmp, &ret[0], cif->rtype->size); 572a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 573a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 574a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT5: 575a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT6: 576a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT7: 577a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT8: 578a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 579a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int ret2[2]; 580a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int off; 581a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 582a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Right justify ret[0] and ret[1] */ 583a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->flags) 584a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 585a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT5: off = 3; break; 586a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT6: off = 2; break; 587a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SMALL_STRUCT7: off = 1; break; 588a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: off = 0; break; 589a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 590a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 591a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memset (ret2, 0, sizeof (ret2)); 592a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy ((char *)ret2 + off, ret, 8 - off); 593a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 594a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT) = ret2[0]; 595a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(stack - FIRST_ARG_SLOT - 1) = ret2[1]; 596a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 597a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 598a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 599a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_POINTER: 600a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_VOID: 601a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 602a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 603a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 604a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project debug(0, "assert with cif->flags: %d\n",cif->flags); 605a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 606a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 607a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 608a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 609a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 610a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 611a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Fill in a closure to refer to the specified fun and user_data. 612a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif specifies the argument and result types for fun. 613a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The cif must already be prep'ed. */ 614a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 615a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_pa32(void); 616a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 617a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status 618a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure, 619a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif* cif, 620a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void (*fun)(ffi_cif*,void*,void**,void*), 621a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *user_data, 622a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *codeloc) 623a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 624a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project UINT32 *tramp = (UINT32 *)(closure->tramp); 625a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX 626a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project UINT32 *tmp; 627a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 628a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 629a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (cif->abi == FFI_PA32); 630a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 631a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Make a small trampoline that will branch to our 632a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project handler function. Use PC-relative addressing. */ 633a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 634a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_LINUX 635a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ 636a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ 637a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */ 638a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ 639a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ 640a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */ 641a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ 642a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2); 643a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 644a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Flush d/icache -- have to flush up 2 two lines because of 645a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project alignment. */ 646a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __asm__ volatile( 647a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fdc 0(%0)\n\t" 648a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fdc %1(%0)\n\t" 649a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fic 0(%%sr4, %0)\n\t" 650a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fic %1(%%sr4, %0)\n\t" 651a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "sync\n\t" 652a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 653a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 654a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 655a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 656a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 657a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 658a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n" 659a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : 660a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : "r"((unsigned long)tramp & ~31), 661a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "r"(32 /* stride */) 662a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : "memory"); 663a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 664a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 665a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX 666a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ 667a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ 668a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */ 669a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ 670a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ 671a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */ 672a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */ 673a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */ 674a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ 675a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2); 676a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 677a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Flush d/icache -- have to flush three lines because of alignment. */ 678a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __asm__ volatile( 679a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "copy %1,%0\n\t" 680a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fdc,m %2(%0)\n\t" 681a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fdc,m %2(%0)\n\t" 682a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fdc,m %2(%0)\n\t" 683a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "ldsid (%1),%0\n\t" 684a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "mtsp %0,%%sr0\n\t" 685a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "copy %1,%0\n\t" 686a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fic,m %2(%%sr0,%0)\n\t" 687a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fic,m %2(%%sr0,%0)\n\t" 688a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "fic,m %2(%%sr0,%0)\n\t" 689a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "sync\n\t" 690a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 691a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 692a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 693a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 694a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 695a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n\t" 696a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "nop\n" 697a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : "=&r" ((unsigned long)tmp) 698a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : "r" ((unsigned long)tramp & ~31), 699a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project "r" (32/* stride */) 700a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : "memory"); 701a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 702a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 703a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->cif = cif; 704a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->user_data = user_data; 705a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->fun = fun; 706a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 707a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 708a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 709a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 710