Home | History | Annotate | Download | only in sparc
      1 /* -----------------------------------------------------------------------
      2    v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
      3 
      4    SPARC 64-bit 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 #ifdef SPARC64
     32 /* Only compile this in for 64bit builds, because otherwise the object file
     33    will have inproper architecture due to used instructions.  */
     34 
     35 #define STACKFRAME 128		/* Minimum stack framesize for SPARC */
     36 #define STACK_BIAS 2047
     37 #define ARGS (128)		/* Offset of register area in frame */
     38 
     39 .text
     40         .align 8
     41 .globl ffi_call_v9
     42 .globl _ffi_call_v9
     43 
     44 ffi_call_v9:
     45 _ffi_call_v9:
     46 .LLFB1:
     47 	save	%sp, -STACKFRAME, %sp
     48 .LLCFI0:
     49 
     50 	sub	%sp, %i2, %sp	! alloca() space in stack for frame to set up
     51 	add	%sp, STACKFRAME+STACK_BIAS, %l0	! %l0 has start of
     52 						! frame to set up
     53 
     54 	mov	%l0, %o0	! call routine to set up frame
     55 	call	%i0
     56 	 mov	%i1, %o1	! (delay)
     57 	brz,pt	%o0, 1f
     58 	 ldx	[%l0+ARGS], %o0	! call foreign function
     59 
     60 	ldd	[%l0+ARGS], %f0
     61 	ldd	[%l0+ARGS+8], %f2
     62 	ldd	[%l0+ARGS+16], %f4
     63 	ldd	[%l0+ARGS+24], %f6
     64 	ldd	[%l0+ARGS+32], %f8
     65 	ldd	[%l0+ARGS+40], %f10
     66 	ldd	[%l0+ARGS+48], %f12
     67 	ldd	[%l0+ARGS+56], %f14
     68 	ldd	[%l0+ARGS+64], %f16
     69 	ldd	[%l0+ARGS+72], %f18
     70 	ldd	[%l0+ARGS+80], %f20
     71 	ldd	[%l0+ARGS+88], %f22
     72 	ldd	[%l0+ARGS+96], %f24
     73 	ldd	[%l0+ARGS+104], %f26
     74 	ldd	[%l0+ARGS+112], %f28
     75 	ldd	[%l0+ARGS+120], %f30
     76 
     77 1:	ldx	[%l0+ARGS+8], %o1
     78 	ldx	[%l0+ARGS+16], %o2
     79 	ldx	[%l0+ARGS+24], %o3
     80 	ldx	[%l0+ARGS+32], %o4
     81 	ldx	[%l0+ARGS+40], %o5
     82 	call	%i5
     83 	 sub	%l0, STACK_BIAS, %sp	! (delay) switch to frame
     84 
     85 	! If the return value pointer is NULL, assume no return value.
     86 	brz,pn	%i4, done
     87 	 nop
     88 
     89 	cmp	%i3, FFI_TYPE_INT
     90 	be,a,pt	%icc, done
     91 	 stx	%o0, [%i4+0]	! (delay)
     92 
     93 	cmp	%i3, FFI_TYPE_FLOAT
     94 	be,a,pn	%icc, done
     95 	 st	%f0, [%i4+0]	! (delay)
     96 
     97 	cmp	%i3, FFI_TYPE_DOUBLE
     98 	be,a,pn	%icc, done
     99 	 std	%f0, [%i4+0]	! (delay)
    100 
    101 	cmp	%i3, FFI_TYPE_STRUCT
    102 	be,pn	%icc, dostruct
    103 
    104 	cmp	%i3, FFI_TYPE_LONGDOUBLE
    105 	bne,pt	%icc, done
    106 	 nop
    107 	std	%f0, [%i4+0]
    108 	std	%f2, [%i4+8]
    109 
    110 done:	ret
    111 	 restore
    112 
    113 dostruct:
    114 	/* This will not work correctly for unions. */
    115 	stx	%o0, [%i4+0]
    116 	stx	%o1, [%i4+8]
    117 	stx	%o2, [%i4+16]
    118 	stx	%o3, [%i4+24]
    119 	std	%f0, [%i4+32]
    120 	std	%f2, [%i4+40]
    121 	std	%f4, [%i4+48]
    122 	std	%f6, [%i4+56]
    123 	ret
    124 	 restore
    125 .LLFE1:
    126 
    127 .ffi_call_v9_end:
    128 	.size	ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
    129 
    130 
    131 #undef STACKFRAME
    132 #define	STACKFRAME	 336	/* 16*8 register window +
    133 				   6*8 args backing store +
    134 				   20*8 locals */
    135 #define	FP		%fp+STACK_BIAS
    136 
    137 /* ffi_closure_v9(...)
    138 
    139    Receives the closure argument in %g1.   */
    140 
    141 	.text
    142 	.align 8
    143 	.globl ffi_closure_v9
    144 
    145 ffi_closure_v9:
    146 .LLFB2:
    147 	save	%sp, -STACKFRAME, %sp
    148 .LLCFI1:
    149 
    150 	! Store all of the potential argument registers in va_list format.
    151 	stx	%i0, [FP+128+0]
    152 	stx	%i1, [FP+128+8]
    153 	stx	%i2, [FP+128+16]
    154 	stx	%i3, [FP+128+24]
    155 	stx	%i4, [FP+128+32]
    156 	stx	%i5, [FP+128+40]
    157 
    158 	! Store possible floating point argument registers too.
    159 	std	%f0,  [FP-128]
    160 	std	%f2,  [FP-120]
    161 	std	%f4,  [FP-112]
    162 	std	%f6,  [FP-104]
    163 	std	%f8,  [FP-96]
    164 	std	%f10, [FP-88]
    165 	std     %f12, [FP-80]
    166 	std     %f14, [FP-72]
    167 	std     %f16, [FP-64]
    168 	std     %f18, [FP-56]
    169 	std     %f20, [FP-48]
    170 	std     %f22, [FP-40]
    171 	std     %f24, [FP-32]
    172 	std     %f26, [FP-24]
    173 	std     %f28, [FP-16]
    174 	std     %f30, [FP-8]
    175 
    176 	! Call ffi_closure_sparc_inner to do the bulk of the work.
    177 	mov	%g1, %o0
    178 	add	%fp, STACK_BIAS-160, %o1
    179 	add	%fp, STACK_BIAS+128, %o2
    180 	call	ffi_closure_sparc_inner_v9
    181 	 add	%fp, STACK_BIAS-128, %o3
    182 
    183 	! Load up the return value in the proper type.
    184 	! See ffi_prep_cif_machdep for the list of cases.
    185 	cmp	%o0, FFI_TYPE_VOID
    186 	be,pn	%icc, done1
    187 
    188 	cmp	%o0, FFI_TYPE_INT
    189 	be,pn	%icc, integer
    190 
    191 	cmp	%o0, FFI_TYPE_FLOAT
    192 	be,a,pn	%icc, done1
    193 	 ld	[FP-160], %f0
    194 
    195 	cmp	%o0, FFI_TYPE_DOUBLE
    196 	be,a,pn	%icc, done1
    197 	 ldd	[FP-160], %f0
    198 
    199 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    200 	cmp	%o0, FFI_TYPE_LONGDOUBLE
    201 	be,a,pn	%icc, longdouble1
    202 	 ldd	[FP-160], %f0
    203 #endif
    204 
    205 	! FFI_TYPE_STRUCT
    206 	ldx	[FP-152], %i1
    207 	ldx	[FP-144], %i2
    208 	ldx	[FP-136], %i3
    209 	ldd	[FP-160], %f0
    210 	ldd	[FP-152], %f2
    211 	ldd	[FP-144], %f4
    212 	ldd	[FP-136], %f6
    213 
    214 integer:
    215 	ldx	[FP-160], %i0
    216 
    217 done1:
    218 	ret
    219 	 restore
    220 
    221 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    222 longdouble1:
    223 	ldd	[FP-152], %f2
    224 	ret
    225 	 restore
    226 #endif
    227 .LLFE2:
    228 
    229 .ffi_closure_v9_end:
    230 	.size	ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
    231 
    232 #ifdef HAVE_RO_EH_FRAME
    233 	.section	".eh_frame",#alloc
    234 #else
    235 	.section	".eh_frame",#alloc,#write
    236 #endif
    237 .LLframe1:
    238 	.uaword	.LLECIE1-.LLSCIE1	! Length of Common Information Entry
    239 .LLSCIE1:
    240 	.uaword	0x0	! CIE Identifier Tag
    241 	.byte	0x1	! CIE Version
    242 	.ascii "zR\0"	! CIE Augmentation
    243 	.byte	0x1	! uleb128 0x1; CIE Code Alignment Factor
    244 	.byte	0x78	! sleb128 -8; CIE Data Alignment Factor
    245 	.byte	0xf	! CIE RA Column
    246 	.byte	0x1	! uleb128 0x1; Augmentation size
    247 #ifdef HAVE_AS_SPARC_UA_PCREL
    248 	.byte	0x1b	! FDE Encoding (pcrel sdata4)
    249 #else
    250 	.byte	0x50	! FDE Encoding (aligned absolute)
    251 #endif
    252 	.byte	0xc	! DW_CFA_def_cfa
    253 	.byte	0xe	! uleb128 0xe
    254 	.byte	0xff,0xf	! uleb128 0x7ff
    255 	.align 8
    256 .LLECIE1:
    257 .LLSFDE1:
    258 	.uaword	.LLEFDE1-.LLASFDE1	! FDE Length
    259 .LLASFDE1:
    260 	.uaword	.LLASFDE1-.LLframe1	! FDE CIE offset
    261 #ifdef HAVE_AS_SPARC_UA_PCREL
    262 	.uaword	%r_disp32(.LLFB1)
    263 	.uaword	.LLFE1-.LLFB1		! FDE address range
    264 #else
    265 	.align 8
    266 	.xword	.LLFB1
    267 	.uaxword	.LLFE1-.LLFB1	! FDE address range
    268 #endif
    269 	.byte	0x0	! uleb128 0x0; Augmentation size
    270 	.byte	0x4	! DW_CFA_advance_loc4
    271 	.uaword	.LLCFI0-.LLFB1
    272 	.byte	0xd	! DW_CFA_def_cfa_register
    273 	.byte	0x1e	! uleb128 0x1e
    274 	.byte	0x2d	! DW_CFA_GNU_window_save
    275 	.byte	0x9	! DW_CFA_register
    276 	.byte	0xf	! uleb128 0xf
    277 	.byte	0x1f	! uleb128 0x1f
    278 	.align 8
    279 .LLEFDE1:
    280 .LLSFDE2:
    281 	.uaword	.LLEFDE2-.LLASFDE2	! FDE Length
    282 .LLASFDE2:
    283 	.uaword	.LLASFDE2-.LLframe1	! FDE CIE offset
    284 #ifdef HAVE_AS_SPARC_UA_PCREL
    285 	.uaword	%r_disp32(.LLFB2)
    286 	.uaword	.LLFE2-.LLFB2		! FDE address range
    287 #else
    288 	.align 8
    289 	.xword	.LLFB2
    290 	.uaxword	.LLFE2-.LLFB2	! FDE address range
    291 #endif
    292 	.byte	0x0	! uleb128 0x0; Augmentation size
    293 	.byte	0x4	! DW_CFA_advance_loc4
    294 	.uaword	.LLCFI1-.LLFB2
    295 	.byte	0xd	! DW_CFA_def_cfa_register
    296 	.byte	0x1e	! uleb128 0x1e
    297 	.byte	0x2d	! DW_CFA_GNU_window_save
    298 	.byte	0x9	! DW_CFA_register
    299 	.byte	0xf	! uleb128 0xf
    300 	.byte	0x1f	! uleb128 0x1f
    301 	.align 8
    302 .LLEFDE2:
    303 #endif
    304 
    305 #ifdef __linux__
    306 	.section	.note.GNU-stack,"",@progbits
    307 #endif
    308