Home | History | Annotate | Download | only in alpha
      1 /* -----------------------------------------------------------------------
      2    osf.S - Copyright (c) 1998, 2001, 2007, 2008 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 	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
    303 __FRAME_BEGIN__:
    304 	.4byte	$LECIE1-$LSCIE1	# Length of Common Information Entry
    305 $LSCIE1:
    306 	.4byte	0x0		# CIE Identifier Tag
    307 	.byte	0x1		# CIE Version
    308 	.ascii "zR\0"		# CIE Augmentation
    309 	.byte	0x1		# uleb128 0x1; CIE Code Alignment Factor
    310 	.byte	0x78		# sleb128 -8; CIE Data Alignment Factor
    311 	.byte	26		# CIE RA Column
    312 	.byte	0x1		# uleb128 0x1; Augmentation size
    313 	.byte	0x1b		# FDE Encoding (pcrel sdata4)
    314 	.byte	0xc		# DW_CFA_def_cfa
    315 	.byte	30		# uleb128 column 30
    316 	.byte	0		# uleb128 offset 0
    317 	.align 3
    318 $LECIE1:
    319 $LSFDE1:
    320 	.4byte	$LEFDE1-$LASFDE1		# FDE Length
    321 $LASFDE1:
    322 	.4byte	$LASFDE1-__FRAME_BEGIN__	# FDE CIE offset
    323 	.4byte	$LFB1-.		# FDE initial location
    324 	.4byte	$LFE1-$LFB1	# FDE address range
    325 	.byte	0x0		# uleb128 0x0; Augmentation size
    326 
    327 	.byte	0x4		# DW_CFA_advance_loc4
    328 	.4byte	$LCFI1-$LFB1
    329 	.byte	0x9a		# DW_CFA_offset, column 26
    330 	.byte	4		# uleb128 4*-8
    331 	.byte	0x8f		# DW_CFA_offset, column 15
    332 	.byte	0x3		# uleb128 3*-8
    333 	.byte	0xc		# DW_CFA_def_cfa
    334 	.byte	15		# uleb128 column 15
    335 	.byte	32		# uleb128 offset 32
    336 
    337 	.byte	0x4		# DW_CFA_advance_loc4
    338 	.4byte	$LCFI2-$LCFI1
    339 	.byte	0xda		# DW_CFA_restore, column 26
    340 	.align 3
    341 $LEFDE1:
    342 
    343 $LSFDE3:
    344 	.4byte	$LEFDE3-$LASFDE3		# FDE Length
    345 $LASFDE3:
    346 	.4byte	$LASFDE3-__FRAME_BEGIN__	# FDE CIE offset
    347 	.4byte	$LFB2-.		# FDE initial location
    348 	.4byte	$LFE2-$LFB2	# FDE address range
    349 	.byte	0x0		# uleb128 0x0; Augmentation size
    350 
    351 	.byte	0x4		# DW_CFA_advance_loc4
    352 	.4byte	$LCFI5-$LFB2
    353 	.byte	0xe		# DW_CFA_def_cfa_offset
    354 	.byte	0x80,0x1	# uleb128 128
    355 
    356 	.byte	0x4		# DW_CFA_advance_loc4
    357 	.4byte	$LCFI6-$LCFI5
    358 	.byte	0x9a		# DW_CFA_offset, column 26
    359 	.byte	16		# uleb128 offset 16*-8
    360 	.align 3
    361 $LEFDE3:
    362 
    363 #ifdef __linux__
    364 	.section	.note.GNU-stack,"",@progbits
    365 #endif
    366 #endif
    367