aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/mips/o32.S
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/mips/o32.S')
-rw-r--r--libffi/src/mips/o32.S62
1 files changed, 47 insertions, 15 deletions
diff --git a/libffi/src/mips/o32.S b/libffi/src/mips/o32.S
index e2dfa8d..7391ce3 100644
--- a/libffi/src/mips/o32.S
+++ b/libffi/src/mips/o32.S
@@ -36,7 +36,6 @@
#define flags a3
#define SIZEOF_FRAME ( 4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG )
-#define SIZEOF_FRAME2 ( 8 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG )
.text
.align 2
@@ -188,7 +187,28 @@ $LFE0:
/* 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. */
+ 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
@@ -202,10 +222,10 @@ $LFB1:
.cpload $25
.set reorder
SUBU $sp, SIZEOF_FRAME2
- .cprestore SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG
+ .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
-$LCFI5:
REG_S ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Save return address
$LCFI6:
move $fp, $sp
@@ -218,14 +238,21 @@ $LCFI7:
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 - 4*FFI_SIZEOF_ARG
+ 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
@@ -235,28 +262,30 @@ $LCFI7:
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 - 4*FFI_SIZEOF_ARG($fp)
+ 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 - 4*FFI_SIZEOF_ARG($fp)
+ 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 - 3*FFI_SIZEOF_ARG($fp)
+ REG_L $3, SIZEOF_FRAME2 - 5*FFI_SIZEOF_ARG($fp)
beq $8, $9, integer
-
li $9, FFI_TYPE_UINT64
- REG_L $3, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($fp)
beq $8, $9, integer
integer:
- REG_L $2, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
+ 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
@@ -319,10 +348,13 @@ $LASFDE1:
.byte 0x4 # DW_CFA_advance_loc4
.4byte $LCFI4-$LFB1
.byte 0xe # DW_CFA_def_cfa_offset
- .uleb128 0x28
+ .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
@@ -332,7 +364,7 @@ $LASFDE1:
.4byte $LCFI7-$LCFI6
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1e
- .uleb128 0x28
+ .uleb128 0x38
.align 2
$LEFDE1: