diff options
Diffstat (limited to 'libffi/src/sh64')
| -rw-r--r-- | libffi/src/sh64/ffi.c | 448 | ||||
| -rw-r--r-- | libffi/src/sh64/ffitarget.h | 52 | ||||
| -rw-r--r-- | libffi/src/sh64/sysv.S | 484 | 
3 files changed, 984 insertions, 0 deletions
| diff --git a/libffi/src/sh64/ffi.c b/libffi/src/sh64/ffi.c new file mode 100644 index 0000000..7709603 --- /dev/null +++ b/libffi/src/sh64/ffi.c @@ -0,0 +1,448 @@ +/* ----------------------------------------------------------------------- +   ffi.c - Copyright (c) 2003 Kaz Kojima +    +   SuperH SHmedia Foreign Function Interface  + +   Permission is hereby granted, free of charge, to any person obtaining +   a copy of this software and associated documentation files (the +   ``Software''), to deal in the Software without restriction, including +   without limitation the rights to use, copy, modify, merge, publish, +   distribute, sublicense, and/or sell copies of the Software, and to +   permit persons to whom the Software is furnished to do so, subject to +   the following conditions: + +   The above copyright notice and this permission notice shall be included +   in all copies or substantial portions of the Software. + +   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS +   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR +   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +   OTHER DEALINGS IN THE SOFTWARE. +   ----------------------------------------------------------------------- */ + +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> + +#define NGREGARG 8 +#define NFREGARG 12 + +/* If the structure has essentialy an unique element, return its type.  */ +static int +simple_type (ffi_type *arg) +{ +  if (arg->type != FFI_TYPE_STRUCT) +    return arg->type; +  else if (arg->elements[1]) +    return FFI_TYPE_STRUCT; + +  return simple_type (arg->elements[0]); +} + +static int +return_type (ffi_type *arg) +{ +  unsigned short type; + +  if (arg->type != FFI_TYPE_STRUCT) +    return arg->type; + +  type = simple_type (arg->elements[0]); +  if (! arg->elements[1]) +    { +      switch (type) +	{ +	case FFI_TYPE_SINT8: +	case FFI_TYPE_UINT8: +	case FFI_TYPE_SINT16: +	case FFI_TYPE_UINT16: +	case FFI_TYPE_SINT32: +	case FFI_TYPE_UINT32: +	case FFI_TYPE_SINT64: +	case FFI_TYPE_UINT64: +	  return FFI_TYPE_UINT64; + +	default: +	  return type; +	} +    } + +  /* gcc uses r2 if the result can be packed in on register.  */ +  if (arg->size <= sizeof (UINT64)) +    return FFI_TYPE_UINT64; + +  return FFI_TYPE_STRUCT; +} + +/* ffi_prep_args is called by the assembly routine once stack space +   has been allocated for the function's arguments */ + +/*@-exportheader@*/ +void ffi_prep_args(char *stack, extended_cif *ecif) +/*@=exportheader@*/ +{ +  register unsigned int i; +  register unsigned int avn; +  register void **p_argv; +  register char *argp; +  register ffi_type **p_arg; + +  argp = stack; + +  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) +    { +      *(void **) argp = ecif->rvalue; +      argp += sizeof (UINT64); +    } + +  avn = ecif->cif->nargs; +  p_argv = ecif->avalue; + +  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) +    { +      size_t z; + +      z = (*p_arg)->size; +      if (z < sizeof (UINT32)) +	{ +	  switch ((*p_arg)->type) +	    { +	    case FFI_TYPE_SINT8: +	      *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv); +	      break; +   +	    case FFI_TYPE_UINT8: +	      *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv); +	      break; +   +	    case FFI_TYPE_SINT16: +	      *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv); +	      break; +   +	    case FFI_TYPE_UINT16: +	      *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv); +	      break; +   +	    case FFI_TYPE_STRUCT: +	      *(UINT64 *) argp = (UINT64) *(UINT32 *)(*p_argv); +	      break; + +	    default: +	      FFI_ASSERT(0); +	    } +	  argp += sizeof (UINT64); +	} +      else if (z == sizeof (UINT32)) +	{ +	  *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv); +	  argp += sizeof (UINT64); +	} +      else if (z == sizeof (UINT64)) +	{ +	  *(UINT64 *) argp = *(UINT64 *) (*p_argv); +	  argp += sizeof (UINT64); +	} +      else +	{ +	  int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64); + +	  memcpy (argp, *p_argv, z); +	  argp += n * sizeof (UINT64); +	} +    } + +  return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ +  int i, j; +  int size, type; +  int n, m; +  int greg; +  int freg; + +  greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0); +  freg = 0; +  cif->flags2 = 0; + +  for (i = j = 0; i < cif->nargs; i++) +    { +      type = (cif->arg_types)[i]->type; +      switch (type) +	{ +	case FFI_TYPE_FLOAT: +	  greg++; +	  cif->bytes += sizeof (UINT64) - sizeof (float); +	  if (freg >= NFREGARG - 1) +	    continue; +	  freg++; +	  cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); +	  break; + +	case FFI_TYPE_DOUBLE: +	  if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG) +	    continue; +	  if ((freg + 1) < NFREGARG) +	    { +	      freg = (freg + 1) & ~1; +	      freg += 2; +	      cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); +	    } +	  else +	    cif->flags2 += FFI_TYPE_INT << (2 * j++); +	  break; +	       +	default: +	  size = (cif->arg_types)[i]->size; +	  if (size < sizeof (UINT64)) +	    cif->bytes += sizeof (UINT64) - size; +	  n = (size + sizeof (UINT64) - 1) / sizeof (UINT64); +	  if (greg >= NGREGARG) +	    continue; +	  else if (greg + n - 1 >= NGREGARG) +	    greg = NGREGARG; +	  else +	    greg += n; +	  for (m = 0; m < n; m++) +	    cif->flags2 += FFI_TYPE_INT << (2 * j++); +	  break; +	} +    } + +  /* Set the return type flag */ +  switch (cif->rtype->type) +    { +    case FFI_TYPE_STRUCT: +      cif->flags = return_type (cif->rtype); +      break; + +    case FFI_TYPE_VOID: +    case FFI_TYPE_FLOAT: +    case FFI_TYPE_DOUBLE: +    case FFI_TYPE_SINT64: +    case FFI_TYPE_UINT64: +      cif->flags = cif->rtype->type; +      break; + +    default: +      cif->flags = FFI_TYPE_INT; +      break; +    } + +  return FFI_OK; +} + +/*@-declundef@*/ +/*@-exportheader@*/ +extern void ffi_call_SYSV(void (*)(char *, extended_cif *),  +			  /*@out@*/ extended_cif *,  +			  unsigned, unsigned, long long, +			  /*@out@*/ unsigned *,  +			  void (*fn)()); +/*@=declundef@*/ +/*@=exportheader@*/ + +void ffi_call(/*@dependent@*/ ffi_cif *cif,  +	      void (*fn)(),  +	      /*@out@*/ void *rvalue,  +	      /*@dependent@*/ void **avalue) +{ +  extended_cif ecif; + +  ecif.cif = cif; +  ecif.avalue = avalue; +   +  /* If the return value is a struct and we don't have a return	*/ +  /* value address then we need to make one		        */ + +  if ((rvalue == NULL) &&  +      (cif->rtype->type == FFI_TYPE_STRUCT)) +    { +      /*@-sysunrecog@*/ +      ecif.rvalue = alloca(cif->rtype->size); +      /*@=sysunrecog@*/ +    } +  else +    ecif.rvalue = rvalue; + +  switch (cif->abi)  +    { +    case FFI_SYSV: +      /*@-usedef@*/ +      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,  +		    cif->flags, cif->flags2, ecif.rvalue, fn); +      /*@=usedef@*/ +      break; +    default: +      FFI_ASSERT(0); +      break; +    } +} + +extern void ffi_closure_SYSV (void); +extern void __ic_invalidate (void *line); + +ffi_status +ffi_prep_closure (ffi_closure *closure, +		  ffi_cif *cif, +		  void (*fun)(ffi_cif*, void*, void**, void*), +		  void *user_data) +{ +  unsigned int *tramp; + +  FFI_ASSERT (cif->abi == FFI_GCC_SYSV); + +  tramp = (unsigned int *) &closure->tramp[0]; +  /* Since ffi_closure is an aligned object, the ffi trampoline is +     called as an SHcompact code.  Sigh. +     SHcompact part: +     mova @(1,pc),r0; add #1,r0; jmp @r0; nop; +     SHmedia part: +     movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0 +     movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63  */ +#ifdef __LITTLE_ENDIAN__ +  tramp[0] = 0x7001c701; +  tramp[1] = 0x0009402b; +#else +  tramp[0] = 0xc7017001; +  tramp[1] = 0x402b0009; +#endif +  tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10; +  tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10; +  tramp[4] = 0x6bf10600; +  tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10; +  tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10; +  tramp[7] = 0x4401fff0; + +  closure->cif = cif; +  closure->fun = fun; +  closure->user_data = user_data; + +  /* Flush the icache.  */ +  asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp)); + +  return FFI_OK; +} + +/* Basically the trampoline invokes ffi_closure_SYSV, and on  + * entry, r3 holds the address of the closure. + * After storing the registers that could possibly contain + * parameters to be passed into the stack frame and setting + * up space for a return value, ffi_closure_SYSV invokes the  + * following helper function to do most of the work. + */ + +int +ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,  +			 UINT64 *pgr, UINT64 *pfr, UINT64 *pst) +{ +  void **avalue; +  ffi_type **p_arg; +  int i, avn; +  int greg, freg; +  ffi_cif *cif; + +  cif = closure->cif; +  avalue = alloca (cif->nargs * sizeof (void *)); + +  /* Copy the caller's structure return value address so that the closure +     returns the data directly to the caller.  */ +  if (cif->rtype->type == FFI_TYPE_STRUCT) +    { +      rvalue = *pgr; +      greg = 1; +    } +  else +    greg = 0; + +  freg = 0; +  cif = closure->cif; +  avn = cif->nargs; + +  /* Grab the addresses of the arguments from the stack frame.  */ +  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) +    { +      size_t z; +      void *p; + +      z = (*p_arg)->size; +      if (z < sizeof (UINT32)) +	{ +	  p = pgr + greg++; + +	  switch ((*p_arg)->type) +	    { +	    case FFI_TYPE_SINT8: +	    case FFI_TYPE_UINT8: +	    case FFI_TYPE_SINT16: +	    case FFI_TYPE_UINT16: +	    case FFI_TYPE_STRUCT: +#ifdef __LITTLE_ENDIAN__ +	      avalue[i] = p; +#else +	      avalue[i] = ((char *) p) + sizeof (UINT32) - z; +#endif +	      break; + +	    default: +	      FFI_ASSERT(0); +	    } +	} +      else if (z == sizeof (UINT32)) +	{ +	  if ((*p_arg)->type == FFI_TYPE_FLOAT) +	    { +	      if (freg < NFREGARG - 1) +#ifdef __LITTLE_ENDIAN__ +		avalue[i] = (UINT32 *) pfr + (1 ^ freg++); +#else +		avalue[i] = (UINT32 *) pfr + freg++; +#endif +	      else +#ifdef __LITTLE_ENDIAN__ +		avalue[i] = pgr + greg; +#else +		avalue[i] = (UINT32 *) (pgr + greg) + 1; +#endif +	    } +	  else +#ifdef __LITTLE_ENDIAN__ +	    avalue[i] = pgr + greg; +#else +	    avalue[i] = (UINT32 *) (pgr + greg) + 1; +#endif +	  greg++; +	} +      else if ((*p_arg)->type == FFI_TYPE_DOUBLE) +	{ +	  if (freg + 1 >= NFREGARG) +	    avalue[i] = pgr + greg; +	  else +	    { +	      freg = (freg + 1) & ~1; +	      avalue[i] = pfr + (freg >> 1); +	      freg += 2; +	    } +	  greg++; +	} +      else +	{ +	  int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64); + +	  avalue[i] = pgr + greg; +	  greg += n; +	} +    } + +  (closure->fun) (cif, rvalue, avalue, closure->user_data); + +  /* Tell ffi_closure_SYSV how to perform return type promotions.  */ +  return cif->rtype->type; +} + diff --git a/libffi/src/sh64/ffitarget.h b/libffi/src/sh64/ffitarget.h new file mode 100644 index 0000000..a174d09 --- /dev/null +++ b/libffi/src/sh64/ffitarget.h @@ -0,0 +1,52 @@ +/* -----------------------------------------------------------------*-C-*- +   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc. +   Target configuration macros for SuperH - SHmedia. + +   Permission is hereby granted, free of charge, to any person obtaining +   a copy of this software and associated documentation files (the +   ``Software''), to deal in the Software without restriction, including +   without limitation the rights to use, copy, modify, merge, publish, +   distribute, sublicense, and/or sell copies of the Software, and to +   permit persons to whom the Software is furnished to do so, subject to +   the following conditions: + +   The above copyright notice and this permission notice shall be included +   in all copies or substantial portions of the Software. + +   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS +   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR +   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +   OTHER DEALINGS IN THE SOFTWARE. + +   ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +/* ---- Generic type definitions ----------------------------------------- */ + +#ifndef LIBFFI_ASM +typedef unsigned long          ffi_arg; +typedef signed long            ffi_sarg; + +typedef enum ffi_abi { +  FFI_FIRST_ABI = 0, +  FFI_SYSV, +  FFI_DEFAULT_ABI = FFI_SYSV, +  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 +} ffi_abi; + +#define FFI_EXTRA_CIF_FIELDS long long flags2 +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 32 +#define FFI_NATIVE_RAW_API 0 + +#endif + diff --git a/libffi/src/sh64/sysv.S b/libffi/src/sh64/sysv.S new file mode 100644 index 0000000..949f69f --- /dev/null +++ b/libffi/src/sh64/sysv.S @@ -0,0 +1,484 @@ +/* ----------------------------------------------------------------------- +   sysv.S - Copyright (c) 2003 Kaz Kojima +    +   SuperH SHmedia Foreign Function Interface  + +   Permission is hereby granted, free of charge, to any person obtaining +   a copy of this software and associated documentation files (the +   ``Software''), to deal in the Software without restriction, including +   without limitation the rights to use, copy, modify, merge, publish, +   distribute, sublicense, and/or sell copies of the Software, and to +   permit persons to whom the Software is furnished to do so, subject to +   the following conditions: + +   The above copyright notice and this permission notice shall be included +   in all copies or substantial portions of the Software. + +   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS +   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR +   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +   OTHER DEALINGS IN THE SOFTWARE. +   ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM	 +#include <fficonfig.h> +#include <ffi.h> +#ifdef HAVE_MACHINE_ASM_H +#include <machine/asm.h> +#else +/* XXX these lose for some platforms, I'm sure. */ +#define CNAME(x) x +#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): +#endif + +#ifdef __LITTLE_ENDIAN__ +#define OFS_FLT	0 +#else +#define OFS_FLT	4 +#endif + +	.section	.text..SHmedia32,"ax" + +	# r2:	ffi_prep_args +	# r3:	&ecif +	# r4:	bytes +	# r5:	flags +	# r6:	flags2 +	# r7:	rvalue +	# r8:	fn + +	# This assumes we are using gas. +	.align	5 +ENTRY(ffi_call_SYSV) +	# Save registers +.LFB1: +	addi.l	r15, -48, r15 +.LCFI0: +	st.q	r15, 40, r32 +	st.q	r15, 32, r31 +	st.q	r15, 24, r30 +	st.q	r15, 16, r29 +	st.q	r15, 8, r28 +	st.l	r15, 4, r18 +	st.l	r15, 0, r14 +	add.l	r15, r63, r14 +.LCFI1: +#	add	r4, r63, r28 +	add	r5, r63, r29 +	add	r6, r63, r30 +	add	r7, r63, r31 +	add	r8, r63, r32 + +	addi	r4, (64 + 7), r4 +	andi	r4, ~7, r4 +	sub.l	r15, r4, r15 + +	ptabs/l	r2, tr0 +	add	r15, r63, r2 +	blink	tr0, r18 + +	addi	r15, 64, r22 +	movi	0, r0 +	movi	0, r1 + +	pt/l	1f, tr1 +	bnei/l	r29, FFI_TYPE_STRUCT, tr1 +	ld.l	r15, 0, r19 +	addi	r15, 8, r15 +	addi	r0, 1, r0 +1: + +.L_pass: +	andi	r30, 3, r20 +	shlri	r30, 2, r30 + +	pt/l	.L_call_it, tr0 +	pt/l	.L_pass_i, tr1 +	pt/l	.L_pass_f, tr2 + +	beqi/l	r20, FFI_TYPE_VOID, tr0 +	beqi/l	r20, FFI_TYPE_INT, tr1 +	beqi/l	r20, FFI_TYPE_FLOAT, tr2 + +.L_pass_d: +	addi	r0, 1, r0 +	addi	r1, 1, r1 +	andi	r1, ~1, r1 + +	pt/l	3f, tr0 +	movi	12, r20 +	bge/l	r1, r20, tr0 + +	pt/l	.L_pop_d, tr1 +	pt/l	2f, tr0 +	blink	tr1, r63 +2: +	addi.l	r15, 8, r15 +3: +	pt/l	.L_pass, tr0 +	addi	r1, 2, r1 +	blink	tr0, r63 + +.L_pop_d: +	pt/l	.L_pop_d_tbl, tr1 +	gettr	tr1, r20 +	shlli	r1, 2, r21 +	add	r20, r21, r20 +	ptabs/l	r20, tr1 +	blink	tr1, r63 + +.L_pop_d_tbl: +	fld.d	r15, 0, dr0 +	blink	tr0, r63 +	fld.d	r15, 0, dr2 +	blink	tr0, r63 +	fld.d	r15, 0, dr4 +	blink	tr0, r63 +	fld.d	r15, 0, dr6 +	blink	tr0, r63 +	fld.d	r15, 0, dr8 +	blink	tr0, r63 +	fld.d	r15, 0, dr10 +	blink	tr0, r63 + +.L_pass_f: +	addi	r0, 1, r0 +	pt/l	3f, tr0 +	movi	12, r20 +	bge/l	r1, r20, tr0 + +	pt/l	.L_pop_f, tr1 +	pt/l	2f, tr0 +	blink	tr1, r63 +2: +	addi.l	r15, 8, r15 +3: +	pt/l	.L_pass, tr0 +	addi	r1, 1, r1 +	blink	tr0, r63 + +.L_pop_f: +	pt/l	.L_pop_f_tbl, tr1 +	gettr	tr1, r20 +	shlli	r1, 3, r21 +	add	r20, r21, r20 +	ptabs/l	r20, tr1 +	blink	tr1, r63 + +.L_pop_f_tbl: +	fld.s	r15, OFS_FLT, fr0 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr1 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr2 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr3 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr4 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr5 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr6 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr7 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr8 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr9 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr10 +	blink	tr0, r63 +	fld.s	r15, OFS_FLT, fr11 +	blink	tr0, r63 + +.L_pass_i: +	pt/l	3f, tr0 +	movi	8, r20 +	bge/l	r0, r20, tr0 + +	pt/l	.L_pop_i, tr1 +	pt/l	2f, tr0 +	blink	tr1, r63 +2: +	addi.l	r15, 8, r15 +3: +	pt/l	.L_pass, tr0 +	addi	r0, 1, r0 +	blink	tr0, r63 + +.L_pop_i: +	pt/l	.L_pop_i_tbl, tr1 +	gettr	tr1, r20 +	shlli	r0, 3, r21 +	add	r20, r21, r20 +	ptabs/l	r20, tr1 +	blink	tr1, r63 + +.L_pop_i_tbl: +	ld.q	r15, 0, r2 +	blink	tr0, r63 +	ld.q	r15, 0, r3 +	blink	tr0, r63 +	ld.q	r15, 0, r4 +	blink	tr0, r63 +	ld.q	r15, 0, r5 +	blink	tr0, r63 +	ld.q	r15, 0, r6 +	blink	tr0, r63 +	ld.q	r15, 0, r7 +	blink	tr0, r63 +	ld.q	r15, 0, r8 +	blink	tr0, r63 +	ld.q	r15, 0, r9 +	blink	tr0, r63 + +.L_call_it: +	# call function +	pt/l	1f, tr1 +	bnei/l	r29, FFI_TYPE_STRUCT, tr1 +	add	r19, r63, r2 +1: +	add	r22, r63, r15 +	ptabs/l	r32, tr0 +	blink	tr0, r18 + +	pt/l	.L_ret_i, tr0 +	pt/l	.L_ret_ll, tr1 +	pt/l	.L_ret_d, tr2 +	pt/l	.L_ret_f, tr3 +	pt/l	.L_epilogue, tr4 + +	beqi/l	r29, FFI_TYPE_INT, tr0 +	beqi/l	r29, FFI_TYPE_SINT64, tr1 +	beqi/l	r29, FFI_TYPE_UINT64, tr1 +	beqi/l	r29, FFI_TYPE_DOUBLE, tr2 +	beqi/l	r29, FFI_TYPE_FLOAT, tr3 +	blink	tr4, r63 + +.L_ret_d: +	fst.d	r31, 0, dr0 +	blink	tr4, r63 + +.L_ret_ll: +	st.q	r31, 0, r2 +	blink	tr4, r63 + +.L_ret_f: +	fst.s	r31, OFS_FLT, fr0 +	blink	tr4, r63 + +.L_ret_i: +	st.l	r31, 0, r2 +	# Fall + +.L_epilogue: +	# Remove the space we pushed for the args +	add	r14, r63, r15 + +	ld.l	r15, 0, r14 +	ld.l	r15, 4, r18 +	ld.q	r15, 8, r28 +	ld.q	r15, 16, r29 +	ld.q	r15, 24, r30 +	ld.q	r15, 32, r31 +	ld.q	r15, 40, r32 +	addi.l	r15, 48, r15 +	ptabs	r18, tr0 +	blink	tr0, r63 + +.LFE1: +.ffi_call_SYSV_end: +	.size	 CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) + +	.align	5 +ENTRY(ffi_closure_SYSV) +.LFB2: +	addi.l	r15, -136, r15 +.LCFI2: +	st.l	r15, 12, r18 +	st.l	r15, 8, r14 +	st.l	r15, 4, r12 +	add	r15, r63, r14 +.LCFI3: +	/* Stack layout:	 +	   ... +	   64 bytes (register parameters) +	   48 bytes (floating register parameters) +	    8 bytes (result) +	    4 bytes (r18) +	    4 bytes (r14) +	    4 bytes (r12) +	    4 bytes (for align) +	   <- new stack pointer +	*/ +	fst.d	r14, 24, dr0 +	fst.d	r14, 32, dr2 +	fst.d	r14, 40, dr4 +	fst.d	r14, 48, dr6 +	fst.d	r14, 56, dr8 +	fst.d	r14, 64, dr10 +	st.q	r14, 72, r2 +	st.q	r14, 80, r3 +	st.q	r14, 88, r4 +	st.q	r14, 96, r5 +	st.q	r14, 104, r6 +	st.q	r14, 112, r7 +	st.q	r14, 120, r8 +	st.q	r14, 128, r9 + +	add	r1, r63, r2 +	addi	r14, 16, r3 +	addi	r14, 72, r4 +	addi	r14, 24, r5 +	addi	r14, 136, r6 +#ifdef PIC +	movi	(((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12 +        shori	((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12 +.LPCS0:	ptrel/u r12, tr0 +	movi	((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1 +	gettr	tr0, r12 +	ldx.l	r1, r12, r1 +	ptabs	r1, tr0 +#else +	pt/l	ffi_closure_helper_SYSV, tr0 +#endif +	blink	tr0, r18 + +	shlli	r2, 1, r1 +        movi    (((datalabel .L_table) >> 16) & 65535), r2 +        shori   ((datalabel .L_table) & 65535), r2 +        ldx.w   r2, r1, r1 +        add     r1, r2, r1 +	pt/l	.L_case_v, tr1 +        ptabs   r1, tr0 +        blink   tr0, r63 + +        .align 2 +.L_table: +	.word	.L_case_v - datalabel .L_table	/* FFI_TYPE_VOID */ +	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_INT */ +	.word	.L_case_f - datalabel .L_table	/* FFI_TYPE_FLOAT */ +	.word	.L_case_d - datalabel .L_table	/* FFI_TYPE_DOUBLE */ +	.word	.L_case_d - datalabel .L_table	/* FFI_TYPE_LONGDOUBLE */ +	.word	.L_case_uq - datalabel .L_table	/* FFI_TYPE_UINT8 */ +	.word	.L_case_q - datalabel .L_table	/* FFI_TYPE_SINT8 */ +	.word	.L_case_uh - datalabel .L_table	/* FFI_TYPE_UINT16 */ +	.word	.L_case_h - datalabel .L_table	/* FFI_TYPE_SINT16 */ +	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_UINT32 */ +	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_SINT32 */ +	.word	.L_case_ll - datalabel .L_table	/* FFI_TYPE_UINT64 */ +	.word	.L_case_ll - datalabel .L_table	/* FFI_TYPE_SINT64 */ +	.word	.L_case_v - datalabel .L_table	/* FFI_TYPE_STRUCT */ +	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_POINTER */ + +        .align 2 +.L_case_d: +	fld.d	r14, 16, dr0 +	blink	tr1, r63 +.L_case_f: +	fld.s	r14, 16, fr0 +	blink	tr1, r63 +.L_case_ll: +	ld.q	r14, 16, r2 +	blink	tr1, r63 +.L_case_i: +	ld.l	r14, 16, r2 +	blink	tr1, r63 +.L_case_q: +	ld.b	r14, 16, r2 +	blink	tr1, r63 +.L_case_uq: +	ld.ub	r14, 16, r2 +	blink	tr1, r63 +.L_case_h: +	ld.w	r14, 16, r2 +	blink	tr1, r63 +.L_case_uh: +	ld.uw	r14, 16, r2 +	blink	tr1, r63 +.L_case_v: +	add.l	r14, r63, r15 +	ld.l	r15, 4, r12 +	ld.l	r15, 8, r14 +	ld.l	r15, 12, r18 +	addi.l	r15, 136, r15 +	ptabs	r18, tr0 +	blink	tr0, r63 + +.LFE2: +.ffi_closure_SYSV_end: +	.size	 CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) + +	.section	".eh_frame","aw",@progbits +__FRAME_BEGIN__: +	.4byte	.LECIE1-.LSCIE1	/* Length of Common Information Entry */ +.LSCIE1: +	.4byte	0x0	/* CIE Identifier Tag */ +	.byte	0x1	/* CIE Version */ +	.ascii "zR\0"	/* CIE Augmentation */ +	.uleb128 0x1	/* CIE Code Alignment Factor */ +	.sleb128 -4	/* CIE Data Alignment Factor */ +	.byte	0x12	/* CIE RA Column */ +	.uleb128 0x1	/* Augmentation size */ +	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */ +	.byte	0xc	/* DW_CFA_def_cfa */ +	.uleb128 0xf +	.uleb128 0x0 +	.align	2 +.LECIE1: +.LSFDE1: +	.4byte	datalabel .LEFDE1-datalabel .LASFDE1	/* FDE Length */ +.LASFDE1: +	.4byte	datalabel .LASFDE1-datalabel __FRAME_BEGIN__ +	.4byte	datalabel .LFB1-.		/* FDE initial location */ +	.4byte	datalabel .LFE1-datalabel .LFB1	/* FDE address range */ +	.byte	0x4	/* DW_CFA_advance_loc4 */ +	.4byte	datalabel .LCFI0-datalabel .LFB1 +	.byte	0xe	/* DW_CFA_def_cfa_offset */ +	.uleb128 0x30 +	.byte	0x4	/* DW_CFA_advance_loc4 */ +	.4byte	datalabel .LCFI1-datalabel .LCFI0 +	.byte   0x8e	/* DW_CFA_offset, column 0xe */ +	.uleb128 0xc +	.byte   0x92	/* DW_CFA_offset, column 0x12 */ +	.uleb128 0xb +	.byte   0x9c	/* DW_CFA_offset, column 0x1c */ +	.uleb128 0xa +	.byte   0x9d	/* DW_CFA_offset, column 0x1d */ +	.uleb128 0x8 +	.byte   0x9e	/* DW_CFA_offset, column 0x1e */ +	.uleb128 0x6 +	.byte   0x9f	/* DW_CFA_offset, column 0x1f */ +	.uleb128 0x4 +	.byte   0xa0	/* DW_CFA_offset, column 0x20 */ +	.uleb128 0x2 +	.byte	0xd	/* DW_CFA_def_cfa_register */ +	.uleb128 0xe +	.align	2 +.LEFDE1: + +.LSFDE3: +	.4byte	datalabel .LEFDE3-datalabel .LASFDE3	/* FDE Length */ +.LASFDE3: +	.4byte	datalabel .LASFDE3-datalabel __FRAME_BEGIN__ +	.4byte	datalabel .LFB2-.		/* FDE initial location */ +	.4byte	datalabel .LFE2-datalabel .LFB2	/* FDE address range */ +	.byte	0x4	/* DW_CFA_advance_loc4 */ +	.4byte	datalabel .LCFI2-datalabel .LFB2 +	.byte	0xe	/* DW_CFA_def_cfa_offset */ +	.uleb128 0x88 +	.byte	0x4	/* DW_CFA_advance_loc4 */ +	.4byte	datalabel .LCFI3-datalabel .LCFI2 +	.byte   0x8c	/* DW_CFA_offset, column 0xc */ +	.uleb128 0x21 +	.byte   0x8e	/* DW_CFA_offset, column 0xe */ +	.uleb128 0x20 +	.byte   0x92	/* DW_CFA_offset, column 0x12 */ +	.uleb128 0x1f +	.byte	0xd	/* DW_CFA_def_cfa_register */ +	.uleb128 0xe +	.align	2 +.LEFDE3: | 
