Edit

kc3-lang/libffi/src/alpha/osf.S

Branch :

  • Show log

    Commit

  • Author : Richard Henderson
    Date : 2014-10-17 21:26:52
    Hash : 9761b7bb
    Message : alpha: Add support for Go closures

  • src/alpha/osf.S
  • /* -----------------------------------------------------------------------
       osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
    
       Alpha/OSF Foreign Function Interface
    
       Permission is hereby granted, free of charge, to any person obtaining
       a copy of this software and associated documentation files (the
       ``Software''), to deal in the Software without restriction, including
       without limitation the rights to use, copy, modify, merge, publish,
       distribute, sublicense, and/or sell copies of the Software, and to
       permit persons to whom the Software is furnished to do so, subject to
       the following conditions:
    
       The above copyright notice and this permission notice shall be included
       in all copies or substantial portions of the Software.
    
       THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
       NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
       HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
       WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
       DEALINGS IN THE SOFTWARE.
       ----------------------------------------------------------------------- */
    
    #define LIBFFI_ASM
    #include <fficonfig.h>
    #include <ffi.h>
    #include <ffi_cfi.h>
    #include "internal.h"
    
    	.arch ev6
    	.text
    
    /* Aid in building a direct addressed jump table, 4 insns per entry.  */
    .macro E index
    	.align	4
    	.org	99b + \index * 16
    .endm
    
    /* ffi_call_osf (void *stack, void *frame, unsigned flags,
    		 void *raddr, void (*fnaddr)(void), void *closure)
    
       Bit o trickiness here -- FRAME is the base of the stack frame
       for this function.  This has been allocated by ffi_call.  We also
       deallocate some of the stack that has been alloca'd.  */
    
    	.align	4
    	.globl	ffi_call_osf
    	.ent	ffi_call_osf
    	FFI_HIDDEN(ffi_call_osf)
    
    ffi_call_osf:
    	cfi_startproc
    	cfi_def_cfa($17, 32)
    	mov	$16, $30
    	stq	$26, 0($17)
    	stq	$15, 8($17)
    	mov	$17, $15
    	.prologue 0
    	cfi_def_cfa_register($15)
    	cfi_rel_offset($26, 0)
    	cfi_rel_offset($15, 8)
    
    	stq	$18, 16($17)		# save flags into frame
    	stq	$19, 24($17)		# save rvalue into frame
    	mov	$20, $27		# fn into place for call
    	mov	$21, $1			# closure into static chain
    
    	# Load up all of the (potential) argument registers.
    	ldq	$16, 0($30)
    	ldt	$f16, 0($30)
    	ldt	$f17, 8($30)
    	ldq	$17, 8($30)
    	ldt	$f18, 16($30)
    	ldq	$18, 16($30)
    	ldt	$f19, 24($30)
    	ldq	$19, 24($30)
    	ldt	$f20, 32($30)
    	ldq	$20, 32($30)
    	ldt	$f21, 40($30)
    	ldq	$21, 40($30)
    
    	# Deallocate the register argument area.
    	lda	$30, 48($30)
    
    	jsr	$26, ($27), 0
    0:
    	ldah	$29, 0($26)		!gpdisp!1
    	ldq	$2, 24($15)		# reload rvalue
    	lda	$29, 0($29)		!gpdisp!1
    	ldq	$3, 16($15)		# reload flags
    	lda	$1, 99f-0b($26)
    	ldq	$26, 0($15)
    	ldq	$15, 8($15)
    	cfi_restore($26)
    	cfi_restore($15)
    	cfi_def_cfa($sp, 0)
    	cmoveq	$2, ALPHA_ST_VOID, $3	# mash null rvalue to void
    	addq	$3, $3, $3
    	s8addq	$3, $1, $1		# 99f + stcode * 16
    	jmp	$31, ($1), $st_int
    
    	.align	4
    99:
    E ALPHA_ST_VOID
    	ret
    E ALPHA_ST_INT
    $st_int:
    	stq	$0, 0($2)
    	ret
    E ALPHA_ST_FLOAT
    	sts	$f0, 0($2)
    	ret
    E ALPHA_ST_DOUBLE
    	stt	$f0, 0($2)
    	ret
    E ALPHA_ST_CPLXF
    	sts	$f0, 0($2)
    	sts	$f1, 4($2)
    	ret
    E ALPHA_ST_CPLXD
    	stt	$f0, 0($2)
    	stt	$f1, 8($2)
    	ret
    
    	cfi_endproc
    	.end	ffi_call_osf
    
    /* ffi_closure_osf(...)
    
       Receives the closure argument in $1.   */
    
    #define CLOSURE_FS	(16*8)
    
    	.align	4
    	.globl	ffi_go_closure_osf
    	.ent	ffi_go_closure_osf
    	FFI_HIDDEN(ffi_go_closure_osf)
    
    ffi_go_closure_osf:
    	cfi_startproc
    	ldgp	$29, 0($27)
    	subq	$30, CLOSURE_FS, $30
    	cfi_adjust_cfa_offset(CLOSURE_FS)
    	stq	$26, 0($30)
    	.prologue 1
    	cfi_rel_offset($26, 0)
    
    	stq	$16, 10*8($30)
    	stq	$17, 11*8($30)
    	stq	$18, 12*8($30)
    
    	ldq	$16, 8($1)			# load cif
    	ldq	$17, 16($1)			# load fun
    	mov	$1, $18				# closure is user_data
    	br	$do_closure
    
    	cfi_endproc
    	.end	ffi_go_closure_osf
    
    	.align	4
    	.globl	ffi_closure_osf
    	.ent	ffi_closure_osf
    	FFI_HIDDEN(ffi_closure_osf)
    
    ffi_closure_osf:
    	cfi_startproc
    	ldgp	$29, 0($27)
    	subq	$30, CLOSURE_FS, $30
    	cfi_adjust_cfa_offset(CLOSURE_FS)
    	stq	$26, 0($30)
    	.prologue 1
    	cfi_rel_offset($26, 0)
    
    	# Store all of the potential argument registers in va_list format.
    	stq	$16, 10*8($30)
    	stq	$17, 11*8($30)
    	stq	$18, 12*8($30)
    
    	ldq	$16, 24($1)			# load cif
    	ldq	$17, 32($1)			# load fun
    	ldq	$18, 40($1)			# load user_data
    
    $do_closure:
    	stq	$19, 13*8($30)
    	stq	$20, 14*8($30)
    	stq	$21, 15*8($30)
    	stt	$f16, 4*8($30)
    	stt	$f17, 5*8($30)
    	stt	$f18, 6*8($30)
    	stt	$f19, 7*8($30)
    	stt	$f20, 8*8($30)
    	stt	$f21, 9*8($30)
    
    	# Call ffi_closure_osf_inner to do the bulk of the work.
    	lda	$19, 2*8($30)
    	lda	$20, 10*8($30)
    	jsr	$26, ffi_closure_osf_inner
    0:
    	ldah	$29, 0($26)			!gpdisp!2
    	lda	$2, 99f-0b($26)
    	s4addq	$0, 0, $1			# ldcode * 4
    	ldq	$0, 16($30)			# preload return value
    	s4addq	$1, $2, $1			# 99f + ldcode * 16
    	lda	$29, 0($29)			!gpdisp!2
    	ldq	$26, 0($30)
    	cfi_restore($26)
    	jmp	$31, ($1), $load_32
    
    .macro epilogue
    	addq	$30, CLOSURE_FS, $30
    	cfi_adjust_cfa_offset(-CLOSURE_FS)
    	ret
    	.align	4
    	cfi_adjust_cfa_offset(CLOSURE_FS)
    .endm
    
    	.align 4
    99:
    E ALPHA_LD_VOID
    	epilogue
    
    E ALPHA_LD_INT64
    	epilogue
    
    E ALPHA_LD_INT32
    $load_32:
    	sextl	$0, $0
    	epilogue
    
    E ALPHA_LD_UINT16
    	zapnot	$0, 3, $0
    	epilogue
    
    E ALPHA_LD_SINT16
    #ifdef __alpha_bwx__
    	sextw	$0, $0
    #else
    	sll	$0, 48, $0
    	sra	$0, 48, $0
    #endif
    	epilogue
    
    E ALPHA_LD_UINT8
    	and	$0, 0xff, $0
    	epilogue
    
    E ALPHA_LD_SINT8
    #ifdef __alpha_bwx__
    	sextb	$0, $0
    #else
    	sll	$0, 56, $0
    	sra	$0, 56, $0
    #endif
    	epilogue
    
    E ALPHA_LD_FLOAT
    	lds	$f0, 16($sp)
    	epilogue
    
    E ALPHA_LD_DOUBLE
    	ldt	$f0, 16($sp)
    	epilogue
    
    E ALPHA_LD_CPLXF
    	lds	$f0, 16($sp)
    	lds	$f1, 20($sp)
    	epilogue
    
    E ALPHA_LD_CPLXD
    	ldt	$f0, 16($sp)
    	ldt	$f1, 24($sp)
    	epilogue
    
    	cfi_endproc
    	.end	ffi_closure_osf
    
    #if defined __ELF__ && defined __linux__
    	.section	.note.GNU-stack,"",@progbits
    #endif