.globl ffi_call_O32
.ent ffi_call_O32
ffi_call_O32:
-
+$LFB0:
# Prologue
SUBU $sp, SIZEOF_FRAME # Frame size
+$LCFI0:
REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
+$LCFI1:
REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
+$LCFI2:
move $fp, $sp
+$LCFI3:
move t9, callback # callback function pointer
REG_S flags, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp) # flags
REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
beqz t1, noretval
- bne t2, FFI_TYPE_INT, retfloat
+ bne t2, FFI_TYPE_INT, retlonglong
jal t9
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t0)
b epilogue
+retlonglong:
+ # Really any 64-bit int, signed or not.
+ bne t2, FFI_TYPE_UINT64, retfloat
+ jal t9
+ REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+ REG_S v1, 4(t0)
+ REG_S v0, 0(t0)
+ b epilogue
+
retfloat:
bne t2, FFI_TYPE_FLOAT, retdouble
jal t9
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
j ra
+$LFE0:
.end ffi_call_O32
+
+
+/* ffi_closure_O32. Expects address of the passed-in ffi_closure
+ in t0. Stores any arguments passed in registers onto the
+ stack, then calls ffi_closure_mips_inner_O32, which
+ then decodes them.
+ Stack layout:
+
+ 14 - Start of parameters, original sp
+ 13 - ra save
+ 12 - fp save
+ 11 - $16 (s0) save
+ 10 - cprestore
+ 9 - return value high (v1)
+ 8 - return value low (v0)
+ 7 - f14 (le high, be low)
+ 6 - f14 (le low, be high)
+ 5 - f12 (le high, be low)
+ 4 - f12 (le low, be high)
+ 3 - Called function a3 save
+ 2 - Called function a2 save
+ 1 - Called function a1 save
+ 0 - Called function a0 save our sp, fp point here
+ */
+
+#define SIZEOF_FRAME2 ( 14 * FFI_SIZEOF_ARG )
+
+ .text
+ .align 2
+ .globl ffi_closure_O32
+ .ent ffi_closure_O32
+ffi_closure_O32:
+$LFB1:
+ # Prologue
+ .frame $fp, SIZEOF_FRAME2, $31
+ .set noreorder
+ .cpload $25
+ .set reorder
+ SUBU $sp, SIZEOF_FRAME2
+ .cprestore SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG
+$LCFI4:
+ REG_S $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Save s0
+ REG_S $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
+ REG_S ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Save return address
+$LCFI6:
+ move $fp, $sp
+
+$LCFI7:
+ # Store all possible argument registers. If there are more than
+ # four arguments, then they should be stored above where we put $7.
+ REG_S $4, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG($fp)
+ REG_S $5, SIZEOF_FRAME2 + 1*FFI_SIZEOF_ARG($fp)
+ REG_S $6, SIZEOF_FRAME2 + 2*FFI_SIZEOF_ARG($fp)
+ REG_S $7, SIZEOF_FRAME2 + 3*FFI_SIZEOF_ARG($fp)
+
+ # Load ABI enum to $16
+ REG_L $16, 20($8) # cif pointer follows tramp.
+ REG_L $16, 0($16) # abi is first member.
+
+ li $13, 1 # FFI_O32
+ bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
+
+ # Store all possible float/double registers.
+ s.d $f12, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG($fp)
+ s.d $f14, SIZEOF_FRAME2 - 8*FFI_SIZEOF_ARG($fp)
+1:
+ # Call ffi_closure_mips_inner_O32 to do the work.
+ la $25, ffi_closure_mips_inner_O32
+ move $4, $8 # Pointer to the ffi_closure
+ addu $5, $fp, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG
+ addu $6, $fp, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG
+ addu $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG
+ jal $31, $25
+
+ # Load the return value into the appropriate register.
+ move $8, $2
+ li $9, FFI_TYPE_VOID
+ beq $8, $9, closure_done
+
+ li $13, 1 # FFI_O32
+ bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT
+
+ li $9, FFI_TYPE_FLOAT
+ l.s $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
+ beq $8, $9, closure_done
+
+ li $9, FFI_TYPE_DOUBLE
+ l.d $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
+ beq $8, $9, closure_done
+1:
+ li $9, FFI_TYPE_SINT64
+ REG_L $3, SIZEOF_FRAME2 - 5*FFI_SIZEOF_ARG($fp)
+ beq $8, $9, integer
+ li $9, FFI_TYPE_UINT64
+ beq $8, $9, integer
+
+integer:
+ REG_L $2, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
+
+closure_done:
+ # Epilogue
+ move $sp, $fp
+ REG_L $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Restore s0
+ REG_L $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
+ REG_L ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Restore return address
+ ADDU $sp, SIZEOF_FRAME2
+ j ra
+$LFE1:
+ .end ffi_closure_O32
+
+/* DWARF-2 unwind info. */
+
+ .section .eh_frame,"a",@progbits
+$Lframe0:
+ .4byte $LECIE0-$LSCIE0 # Length of Common Information Entry
+$LSCIE0:
+ .4byte 0x0 # CIE Identifier Tag
+ .byte 0x1 # CIE Version
+ .ascii "zR\0" # CIE Augmentation
+ .uleb128 0x1 # CIE Code Alignment Factor
+ .sleb128 4 # CIE Data Alignment Factor
+ .byte 0x1f # CIE RA Column
+ .uleb128 0x1 # Augmentation size
+ .byte 0x1b # FDE Encoding (pcrel sdata4)
+ .byte 0xc # DW_CFA_def_cfa
+ .uleb128 0x1d
+ .uleb128 0x0
+ .align 2
+$LECIE0:
+$LSFDE0:
+ .4byte $LEFDE0-$LASFDE0 # FDE Length
+$LASFDE0:
+ .4byte $LASFDE0-$Lframe0 # FDE CIE offset
+ .4byte $LFB0-. # FDE initial location
+ .4byte $LFE0-$LFB0 # FDE address range
+ .uleb128 0x0 # Augmentation size
+ .byte 0x4 # DW_CFA_advance_loc4
+ .4byte $LCFI0-$LFB0
+ .byte 0xe # DW_CFA_def_cfa_offset
+ .uleb128 0x18
+ .byte 0x4 # DW_CFA_advance_loc4
+ .4byte $LCFI2-$LCFI0
+ .byte 0x11 # DW_CFA_offset_extended_sf
+ .uleb128 0x1e # $fp
+ .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
+ .byte 0x11 # DW_CFA_offset_extended_sf
+ .uleb128 0x1f # $ra
+ .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
+ .byte 0x4 # DW_CFA_advance_loc4
+ .4byte $LCFI3-$LCFI2
+ .byte 0xc # DW_CFA_def_cfa
+ .uleb128 0x1e
+ .uleb128 0x18
+ .align 2
+$LEFDE0:
+$LSFDE1:
+ .4byte $LEFDE1-$LASFDE1 # FDE Length
+$LASFDE1:
+ .4byte $LASFDE1-$Lframe0 # FDE CIE offset
+ .4byte $LFB1-. # FDE initial location
+ .4byte $LFE1-$LFB1 # FDE address range
+ .uleb128 0x0 # Augmentation size
+ .byte 0x4 # DW_CFA_advance_loc4
+ .4byte $LCFI4-$LFB1
+ .byte 0xe # DW_CFA_def_cfa_offset
+ .uleb128 0x38
+ .byte 0x4 # DW_CFA_advance_loc4
+ .4byte $LCFI6-$LCFI4
+ .byte 0x11 # DW_CFA_offset_extended_sf
+ .uleb128 0x10 # $16
+ .sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
+ .byte 0x11 # DW_CFA_offset_extended_sf
+ .uleb128 0x1e # $fp
+ .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
+ .byte 0x11 # DW_CFA_offset_extended_sf
+ .uleb128 0x1f # $ra
+ .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
+ .byte 0x4 # DW_CFA_advance_loc4
+ .4byte $LCFI7-$LCFI6
+ .byte 0xc # DW_CFA_def_cfa
+ .uleb128 0x1e
+ .uleb128 0x38
+ .align 2
+$LEFDE1:
+
#endif