/* ----------------------------------------------------------------------- n32.S - Copyright (c) 1996, 1998, 2005, 2007, 2009, 2010 Red Hat, Inc. MIPS 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 #include /* 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 closure a6 /* Note: to keep stack 16 byte aligned we need even number slots used 9 slots here */ #define SIZEOF_FRAME ( 10 * FFI_SIZEOF_ARG ) #ifdef __GNUC__ .abicalls #endif #if !defined(__mips_isa_rev) || (__mips_isa_rev<6) .set mips4 #endif .text .align 2 .globl ffi_call_N32 .ent ffi_call_N32 ffi_call_N32: .LFB0: .frame $fp, SIZEOF_FRAME, ra .mask 0xc0000000,-FFI_SIZEOF_ARG .fmask 0x00000000,0 # Prologue SUBU $sp, SIZEOF_FRAME # Frame size .LCFI00: REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address .LCFI01: move $fp, $sp .LCFI02: move t9, callback # callback function pointer REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn REG_S closure, 6*FFI_SIZEOF_ARG($fp) # closure # Allocate at least 4 words in the argstack move v0, bytes bge bytes, 4 * FFI_SIZEOF_ARG, bigger LI v0, 4 * FFI_SIZEOF_ARG b sixteen bigger: ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry. sixteen: SUBU $sp, $sp, v0 # move the stack pointer to reflect the # arg space move a0, $sp # 4 * FFI_SIZEOF_ARG ADDU a3, $fp, 3 * FFI_SIZEOF_ARG # Call ffi_prep_args jal t9 # 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*FFI_SIZEOF_ARG($fp) # Is it bigger than 8 * FFI_SIZEOF_ARG? daddiu t8, t6, -(8 * FFI_SIZEOF_ARG) bltz t8, loadregs ADDU t9, t9, t8 loadregs: REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6. # when retval is _Complex long double, $f12/$a0, $f13/$a1 will be skipped # no idea why, but gcc does it. SRL t4, t6, 8*FFI_FLAG_BITS move t8, t6 bne t4, FFI_TYPE_COMPLEX_LDLD, loadregs1 SLL t8, t6, 2*FFI_FLAG_BITS loadregs1: #ifdef __mips_soft_float REG_L a0, 0*FFI_SIZEOF_ARG(t9) REG_L a1, 1*FFI_SIZEOF_ARG(t9) REG_L a2, 2*FFI_SIZEOF_ARG(t9) REG_L a3, 3*FFI_SIZEOF_ARG(t9) REG_L a4, 4*FFI_SIZEOF_ARG(t9) REG_L a5, 5*FFI_SIZEOF_ARG(t9) REG_L a6, 6*FFI_SIZEOF_ARG(t9) REG_L a7, 7*FFI_SIZEOF_ARG(t9) #else and t4, t8, ((1<