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

     1  /* -----------------------------------------------------------------------
     2     sysv.S - Copyright (c) 2012, 2013 Xilinx, Inc
     3  
     4     MicroBlaze 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  	/*
    32  	 * arg[0] (r5)  = ffi_prep_args,
    33  	 * arg[1] (r6)  = &ecif,
    34  	 * arg[2] (r7)  = cif->bytes,
    35  	 * arg[3] (r8)  = cif->flags,
    36  	 * arg[4] (r9)  = ecif.rvalue,
    37  	 * arg[5] (r10) = fn
    38  	 * arg[6] (sp[0]) = cif->rtype->type
    39  	 * arg[7] (sp[4]) = cif->rtype->size
    40  	 */
    41  	.text
    42  	.globl ffi_call_SYSV
    43  	.type ffi_call_SYSV, @function
    44  ffi_call_SYSV:
    45  	/* push callee saves */
    46  	addik r1, r1, -20
    47  	swi r19, r1, 0 /* Frame Pointer */
    48  	swi r20, r1, 4 /* PIC register */
    49  	swi r21, r1, 8 /* PIC register */
    50  	swi r22, r1, 12 /* save for locals */
    51  	swi r23, r1, 16 /* save for locals */
    52  	
    53  	/* save the r5-r10 registers in the stack */
    54  	addik r1, r1, -24 /* increment sp to store 6x 32-bit words */
    55  	swi r5, r1, 0
    56  	swi r6, r1, 4
    57  	swi r7, r1, 8
    58  	swi r8, r1, 12
    59  	swi r9, r1, 16
    60  	swi r10, r1, 20
    61  
    62  	/* save function pointer */
    63  	addik r3, r5, 0 /* copy ffi_prep_args into r3 */
    64  	addik r22, r1, 0 /* save sp for unallocated args into r22 (callee-saved) */
    65  	addik r23, r10, 0 /* save function address into r23 (callee-saved) */
    66  
    67  	/* prepare stack with allocation for n (bytes = r7) args */
    68  	rsub r1, r7, r1 /* subtract bytes from sp */
    69  
    70  	/* prep args for ffi_prep_args call */
    71  	addik r5, r1, 0 /* store stack pointer into arg[0] */
    72  	/* r6 still holds ecif for arg[1] */
    73  
    74  	/* Call ffi_prep_args(stack, &ecif). */
    75  	addik r1, r1, -4
    76  	swi r15, r1, 0 /* store the link register in the frame */
    77  	brald r15, r3
    78  	nop /* branch has delay slot */
    79  	lwi r15, r1, 0
    80  	addik r1, r1, 4 /* restore the link register from the frame */
    81  	/* returns calling stack pointer location */
    82  
    83  	/* prepare args for fn call, prep_args populates them onto the stack */
    84  	lwi r5, r1, 0 /* arg[0] */
    85  	lwi r6, r1, 4 /* arg[1] */
    86  	lwi r7, r1, 8 /* arg[2] */
    87  	lwi r8, r1, 12 /* arg[3] */
    88  	lwi r9, r1, 16 /* arg[4] */
    89  	lwi r10, r1, 20 /* arg[5] */
    90  
    91  	/* call (fn) (...). */
    92  	addik r1, r1, -4
    93  	swi r15, r1, 0 /* store the link register in the frame */
    94  	brald r15, r23
    95  	nop /* branch has delay slot */
    96  	lwi r15, r1, 0
    97  	addik r1, r1, 4 /* restore the link register from the frame */
    98  
    99  	/* Remove the space we pushed for the args. */
   100  	addik r1, r22, 0 /* restore old SP */
   101  
   102  	/* restore this functions parameters */
   103  	lwi r5, r1, 0 /* arg[0] */
   104  	lwi r6, r1, 4 /* arg[1] */
   105  	lwi r7, r1, 8 /* arg[2] */
   106  	lwi r8, r1, 12 /* arg[3] */
   107  	lwi r9, r1, 16 /* arg[4] */
   108  	lwi r10, r1, 20 /* arg[5] */
   109  	addik r1, r1, 24 /* decrement sp to de-allocate 6x 32-bit words */
   110  
   111  	/* If the return value pointer is NULL, assume no return value. */
   112  	beqi r9, ffi_call_SYSV_end
   113  
   114  	lwi r22, r1, 48 /* get return type (20 for locals + 28 for arg[6]) */
   115  	lwi r23, r1, 52 /* get return size (20 for locals + 32 for arg[7])  */
   116  	
   117  	/* Check if return type is actually a struct, do nothing */
   118  	rsubi r11, r22, FFI_TYPE_STRUCT
   119  	beqi r11, ffi_call_SYSV_end
   120  
   121  	/* Return 8bit */
   122  	rsubi r11, r23, 1
   123  	beqi r11, ffi_call_SYSV_store8
   124  
   125  	/* Return 16bit */
   126  	rsubi r11, r23, 2
   127  	beqi r11, ffi_call_SYSV_store16
   128  
   129  	/* Return 32bit */
   130  	rsubi r11, r23, 4
   131  	beqi r11, ffi_call_SYSV_store32
   132  
   133  	/* Return 64bit */
   134  	rsubi r11, r23, 8
   135  	beqi r11, ffi_call_SYSV_store64
   136  
   137  	/* Didn't match anything */
   138  	bri ffi_call_SYSV_end
   139  
   140  ffi_call_SYSV_store64:
   141  	swi r3, r9, 0 /* store word r3 into return value */
   142  	swi r4, r9, 4 /* store word r4 into return value */
   143  	bri ffi_call_SYSV_end
   144  
   145  ffi_call_SYSV_store32:
   146  	swi r3, r9, 0 /* store word r3 into return value */
   147  	bri ffi_call_SYSV_end
   148  
   149  ffi_call_SYSV_store16:
   150  #ifdef __BIG_ENDIAN__
   151  	shi r3, r9, 2 /* store half-word r3 into return value */
   152  #else
   153  	shi r3, r9, 0 /* store half-word r3 into return value */
   154  #endif
   155  	bri ffi_call_SYSV_end
   156  
   157  ffi_call_SYSV_store8:
   158  #ifdef __BIG_ENDIAN__
   159  	sbi r3, r9, 3 /* store byte r3 into return value */
   160  #else
   161  	sbi r3, r9, 0 /* store byte r3 into return value */
   162  #endif
   163  	bri ffi_call_SYSV_end
   164  
   165  ffi_call_SYSV_end:
   166  	/* callee restores */
   167  	lwi r19, r1, 0 /* frame pointer */
   168  	lwi r20, r1, 4 /* PIC register */
   169  	lwi r21, r1, 8 /* PIC register */
   170  	lwi r22, r1, 12
   171  	lwi r23, r1, 16
   172  	addik r1, r1, 20
   173  
   174  	/* return from sub-routine (with delay slot) */
   175  	rtsd r15, 8
   176  	nop
   177  
   178  	.size ffi_call_SYSV, . - ffi_call_SYSV
   179  
   180  /* ------------------------------------------------------------------------- */
   181  
   182  	/*
   183  	 * args passed into this function, are passed down to the callee.
   184  	 * this function is the target of the closure trampoline, as such r12 is 
   185  	 * a pointer to the closure object.
   186  	 */
   187  	.text
   188  	.globl ffi_closure_SYSV
   189  	.type ffi_closure_SYSV, @function
   190  ffi_closure_SYSV:
   191  	/* push callee saves */
   192  	addik r11, r1, 28 /* save stack args start location (excluding regs/link) */
   193  	addik r1, r1, -12
   194  	swi r19, r1, 0 /* Frame Pointer */
   195  	swi r20, r1, 4 /* PIC register */
   196  	swi r21, r1, 8 /* PIC register */
   197  
   198  	/* store register args on stack */
   199  	addik r1, r1, -24
   200  	swi r5, r1, 0
   201  	swi r6, r1, 4
   202  	swi r7, r1, 8
   203  	swi r8, r1, 12
   204  	swi r9, r1, 16
   205  	swi r10, r1, 20
   206  
   207  	/* setup args */
   208  	addik r5, r1, 0 /* register_args */
   209  	addik r6, r11, 0 /* stack_args */
   210  	addik r7, r12, 0 /* closure object */
   211  	addik r1, r1, -8 /* allocate return value */
   212  	addik r8, r1, 0 /* void* rvalue */
   213  	addik r1, r1, -8 /* allocate for return type/size values */
   214  	addik r9, r1, 0 /* void* rtype */
   215  	addik r10, r1, 4 /* void* rsize */
   216  
   217  	/* call the wrap_call function */
   218  	addik r1, r1, -28 /* allocate args + link reg */
   219  	swi r15, r1, 0 /* store the link register in the frame */
   220  	brald r15, r3
   221  	nop /* branch has delay slot */
   222  	lwi r15, r1, 0
   223  	addik r1, r1, 28 /* restore the link register from the frame */
   224  
   225  ffi_closure_SYSV_prepare_return:
   226  	lwi r9, r1, 0 /* rtype */
   227  	lwi r10, r1, 4 /* rsize */
   228  	addik r1, r1, 8 /* de-allocate return info values */
   229  
   230  	/* Check if return type is actually a struct, store 4 bytes */
   231  	rsubi r11, r9, FFI_TYPE_STRUCT
   232  	beqi r11, ffi_closure_SYSV_store32
   233  
   234  	/* Return 8bit */
   235  	rsubi r11, r10, 1
   236  	beqi r11, ffi_closure_SYSV_store8
   237  
   238  	/* Return 16bit */
   239  	rsubi r11, r10, 2
   240  	beqi r11, ffi_closure_SYSV_store16
   241  
   242  	/* Return 32bit */
   243  	rsubi r11, r10, 4
   244  	beqi r11, ffi_closure_SYSV_store32
   245  
   246  	/* Return 64bit */
   247  	rsubi r11, r10, 8
   248  	beqi r11, ffi_closure_SYSV_store64
   249  
   250  	/* Didn't match anything */
   251  	bri ffi_closure_SYSV_end
   252  
   253  ffi_closure_SYSV_store64:
   254  	lwi r3, r1, 0 /* store word r3 into return value */
   255  	lwi r4, r1, 4 /* store word r4 into return value */
   256  	/* 64 bits == 2 words, no sign extend occurs */
   257  	bri ffi_closure_SYSV_end
   258  
   259  ffi_closure_SYSV_store32:
   260  	lwi r3, r1, 0 /* store word r3 into return value */
   261  	/* 32 bits == 1 word, no sign extend occurs */
   262  	bri ffi_closure_SYSV_end
   263  
   264  ffi_closure_SYSV_store16:
   265  #ifdef __BIG_ENDIAN__
   266  	lhui r3, r1, 2 /* store half-word r3 into return value */
   267  #else
   268  	lhui r3, r1, 0 /* store half-word r3 into return value */
   269  #endif
   270  	rsubi r11, r9, FFI_TYPE_SINT16
   271  	bnei r11, ffi_closure_SYSV_end
   272  	sext16 r3, r3 /* fix sign extend of sint8 */
   273  	bri ffi_closure_SYSV_end
   274  
   275  ffi_closure_SYSV_store8:
   276  #ifdef __BIG_ENDIAN__
   277  	lbui r3, r1, 3 /* store byte r3 into return value */
   278  #else
   279  	lbui r3, r1, 0 /* store byte r3 into return value */
   280  #endif
   281  	rsubi r11, r9, FFI_TYPE_SINT8
   282  	bnei r11, ffi_closure_SYSV_end
   283  	sext8 r3, r3 /* fix sign extend of sint8 */
   284  	bri ffi_closure_SYSV_end
   285  
   286  ffi_closure_SYSV_end:
   287  	addik r1, r1, 8 /* de-allocate return value */
   288  
   289  	/* de-allocate stored args */
   290  	addik r1, r1, 24
   291  
   292  	/* callee restores */
   293  	lwi r19, r1, 0 /* frame pointer */
   294  	lwi r20, r1, 4 /* PIC register */
   295  	lwi r21, r1, 8 /* PIC register */
   296  	addik r1, r1, 12
   297  
   298  	/* return from sub-routine (with delay slot) */
   299  	rtsd r15, 8
   300  	nop
   301  
   302  	.size ffi_closure_SYSV, . - ffi_closure_SYSV