Import of v1 code.
This commit is contained in:
320
libffi/src/mips/n32.S
Normal file
320
libffi/src/mips/n32.S
Normal file
@@ -0,0 +1,320 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
n32.S - Copyright (c) 1996, 1998 Cygnus Solutions
|
||||
|
||||
MIPS Foreign Function Interface
|
||||
|
||||
$Id: n32.S,v 1.1 1998/11/29 16:48:16 green Exp $
|
||||
|
||||
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 CYGNUS SOLUTIONS 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 <ffi.h>
|
||||
|
||||
/* Only build this code if we are compiling for n32 */
|
||||
|
||||
#if defined(FFI_MIPS_N32)
|
||||
|
||||
#define callback a0
|
||||
#define bytes a2
|
||||
#define flags a3
|
||||
#define raddr a4
|
||||
#define fn a5
|
||||
|
||||
#define SIZEOF_FRAME ( 8 * SIZEOF_ARG )
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_call_N32
|
||||
.ent ffi_call_N32
|
||||
ffi_call_N32:
|
||||
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
REG_S $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Save frame pointer
|
||||
REG_S ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Save return address
|
||||
move $fp, $sp
|
||||
|
||||
move t9, callback # callback function pointer
|
||||
REG_S bytes, 2*SIZEOF_ARG($fp) # bytes
|
||||
REG_S flags, 3*SIZEOF_ARG($fp) # flags
|
||||
REG_S raddr, 4*SIZEOF_ARG($fp) # raddr
|
||||
REG_S fn, 5*SIZEOF_ARG($fp) # fn
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
move v0, bytes
|
||||
bge bytes, 4 * SIZEOF_ARG, bigger
|
||||
LI v0, 4 * SIZEOF_ARG
|
||||
b sixteen
|
||||
|
||||
bigger:
|
||||
ADDU t4, v0, 2 * SIZEOF_ARG -1 # make sure it is aligned
|
||||
and v0, t4, -2 * SIZEOF_ARG # to a proper boundry.
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
ADDU a0, $sp, 0 # 4 * SIZEOF_ARG
|
||||
ADDU a3, $fp, 3 * SIZEOF_ARG
|
||||
|
||||
# Call ffi_prep_args
|
||||
jal t9
|
||||
|
||||
# ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
|
||||
|
||||
# Copy the stack pointer to t9
|
||||
move t9, $sp
|
||||
|
||||
# Fix the stack if there are more than 8 64bit slots worth
|
||||
# of arguments.
|
||||
|
||||
# Load the number of bytes
|
||||
REG_L t6, 2*SIZEOF_ARG($fp)
|
||||
|
||||
# Is it bigger than 8 * SIZEOF_ARG?
|
||||
dadd t7, $0, 8 * SIZEOF_ARG
|
||||
dsub t8, t6, t7
|
||||
bltz t8, loadregs
|
||||
|
||||
add t9, t9, t8
|
||||
|
||||
loadregs:
|
||||
|
||||
REG_L t4, 3*SIZEOF_ARG($fp) # load the flags word
|
||||
add t6, t4, 0 # and copy it into t6
|
||||
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg1_floatp
|
||||
REG_L a0, 0*SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg1_doublep
|
||||
l.s $f12, 0*SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_doublep:
|
||||
l.d $f12, 0*SIZEOF_ARG(t9)
|
||||
arg1_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 1*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg2_floatp
|
||||
REG_L a1, 1*SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg2_doublep
|
||||
l.s $f13, 1*SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_doublep:
|
||||
l.d $f13, 1*SIZEOF_ARG(t9)
|
||||
arg2_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 2*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg3_floatp
|
||||
REG_L a2, 2*SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg3_doublep
|
||||
l.s $f14, 2*SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_doublep:
|
||||
l.d $f14, 2*SIZEOF_ARG(t9)
|
||||
arg3_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 3*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg4_floatp
|
||||
REG_L a3, 3*SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg4_doublep
|
||||
l.s $f15, 3*SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_doublep:
|
||||
l.d $f15, 3*SIZEOF_ARG(t9)
|
||||
arg4_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 4*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg5_floatp
|
||||
REG_L a4, 4*SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg5_doublep
|
||||
l.s $f16, 4*SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_doublep:
|
||||
l.d $f16, 4*SIZEOF_ARG(t9)
|
||||
arg5_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 5*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg6_floatp
|
||||
REG_L a5, 5*SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg6_doublep
|
||||
l.s $f17, 5*SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_doublep:
|
||||
l.d $f17, 5*SIZEOF_ARG(t9)
|
||||
arg6_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 6*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg7_floatp
|
||||
REG_L a6, 6*SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg7_doublep
|
||||
l.s $f18, 6*SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_doublep:
|
||||
l.d $f18, 6*SIZEOF_ARG(t9)
|
||||
arg7_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 7*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg8_floatp
|
||||
REG_L a7, 7*SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg8_doublep
|
||||
l.s $f19, 7*SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_doublep:
|
||||
l.d $f19, 7*SIZEOF_ARG(t9)
|
||||
arg8_next:
|
||||
|
||||
callit:
|
||||
# Load the function pointer
|
||||
REG_L t9, 5*SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t5, 4*SIZEOF_ARG($fp)
|
||||
beqz t5, noretval
|
||||
|
||||
# Shift the return type flag over
|
||||
SRL t6, 8*FFI_FLAG_BITS
|
||||
|
||||
bne t6, FFI_TYPE_INT, retfloat
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t6, FFI_TYPE_FLOAT, retdouble
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t6, FFI_TYPE_DOUBLE, retstruct_d
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d:
|
||||
bne t6, FFI_TYPE_STRUCT_D, retstruct_f
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f:
|
||||
bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_d:
|
||||
bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_f:
|
||||
bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.s $f2, 4(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_f:
|
||||
bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.s $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f_d:
|
||||
bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_small:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_small2:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
REG_S v1, 8(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct:
|
||||
noretval:
|
||||
jal t9
|
||||
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
|
||||
REG_L ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
.end ffi_call_N32
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user