OSDN Git Service

2005-12-07 Thiemo Seufer <ths@networkno.de>
[pf3gnuchains/gcc-fork.git] / libffi / src / mips / o32.S
index e2dfa8d..63f3d14 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   o32.S - Copyright (c) 1996, 1998  Red Hat, Inc.
+   o32.S - Copyright (c) 1996, 1998, 2005  Red Hat, Inc.
    
    MIPS Foreign Function Interface 
 
 #define bytes   a2
 #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 )
+#define SIZEOF_FRAME   (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
+#define A3_OFF         (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
+#define FP_OFF         (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
+#define RA_OFF         (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
 
+       .abicalls
        .text
        .align  2
        .globl  ffi_call_O32
 ffi_call_O32:  
 $LFB0:
        # Prologue
-       SUBU    $sp, SIZEOF_FRAME                       # Frame size
+       SUBU    $sp, SIZEOF_FRAME       # Frame size
 $LCFI0:
-       REG_S   $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp)       # Save frame pointer
+       REG_S   $fp, FP_OFF($sp)        # Save frame pointer
 $LCFI1:
-       REG_S   ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)        # Save return address
+       REG_S   ra, RA_OFF($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
+       move    t9, callback            # callback function pointer
+       REG_S   flags, A3_OFF($fp)      # flags
 
        # 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
+       blt     bytes, v0, sixteen
 
-bigger:        
-       ADDU    t0, v0, 2 * FFI_SIZEOF_ARG -1   # make sure it is aligned 
-       and     v0, t0, -2 * FFI_SIZEOF_ARG             # to an 8 byte boundry
+       ADDU    v0, bytes, 7    # make sure it is aligned 
+       and     v0, -8          # to an 8 byte boundry
 
 sixteen:
-       SUBU    $sp, $sp, v0    # move the stack pointer to reflect the
+       SUBU    $sp, v0         # move the stack pointer to reflect the
                                # arg space
 
        ADDU    a0, $sp, 4 * FFI_SIZEOF_ARG
-       ADDU    a3, $fp, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG
 
-       jal     t9
+       jalr    t9
        
-       REG_L   t0, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp)  # load the flags word
-       add     t2, t0, 0                          # and copy it into t2
-
+       REG_L   t0, A3_OFF($fp)         # load the flags word
+       SRL     t2, t0, 4               # shift our arg info
        and     t0, ((1<<4)-1)          # mask out the return type
-       SRL     t2, 4                   # shift our arg info
                
-       ADDU    $sp, $sp, 4 * FFI_SIZEOF_ARG    # adjust $sp to new args
+       ADDU    $sp, 4 * FFI_SIZEOF_ARG         # adjust $sp to new args
 
        bnez    t0, pass_d                      # make it quick for int
-       REG_L   a0, 0*FFI_SIZEOF_ARG($sp)               # just go ahead and load the
-       REG_L   a1, 1*FFI_SIZEOF_ARG($sp)               # four regs.
+       REG_L   a0, 0*FFI_SIZEOF_ARG($sp)       # just go ahead and load the
+       REG_L   a1, 1*FFI_SIZEOF_ARG($sp)       # four regs.
        REG_L   a2, 2*FFI_SIZEOF_ARG($sp)
        REG_L   a3, 3*FFI_SIZEOF_ARG($sp)
        b       call_it
@@ -142,7 +139,7 @@ call_it:
        beqz    t1, noretval
 
        bne     t2, FFI_TYPE_INT, retlonglong
-       jal     t9
+       jalr    t9
        REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
        REG_S   v0, 0(t0)
        b       epilogue
@@ -150,7 +147,7 @@ call_it:
 retlonglong:
        # Really any 64-bit int, signed or not.
        bne     t2, FFI_TYPE_UINT64, retfloat
-       jal     t9
+       jalr    t9
        REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
        REG_S   v1, 4(t0)
        REG_S   v0, 0(t0)
@@ -158,27 +155,27 @@ retlonglong:
 
 retfloat:
        bne     t2, FFI_TYPE_FLOAT, retdouble
-       jal     t9
+       jalr    t9
        REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
        s.s     $f0, 0(t0)
        b       epilogue
 
 retdouble:     
        bne     t2, FFI_TYPE_DOUBLE, noretval
-       jal     t9
+       jalr    t9
        REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
        s.d     $f0, 0(t0)
        b       epilogue
        
 noretval:      
-       jal     t9
+       jalr    t9
        
        # Epilogue
 epilogue:      
        move    $sp, $fp        
-       REG_L   $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
-       REG_L   ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)  # Restore return address
-       ADDU    $sp, SIZEOF_FRAME                     # Fix stack pointer
+       REG_L   $fp, FP_OFF($sp)        # Restore frame pointer
+       REG_L   ra, RA_OFF($sp)         # Restore return address
+       ADDU    $sp, SIZEOF_FRAME       # Fix stack pointer
        j       ra
 
 $LFE0:
@@ -188,7 +185,42 @@ $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)
+#define A3_OFF2                (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
+#define A2_OFF2                (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
+#define A1_OFF2                (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
+#define A0_OFF2                (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
+#define RA_OFF2                (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
+#define FP_OFF2                (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
+#define S0_OFF2                (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
+#define GP_OFF2                (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
+#define V1_OFF2                (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
+#define V0_OFF2                (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
+#define FA_1_1_OFF2    (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
+#define FA_1_0_OFF2    (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
+#define FA_0_1_OFF2    (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
+#define FA_0_0_OFF2    (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
 
        .text
        .align  2
@@ -197,68 +229,71 @@ $LFE0:
 ffi_closure_O32:
 $LFB1:
        # Prologue
-       .frame  $fp, SIZEOF_FRAME2, $31
+       .frame  $fp, SIZEOF_FRAME2, ra
        .set    noreorder
-       .cpload $25
+       .cpload t9
        .set    reorder
        SUBU    $sp, SIZEOF_FRAME2
-       .cprestore SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG
+       .cprestore GP_OFF2
 $LCFI4:
-       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
+       REG_S   $16, S0_OFF2($sp)        # Save s0
+       REG_S   $fp, FP_OFF2($sp)        # Save frame pointer
+       REG_S   ra, RA_OFF2($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)
-
+       # four arguments, then they are stored above where we put a3.
+       REG_S   a0, A0_OFF2($fp)
+       REG_S   a1, A1_OFF2($fp)
+       REG_S   a2, A2_OFF2($fp)
+       REG_S   a3, A3_OFF2($fp)
+
+       # Load ABI enum to s0
+       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)
-
+       s.d     $f12, FA_0_0_OFF2($fp)
+       s.d     $f14, FA_1_0_OFF2($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    $6, $fp, SIZEOF_FRAME2 +  0*FFI_SIZEOF_ARG
-       addu    $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG
-       jal     $31, $25
+       la      t9, ffi_closure_mips_inner_O32
+       move    a0, $8   # Pointer to the ffi_closure
+       addu    a1, $fp, V0_OFF2
+       addu    a2, $fp, A0_OFF2
+       addu    a3, $fp, FA_0_0_OFF2
+       jalr    t9
 
        # 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 - 4*FFI_SIZEOF_ARG($fp)
+       l.s     $f0, V0_OFF2($fp)
        beq     $8, $9, closure_done
 
        li      $9, FFI_TYPE_DOUBLE
-       l.d     $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
+       l.d     $f0, V0_OFF2($fp)
        beq     $8, $9, closure_done
-
-       li      $9, FFI_TYPE_SINT64
-       REG_L   $3, SIZEOF_FRAME2 - 3*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)
+1:     
+       REG_L   $3, V1_OFF2($fp)
+       REG_L   $2, V0_OFF2($fp)
 
 closure_done:
        # Epilogue
        move    $sp, $fp
-       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
+       REG_L   $16, S0_OFF2($sp)        # Restore s0
+       REG_L   $fp, FP_OFF2($sp)        # Restore frame pointer
+       REG_L   ra,  RA_OFF2($sp)        # Restore return address
        ADDU    $sp, SIZEOF_FRAME2
        j       ra
 $LFE1:
@@ -277,7 +312,7 @@ $LSCIE0:
        .sleb128 4       # CIE Data Alignment Factor
        .byte   0x1f     # CIE RA Column
        .uleb128 0x1     # Augmentation size
-       .byte   0x1b     # FDE Encoding (pcrel sdata4)
+       .byte   0x00     # FDE Encoding (absptr)
        .byte   0xc      # DW_CFA_def_cfa
        .uleb128 0x1d
        .uleb128 0x0
@@ -287,7 +322,7 @@ $LSFDE0:
        .4byte  $LEFDE0-$LASFDE0         # FDE Length
 $LASFDE0:
        .4byte  $LASFDE0-$Lframe0        # FDE CIE offset
-       .4byte  $LFB0-.  # FDE initial location
+       .4byte  $LFB0    # FDE initial location
        .4byte  $LFE0-$LFB0      # FDE address range
        .uleb128 0x0     # Augmentation size
        .byte   0x4      # DW_CFA_advance_loc4
@@ -313,16 +348,19 @@ $LSFDE1:
        .4byte  $LEFDE1-$LASFDE1         # FDE Length
 $LASFDE1:
        .4byte  $LASFDE1-$Lframe0        # FDE CIE offset
-       .4byte  $LFB1-.  # FDE initial location
+       .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 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 +370,7 @@ $LASFDE1:
        .4byte  $LCFI7-$LCFI6
        .byte   0xc      # DW_CFA_def_cfa
        .uleb128 0x1e
-       .uleb128 0x28
+       .uleb128 0x38
        .align  2
 $LEFDE1: