]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libgcc/config/mips/mips16.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / mips / mips16.S
index a087508d4a64486d7c76789ef09f55f670bd172d..396285eeabeed6a699f7567114f73506dc07e513 100644 (file)
@@ -1,6 +1,5 @@
 /* mips16 floating point support code
-   Copyright (C) 1996, 1997, 1998, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2020 Free Software Foundation, Inc.
    Contributed by Cygnus Support
 
 This file is free software; you can redistribute it and/or modify it
@@ -22,6 +21,27 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
+#include "auto-host.h"
+
+#if defined(__mips_micromips) || defined(__mips_soft_float) \
+    || __mips_isa_rev >= 6
+  /* Do nothing because this code is only needed when linking
+     against mips16 hard-float objects.  Neither micromips code
+     nor soft-float nor MIPS R6 code can be linked against mips16
+     hard-float objects so we do not need these routines when
+     building libgcc for those cases.  */
+#else
+
+#if defined(HAVE_AS_MODULE)
+#if __mips_fpr == 32
+       .module fp=32
+#elif __mips_fpr == 0
+       .module fp=xx
+#elif __mips_fpr == 64
+       .module fp=64
+#endif
+#endif
+
 /* This file contains mips16 floating point support functions.  These
    functions are called by mips16 code to handle floating point when
    -msoft-float is not used.  They accept the arguments and return
@@ -86,8 +106,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
        OPCODE, OP2;                            \
        .set    reorder
 
+#if __mips >= 4
+/* Coprocessor moves are interlocked from the MIPS IV ISA up.  */
+#define DELAYf(T, OPCODE, OP2) DELAYt (T, OPCODE, OP2)
+#else
 /* Use "OPCODE. OP2" and jump to T.  */
 #define DELAYf(T, OPCODE, OP2) OPCODE, OP2; jr T
+#endif
 
 /* MOVE_SF_BYTE0(D)
        Move the first single-precision floating-point argument between
@@ -140,8 +165,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 /* The high 32 bits of $2 correspond to the second word in memory;
    i.e. the imaginary part.  */
 #define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f1, $f0); jr T
-#elif __mips_fpr == 64
-#define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)
 #else
 #define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f2)
 #endif
@@ -162,16 +185,29 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define MOVE_DF_BYTE8(D) dm##D##c1 $5,$f13
 #define MOVE_DF_RET(D, T) DELAY##D (T, dm##D##c1 $2,$f0)
 #define MOVE_DC_RET(D, T) dm##D##c1 $3,$f1; MOVE_DF_RET (D, T)
-#elif __mips_fpr == 64 && defined(__MIPSEB__)
+#elif __mips_fpr != 32 && __mips_isa_rev >= 2 && defined(__MIPSEB__)
 #define MOVE_DF_BYTE0(D) m##D##c1 $5,$f12; m##D##hc1 $4,$f12
 #define MOVE_DF_BYTE8(D) m##D##c1 $7,$f14; m##D##hc1 $6,$f14
 #define MOVE_DF_RET(D, T) m##D##c1 $3,$f0; DELAY##D (T, m##D##hc1 $2,$f0)
-#define MOVE_DC_RET(D, T) m##D##c1 $5,$f1; m##D##hc1 $4,$f1; MOVE_DF_RET (D, T)
-#elif __mips_fpr == 64
+#define MOVE_DC_RET(D, T) m##D##c1 $5,$f2; m##D##hc1 $4,$f2; MOVE_DF_RET (D, T)
+#elif __mips_fpr != 32 && __mips_isa_rev >= 2
 #define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##hc1 $5,$f12
 #define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##hc1 $7,$f14
 #define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##hc1 $3,$f0)
-#define MOVE_DC_RET(D, T) m##D##c1 $4,$f1; m##D##hc1 $5,$f1; MOVE_DF_RET (D, T)
+#define MOVE_DC_RET(D, T) m##D##c1 $4,$f2; m##D##hc1 $5,$f2; MOVE_DF_RET (D, T)
+#elif __mips_fpr == 0
+#define MOVE_DF_BYTE0t sw $4, 0($29); sw $5, 4($29); ldc1 $f12, 0($29)
+#define MOVE_DF_BYTE0f sdc1 $f12, 0($29); lw $4, 0($29); lw $5, 4($29)
+#define MOVE_DF_BYTE0(D) MOVE_DF_BYTE0##D
+#define MOVE_DF_BYTE8t sw $6, 8($29); sw $7, 12($29); ldc1 $f14, 8($29)
+#define MOVE_DF_BYTE8f sdc1 $f14, 8($29); lw $6, 8($29); lw $7, 12($29)
+#define MOVE_DF_BYTE8(D) MOVE_DF_BYTE8##D
+#define MOVE_DF_RETt(T) sw $2, 0($29); sw $3, 4($29); DELAYt (T, ldc1 $f0, 0($29))
+#define MOVE_DF_RETf(T) sdc1 $f0, 0($29); lw $2, 0($29); DELAYf (T, lw $3, 4($29))
+#define MOVE_DF_RET(D, T) MOVE_DF_RET##D(T)
+#define MOVE_DC_RETt(T) sw $4, 8($29); sw $5, 12($29); ldc1 $f2, 8($29); MOVE_DF_RETt(T)
+#define MOVE_DC_RETf(T) sdc1 $f2, 8($29); lw $4, 8($29); lw $5, 12($29); MOVE_DF_RETf(T)
+#define MOVE_DC_RET(D, T) MOVE_DF_RET##D(T)
 #elif defined(__MIPSEB__)
 /* FPRs are little-endian.  */
 #define MOVE_DF_BYTE0(D) m##D##c1 $4,$f13; m##D##c1 $5,$f12
