Home | History | Annotate | Download | only in cris
      1 /* -----------------------------------------------------------------------
      2    sysv.S - Copyright (c) 2004 Simon Posnjak
      3 	    Copyright (c) 2005 Axis Communications AB
      4 
      5    CRIS Foreign Function Interface
      6 
      7    Permission is hereby granted, free of charge, to any person obtaining
      8    a copy of this software and associated documentation files (the
      9    ``Software''), to deal in the Software without restriction, including
     10    without limitation the rights to use, copy, modify, merge, publish,
     11    distribute, sublicense, and/or sell copies of the Software, and to
     12    permit persons to whom the Software is furnished to do so, subject to
     13    the following conditions:
     14 
     15    The above copyright notice and this permission notice shall be included
     16    in all copies or substantial portions of the Software.
     17 
     18    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     21    IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24    OTHER DEALINGS IN THE SOFTWARE.
     25    ----------------------------------------------------------------------- */
     26 
     27 #define LIBFFI_ASM
     28 #include <ffi.h>
     29 #define CONCAT(x,y) x ## y
     30 #define XCONCAT(x,y) CONCAT (x, y)
     31 #define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
     32 
     33 	.text
     34 
     35 	;; OK, when we get called we should have this (according to
     36 	;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
     37 	;;
     38 	;; R10:	 ffi_prep_args (func. pointer)
     39 	;; R11:  &ecif
     40 	;; R12:  cif->bytes
     41 	;; R13:  fig->flags
     42 	;; sp+0: ecif.rvalue
     43 	;; sp+4: fn (function pointer to the function that we need to call)
     44 
     45 	.globl  L(ffi_call_SYSV)
     46 	.type   L(ffi_call_SYSV),@function
     47 	.hidden	L(ffi_call_SYSV)
     48 
     49 L(ffi_call_SYSV):
     50 	;; Save the regs to the stack.
     51 	push $srp
     52 	;; Used for stack pointer saving.
     53 	push $r6
     54 	;; Used for function address pointer.
     55 	push $r7
     56 	;; Used for stack pointer saving.
     57 	push $r8
     58 	;; We save fig->flags to stack we will need them after we
     59 	;; call The Function.
     60 	push $r13
     61 
     62 	;; Saving current stack pointer.
     63 	move.d $sp,$r8
     64 	move.d $sp,$r6
     65 
     66 	;; Move address of ffi_prep_args to r13.
     67 	move.d $r10,$r13
     68 
     69 	;; Make room on the stack for the args of fn.
     70 	sub.d  $r12,$sp
     71 
     72 	;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
     73 	;; 	r10 <-- stack pointer
     74 	;; 	r11 <-- &ecif (already there)
     75 	move.d $sp,$r10
     76 
     77 	;; Call the function.
     78 	jsr $r13
     79 
     80 	;; Save the size of the structures which are passed on stack.
     81 	move.d $r10,$r7
     82 
     83 	;; Move first four args in to r10..r13.
     84 	move.d [$sp+0],$r10
     85 	move.d [$sp+4],$r11
     86 	move.d [$sp+8],$r12
     87 	move.d [$sp+12],$r13
     88 
     89 	;; Adjust the stack and check if any parameters are given on stack.
     90 	addq 16,$sp
     91 	sub.d $r7,$r6
     92 	cmp.d $sp,$r6
     93 
     94 	bpl go_on
     95 	nop
     96 
     97 go_on_no_params_on_stack:
     98 	move.d $r6,$sp
     99 
    100 go_on:
    101 	;; Discover if we need to put rval address in to r9.
    102 	move.d [$r8+0],$r7
    103 	cmpq FFI_TYPE_STRUCT,$r7
    104 	bne call_now
    105 	nop
    106 
    107 	;; Move rval address to $r9.
    108 	move.d [$r8+20],$r9
    109 
    110 call_now:
    111 	;; Move address of The Function in to r7.
    112 	move.d [$r8+24],$r7
    113 
    114 	;; Call The Function.
    115 	jsr $r7
    116 
    117 	;; Reset stack.
    118 	move.d $r8,$sp
    119 
    120 	;; Load rval type (fig->flags) in to r13.
    121 	pop $r13
    122 
    123 	;; Detect rval type.
    124 	cmpq FFI_TYPE_VOID,$r13
    125 	beq epilogue
    126 
    127 	cmpq FFI_TYPE_STRUCT,$r13
    128 	beq epilogue
    129 
    130 	cmpq FFI_TYPE_DOUBLE,$r13
    131 	beq return_double_or_longlong
    132 
    133 	cmpq FFI_TYPE_UINT64,$r13
    134 	beq return_double_or_longlong
    135 
    136 	cmpq FFI_TYPE_SINT64,$r13
    137 	beq return_double_or_longlong
    138 	nop
    139 
    140 	;; Just return the 32 bit value.
    141 	ba return
    142 	nop
    143 
    144 return_double_or_longlong:
    145 	;; Load half of the rval to r10 and the other half to r11.
    146 	move.d [$sp+16],$r13
    147 	move.d $r10,[$r13]
    148 	addq 4,$r13
    149 	move.d $r11,[$r13]
    150 	ba epilogue
    151 	nop
    152 
    153 return:
    154 	;; Load the rval to r10.
    155 	move.d [$sp+16],$r13
    156 	move.d $r10,[$r13]
    157 
    158 epilogue:
    159 	pop $r8
    160 	pop $r7
    161 	pop $r6
    162 	Jump [$sp+]
    163 
    164 	.size   ffi_call_SYSV,.-ffi_call_SYSV
    165 
    166 /* Save R10..R13 into an array, somewhat like varargs.  Copy the next
    167    argument too, to simplify handling of any straddling parameter.
    168    Save R9 and SP after those.  Jump to function handling the rest.
    169    Since this is a template, copied and the main function filled in by
    170    the user.  */
    171 
    172 	.globl	L(ffi_cris_trampoline_template)
    173 	.type	L(ffi_cris_trampoline_template),@function
    174 	.hidden	L(ffi_cris_trampoline_template)
    175 
    176 L(ffi_cris_trampoline_template):
    177 0:
    178 	/* The value we get for "PC" is right after the prefix instruction,
    179 	   two bytes from the beginning, i.e. 0b+2. */
    180 	move.d $r10,[$pc+2f-(0b+2)]
    181 	move.d $pc,$r10
    182 1:
    183 	addq 2f-1b+4,$r10
    184 	move.d $r11,[$r10+]
    185 	move.d $r12,[$r10+]
    186 	move.d $r13,[$r10+]
    187 	move.d [$sp],$r11
    188 	move.d $r11,[$r10+]
    189 	move.d $r9,[$r10+]
    190 	move.d $sp,[$r10+]
    191 	subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
    192 	move.d 0,$r11
    193 3:
    194         jump 0
    195 2:
    196 	.size	ffi_cris_trampoline_template,.-0b
    197 
    198 /* This macro create a constant usable as "extern const int \name" in
    199    C from within libffi, when \name has no prefix decoration.  */
    200 
    201 	.macro const name,value
    202 	.globl	\name
    203 	.type	\name,@object
    204 	.hidden	\name
    205 \name:
    206 	.dword  \value
    207 	.size	\name,4
    208 	.endm
    209 
    210 /* Constants for offsets within the trampoline.  We could do this with
    211    just symbols, avoiding memory contents and memory accesses, but the
    212    C usage code would look a bit stranger.  */
    213 
    214 	const L(ffi_cris_trampoline_fn_offset),2b-4-0b
    215 	const L(ffi_cris_trampoline_closure_offset),3b-4-0b
    216