1*1fd5a2e1SPrashanth Swaminathan/* ----------------------------------------------------------------------- 2*1fd5a2e1SPrashanth Swaminathan o32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc. 3*1fd5a2e1SPrashanth Swaminathan 4*1fd5a2e1SPrashanth Swaminathan MIPS Foreign Function Interface 5*1fd5a2e1SPrashanth Swaminathan 6*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining 7*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the 8*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including 9*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish, 10*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to 11*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to 12*1fd5a2e1SPrashanth Swaminathan the following conditions: 13*1fd5a2e1SPrashanth Swaminathan 14*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included 15*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software. 16*1fd5a2e1SPrashanth Swaminathan 17*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 18*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE. 25*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */ 26*1fd5a2e1SPrashanth Swaminathan 27*1fd5a2e1SPrashanth Swaminathan#define LIBFFI_ASM 28*1fd5a2e1SPrashanth Swaminathan#include <fficonfig.h> 29*1fd5a2e1SPrashanth Swaminathan#include <ffi.h> 30*1fd5a2e1SPrashanth Swaminathan 31*1fd5a2e1SPrashanth Swaminathan/* Only build this code if we are compiling for o32 */ 32*1fd5a2e1SPrashanth Swaminathan 33*1fd5a2e1SPrashanth Swaminathan#if defined(FFI_MIPS_O32) 34*1fd5a2e1SPrashanth Swaminathan 35*1fd5a2e1SPrashanth Swaminathan#define callback a0 36*1fd5a2e1SPrashanth Swaminathan#define bytes a2 37*1fd5a2e1SPrashanth Swaminathan#define flags a3 38*1fd5a2e1SPrashanth Swaminathan 39*1fd5a2e1SPrashanth Swaminathan#define SIZEOF_FRAME (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG) 40*1fd5a2e1SPrashanth Swaminathan#define A3_OFF (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG) 41*1fd5a2e1SPrashanth Swaminathan#define FP_OFF (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG) 42*1fd5a2e1SPrashanth Swaminathan#define RA_OFF (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG) 43*1fd5a2e1SPrashanth Swaminathan 44*1fd5a2e1SPrashanth Swaminathan .abicalls 45*1fd5a2e1SPrashanth Swaminathan .text 46*1fd5a2e1SPrashanth Swaminathan .align 2 47*1fd5a2e1SPrashanth Swaminathan .globl ffi_call_O32 48*1fd5a2e1SPrashanth Swaminathan .ent ffi_call_O32 49*1fd5a2e1SPrashanth Swaminathanffi_call_O32: 50*1fd5a2e1SPrashanth Swaminathan$LFB0: 51*1fd5a2e1SPrashanth Swaminathan # Prologue 52*1fd5a2e1SPrashanth Swaminathan SUBU $sp, SIZEOF_FRAME # Frame size 53*1fd5a2e1SPrashanth Swaminathan$LCFI00: 54*1fd5a2e1SPrashanth Swaminathan REG_S $fp, FP_OFF($sp) # Save frame pointer 55*1fd5a2e1SPrashanth Swaminathan$LCFI01: 56*1fd5a2e1SPrashanth Swaminathan REG_S ra, RA_OFF($sp) # Save return address 57*1fd5a2e1SPrashanth Swaminathan$LCFI02: 58*1fd5a2e1SPrashanth Swaminathan move $fp, $sp 59*1fd5a2e1SPrashanth Swaminathan 60*1fd5a2e1SPrashanth Swaminathan$LCFI03: 61*1fd5a2e1SPrashanth Swaminathan move t9, callback # callback function pointer 62*1fd5a2e1SPrashanth Swaminathan REG_S flags, A3_OFF($fp) # flags 63*1fd5a2e1SPrashanth Swaminathan 64*1fd5a2e1SPrashanth Swaminathan # Allocate at least 4 words in the argstack 65*1fd5a2e1SPrashanth Swaminathan LI v0, 4 * FFI_SIZEOF_ARG 66*1fd5a2e1SPrashanth Swaminathan blt bytes, v0, sixteen 67*1fd5a2e1SPrashanth Swaminathan 68*1fd5a2e1SPrashanth Swaminathan ADDU v0, bytes, 7 # make sure it is aligned 69*1fd5a2e1SPrashanth Swaminathan and v0, -8 # to an 8 byte boundry 70*1fd5a2e1SPrashanth Swaminathan 71*1fd5a2e1SPrashanth Swaminathansixteen: 72*1fd5a2e1SPrashanth Swaminathan SUBU $sp, v0 # move the stack pointer to reflect the 73*1fd5a2e1SPrashanth Swaminathan # arg space 74*1fd5a2e1SPrashanth Swaminathan 75*1fd5a2e1SPrashanth Swaminathan ADDU a0, $sp, 4 * FFI_SIZEOF_ARG 76*1fd5a2e1SPrashanth Swaminathan 77*1fd5a2e1SPrashanth Swaminathan jalr t9 78*1fd5a2e1SPrashanth Swaminathan 79*1fd5a2e1SPrashanth Swaminathan REG_L t0, A3_OFF($fp) # load the flags word 80*1fd5a2e1SPrashanth Swaminathan SRL t2, t0, 4 # shift our arg info 81*1fd5a2e1SPrashanth Swaminathan and t0, ((1<<4)-1) # mask out the return type 82*1fd5a2e1SPrashanth Swaminathan 83*1fd5a2e1SPrashanth Swaminathan ADDU $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args 84*1fd5a2e1SPrashanth Swaminathan 85*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float 86*1fd5a2e1SPrashanth Swaminathan bnez t0, pass_d # make it quick for int 87*1fd5a2e1SPrashanth Swaminathan#endif 88*1fd5a2e1SPrashanth Swaminathan REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the 89*1fd5a2e1SPrashanth Swaminathan REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs. 90*1fd5a2e1SPrashanth Swaminathan REG_L a2, 2*FFI_SIZEOF_ARG($sp) 91*1fd5a2e1SPrashanth Swaminathan REG_L a3, 3*FFI_SIZEOF_ARG($sp) 92*1fd5a2e1SPrashanth Swaminathan b call_it 93*1fd5a2e1SPrashanth Swaminathan 94*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float 95*1fd5a2e1SPrashanth Swaminathanpass_d: 96*1fd5a2e1SPrashanth Swaminathan bne t0, FFI_ARGS_D, pass_f 97*1fd5a2e1SPrashanth Swaminathan l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args 98*1fd5a2e1SPrashanth Swaminathan REG_L a2, 2*FFI_SIZEOF_ARG($sp) # passing a double 99*1fd5a2e1SPrashanth Swaminathan REG_L a3, 3*FFI_SIZEOF_ARG($sp) 100*1fd5a2e1SPrashanth Swaminathan b call_it 101*1fd5a2e1SPrashanth Swaminathan 102*1fd5a2e1SPrashanth Swaminathanpass_f: 103*1fd5a2e1SPrashanth Swaminathan bne t0, FFI_ARGS_F, pass_d_d 104*1fd5a2e1SPrashanth Swaminathan l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args 105*1fd5a2e1SPrashanth Swaminathan REG_L a1, 1*FFI_SIZEOF_ARG($sp) # passing a float 106*1fd5a2e1SPrashanth Swaminathan REG_L a2, 2*FFI_SIZEOF_ARG($sp) 107*1fd5a2e1SPrashanth Swaminathan REG_L a3, 3*FFI_SIZEOF_ARG($sp) 108*1fd5a2e1SPrashanth Swaminathan b call_it 109*1fd5a2e1SPrashanth Swaminathan 110*1fd5a2e1SPrashanth Swaminathanpass_d_d: 111*1fd5a2e1SPrashanth Swaminathan bne t0, FFI_ARGS_DD, pass_f_f 112*1fd5a2e1SPrashanth Swaminathan l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args 113*1fd5a2e1SPrashanth Swaminathan l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing two doubles 114*1fd5a2e1SPrashanth Swaminathan b call_it 115*1fd5a2e1SPrashanth Swaminathan 116*1fd5a2e1SPrashanth Swaminathanpass_f_f: 117*1fd5a2e1SPrashanth Swaminathan bne t0, FFI_ARGS_FF, pass_d_f 118*1fd5a2e1SPrashanth Swaminathan l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args 119*1fd5a2e1SPrashanth Swaminathan l.s $f14, 1*FFI_SIZEOF_ARG($sp) # passing two floats 120*1fd5a2e1SPrashanth Swaminathan REG_L a2, 2*FFI_SIZEOF_ARG($sp) 121*1fd5a2e1SPrashanth Swaminathan REG_L a3, 3*FFI_SIZEOF_ARG($sp) 122*1fd5a2e1SPrashanth Swaminathan b call_it 123*1fd5a2e1SPrashanth Swaminathan 124*1fd5a2e1SPrashanth Swaminathanpass_d_f: 125*1fd5a2e1SPrashanth Swaminathan bne t0, FFI_ARGS_DF, pass_f_d 126*1fd5a2e1SPrashanth Swaminathan l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args 127*1fd5a2e1SPrashanth Swaminathan l.s $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float 128*1fd5a2e1SPrashanth Swaminathan REG_L a3, 3*FFI_SIZEOF_ARG($sp) 129*1fd5a2e1SPrashanth Swaminathan b call_it 130*1fd5a2e1SPrashanth Swaminathan 131*1fd5a2e1SPrashanth Swaminathanpass_f_d: 132*1fd5a2e1SPrashanth Swaminathan # assume that the only other combination must be float then double 133*1fd5a2e1SPrashanth Swaminathan # bne t0, FFI_ARGS_F_D, call_it 134*1fd5a2e1SPrashanth Swaminathan l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args 135*1fd5a2e1SPrashanth Swaminathan l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float 136*1fd5a2e1SPrashanth Swaminathan#endif 137*1fd5a2e1SPrashanth Swaminathan 138*1fd5a2e1SPrashanth Swaminathancall_it: 139*1fd5a2e1SPrashanth Swaminathan # Load the static chain pointer 140*1fd5a2e1SPrashanth Swaminathan REG_L t7, SIZEOF_FRAME + 6*FFI_SIZEOF_ARG($fp) 141*1fd5a2e1SPrashanth Swaminathan 142*1fd5a2e1SPrashanth Swaminathan # Load the function pointer 143*1fd5a2e1SPrashanth Swaminathan REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp) 144*1fd5a2e1SPrashanth Swaminathan 145*1fd5a2e1SPrashanth Swaminathan # If the return value pointer is NULL, assume no return value. 146*1fd5a2e1SPrashanth Swaminathan REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) 147*1fd5a2e1SPrashanth Swaminathan beqz t1, noretval 148*1fd5a2e1SPrashanth Swaminathan 149*1fd5a2e1SPrashanth Swaminathan bne t2, FFI_TYPE_INT, retlonglong 150*1fd5a2e1SPrashanth Swaminathan jalr t9 151*1fd5a2e1SPrashanth Swaminathan REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) 152*1fd5a2e1SPrashanth Swaminathan REG_S v0, 0(t0) 153*1fd5a2e1SPrashanth Swaminathan b epilogue 154*1fd5a2e1SPrashanth Swaminathan 155*1fd5a2e1SPrashanth Swaminathanretlonglong: 156*1fd5a2e1SPrashanth Swaminathan # Really any 64-bit int, signed or not. 157*1fd5a2e1SPrashanth Swaminathan bne t2, FFI_TYPE_UINT64, retfloat 158*1fd5a2e1SPrashanth Swaminathan jalr t9 159*1fd5a2e1SPrashanth Swaminathan REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) 160*1fd5a2e1SPrashanth Swaminathan REG_S v1, 4(t0) 161*1fd5a2e1SPrashanth Swaminathan REG_S v0, 0(t0) 162*1fd5a2e1SPrashanth Swaminathan b epilogue 163*1fd5a2e1SPrashanth Swaminathan 164*1fd5a2e1SPrashanth Swaminathanretfloat: 165*1fd5a2e1SPrashanth Swaminathan bne t2, FFI_TYPE_FLOAT, retdouble 166*1fd5a2e1SPrashanth Swaminathan jalr t9 167*1fd5a2e1SPrashanth Swaminathan REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) 168*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float 169*1fd5a2e1SPrashanth Swaminathan s.s $f0, 0(t0) 170*1fd5a2e1SPrashanth Swaminathan#else 171*1fd5a2e1SPrashanth Swaminathan REG_S v0, 0(t0) 172*1fd5a2e1SPrashanth Swaminathan#endif 173*1fd5a2e1SPrashanth Swaminathan b epilogue 174*1fd5a2e1SPrashanth Swaminathan 175*1fd5a2e1SPrashanth Swaminathanretdouble: 176*1fd5a2e1SPrashanth Swaminathan bne t2, FFI_TYPE_DOUBLE, noretval 177*1fd5a2e1SPrashanth Swaminathan jalr t9 178*1fd5a2e1SPrashanth Swaminathan REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) 179*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float 180*1fd5a2e1SPrashanth Swaminathan s.d $f0, 0(t0) 181*1fd5a2e1SPrashanth Swaminathan#else 182*1fd5a2e1SPrashanth Swaminathan REG_S v1, 4(t0) 183*1fd5a2e1SPrashanth Swaminathan REG_S v0, 0(t0) 184*1fd5a2e1SPrashanth Swaminathan#endif 185*1fd5a2e1SPrashanth Swaminathan b epilogue 186*1fd5a2e1SPrashanth Swaminathan 187*1fd5a2e1SPrashanth Swaminathannoretval: 188*1fd5a2e1SPrashanth Swaminathan jalr t9 189*1fd5a2e1SPrashanth Swaminathan 190*1fd5a2e1SPrashanth Swaminathan # Epilogue 191*1fd5a2e1SPrashanth Swaminathanepilogue: 192*1fd5a2e1SPrashanth Swaminathan move $sp, $fp 193*1fd5a2e1SPrashanth Swaminathan REG_L $fp, FP_OFF($sp) # Restore frame pointer 194*1fd5a2e1SPrashanth Swaminathan REG_L ra, RA_OFF($sp) # Restore return address 195*1fd5a2e1SPrashanth Swaminathan ADDU $sp, SIZEOF_FRAME # Fix stack pointer 196*1fd5a2e1SPrashanth Swaminathan j ra 197*1fd5a2e1SPrashanth Swaminathan 198*1fd5a2e1SPrashanth Swaminathan$LFE0: 199*1fd5a2e1SPrashanth Swaminathan .end ffi_call_O32 200*1fd5a2e1SPrashanth Swaminathan 201*1fd5a2e1SPrashanth Swaminathan 202*1fd5a2e1SPrashanth Swaminathan/* ffi_closure_O32. Expects address of the passed-in ffi_closure 203*1fd5a2e1SPrashanth Swaminathan in t4 ($12). Stores any arguments passed in registers onto the 204*1fd5a2e1SPrashanth Swaminathan stack, then calls ffi_closure_mips_inner_O32, which 205*1fd5a2e1SPrashanth Swaminathan then decodes them. 206*1fd5a2e1SPrashanth Swaminathan 207*1fd5a2e1SPrashanth Swaminathan Stack layout: 208*1fd5a2e1SPrashanth Swaminathan 209*1fd5a2e1SPrashanth Swaminathan 3 - a3 save 210*1fd5a2e1SPrashanth Swaminathan 2 - a2 save 211*1fd5a2e1SPrashanth Swaminathan 1 - a1 save 212*1fd5a2e1SPrashanth Swaminathan 0 - a0 save, original sp 213*1fd5a2e1SPrashanth Swaminathan -1 - ra save 214*1fd5a2e1SPrashanth Swaminathan -2 - fp save 215*1fd5a2e1SPrashanth Swaminathan -3 - $16 (s0) save 216*1fd5a2e1SPrashanth Swaminathan -4 - cprestore 217*1fd5a2e1SPrashanth Swaminathan -5 - return value high (v1) 218*1fd5a2e1SPrashanth Swaminathan -6 - return value low (v0) 219*1fd5a2e1SPrashanth Swaminathan -7 - f14 (le high, be low) 220*1fd5a2e1SPrashanth Swaminathan -8 - f14 (le low, be high) 221*1fd5a2e1SPrashanth Swaminathan -9 - f12 (le high, be low) 222*1fd5a2e1SPrashanth Swaminathan -10 - f12 (le low, be high) 223*1fd5a2e1SPrashanth Swaminathan -11 - Called function a5 save 224*1fd5a2e1SPrashanth Swaminathan -12 - Called function a4 save 225*1fd5a2e1SPrashanth Swaminathan -13 - Called function a3 save 226*1fd5a2e1SPrashanth Swaminathan -14 - Called function a2 save 227*1fd5a2e1SPrashanth Swaminathan -15 - Called function a1 save 228*1fd5a2e1SPrashanth Swaminathan -16 - Called function a0 save, our sp and fp point here 229*1fd5a2e1SPrashanth Swaminathan */ 230*1fd5a2e1SPrashanth Swaminathan 231*1fd5a2e1SPrashanth Swaminathan#define SIZEOF_FRAME2 (16 * FFI_SIZEOF_ARG) 232*1fd5a2e1SPrashanth Swaminathan#define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG) 233*1fd5a2e1SPrashanth Swaminathan#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG) 234*1fd5a2e1SPrashanth Swaminathan#define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG) 235*1fd5a2e1SPrashanth Swaminathan#define A0_OFF2 (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG) 236*1fd5a2e1SPrashanth Swaminathan#define RA_OFF2 (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG) 237*1fd5a2e1SPrashanth Swaminathan#define FP_OFF2 (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG) 238*1fd5a2e1SPrashanth Swaminathan#define S0_OFF2 (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG) 239*1fd5a2e1SPrashanth Swaminathan#define GP_OFF2 (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG) 240*1fd5a2e1SPrashanth Swaminathan#define V1_OFF2 (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG) 241*1fd5a2e1SPrashanth Swaminathan#define V0_OFF2 (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG) 242*1fd5a2e1SPrashanth Swaminathan#define FA_1_1_OFF2 (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG) 243*1fd5a2e1SPrashanth Swaminathan#define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG) 244*1fd5a2e1SPrashanth Swaminathan#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG) 245*1fd5a2e1SPrashanth Swaminathan#define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG) 246*1fd5a2e1SPrashanth Swaminathan#define CALLED_A5_OFF2 (SIZEOF_FRAME2 - 11 * FFI_SIZEOF_ARG) 247*1fd5a2e1SPrashanth Swaminathan#define CALLED_A4_OFF2 (SIZEOF_FRAME2 - 12 * FFI_SIZEOF_ARG) 248*1fd5a2e1SPrashanth Swaminathan 249*1fd5a2e1SPrashanth Swaminathan .text 250*1fd5a2e1SPrashanth Swaminathan 251*1fd5a2e1SPrashanth Swaminathan .align 2 252*1fd5a2e1SPrashanth Swaminathan .globl ffi_go_closure_O32 253*1fd5a2e1SPrashanth Swaminathan .ent ffi_go_closure_O32 254*1fd5a2e1SPrashanth Swaminathanffi_go_closure_O32: 255*1fd5a2e1SPrashanth Swaminathan$LFB1: 256*1fd5a2e1SPrashanth Swaminathan # Prologue 257*1fd5a2e1SPrashanth Swaminathan .frame $fp, SIZEOF_FRAME2, ra 258*1fd5a2e1SPrashanth Swaminathan .set noreorder 259*1fd5a2e1SPrashanth Swaminathan .cpload t9 260*1fd5a2e1SPrashanth Swaminathan .set reorder 261*1fd5a2e1SPrashanth Swaminathan SUBU $sp, SIZEOF_FRAME2 262*1fd5a2e1SPrashanth Swaminathan .cprestore GP_OFF2 263*1fd5a2e1SPrashanth Swaminathan$LCFI10: 264*1fd5a2e1SPrashanth Swaminathan 265*1fd5a2e1SPrashanth Swaminathan REG_S $16, S0_OFF2($sp) # Save s0 266*1fd5a2e1SPrashanth Swaminathan REG_S $fp, FP_OFF2($sp) # Save frame pointer 267*1fd5a2e1SPrashanth Swaminathan REG_S ra, RA_OFF2($sp) # Save return address 268*1fd5a2e1SPrashanth Swaminathan$LCFI11: 269*1fd5a2e1SPrashanth Swaminathan 270*1fd5a2e1SPrashanth Swaminathan move $fp, $sp 271*1fd5a2e1SPrashanth Swaminathan$LCFI12: 272*1fd5a2e1SPrashanth Swaminathan 273*1fd5a2e1SPrashanth Swaminathan REG_S a0, A0_OFF2($fp) 274*1fd5a2e1SPrashanth Swaminathan REG_S a1, A1_OFF2($fp) 275*1fd5a2e1SPrashanth Swaminathan REG_S a2, A2_OFF2($fp) 276*1fd5a2e1SPrashanth Swaminathan REG_S a3, A3_OFF2($fp) 277*1fd5a2e1SPrashanth Swaminathan 278*1fd5a2e1SPrashanth Swaminathan # Load ABI enum to s0 279*1fd5a2e1SPrashanth Swaminathan REG_L $16, 4($15) # cif 280*1fd5a2e1SPrashanth Swaminathan REG_L $16, 0($16) # abi is first member. 281*1fd5a2e1SPrashanth Swaminathan 282*1fd5a2e1SPrashanth Swaminathan li $13, 1 # FFI_O32 283*1fd5a2e1SPrashanth Swaminathan bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT 284*1fd5a2e1SPrashanth Swaminathan 285*1fd5a2e1SPrashanth Swaminathan # Store all possible float/double registers. 286*1fd5a2e1SPrashanth Swaminathan s.d $f12, FA_0_0_OFF2($fp) 287*1fd5a2e1SPrashanth Swaminathan s.d $f14, FA_1_0_OFF2($fp) 288*1fd5a2e1SPrashanth Swaminathan1: 289*1fd5a2e1SPrashanth Swaminathan # prepare arguments for ffi_closure_mips_inner_O32 290*1fd5a2e1SPrashanth Swaminathan REG_L a0, 4($15) # cif 291*1fd5a2e1SPrashanth Swaminathan REG_L a1, 8($15) # fun 292*1fd5a2e1SPrashanth Swaminathan move a2, $15 # user_data = go closure 293*1fd5a2e1SPrashanth Swaminathan addu a3, $fp, V0_OFF2 # rvalue 294*1fd5a2e1SPrashanth Swaminathan 295*1fd5a2e1SPrashanth Swaminathan addu t9, $fp, A0_OFF2 # ar 296*1fd5a2e1SPrashanth Swaminathan REG_S t9, CALLED_A4_OFF2($fp) 297*1fd5a2e1SPrashanth Swaminathan 298*1fd5a2e1SPrashanth Swaminathan addu t9, $fp, FA_0_0_OFF2 #fpr 299*1fd5a2e1SPrashanth Swaminathan REG_S t9, CALLED_A5_OFF2($fp) 300*1fd5a2e1SPrashanth Swaminathan 301*1fd5a2e1SPrashanth Swaminathan b $do_closure 302*1fd5a2e1SPrashanth Swaminathan 303*1fd5a2e1SPrashanth Swaminathan$LFE1: 304*1fd5a2e1SPrashanth Swaminathan .end ffi_go_closure_O32 305*1fd5a2e1SPrashanth Swaminathan 306*1fd5a2e1SPrashanth Swaminathan .align 2 307*1fd5a2e1SPrashanth Swaminathan .globl ffi_closure_O32 308*1fd5a2e1SPrashanth Swaminathan .ent ffi_closure_O32 309*1fd5a2e1SPrashanth Swaminathanffi_closure_O32: 310*1fd5a2e1SPrashanth Swaminathan$LFB2: 311*1fd5a2e1SPrashanth Swaminathan # Prologue 312*1fd5a2e1SPrashanth Swaminathan .frame $fp, SIZEOF_FRAME2, ra 313*1fd5a2e1SPrashanth Swaminathan .set noreorder 314*1fd5a2e1SPrashanth Swaminathan .cpload t9 315*1fd5a2e1SPrashanth Swaminathan .set reorder 316*1fd5a2e1SPrashanth Swaminathan SUBU $sp, SIZEOF_FRAME2 317*1fd5a2e1SPrashanth Swaminathan .cprestore GP_OFF2 318*1fd5a2e1SPrashanth Swaminathan$LCFI20: 319*1fd5a2e1SPrashanth Swaminathan REG_S $16, S0_OFF2($sp) # Save s0 320*1fd5a2e1SPrashanth Swaminathan REG_S $fp, FP_OFF2($sp) # Save frame pointer 321*1fd5a2e1SPrashanth Swaminathan REG_S ra, RA_OFF2($sp) # Save return address 322*1fd5a2e1SPrashanth Swaminathan$LCFI21: 323*1fd5a2e1SPrashanth Swaminathan move $fp, $sp 324*1fd5a2e1SPrashanth Swaminathan 325*1fd5a2e1SPrashanth Swaminathan$LCFI22: 326*1fd5a2e1SPrashanth Swaminathan # Store all possible argument registers. If there are more than 327*1fd5a2e1SPrashanth Swaminathan # four arguments, then they are stored above where we put a3. 328*1fd5a2e1SPrashanth Swaminathan REG_S a0, A0_OFF2($fp) 329*1fd5a2e1SPrashanth Swaminathan REG_S a1, A1_OFF2($fp) 330*1fd5a2e1SPrashanth Swaminathan REG_S a2, A2_OFF2($fp) 331*1fd5a2e1SPrashanth Swaminathan REG_S a3, A3_OFF2($fp) 332*1fd5a2e1SPrashanth Swaminathan 333*1fd5a2e1SPrashanth Swaminathan # Load ABI enum to s0 334*1fd5a2e1SPrashanth Swaminathan REG_L $16, 20($12) # cif pointer follows tramp. 335*1fd5a2e1SPrashanth Swaminathan REG_L $16, 0($16) # abi is first member. 336*1fd5a2e1SPrashanth Swaminathan 337*1fd5a2e1SPrashanth Swaminathan li $13, 1 # FFI_O32 338*1fd5a2e1SPrashanth Swaminathan bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT 339*1fd5a2e1SPrashanth Swaminathan 340*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float 341*1fd5a2e1SPrashanth Swaminathan # Store all possible float/double registers. 342*1fd5a2e1SPrashanth Swaminathan s.d $f12, FA_0_0_OFF2($fp) 343*1fd5a2e1SPrashanth Swaminathan s.d $f14, FA_1_0_OFF2($fp) 344*1fd5a2e1SPrashanth Swaminathan#endif 345*1fd5a2e1SPrashanth Swaminathan1: 346*1fd5a2e1SPrashanth Swaminathan # prepare arguments for ffi_closure_mips_inner_O32 347*1fd5a2e1SPrashanth Swaminathan REG_L a0, 20($12) # cif pointer follows tramp. 348*1fd5a2e1SPrashanth Swaminathan REG_L a1, 24($12) # fun 349*1fd5a2e1SPrashanth Swaminathan REG_L a2, 28($12) # user_data 350*1fd5a2e1SPrashanth Swaminathan addu a3, $fp, V0_OFF2 # rvalue 351*1fd5a2e1SPrashanth Swaminathan 352*1fd5a2e1SPrashanth Swaminathan addu t9, $fp, A0_OFF2 # ar 353*1fd5a2e1SPrashanth Swaminathan REG_S t9, CALLED_A4_OFF2($fp) 354*1fd5a2e1SPrashanth Swaminathan 355*1fd5a2e1SPrashanth Swaminathan addu t9, $fp, FA_0_0_OFF2 #fpr 356*1fd5a2e1SPrashanth Swaminathan REG_S t9, CALLED_A5_OFF2($fp) 357*1fd5a2e1SPrashanth Swaminathan 358*1fd5a2e1SPrashanth Swaminathan$do_closure: 359*1fd5a2e1SPrashanth Swaminathan la t9, ffi_closure_mips_inner_O32 360*1fd5a2e1SPrashanth Swaminathan # Call ffi_closure_mips_inner_O32 to do the work. 361*1fd5a2e1SPrashanth Swaminathan jalr t9 362*1fd5a2e1SPrashanth Swaminathan 363*1fd5a2e1SPrashanth Swaminathan # Load the return value into the appropriate register. 364*1fd5a2e1SPrashanth Swaminathan move $8, $2 365*1fd5a2e1SPrashanth Swaminathan li $9, FFI_TYPE_VOID 366*1fd5a2e1SPrashanth Swaminathan beq $8, $9, closure_done 367*1fd5a2e1SPrashanth Swaminathan 368*1fd5a2e1SPrashanth Swaminathan li $13, 1 # FFI_O32 369*1fd5a2e1SPrashanth Swaminathan bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT 370*1fd5a2e1SPrashanth Swaminathan 371*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float 372*1fd5a2e1SPrashanth Swaminathan li $9, FFI_TYPE_FLOAT 373*1fd5a2e1SPrashanth Swaminathan l.s $f0, V0_OFF2($fp) 374*1fd5a2e1SPrashanth Swaminathan beq $8, $9, closure_done 375*1fd5a2e1SPrashanth Swaminathan 376*1fd5a2e1SPrashanth Swaminathan li $9, FFI_TYPE_DOUBLE 377*1fd5a2e1SPrashanth Swaminathan l.d $f0, V0_OFF2($fp) 378*1fd5a2e1SPrashanth Swaminathan beq $8, $9, closure_done 379*1fd5a2e1SPrashanth Swaminathan#endif 380*1fd5a2e1SPrashanth Swaminathan1: 381*1fd5a2e1SPrashanth Swaminathan REG_L $3, V1_OFF2($fp) 382*1fd5a2e1SPrashanth Swaminathan REG_L $2, V0_OFF2($fp) 383*1fd5a2e1SPrashanth Swaminathan 384*1fd5a2e1SPrashanth Swaminathanclosure_done: 385*1fd5a2e1SPrashanth Swaminathan # Epilogue 386*1fd5a2e1SPrashanth Swaminathan move $sp, $fp 387*1fd5a2e1SPrashanth Swaminathan REG_L $16, S0_OFF2($sp) # Restore s0 388*1fd5a2e1SPrashanth Swaminathan REG_L $fp, FP_OFF2($sp) # Restore frame pointer 389*1fd5a2e1SPrashanth Swaminathan REG_L ra, RA_OFF2($sp) # Restore return address 390*1fd5a2e1SPrashanth Swaminathan ADDU $sp, SIZEOF_FRAME2 391*1fd5a2e1SPrashanth Swaminathan j ra 392*1fd5a2e1SPrashanth Swaminathan$LFE2: 393*1fd5a2e1SPrashanth Swaminathan .end ffi_closure_O32 394*1fd5a2e1SPrashanth Swaminathan 395*1fd5a2e1SPrashanth Swaminathan/* DWARF-2 unwind info. */ 396*1fd5a2e1SPrashanth Swaminathan 397*1fd5a2e1SPrashanth Swaminathan .section .eh_frame,"a",@progbits 398*1fd5a2e1SPrashanth Swaminathan$Lframe0: 399*1fd5a2e1SPrashanth Swaminathan .4byte $LECIE0-$LSCIE0 # Length of Common Information Entry 400*1fd5a2e1SPrashanth Swaminathan$LSCIE0: 401*1fd5a2e1SPrashanth Swaminathan .4byte 0x0 # CIE Identifier Tag 402*1fd5a2e1SPrashanth Swaminathan .byte 0x1 # CIE Version 403*1fd5a2e1SPrashanth Swaminathan .ascii "zR\0" # CIE Augmentation 404*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1 # CIE Code Alignment Factor 405*1fd5a2e1SPrashanth Swaminathan .sleb128 4 # CIE Data Alignment Factor 406*1fd5a2e1SPrashanth Swaminathan .byte 0x1f # CIE RA Column 407*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1 # Augmentation size 408*1fd5a2e1SPrashanth Swaminathan .byte 0x00 # FDE Encoding (absptr) 409*1fd5a2e1SPrashanth Swaminathan .byte 0xc # DW_CFA_def_cfa 410*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1d 411*1fd5a2e1SPrashanth Swaminathan .uleb128 0x0 412*1fd5a2e1SPrashanth Swaminathan .align 2 413*1fd5a2e1SPrashanth Swaminathan$LECIE0: 414*1fd5a2e1SPrashanth Swaminathan 415*1fd5a2e1SPrashanth Swaminathan$LSFDE0: 416*1fd5a2e1SPrashanth Swaminathan .4byte $LEFDE0-$LASFDE0 # FDE Length 417*1fd5a2e1SPrashanth Swaminathan$LASFDE0: 418*1fd5a2e1SPrashanth Swaminathan .4byte $LASFDE0-$Lframe0 # FDE CIE offset 419*1fd5a2e1SPrashanth Swaminathan .4byte $LFB0 # FDE initial location 420*1fd5a2e1SPrashanth Swaminathan .4byte $LFE0-$LFB0 # FDE address range 421*1fd5a2e1SPrashanth Swaminathan .uleb128 0x0 # Augmentation size 422*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 423*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI00-$LFB0 424*1fd5a2e1SPrashanth Swaminathan .byte 0xe # DW_CFA_def_cfa_offset 425*1fd5a2e1SPrashanth Swaminathan .uleb128 0x18 426*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 427*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI01-$LCFI00 428*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 429*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1e # $fp 430*1fd5a2e1SPrashanth Swaminathan .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) 431*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 432*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1f # $ra 433*1fd5a2e1SPrashanth Swaminathan .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) 434*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 435*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI02-$LCFI01 436*1fd5a2e1SPrashanth Swaminathan .byte 0xc # DW_CFA_def_cfa 437*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1e 438*1fd5a2e1SPrashanth Swaminathan .uleb128 0x18 439*1fd5a2e1SPrashanth Swaminathan .align 2 440*1fd5a2e1SPrashanth Swaminathan$LEFDE0: 441*1fd5a2e1SPrashanth Swaminathan 442*1fd5a2e1SPrashanth Swaminathan$LSFDE1: 443*1fd5a2e1SPrashanth Swaminathan .4byte $LEFDE1-$LASFDE1 # FDE Length 444*1fd5a2e1SPrashanth Swaminathan$LASFDE1: 445*1fd5a2e1SPrashanth Swaminathan .4byte $LASFDE1-$Lframe0 # FDE CIE offset 446*1fd5a2e1SPrashanth Swaminathan .4byte $LFB1 # FDE initial location 447*1fd5a2e1SPrashanth Swaminathan .4byte $LFE1-$LFB1 # FDE address range 448*1fd5a2e1SPrashanth Swaminathan .uleb128 0x0 # Augmentation size 449*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 450*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI10-$LFB1 451*1fd5a2e1SPrashanth Swaminathan .byte 0xe # DW_CFA_def_cfa_offset 452*1fd5a2e1SPrashanth Swaminathan .uleb128 SIZEOF_FRAME2 453*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 454*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI11-$LCFI10 455*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 456*1fd5a2e1SPrashanth Swaminathan .uleb128 0x10 # $16 457*1fd5a2e1SPrashanth Swaminathan .sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) 458*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 459*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1e # $fp 460*1fd5a2e1SPrashanth Swaminathan .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) 461*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 462*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1f # $ra 463*1fd5a2e1SPrashanth Swaminathan .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) 464*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 465*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI12-$LCFI11 466*1fd5a2e1SPrashanth Swaminathan .byte 0xc # DW_CFA_def_cfa 467*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1e 468*1fd5a2e1SPrashanth Swaminathan .uleb128 SIZEOF_FRAME2 469*1fd5a2e1SPrashanth Swaminathan .align 2 470*1fd5a2e1SPrashanth Swaminathan$LEFDE1: 471*1fd5a2e1SPrashanth Swaminathan 472*1fd5a2e1SPrashanth Swaminathan$LSFDE2: 473*1fd5a2e1SPrashanth Swaminathan .4byte $LEFDE2-$LASFDE2 # FDE Length 474*1fd5a2e1SPrashanth Swaminathan$LASFDE2: 475*1fd5a2e1SPrashanth Swaminathan .4byte $LASFDE2-$Lframe0 # FDE CIE offset 476*1fd5a2e1SPrashanth Swaminathan .4byte $LFB2 # FDE initial location 477*1fd5a2e1SPrashanth Swaminathan .4byte $LFE2-$LFB2 # FDE address range 478*1fd5a2e1SPrashanth Swaminathan .uleb128 0x0 # Augmentation size 479*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 480*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI20-$LFB2 481*1fd5a2e1SPrashanth Swaminathan .byte 0xe # DW_CFA_def_cfa_offset 482*1fd5a2e1SPrashanth Swaminathan .uleb128 SIZEOF_FRAME2 483*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 484*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI21-$LCFI20 485*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 486*1fd5a2e1SPrashanth Swaminathan .uleb128 0x10 # $16 487*1fd5a2e1SPrashanth Swaminathan .sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) 488*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 489*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1e # $fp 490*1fd5a2e1SPrashanth Swaminathan .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) 491*1fd5a2e1SPrashanth Swaminathan .byte 0x11 # DW_CFA_offset_extended_sf 492*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1f # $ra 493*1fd5a2e1SPrashanth Swaminathan .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) 494*1fd5a2e1SPrashanth Swaminathan .byte 0x4 # DW_CFA_advance_loc4 495*1fd5a2e1SPrashanth Swaminathan .4byte $LCFI22-$LCFI21 496*1fd5a2e1SPrashanth Swaminathan .byte 0xc # DW_CFA_def_cfa 497*1fd5a2e1SPrashanth Swaminathan .uleb128 0x1e 498*1fd5a2e1SPrashanth Swaminathan .uleb128 SIZEOF_FRAME2 499*1fd5a2e1SPrashanth Swaminathan .align 2 500*1fd5a2e1SPrashanth Swaminathan$LEFDE2: 501*1fd5a2e1SPrashanth Swaminathan 502*1fd5a2e1SPrashanth Swaminathan#endif 503