@@ -471,13 +507,35 @@ STARTFN (__mips16_fix_truncdfsi)
 #endif
 #endif /* !__mips_single_float */
 
+/* We don't export stubs from libgcc_s.so and always require static
+   versions to be pulled from libgcc.a as needed because they use $2
+   and possibly $3 as arguments, diverging from the standard SysV ABI,
+   and as such would require severe pessimisation of MIPS16 PLT entries
+   just for this single special case.
+
+   For compatibility with old binaries that used safe standard MIPS PLT
+   entries and referred to these functions we still export them at
+   version GCC_4.4.0 for run-time loading only.  */
+
+#ifdef SHARED
+#define CE_STARTFN(NAME)                       \
+STARTFN (NAME##_compat);                       \
+       .symver NAME##_compat, NAME@GCC_4.4.0
+#define CE_ENDFN(NAME) ENDFN (NAME##_compat)
+#else
+#define CE_STARTFN(NAME)                       \
+STARTFN (NAME);                                        \
+       .hidden NAME
+#define CE_ENDFN(NAME) ENDFN (NAME)
+#endif
+
 /* Define a function NAME that moves a return value of mode MODE from
    FPRs to GPRs.  */
 
 #define RET_FUNCTION(NAME, MODE)       \
-STARTFN (NAME);                                \
+CE_STARTFN (NAME);                     \
        MOVE_##MODE##_RET (t, $31);     \
-       ENDFN (NAME)
+       CE_ENDFN (NAME)
 
 #ifdef L_m16retsf
 RET_FUNCTION (__mips16_ret_sf, SF)
@@ -518,13 +576,13 @@ RET_FUNCTION (__mips16_ret_dc, DC)
    to FPRs and then call function $2.  */
 
 #define CALL_STUB_NO_RET(NAME, CODE)   \
-STARTFN (NAME);                                \
+CE_STARTFN (NAME);                     \
        STUB_ARGS_##CODE;               \
        .set    noreorder;              \
        jr      $2;                     \
        move    $25,$2;                 \
        .set    reorder;                \
-       ENDFN (NAME)
+       CE_ENDFN (NAME)
 
 #ifdef L_m16stub1
 CALL_STUB_NO_RET (__mips16_call_stub_1, 1)
@@ -566,16 +624,24 @@ CALL_STUB_NO_RET (__mips16_call_stub_10, 10)
    being called is 16 bits, in which case the copy is unnecessary;
    however, it's faster to always do the copy.  */
 
-#define CALL_STUB_RET(NAME, CODE, MODE)        \
-STARTFN (NAME);                                \
-       move    $18,$31;                \
-       STUB_ARGS_##CODE;               \
-       .set    noreorder;              \
-       jalr    $2;                     \
-       move    $25,$2;                 \
-       .set    reorder;                \
-       MOVE_##MODE##_RET (f, $18);     \
-       ENDFN (NAME)
+#define CALL_STUB_RET(NAME, CODE, MODE)                                        \
+CE_STARTFN (NAME);                                                     \
+       .cfi_startproc;                                                 \
+       /* Create a fake CFA 4 bytes below the stack pointer.  */       \
+       .cfi_def_cfa 29,-4;                                             \
+       /* "Save" $sp in itself so we don't use the fake CFA.           \
+          This is: DW_CFA_val_expression r29, { DW_OP_reg29 }.  */     \
+       .cfi_escape 0x16,29,1,0x6d;                                     \
+       move    $18,$31;                                                \
+       .cfi_register 31,18;                                            \
+       STUB_ARGS_##CODE;                                               \
+       .set    noreorder;                                              \
+       jalr    $2;                                                     \
+       move    $25,$2;                                                 \
+       .set    reorder;                                                \
+       MOVE_##MODE##_RET (f, $18);                                     \
+       .cfi_endproc;                                                   \
+       CE_ENDFN (NAME)
 
 /* First, instantiate the single-float set.  */
 
@@ -710,14 +776,5 @@ CALL_STUB_RET (__mips16_call_stub_dc_10, 10, DC)
 #endif
 #endif /* !__mips_single_float */
 
-#ifdef L_m16rdhwr
-STARTFN (__mips16_rdhwr)
-       .set    push
-       .set    mips32r2
-       .set    noreorder
-       rdhwr   $3,$29
-       .set    pop
-       j       $31
-       ENDFN (__mips16_rdhwr)
-#endif
 #endif
+#endif /* defined(__mips_micromips) || defined(__mips_soft_float) */