Home | History | Annotate | Download | only in alpha
      1 /* -----------------------------------------------------------------------
      2    osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
      3 
      4    Alpha/OSF 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 	.arch ev6
     32 	.text
     33 
     34 /* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
     35 		 void *raddr, void (*fnaddr)(void));
     36 
     37    Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
     38    for this function.  This has been allocated by ffi_call.  We also
     39    deallocate some of the stack that has been alloca'd.  */
     40 
     41 	.align	3
     42 	.globl	ffi_call_osf
     43 	.ent	ffi_call_osf
     44 	FFI_HIDDEN(ffi_call_osf)
     45 
     46 ffi_call_osf:
     47 	.frame	$15, 32, $26, 0
     48 	.mask   0x4008000, -32
     49 $LFB1:
     50 	addq	$16,$17,$1
     51 	mov	$16, $30
     52 	stq	$26, 0($1)
     53 	stq	$15, 8($1)
     54 	stq	$18, 16($1)
     55 	mov	$1, $15
     56 $LCFI1:
     57 	.prologue 0
     58 
     59 	stq	$19, 24($1)
     60 	mov	$20, $27
     61 
     62 	# Load up all of the (potential) argument registers.
     63 	ldq	$16, 0($30)
     64 	ldt	$f16, 0($30)
     65 	ldt	$f17, 8($30)
     66 	ldq	$17, 8($30)
     67 	ldt	$f18, 16($30)
     68 	ldq	$18, 16($30)
     69 	ldt	$f19, 24($30)
     70 	ldq	$19, 24($30)
     71 	ldt	$f20, 32($30)
     72 	ldq	$20, 32($30)
     73 	ldt	$f21, 40($30)
     74 	ldq	$21, 40($30)
     75 
     76 	# Deallocate the register argument area.
     77 	lda	$30, 48($30)
     78 
     79 	jsr	$26, ($27), 0
     80 	ldgp	$29, 0($26)
     81 
     82 	# If the return value pointer is NULL, assume no return value.
     83 	ldq	$19, 24($15)
     84 	ldq	$18, 16($15)
     85 	ldq	$26, 0($15)
     86 $LCFI2:
     87 	beq	$19, $noretval
     88 
     89 	# Store the return value out in the proper type.
     90 	cmpeq	$18, FFI_TYPE_INT, $1
     91 	bne	$1, $retint
     92 	cmpeq	$18, FFI_TYPE_FLOAT, $2
     93 	bne	$2, $retfloat
     94 	cmpeq	$18, FFI_TYPE_DOUBLE, $3
     95 	bne	$3, $retdouble
     96 
     97 	.align	3
     98 $noretval:
     99 	ldq	$15, 8($15)
    100 	ret
    101 
    102 	.align	4
    103 $retint:
    104 	stq	$0, 0($19)
    105 	nop
    106 	ldq	$15, 8($15)
    107 	ret
    108 
    109 	.align	4
    110 $retfloat:
    111 	sts	$f0, 0($19)
    112 	nop
    113 	ldq	$15, 8($15)
    114 	ret
    115 
    116 	.align	4
    117 $retdouble:
    118 	stt	$f0, 0($19)
    119 	nop
    120 	ldq	$15, 8($15)
    121 	ret
    122 $LFE1:
    123 
    124 	.end	ffi_call_osf
    125 
    126 /* ffi_closure_osf(...)
    127 
    128    Receives the closure argument in $1.   */
    129 
    130 	.align	3
    131 	.globl	ffi_closure_osf
    132 	.ent	ffi_closure_osf
    133 	FFI_HIDDEN(ffi_closure_osf)
    134 
    135 ffi_closure_osf:
    136 	.frame	$30, 16*8, $26, 0
    137 	.mask	0x4000000, -16*8
    138 $LFB2:
    139 	ldgp	$29, 0($27)
    140 	subq	$30, 16*8, $30
    141 $LCFI5:
    142 	stq	$26, 0($30)
    143 $LCFI6:
    144 	.prologue 1
    145 
    146 	# Store all of the potential argument registers in va_list format.
    147 	stt	$f16, 4*8($30)
    148 	stt	$f17, 5*8($30)
    149 	stt	$f18, 6*8($30)
    150 	stt	$f19, 7*8($30)
    151 	stt	$f20, 8*8($30)
    152 	stt	$f21, 9*8($30)
    153 	stq	$16, 10*8($30)
    154 	stq	$17, 11*8($30)
    155 	stq	$18, 12*8($30)
    156 	stq	$19, 13*8($30)
    157 	stq	$20, 14*8($30)
    158 	stq	$21, 15*8($30)
    159 
    160 	# Call ffi_closure_osf_inner to do the bulk of the work.
    161 	mov	$1, $16
    162 	lda	$17, 2*8($30)
    163 	lda	$18, 10*8($30)
    164 	jsr	$26, ffi_closure_osf_inner
    165 	ldgp	$29, 0($26)
    166 	ldq	$26, 0($30)
    167 
    168 	# Load up the return value in the proper type.
    169 	lda	$1, $load_table
    170 	s4addq	$0, $1, $1
    171 	ldl	$1, 0($1)
    172 	addq	$1, $29, $1
    173 	jmp	$31, ($1), $load_32
    174 
    175 	.align 4
    176 $load_none:
    177 	addq	$30, 16*8, $30
    178 	ret
    179 
    180 	.align 4
    181 $load_float:
    182 	lds	$f0, 16($30)
    183 	nop
    184 	addq	$30, 16*8, $30
    185 	ret
    186 
    187 	.align 4
    188 $load_double:
    189 	ldt	$f0, 16($30)
    190 	nop
    191 	addq	$30, 16*8, $30
    192 	ret
    193 
    194 	.align 4
    195 $load_u8:
    196 #ifdef __alpha_bwx__
    197 	ldbu	$0, 16($30)
    198 	nop
    199 #else
    200 	ldq	$0, 16($30)
    201 	and	$0, 255, $0
    202 #endif
    203 	addq	$30, 16*8, $30
    204 	ret
    205 
    206 	.align 4
    207 $load_s8:
    208 #ifdef __alpha_bwx__
    209 	ldbu	$0, 16($30)
    210 	sextb	$0, $0
    211 #else
    212 	ldq	$0, 16($30)
    213 	sll	$0, 56, $0
    214 	sra	$0, 56, $0
    215 #endif
    216 	addq	$30, 16*8, $30
    217 	ret
    218 
    219 	.align 4
    220 $load_u16:
    221 #ifdef __alpha_bwx__
    222 	ldwu	$0, 16($30)
    223 	nop
    224 #else
    225 	ldq	$0, 16($30)
    226 	zapnot	$0, 3, $0
    227 #endif
    228 	addq	$30, 16*8, $30
    229 	ret
    230 
    231 	.align 4
    232 $load_s16:
    233 #ifdef __alpha_bwx__
    234 	ldwu	$0, 16($30)
    235 	sextw	$0, $0
    236 #else
    237 	ldq	$0, 16($30)
    238 	sll	$0, 48, $0
    239 	sra	$0, 48, $0
    240 #endif
    241 	addq	$30, 16*8, $30
    242 	ret
    243 
    244 	.align 4
    245 $load_32:
    246 	ldl	$0, 16($30)
    247 	nop
    248 	addq	$30, 16*8, $30
    249 	ret
    250 
    251 	.align 4
    252 $load_64:
    253 	ldq	$0, 16($30)
    254 	nop
    255 	addq	$30, 16*8, $30
    256 	ret
    257 $LFE2:
    258 
    259 	.end	ffi_closure_osf
    260 
    261 #ifdef __ELF__
    262 .section .rodata
    263 #else
    264 .rdata
    265 #endif
    266 $load_table:
    267 	.gprel32 $load_none	# FFI_TYPE_VOID
    268 	.gprel32 $load_32	# FFI_TYPE_INT
    269 	.gprel32 $load_float	# FFI_TYPE_FLOAT
    270 	.gprel32 $load_double	# FFI_TYPE_DOUBLE
    271 	.gprel32 $load_none	# FFI_TYPE_LONGDOUBLE
    272 	.gprel32 $load_u8	# FFI_TYPE_UINT8
    273 	.gprel32 $load_s8	# FFI_TYPE_SINT8
    274 	.gprel32 $load_u16	# FFI_TYPE_UINT16
    275 	.gprel32 $load_s16	# FFI_TYPE_SINT16
    276 	.gprel32 $load_32	# FFI_TYPE_UINT32
    277 	.gprel32 $load_32	# FFI_TYPE_SINT32
    278 	.gprel32 $load_64	# FFI_TYPE_UINT64
    279 	.gprel32 $load_64	# FFI_TYPE_SINT64
    280 	.gprel32 $load_none	# FFI_TYPE_STRUCT
    281 	.gprel32 $load_64	# FFI_TYPE_POINTER
    282 
    283 /* Assert that the table above is in sync with ffi.h.  */
    284 
    285 #if	   FFI_TYPE_FLOAT != 2		\
    286 	|| FFI_TYPE_DOUBLE != 3		\
    287 	|| FFI_TYPE_UINT8 != 5		\
    288 	|| FFI_TYPE_SINT8 != 6		\
    289 	|| FFI_TYPE_UINT16 != 7		\
    290 	|| FFI_TYPE_SINT16 != 8		\
    291 	|| FFI_TYPE_UINT32 != 9		\
    292 	|| FFI_TYPE_SINT32 != 10	\
    293 	|| FFI_TYPE_UINT64 != 11	\
    294 	|| FFI_TYPE_SINT64 != 12	\
    295 	|| FFI_TYPE_STRUCT != 13	\
    296 	|| FFI_TYPE_POINTER != 14	\
    297 	|| FFI_TYPE_LAST != 14
    298 #error "osf.S out of sync with ffi.h"
    299 #endif
    300 
    301 #ifdef __ELF__
    302 # define UA_SI		.4byte
    303 # define FDE_ENCODING	0x1b	/* pcrel sdata4 */
    304 # define FDE_ENCODE(X)	.4byte X-.
    305 # define FDE_ARANGE(X)	.4byte X
    306 #elif defined __osf__
    307 # define UA_SI		.align 0; .long
    308 # define FDE_ENCODING	0x50	/* aligned absolute */
    309 # define FDE_ENCODE(X)	.align 3; .quad X
    310 # define FDE_ARANGE(X)	.align 0; .quad X
    311 #endif
    312 
    313 #ifdef __ELF__
    314 	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
    315 #elif defined __osf__
    316 	.data
    317 	.align 3
    318 	.globl _GLOBAL__F_ffi_call_osf
    319 _GLOBAL__F_ffi_call_osf:
    320 #endif
    321 __FRAME_BEGIN__:
    322 	UA_SI	$LECIE1-$LSCIE1	# Length of Common Information Entry
    323 $LSCIE1:
    324 	UA_SI	0x0		# CIE Identifier Tag
    325 	.byte	0x1		# CIE Version
    326 	.ascii "zR\0"		# CIE Augmentation
    327 	.byte	0x1		# uleb128 0x1; CIE Code Alignment Factor
    328 	.byte	0x78		# sleb128 -8; CIE Data Alignment Factor
    329 	.byte	26		# CIE RA Column
    330 	.byte	0x1		# uleb128 0x1; Augmentation size
    331 	.byte	FDE_ENCODING	# FDE Encoding
    332 	.byte	0xc		# DW_CFA_def_cfa
    333 	.byte	30		# uleb128 column 30
    334 	.byte	0		# uleb128 offset 0
    335 	.align 3
    336 $LECIE1:
    337 $LSFDE1:
    338 	UA_SI	$LEFDE1-$LASFDE1		# FDE Length
    339 $LASFDE1:
    340 	UA_SI	$LASFDE1-__FRAME_BEGIN__	# FDE CIE offset
    341 	FDE_ENCODE($LFB1)			# FDE initial location
    342 	FDE_ARANGE($LFE1-$LFB1)			# FDE address range
    343 	.byte	0x0		# uleb128 0x0; Augmentation size
    344 
    345 	.byte	0x4		# DW_CFA_advance_loc4
    346 	UA_SI	$LCFI1-$LFB1
    347 	.byte	0x9a		# DW_CFA_offset, column 26
    348 	.byte	4		# uleb128 4*-8
    349 	.byte	0x8f		# DW_CFA_offset, column 15
    350 	.byte	0x3		# uleb128 3*-8
    351 	.byte	0xc		# DW_CFA_def_cfa
    352 	.byte	15		# uleb128 column 15
    353 	.byte	32		# uleb128 offset 32
    354 
    355 	.byte	0x4		# DW_CFA_advance_loc4
    356 	UA_SI	$LCFI2-$LCFI1
    357 	.byte	0xda		# DW_CFA_restore, column 26
    358 	.align 3
    359 $LEFDE1:
    360 
    361 $LSFDE3:
    362 	UA_SI	$LEFDE3-$LASFDE3		# FDE Length
    363 $LASFDE3:
    364 	UA_SI	$LASFDE3-__FRAME_BEGIN__	# FDE CIE offset
    365 	FDE_ENCODE($LFB2)			# FDE initial location
    366 	FDE_ARANGE($LFE2-$LFB2)			# FDE address range
    367 	.byte	0x0		# uleb128 0x0; Augmentation size
    368 
    369 	.byte	0x4		# DW_CFA_advance_loc4
    370 	UA_SI	$LCFI5-$LFB2
    371 	.byte	0xe		# DW_CFA_def_cfa_offset
    372 	.byte	0x80,0x1	# uleb128 128
    373 
    374 	.byte	0x4		# DW_CFA_advance_loc4
    375 	UA_SI	$LCFI6-$LCFI5
    376 	.byte	0x9a		# DW_CFA_offset, column 26
    377 	.byte	16		# uleb128 offset 16*-8
    378 	.align 3
    379 $LEFDE3:
    380 #if defined __osf__
    381 	.align 0
    382 	.long	0		# End of Table
    383 #endif
    384 
    385 #if defined __ELF__ && defined __linux__
    386 	.section	.note.GNU-stack,"",@progbits
    387 #endif
    388