github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/xtensa/sysv.S (about)

     1  /* -----------------------------------------------------------------------
     2     sysv.S - Copyright (c) 2013 Tensilica, Inc.
     3     
     4     XTENSA Foreign Function Interface 
     5  
     6     Permission is hereby granted, free of charge, to any person obtaining
     7     a copy of this software and associated documentation files (the
     8     ``Software''), to deal in the Software without restriction, including
     9     without limitation the rights to use, copy, modify, merge, publish,
    10     distribute, sublicense, and/or sell copies of the Software, and to
    11     permit persons to whom the Software is furnished to do so, subject to
    12     the following conditions:
    13  
    14     The above copyright notice and this permission notice shall be included
    15     in all copies or substantial portions of the Software.
    16  
    17     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
    18     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    19     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    20     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    21     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    22     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    23     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    24     DEALINGS IN THE SOFTWARE.
    25     ----------------------------------------------------------------------- */
    26  
    27  #define LIBFFI_ASM
    28  #include <fficonfig.h>
    29  #include <ffi.h>
    30  
    31  #define ENTRY(name) .text; .globl name; .type  name,@function; .align 4; name:
    32  #define END(name) .size name , . - name
    33  
    34  /* Assert that the table below is in sync with ffi.h.  */
    35  
    36  #if	   FFI_TYPE_UINT8 != 5          \
    37          || FFI_TYPE_SINT8 != 6          \
    38          || FFI_TYPE_UINT16 != 7         \
    39          || FFI_TYPE_SINT16 != 8         \
    40          || FFI_TYPE_UINT32 != 9         \
    41          || FFI_TYPE_SINT32 != 10        \
    42          || FFI_TYPE_UINT64 != 11
    43  #error "xtensa/sysv.S out of sync with ffi.h"
    44  #endif
    45  
    46  
    47  /* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif)
    48        void *rvalue;            a2
    49        unsigned long rbytes;    a3
    50        unsigned flags;          a4
    51        void (*fnaddr)();        a5
    52        unsigned long bytes;     a6
    53        extended_cif* ecif)      a7
    54  */
    55  
    56  ENTRY(ffi_call_SYSV)
    57  
    58  	entry	a1, 32              # 32 byte frame for using call8 below
    59  
    60  	mov	a10, a7             # a10(->arg0): ecif
    61  	sub	a11, a1, a6         # a11(->arg1): stack pointer
    62  	mov	a7, a1              # fp
    63  	movsp	a1, a11             # set new sp = old_sp - bytes
    64  
    65  	movi	a8, ffi_prep_args
    66  	callx8	a8                  # ffi_prep_args(ecif, stack)
    67  
    68  	# prepare to move stack pointer back up to 6 arguments
    69  	# note that 'bytes' is already aligned
    70  
    71  	movi	a10, 6*4 
    72  	sub	a11, a6, a10
    73  	movgez	a6, a10, a11
    74  	add	a6, a1, a6
    75  
    76  	
    77  	# we can pass up to 6 arguments in registers
    78  	# for simplicity, just load 6 arguments
    79  	# (the stack size is at least 32 bytes, so no risk to cross boundaries)
    80  
    81  	l32i	a10, a1, 0
    82  	l32i	a11, a1, 4
    83  	l32i	a12, a1, 8
    84  	l32i	a13, a1, 12
    85  	l32i	a14, a1, 16
    86  	l32i	a15, a1, 20
    87  
    88  	# move stack pointer
    89  
    90  	movsp	a1, a6
    91  
    92  	callx8	a5                  # (*fn)(args...)
    93  
    94  	# Handle return value(s)
    95  
    96  	beqz	a2, .Lexit
    97  
    98  	movi	a5, FFI_TYPE_STRUCT
    99  	bne	a4, a5, .Lstore
   100  	movi	a5, 16
   101  	blt	a5, a3, .Lexit
   102  
   103  	s32i	a10, a2, 0
   104  	blti	a3, 5, .Lexit
   105  	addi	a3, a3, -1
   106  	s32i	a11, a2, 4
   107  	blti	a3, 8, .Lexit
   108  	s32i	a12, a2, 8
   109  	blti	a3, 12, .Lexit
   110  	s32i	a13, a2, 12
   111  
   112  .Lexit:	retw
   113  
   114  .Lstore:
   115  	addi	a4, a4, -FFI_TYPE_UINT8
   116  	bgei	a4, 7, .Lexit	# should never happen
   117  	movi	a6, store_calls
   118  	add	a4, a4, a4
   119  	addx4	a6, a4, a6	# store_table + idx * 8
   120  	jx	a6
   121  
   122  	.align	8
   123  store_calls:
   124  	# UINT8
   125  	s8i	a10, a2, 0
   126  	retw
   127  
   128  	# SINT8
   129  	.align	8
   130  	s8i	a10, a2, 0
   131  	retw
   132  
   133  	# UINT16
   134  	.align	8
   135  	s16i	a10, a2, 0
   136  	retw
   137  
   138  	# SINT16
   139  	.align	8
   140  	s16i	a10, a2, 0
   141  	retw
   142  
   143  	# UINT32
   144  	.align	8
   145  	s32i	a10, a2, 0
   146  	retw
   147  
   148  	# SINT32
   149  	.align	8
   150  	s32i	a10, a2, 0
   151  	retw
   152  
   153  	# UINT64
   154  	.align	8
   155  	s32i	a10, a2, 0
   156  	s32i	a11, a2, 4
   157  	retw
   158  
   159  END(ffi_call_SYSV)
   160  
   161  
   162  /*
   163   * void ffi_cacheflush (unsigned long start, unsigned long end)
   164   */
   165  
   166  #define EXTRA_ARGS_SIZE	24
   167  
   168  ENTRY(ffi_cacheflush)
   169  
   170  	entry	a1, 16
   171  
   172  1:	dhwbi	a2, 0
   173  	ihi	a2, 0
   174  	addi	a2, a2, 4
   175  	blt	a2, a3, 1b
   176  
   177  	retw
   178  
   179  END(ffi_cacheflush)
   180  
   181  /* ffi_trampoline is copied to the stack */
   182  
   183  ENTRY(ffi_trampoline)
   184  
   185  	entry	a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4)   # [ 0]
   186  	j	2f                                # [ 3]
   187  	.align	4                                 # [ 6]
   188  1:	.long	0                                 # [ 8]
   189  2:	l32r	a15, 1b                           # [12]
   190  	_mov 	a14, a0                           # [15]
   191  	callx0	a15                               # [18]
   192                                                    # [21]
   193  END(ffi_trampoline)
   194  
   195  /*
   196   * ffi_closure()
   197   *
   198   * a0:  closure + 21
   199   * a14: return address (a0)
   200   */
   201  
   202  ENTRY(ffi_closure_SYSV)
   203  
   204  	/* intentionally omitting entry here */
   205  
   206  	# restore return address (a0) and move pointer to closure to a10
   207  	addi	a10, a0, -21
   208  	mov	a0, a14
   209  
   210  	# allow up to 4 arguments as return values
   211  	addi	a11, a1, 4 * 4
   212  
   213  	# save up to 6 arguments to stack (allocated by entry below)
   214  	s32i	a2, a11,  0
   215  	s32i	a3, a11,  4
   216  	s32i	a4, a11,  8
   217  	s32i	a5, a11, 12
   218  	s32i	a6, a11, 16
   219  	s32i	a7, a11, 20
   220  
   221  	movi	a8, ffi_closure_SYSV_inner
   222  	mov	a12, a1
   223  	callx8	a8			# .._inner(*closure, **avalue, *rvalue)
   224  
   225  	# load up to four return arguments
   226  	l32i	a2, a1,  0
   227  	l32i	a3, a1,  4
   228  	l32i	a4, a1,  8
   229  	l32i	a5, a1, 12
   230  
   231  	# (sign-)extend return value
   232  	movi	a11, FFI_TYPE_UINT8
   233  	bne	a10, a11, 1f
   234  	extui	a2, a2, 0, 8
   235  	retw
   236  
   237  1:	movi	a11, FFI_TYPE_SINT8
   238  	bne	a10, a11, 1f
   239  	sext	a2, a2, 7
   240  	retw
   241  
   242  1:	movi	a11, FFI_TYPE_UINT16
   243  	bne	a10, a11, 1f
   244  	extui	a2, a2, 0, 16
   245  	retw
   246  
   247  1:	movi	a11, FFI_TYPE_SINT16
   248  	bne	a10, a11, 1f
   249  	sext	a2, a2, 15
   250  
   251  1:	retw
   252  
   253  END(ffi_closure_SYSV)