diff options
Diffstat (limited to 'gcc-4.9/libgcc/config/mips')
-rw-r--r-- | gcc-4.9/libgcc/config/mips/crtfastmath.c | 53 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/crti.S | 49 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/crtn.S | 54 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/gthr-mipssde.h | 237 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/lib2funcs.c | 44 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/libgcc-mips16.ver | 48 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/linux-unwind.h | 125 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/mips16.S | 752 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/sfp-machine.h | 180 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-crtstuff | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-elf | 3 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-mips | 9 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-mips16 | 45 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-mips64 | 1 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-sdemtk | 3 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-softfp-tf | 3 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/t-vr | 2 | ||||
-rw-r--r-- | gcc-4.9/libgcc/config/mips/vr4120-div.S | 79 |
18 files changed, 1689 insertions, 0 deletions
diff --git a/gcc-4.9/libgcc/config/mips/crtfastmath.c b/gcc-4.9/libgcc/config/mips/crtfastmath.c new file mode 100644 index 000000000..a64e13d44 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/crtfastmath.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2010-2014 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License + and 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/>. */ + +#ifdef __mips_hard_float + +/* Flush denormalized numbers to zero. */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* Rounding control. */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 +#define _FPU_RC_UP 0x2 +#define _FPU_RC_DOWN 0x3 + +/* Enable interrupts for IEEE exceptions. */ +#define _FPU_IEEE 0x00000F80 + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) + +static void __attribute__((constructor,nomips16)) +set_fast_math (void) +{ + unsigned int fcr; + + /* Flush to zero, round to nearest, IEEE exceptions disabled. */ + fcr = _FPU_FLUSH_TZ | _FPU_RC_NEAREST; + + _FPU_SETCW(fcr); +} + +#endif /* __mips_hard_float */ diff --git a/gcc-4.9/libgcc/config/mips/crti.S b/gcc-4.9/libgcc/config/mips/crti.S new file mode 100644 index 000000000..698059464 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/crti.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2001-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +/* 4 slots for argument spill area. 1 for cpreturn, 1 for stack. + Return spill offset of 40 and 20. Aligned to 16 bytes for n32. */ + + .section .init,"ax",@progbits + .globl _init + .type _init,@function +_init: +#ifdef __mips64 + daddu $sp,$sp,-48 + sd $31,40($sp) +#else + addu $sp,$sp,-32 + sw $31,20($sp) +#endif + + .section .fini,"ax",@progbits + .globl _fini + .type _fini,@function +_fini: +#ifdef __mips64 + daddu $sp,$sp,-48 + sd $31,40($sp) +#else + addu $sp,$sp,-32 + sw $31,20($sp) +#endif diff --git a/gcc-4.9/libgcc/config/mips/crtn.S b/gcc-4.9/libgcc/config/mips/crtn.S new file mode 100644 index 000000000..0de2d0c41 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/crtn.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2001-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +/* 4 slots for argument spill area. 1 for cpreturn, 1 for stack. + Return spill offset of 40 and 20. Aligned to 16 bytes for n32. */ + +#ifdef __mips16 +#define RA $7 +#else +#define RA $31 +#endif + + .section .init,"ax",@progbits +init: +#ifdef __mips64 + ld RA,40($sp) + daddu $sp,$sp,48 +#else + lw RA,20($sp) + addu $sp,$sp,32 +#endif + j RA + + .section .fini,"ax",@progbits +fini: +#ifdef __mips64 + ld RA,40($sp) + daddu $sp,$sp,48 +#else + lw RA,20($sp) + addu $sp,$sp,32 +#endif + j RA + diff --git a/gcc-4.9/libgcc/config/mips/gthr-mipssde.h b/gcc-4.9/libgcc/config/mips/gthr-mipssde.h new file mode 100644 index 000000000..834701399 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/gthr-mipssde.h @@ -0,0 +1,237 @@ +/* MIPS SDE threads compatibility routines for libgcc2 and libobjc. */ +/* Compile this one with gcc. */ +/* Copyright (C) 2006-2014 Free Software Foundation, Inc. + Contributed by Nigel Stephens <nigel@mips.com> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +#ifndef GCC_GTHR_MIPSSDE_H +#define GCC_GTHR_MIPSSDE_H + +/* MIPS SDE threading API specific definitions. + Easy, since the interface is pretty much one-to-one. */ + +#define __GTHREADS 1 + +#include <sdethread.h> +#include <unistd.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __sdethread_key_t __gthread_key_t; +typedef __sdethread_once_t __gthread_once_t; +typedef __sdethread_mutex_t __gthread_mutex_t; + +typedef struct { + long depth; + __sdethread_t owner; + __sdethread_mutex_t actual; +} __gthread_recursive_mutex_t; + +#define __GTHREAD_MUTEX_INIT __SDETHREAD_MUTEX_INITIALIZER("gthr") +#define __GTHREAD_ONCE_INIT __SDETHREAD_ONCE_INIT +static inline int +__gthread_recursive_mutex_init_function(__gthread_recursive_mutex_t *__mutex); +#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function + +#if SUPPORTS_WEAK && GTHREAD_USE_WEAK +# define __gthrw(name) \ + static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))); +# define __gthrw_(name) __gthrw_ ## name +#else +# define __gthrw(name) +# define __gthrw_(name) name +#endif + +__gthrw(__sdethread_once) +__gthrw(__sdethread_key_create) +__gthrw(__sdethread_key_delete) +__gthrw(__sdethread_getspecific) +__gthrw(__sdethread_setspecific) + +__gthrw(__sdethread_self) + +__gthrw(__sdethread_mutex_lock) +__gthrw(__sdethread_mutex_trylock) +__gthrw(__sdethread_mutex_unlock) + +__gthrw(__sdethread_mutex_init) + +__gthrw(__sdethread_threading) + +#if SUPPORTS_WEAK && GTHREAD_USE_WEAK + +static inline int +__gthread_active_p (void) +{ + return !!(void *)&__sdethread_threading; +} + +#else /* not SUPPORTS_WEAK */ + +static inline int +__gthread_active_p (void) +{ + return 1; +} + +#endif /* SUPPORTS_WEAK */ + +static inline int +__gthread_once (__gthread_once_t *__once, void (*__func) (void)) +{ + if (__gthread_active_p ()) + return __gthrw_(__sdethread_once) (__once, __func); + else + return -1; +} + +static inline int +__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) +{ + return __gthrw_(__sdethread_key_create) (__key, __dtor); +} + +static inline int +__gthread_key_delete (__gthread_key_t __key) +{ + return __gthrw_(__sdethread_key_delete) (__key); +} + +static inline void * +__gthread_getspecific (__gthread_key_t __key) +{ + return __gthrw_(__sdethread_getspecific) (__key); +} + +static inline int +__gthread_setspecific (__gthread_key_t __key, const void *__ptr) +{ + return __gthrw_(__sdethread_setspecific) (__key, __ptr); +} + +static inline int +__gthread_mutex_destroy (__gthread_mutex_t * UNUSED(__mutex)) +{ + return 0; +} + +static inline int +__gthread_mutex_lock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(__sdethread_mutex_lock) (__mutex); + else + return 0; +} + +static inline int +__gthread_mutex_trylock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(__sdethread_mutex_trylock) (__mutex); + else + return 0; +} + +static inline int +__gthread_mutex_unlock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthrw_(__sdethread_mutex_unlock) (__mutex); + else + return 0; +} + +static inline int +__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) +{ + __mutex->depth = 0; + __mutex->owner = __gthrw_(__sdethread_self) (); + return __gthrw_(__sdethread_mutex_init) (&__mutex->actual, NULL); +} + +static inline int +__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + { + __sdethread_t __me = __gthrw_(__sdethread_self) (); + + if (__mutex->owner != __me) + { + __gthrw_(__sdethread_mutex_lock) (&__mutex->actual); + __mutex->owner = __me; + } + + __mutex->depth++; + } + return 0; +} + +static inline int +__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + { + __sdethread_t __me = __gthrw_(__sdethread_self) (); + + if (__mutex->owner != __me) + { + if (__gthrw_(__sdethread_mutex_trylock) (&__mutex->actual)) + return 1; + __mutex->owner = __me; + } + + __mutex->depth++; + } + return 0; +} + +static inline int +__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + { + if (--__mutex->depth == 0) + { + __mutex->owner = (__sdethread_t) 0; + __gthrw_(__sdethread_mutex_unlock) (&__mutex->actual); + } + } + return 0; +} + +static inline int +__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t + * UNUSED(__mutex)) +{ + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* ! GCC_GTHR_MIPSSDE_H */ diff --git a/gcc-4.9/libgcc/config/mips/lib2funcs.c b/gcc-4.9/libgcc/config/mips/lib2funcs.c new file mode 100644 index 000000000..395433e95 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/lib2funcs.c @@ -0,0 +1,44 @@ +/* libgcc routines for MIPS + Copyright (C) 2013-2014 Free Software Foundation, Inc. + DMULT/DDIV replacement support by Juergen Urban, JuergenUrban@gmx.de. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +#if defined(__mips64) && defined(_MIPS_ARCH_R5900) + +/* Build DI version of libgcc functions. */ +#define LIBGCC2_UNITS_PER_WORD 4 + +/* The following function is needed when !ISA_HAS_DMULT. */ +#define L_muldi3 + +/* The following functions are needed when !ISA_HAS_DDIV. */ +#define L_divdi3 +#define L_moddi3 +#define L_udivdi3 +#define L_umoddi3 +#define L_udivmoddi4 + +/* Use generic definition of functions. */ +#include "libgcc2.c" + +#endif diff --git a/gcc-4.9/libgcc/config/mips/libgcc-mips16.ver b/gcc-4.9/libgcc/config/mips/libgcc-mips16.ver new file mode 100644 index 000000000..e26d58c98 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/libgcc-mips16.ver @@ -0,0 +1,48 @@ +# Copyright (C) 2008-2014 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +GCC_4.4.0 { + __mips16_addsf3 + __mips16_subsf3 + __mips16_mulsf3 + __mips16_divsf3 + __mips16_eqsf2 + __mips16_nesf2 + __mips16_gtsf2 + __mips16_gesf2 + __mips16_lesf2 + __mips16_ltsf2 + __mips16_floatsisf + __mips16_floatunsisf + __mips16_fix_truncsfsi + __mips16_adddf3 + __mips16_subdf3 + __mips16_muldf3 + __mips16_divdf3 + __mips16_extendsfdf2 + __mips16_truncdfsf2 + __mips16_eqdf2 + __mips16_nedf2 + __mips16_gtdf2 + __mips16_gedf2 + __mips16_ledf2 + __mips16_ltdf2 + __mips16_floatsidf + __mips16_floatunsidf + __mips16_fix_truncdfsi +} diff --git a/gcc-4.9/libgcc/config/mips/linux-unwind.h b/gcc-4.9/libgcc/config/mips/linux-unwind.h new file mode 100644 index 000000000..9cf7c807e --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/linux-unwind.h @@ -0,0 +1,125 @@ +/* DWARF2 EH unwinding support for MIPS Linux. + Copyright (C) 2004-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +#ifndef inhibit_libc +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#include <signal.h> +#include <asm/unistd.h> + +/* The third parameter to the signal handler points to something with + * this structure defined in asm/ucontext.h, but the name clashes with + * struct ucontext from sys/ucontext.h so this private copy is used. */ +typedef struct _sig_ucontext { + unsigned long uc_flags; + struct _sig_ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; +} _sig_ucontext_t; + +#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state + +static _Unwind_Reason_Code +mips_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + u_int32_t *pc = (u_int32_t *) context->ra; + struct sigcontext *sc; + _Unwind_Ptr new_cfa, reg_offset; + int i; + + /* A MIPS16 or microMIPS frame. Signal frames always use the standard + ISA encoding. */ + if ((_Unwind_Ptr) pc & 3) + return _URC_END_OF_STACK; + + /* 24021061 li v0, 0x1061 (rt_sigreturn)*/ + /* 0000000c syscall */ + /* or */ + /* 24021017 li v0, 0x1017 (sigreturn) */ + /* 0000000c syscall */ + if (pc[1] != 0x0000000c) + return _URC_END_OF_STACK; +#if _MIPS_SIM == _ABIO32 + if (pc[0] == (0x24020000 | __NR_sigreturn)) + { + struct sigframe { + u_int32_t ass[4]; /* Argument save space for o32. */ + u_int32_t trampoline[2]; + struct sigcontext sigctx; + } *rt_ = context->cfa; + sc = &rt_->sigctx; + } + else +#endif + if (pc[0] == (0x24020000 | __NR_rt_sigreturn)) + { + struct rt_sigframe { + u_int32_t ass[4]; /* Argument save space for o32. */ + u_int32_t trampoline[2]; + siginfo_t info; + _sig_ucontext_t uc; + } *rt_ = context->cfa; + sc = &rt_->uc.uc_mcontext; + } + else + return _URC_END_OF_STACK; + + new_cfa = (_Unwind_Ptr) sc; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = STACK_POINTER_REGNUM; + fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; + + /* On o32 Linux, the register save slots in the sigcontext are + eight bytes. We need the lower half of each register slot, + so slide our view of the structure back four bytes. */ +#if _MIPS_SIM == _ABIO32 && defined __MIPSEB__ + reg_offset = 4; +#else + reg_offset = 0; +#endif + + for (i = 0; i < 32; i++) { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset + = (_Unwind_Ptr)&(sc->sc_regs[i]) + reg_offset - new_cfa; + } + /* "PC & -2" points to the faulting instruction, but the unwind code + searches for "(ADDR & -2) - 1". (See MASK_RETURN_ADDR for the source + of the -2 mask.) Adding 2 here ensures that "(ADDR & -2) - 1" is the + address of the second byte of the faulting instruction. + + Note that setting fs->signal_frame would not work. As the comment + above MASK_RETURN_ADDR explains, MIPS unwinders must earch for an + odd-valued address. */ + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_VAL_OFFSET; + fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset + = (_Unwind_Ptr)(sc->sc_pc) + 2 - new_cfa; + fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; + + return _URC_NO_REASON; +} +#endif diff --git a/gcc-4.9/libgcc/config/mips/mips16.S b/gcc-4.9/libgcc/config/mips/mips16.S new file mode 100644 index 000000000..6a43a9839 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/mips16.S @@ -0,0 +1,752 @@ +/* mips16 floating point support code + Copyright (C) 1996-2014 Free Software Foundation, Inc. + Contributed by Cygnus Support + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3, or (at your option) any +later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +#ifdef __mips_micromips + /* DO NOTHING */ +#else + +/* 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 + values using the soft-float calling convention, but do the actual + operation using the hard floating point instructions. */ + +#if defined _MIPS_SIM && (_MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIO64) + +/* This file contains 32-bit assembly code. */ + .set nomips16 + +/* Start a function. */ + +#define STARTFN(NAME) .globl NAME; .ent NAME; NAME: + +/* Finish a function. */ + +#define ENDFN(NAME) .end NAME + +/* ARG1 + The FPR that holds the first floating-point argument. + + ARG2 + The FPR that holds the second floating-point argument. + + RET + The FPR that holds a floating-point return value. */ + +#define RET $f0 +#define ARG1 $f12 +#ifdef __mips64 +#define ARG2 $f13 +#else +#define ARG2 $f14 +#endif + +/* Set 64-bit register GPR so that its high 32 bits contain HIGH_FPR + and so that its low 32 bits contain LOW_FPR. */ +#define MERGE_GPRf(GPR, HIGH_FPR, LOW_FPR) \ + .set noat; \ + mfc1 $1, LOW_FPR; \ + mfc1 GPR, HIGH_FPR; \ + dsll $1, $1, 32; \ + dsll GPR, GPR, 32; \ + dsrl $1, $1, 32; \ + or GPR, GPR, $1; \ + .set at + +/* Move the high 32 bits of GPR to HIGH_FPR and the low 32 bits of + GPR to LOW_FPR. */ +#define MERGE_GPRt(GPR, HIGH_FPR, LOW_FPR) \ + .set noat; \ + dsrl $1, GPR, 32; \ + mtc1 GPR, LOW_FPR; \ + mtc1 $1, HIGH_FPR; \ + .set at + +/* Jump to T, and use "OPCODE, OP2" to implement a delayed move. */ +#define DELAYt(T, OPCODE, OP2) \ + .set noreorder; \ + jr T; \ + 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 + GPRs and FPRs. + + MOVE_SI_BYTE0(D) + Likewise the first single-precision integer argument. + + MOVE_SF_BYTE4(D) + Move the second single-precision floating-point argument between + GPRs and FPRs, given that the first argument occupies 4 bytes. + + MOVE_SF_BYTE8(D) + Move the second single-precision floating-point argument between + GPRs and FPRs, given that the first argument occupies 8 bytes. + + MOVE_DF_BYTE0(D) + Move the first double-precision floating-point argument between + GPRs and FPRs. + + MOVE_DF_BYTE8(D) + Likewise the second double-precision floating-point argument. + + MOVE_SF_RET(D, T) + Likewise a single-precision floating-point return value, + then jump to T. + + MOVE_SC_RET(D, T) + Likewise a complex single-precision floating-point return value. + + MOVE_DF_RET(D, T) + Likewise a double-precision floating-point return value. + + MOVE_DC_RET(D, T) + Likewise a complex double-precision floating-point return value. + + MOVE_SI_RET(D, T) + Likewise a single-precision integer return value. + + The D argument is "t" to move to FPRs and "f" to move from FPRs. + The return macros may assume that the target of the jump does not + use a floating-point register. */ + +#define MOVE_SF_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0) +#define MOVE_SI_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0) + +#if defined(__mips64) && defined(__MIPSEB__) +#define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f0, $f1); jr T +#elif defined(__mips64) +/* 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 + +#if defined(__mips64) +#define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12 +#define MOVE_SF_BYTE4(D) m##D##c1 $5,$f13 +#define MOVE_SF_BYTE8(D) m##D##c1 $5,$f13 +#else +#define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12 +#define MOVE_SF_BYTE4(D) m##D##c1 $5,$f14 +#define MOVE_SF_BYTE8(D) m##D##c1 $6,$f14 +#endif +#define MOVE_SI_BYTE0(D) MOVE_SF_BYTE0(D) + +#if defined(__mips64) +#define MOVE_DF_BYTE0(D) dm##D##c1 $4,$f12 +#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__) +#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_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) +#elif defined(__MIPSEB__) +/* FPRs are little-endian. */ +#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f13; m##D##c1 $5,$f12 +#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f15; m##D##c1 $7,$f14 +#define MOVE_DF_RET(D, T) m##D##c1 $2,$f1; DELAY##D (T, m##D##c1 $3,$f0) +#define MOVE_DC_RET(D, T) m##D##c1 $4,$f3; m##D##c1 $5,$f2; MOVE_DF_RET (D, T) +#else +#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##c1 $5,$f13 +#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##c1 $7,$f15 +#define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1) +#define MOVE_DC_RET(D, T) m##D##c1 $4,$f2; m##D##c1 $5,$f3; MOVE_DF_RET (D, T) +#endif + +/* Single-precision math. */ + +/* Define a function NAME that loads two single-precision values, + performs FPU operation OPCODE on them, and returns the single- + precision result. */ + +#define OPSF3(NAME, OPCODE) \ +STARTFN (NAME); \ + MOVE_SF_BYTE0 (t); \ + MOVE_SF_BYTE4 (t); \ + OPCODE RET,ARG1,ARG2; \ + MOVE_SF_RET (f, $31); \ + ENDFN (NAME) + +#ifdef L_m16addsf3 +OPSF3 (__mips16_addsf3, add.s) +#endif +#ifdef L_m16subsf3 +OPSF3 (__mips16_subsf3, sub.s) +#endif +#ifdef L_m16mulsf3 +OPSF3 (__mips16_mulsf3, mul.s) +#endif +#ifdef L_m16divsf3 +OPSF3 (__mips16_divsf3, div.s) +#endif + +/* Define a function NAME that loads a single-precision value, + performs FPU operation OPCODE on it, and returns the single- + precision result. */ + +#define OPSF2(NAME, OPCODE) \ +STARTFN (NAME); \ + MOVE_SF_BYTE0 (t); \ + OPCODE RET,ARG1; \ + MOVE_SF_RET (f, $31); \ + ENDFN (NAME) + +#ifdef L_m16negsf2 +OPSF2 (__mips16_negsf2, neg.s) +#endif +#ifdef L_m16abssf2 +OPSF2 (__mips16_abssf2, abs.s) +#endif + +/* Single-precision comparisons. */ + +/* Define a function NAME that loads two single-precision values, + performs floating point comparison OPCODE, and returns TRUE or + FALSE depending on the result. */ + +#define CMPSF(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + MOVE_SF_BYTE0 (t); \ + MOVE_SF_BYTE4 (t); \ + OPCODE ARG1,ARG2; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +/* Like CMPSF, but reverse the comparison operands. */ + +#define REVCMPSF(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + MOVE_SF_BYTE0 (t); \ + MOVE_SF_BYTE4 (t); \ + OPCODE ARG2,ARG1; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +#ifdef L_m16eqsf2 +CMPSF (__mips16_eqsf2, c.eq.s, 0, 1) +#endif +#ifdef L_m16nesf2 +CMPSF (__mips16_nesf2, c.eq.s, 0, 1) +#endif +#ifdef L_m16gtsf2 +REVCMPSF (__mips16_gtsf2, c.lt.s, 1, 0) +#endif +#ifdef L_m16gesf2 +REVCMPSF (__mips16_gesf2, c.le.s, 0, -1) +#endif +#ifdef L_m16lesf2 +CMPSF (__mips16_lesf2, c.le.s, 0, 1) +#endif +#ifdef L_m16ltsf2 +CMPSF (__mips16_ltsf2, c.lt.s, -1, 0) +#endif +#ifdef L_m16unordsf2 +CMPSF(__mips16_unordsf2, c.un.s, 1, 0) +#endif + + +/* Single-precision conversions. */ + +#ifdef L_m16fltsisf +STARTFN (__mips16_floatsisf) + MOVE_SF_BYTE0 (t) + cvt.s.w RET,ARG1 + MOVE_SF_RET (f, $31) + ENDFN (__mips16_floatsisf) +#endif + +#ifdef L_m16fltunsisf +STARTFN (__mips16_floatunsisf) + .set noreorder + bltz $4,1f + MOVE_SF_BYTE0 (t) + .set reorder + cvt.s.w RET,ARG1 + MOVE_SF_RET (f, $31) +1: + and $2,$4,1 + srl $3,$4,1 + or $2,$2,$3 + mtc1 $2,RET + cvt.s.w RET,RET + add.s RET,RET,RET + MOVE_SF_RET (f, $31) + ENDFN (__mips16_floatunsisf) +#endif + +#ifdef L_m16fix_truncsfsi +STARTFN (__mips16_fix_truncsfsi) + MOVE_SF_BYTE0 (t) + trunc.w.s RET,ARG1,$4 + MOVE_SI_RET (f, $31) + ENDFN (__mips16_fix_truncsfsi) +#endif + +#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) + +/* Double-precision math. */ + +/* Define a function NAME that loads two double-precision values, + performs FPU operation OPCODE on them, and returns the double- + precision result. */ + +#define OPDF3(NAME, OPCODE) \ +STARTFN (NAME); \ + MOVE_DF_BYTE0 (t); \ + MOVE_DF_BYTE8 (t); \ + OPCODE RET,ARG1,ARG2; \ + MOVE_DF_RET (f, $31); \ + ENDFN (NAME) + +#ifdef L_m16adddf3 +OPDF3 (__mips16_adddf3, add.d) +#endif +#ifdef L_m16subdf3 +OPDF3 (__mips16_subdf3, sub.d) +#endif +#ifdef L_m16muldf3 +OPDF3 (__mips16_muldf3, mul.d) +#endif +#ifdef L_m16divdf3 +OPDF3 (__mips16_divdf3, div.d) +#endif + +/* Define a function NAME that loads a double-precision value, + performs FPU operation OPCODE on it, and returns the double- + precision result. */ + +#define OPDF2(NAME, OPCODE) \ +STARTFN (NAME); \ + MOVE_DF_BYTE0 (t); \ + OPCODE RET,ARG1; \ + MOVE_DF_RET (f, $31); \ + ENDFN (NAME) + +#ifdef L_m16negdf2 +OPDF2 (__mips16_negdf2, neg.d) +#endif +#ifdef L_m16absdf2 +OPDF2 (__mips16_absdf2, abs.d) +#endif + +/* Conversions between single and double precision. */ + +#ifdef L_m16extsfdf2 +STARTFN (__mips16_extendsfdf2) + MOVE_SF_BYTE0 (t) + cvt.d.s RET,ARG1 + MOVE_DF_RET (f, $31) + ENDFN (__mips16_extendsfdf2) +#endif + +#ifdef L_m16trdfsf2 +STARTFN (__mips16_truncdfsf2) + MOVE_DF_BYTE0 (t) + cvt.s.d RET,ARG1 + MOVE_SF_RET (f, $31) + ENDFN (__mips16_truncdfsf2) +#endif + +/* Double-precision comparisons. */ + +/* Define a function NAME that loads two double-precision values, + performs floating point comparison OPCODE, and returns TRUE or + FALSE depending on the result. */ + +#define CMPDF(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + MOVE_DF_BYTE0 (t); \ + MOVE_DF_BYTE8 (t); \ + OPCODE ARG1,ARG2; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +/* Like CMPDF, but reverse the comparison operands. */ + +#define REVCMPDF(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + MOVE_DF_BYTE0 (t); \ + MOVE_DF_BYTE8 (t); \ + OPCODE ARG2,ARG1; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +#ifdef L_m16eqdf2 +CMPDF (__mips16_eqdf2, c.eq.d, 0, 1) +#endif +#ifdef L_m16nedf2 +CMPDF (__mips16_nedf2, c.eq.d, 0, 1) +#endif +#ifdef L_m16gtdf2 +REVCMPDF (__mips16_gtdf2, c.lt.d, 1, 0) +#endif +#ifdef L_m16gedf2 +REVCMPDF (__mips16_gedf2, c.le.d, 0, -1) +#endif +#ifdef L_m16ledf2 +CMPDF (__mips16_ledf2, c.le.d, 0, 1) +#endif +#ifdef L_m16ltdf2 +CMPDF (__mips16_ltdf2, c.lt.d, -1, 0) +#endif +#ifdef L_m16unorddf2 +CMPDF(__mips16_unorddf2, c.un.d, 1, 0) +#endif + +/* Double-precision conversions. */ + +#ifdef L_m16fltsidf +STARTFN (__mips16_floatsidf) + MOVE_SI_BYTE0 (t) + cvt.d.w RET,ARG1 + MOVE_DF_RET (f, $31) + ENDFN (__mips16_floatsidf) +#endif + +#ifdef L_m16fltunsidf +STARTFN (__mips16_floatunsidf) + MOVE_SI_BYTE0 (t) + cvt.d.w RET,ARG1 + bgez $4,1f + li.d ARG1, 4.294967296e+9 + add.d RET, RET, ARG1 +1: MOVE_DF_RET (f, $31) + ENDFN (__mips16_floatunsidf) +#endif + +#ifdef L_m16fix_truncdfsi +STARTFN (__mips16_fix_truncdfsi) + MOVE_DF_BYTE0 (t) + trunc.w.d RET,ARG1,$4 + MOVE_SI_RET (f, $31) + ENDFN (__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) \ +CE_STARTFN (NAME); \ + MOVE_##MODE##_RET (t, $31); \ + CE_ENDFN (NAME) + +#ifdef L_m16retsf +RET_FUNCTION (__mips16_ret_sf, SF) +#endif + +#ifdef L_m16retsc +RET_FUNCTION (__mips16_ret_sc, SC) +#endif + +#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) +#ifdef L_m16retdf +RET_FUNCTION (__mips16_ret_df, DF) +#endif + +#ifdef L_m16retdc +RET_FUNCTION (__mips16_ret_dc, DC) +#endif +#endif /* !__mips_single_float */ + +/* STUB_ARGS_X copies the arguments from GPRs to FPRs for argument + code X. X is calculated as ARG1 + ARG2 * 4, where ARG1 and ARG2 + classify the first and second arguments as follows: + + 1: a single-precision argument + 2: a double-precision argument + 0: no argument, or not one of the above. */ + +#define STUB_ARGS_0 /* () */ +#define STUB_ARGS_1 MOVE_SF_BYTE0 (t) /* (sf) */ +#define STUB_ARGS_5 MOVE_SF_BYTE0 (t); MOVE_SF_BYTE4 (t) /* (sf, sf) */ +#define STUB_ARGS_9 MOVE_SF_BYTE0 (t); MOVE_DF_BYTE8 (t) /* (sf, df) */ +#define STUB_ARGS_2 MOVE_DF_BYTE0 (t) /* (df) */ +#define STUB_ARGS_6 MOVE_DF_BYTE0 (t); MOVE_SF_BYTE8 (t) /* (df, sf) */ +#define STUB_ARGS_10 MOVE_DF_BYTE0 (t); MOVE_DF_BYTE8 (t) /* (df, df) */ + +/* These functions are used by 16-bit code when calling via a function + pointer. They must copy the floating point arguments from the GPRs + to FPRs and then call function $2. */ + +#define CALL_STUB_NO_RET(NAME, CODE) \ +CE_STARTFN (NAME); \ + STUB_ARGS_##CODE; \ + .set noreorder; \ + jr $2; \ + move $25,$2; \ + .set reorder; \ + CE_ENDFN (NAME) + +#ifdef L_m16stub1 +CALL_STUB_NO_RET (__mips16_call_stub_1, 1) +#endif + +#ifdef L_m16stub5 +CALL_STUB_NO_RET (__mips16_call_stub_5, 5) +#endif + +#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) + +#ifdef L_m16stub2 +CALL_STUB_NO_RET (__mips16_call_stub_2, 2) +#endif + +#ifdef L_m16stub6 +CALL_STUB_NO_RET (__mips16_call_stub_6, 6) +#endif + +#ifdef L_m16stub9 +CALL_STUB_NO_RET (__mips16_call_stub_9, 9) +#endif + +#ifdef L_m16stub10 +CALL_STUB_NO_RET (__mips16_call_stub_10, 10) +#endif +#endif /* !__mips_single_float */ + +/* Now we have the same set of functions, except that this time the + function being called returns an SFmode, SCmode, DFmode or DCmode + value; we need to instantiate a set for each case. The calling + function will arrange to preserve $18, so these functions are free + to use it to hold the return address. + + Note that we do not know whether the function we are calling is 16 + bit or 32 bit. However, it does not matter, because 16-bit + functions always return floating point values in both the gp and + the fp regs. It would be possible to check whether the function + 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) \ +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. */ + +#ifdef L_m16stubsf0 +CALL_STUB_RET (__mips16_call_stub_sf_0, 0, SF) +#endif + +#ifdef L_m16stubsf1 +CALL_STUB_RET (__mips16_call_stub_sf_1, 1, SF) +#endif + +#ifdef L_m16stubsf5 +CALL_STUB_RET (__mips16_call_stub_sf_5, 5, SF) +#endif + +#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) +#ifdef L_m16stubsf2 +CALL_STUB_RET (__mips16_call_stub_sf_2, 2, SF) +#endif + +#ifdef L_m16stubsf6 +CALL_STUB_RET (__mips16_call_stub_sf_6, 6, SF) +#endif + +#ifdef L_m16stubsf9 +CALL_STUB_RET (__mips16_call_stub_sf_9, 9, SF) +#endif + +#ifdef L_m16stubsf10 +CALL_STUB_RET (__mips16_call_stub_sf_10, 10, SF) +#endif +#endif /* !__mips_single_float */ + + +/* Now we have the same set of functions again, except that this time + the function being called returns an DFmode value. */ + +#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) +#ifdef L_m16stubdf0 +CALL_STUB_RET (__mips16_call_stub_df_0, 0, DF) +#endif + +#ifdef L_m16stubdf1 +CALL_STUB_RET (__mips16_call_stub_df_1, 1, DF) +#endif + +#ifdef L_m16stubdf5 +CALL_STUB_RET (__mips16_call_stub_df_5, 5, DF) +#endif + +#ifdef L_m16stubdf2 +CALL_STUB_RET (__mips16_call_stub_df_2, 2, DF) +#endif + +#ifdef L_m16stubdf6 +CALL_STUB_RET (__mips16_call_stub_df_6, 6, DF) +#endif + +#ifdef L_m16stubdf9 +CALL_STUB_RET (__mips16_call_stub_df_9, 9, DF) +#endif + +#ifdef L_m16stubdf10 +CALL_STUB_RET (__mips16_call_stub_df_10, 10, DF) +#endif +#endif /* !__mips_single_float */ + + +/* Ho hum. Here we have the same set of functions again, this time + for when the function being called returns an SCmode value. */ + +#ifdef L_m16stubsc0 +CALL_STUB_RET (__mips16_call_stub_sc_0, 0, SC) +#endif + +#ifdef L_m16stubsc1 +CALL_STUB_RET (__mips16_call_stub_sc_1, 1, SC) +#endif + +#ifdef L_m16stubsc5 +CALL_STUB_RET (__mips16_call_stub_sc_5, 5, SC) +#endif + +#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) +#ifdef L_m16stubsc2 +CALL_STUB_RET (__mips16_call_stub_sc_2, 2, SC) +#endif + +#ifdef L_m16stubsc6 +CALL_STUB_RET (__mips16_call_stub_sc_6, 6, SC) +#endif + +#ifdef L_m16stubsc9 +CALL_STUB_RET (__mips16_call_stub_sc_9, 9, SC) +#endif + +#ifdef L_m16stubsc10 +CALL_STUB_RET (__mips16_call_stub_sc_10, 10, SC) +#endif +#endif /* !__mips_single_float */ + + +/* Finally, another set of functions for DCmode. */ + +#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) +#ifdef L_m16stubdc0 +CALL_STUB_RET (__mips16_call_stub_dc_0, 0, DC) +#endif + +#ifdef L_m16stubdc1 +CALL_STUB_RET (__mips16_call_stub_dc_1, 1, DC) +#endif + +#ifdef L_m16stubdc5 +CALL_STUB_RET (__mips16_call_stub_dc_5, 5, DC) +#endif + +#ifdef L_m16stubdc2 +CALL_STUB_RET (__mips16_call_stub_dc_2, 2, DC) +#endif + +#ifdef L_m16stubdc6 +CALL_STUB_RET (__mips16_call_stub_dc_6, 6, DC) +#endif + +#ifdef L_m16stubdc9 +CALL_STUB_RET (__mips16_call_stub_dc_9, 9, DC) +#endif + +#ifdef L_m16stubdc10 +CALL_STUB_RET (__mips16_call_stub_dc_10, 10, DC) +#endif +#endif /* !__mips_single_float */ + +#endif +#endif /* __mips_micromips */ diff --git a/gcc-4.9/libgcc/config/mips/sfp-machine.h b/gcc-4.9/libgcc/config/mips/sfp-machine.h new file mode 100644 index 000000000..e9d33b7dc --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/sfp-machine.h @@ -0,0 +1,180 @@ +/* softfp machine description for MIPS. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +#ifdef __mips64 +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE unsigned long long +#define _FP_WS_TYPE signed long long +#define _FP_I_TYPE long long + +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#define TI_BITS (__CHAR_BIT__ * (int) sizeof (TItype)) + +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) + +#ifdef __mips_nan2008 +# define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +# define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1) +# define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1 +#else +# define _FP_NANFRAC_S (_FP_QNANBIT_S - 1) +# define _FP_NANFRAC_D (_FP_QNANBIT_D - 1) +# define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1 +#endif +#else +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned int +#define _FP_WS_TYPE signed int +#define _FP_I_TYPE int + +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) + +#ifdef __mips_nan2008 +# define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +# define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 +# define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#else +# define _FP_NANFRAC_S (_FP_QNANBIT_S - 1) +# define _FP_NANFRAC_D (_FP_QNANBIT_D - 1), -1 +# define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1, -1, -1 +#endif +#endif + +/* The type of the result of a floating point comparison. This must + match __libgcc_cmp_return__ in GCC for the target. */ +typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); +#define CMPtype __gcc_CMPtype + +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 0 +#define _FP_NANSIGN_Q 0 + +#define _FP_KEEPNANFRACP 1 +#ifdef __mips_nan2008 +# define _FP_QNANNEGATEDP 0 +#else +# define _FP_QNANNEGATEDP 1 +#endif + +/* Comment from glibc: */ +/* From my experiments it seems X is chosen unless one of the + NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs(X) | \ + _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs) \ + { \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#ifdef __mips_hard_float +#define FP_EX_INVALID 0x40 +#define FP_EX_DIVZERO 0x20 +#define FP_EX_OVERFLOW 0x10 +#define FP_EX_UNDERFLOW 0x08 +#define FP_EX_INEXACT 0x04 +#define FP_EX_ALL \ + (FP_EX_INVALID | FP_EX_DIVZERO | FP_EX_OVERFLOW | FP_EX_UNDERFLOW \ + | FP_EX_INEXACT) + +#define FP_EX_ENABLE_SHIFT 5 +#define FP_EX_CAUSE_SHIFT 10 + +#define FP_RND_NEAREST 0x0 +#define FP_RND_ZERO 0x1 +#define FP_RND_PINF 0x2 +#define FP_RND_MINF 0x3 +#define FP_RND_MASK 0x3 + +#define _FP_DECL_EX \ + unsigned long int _fcsr __attribute__ ((unused)) = FP_RND_NEAREST + +#define FP_INIT_ROUNDMODE \ + do { \ + _fcsr = __builtin_mips_get_fcsr (); \ + } while (0) + +#define FP_ROUNDMODE (_fcsr & FP_RND_MASK) + +#define FP_TRAPPING_EXCEPTIONS ((_fcsr >> FP_EX_ENABLE_SHIFT) & FP_EX_ALL) + +#define FP_HANDLE_EXCEPTIONS \ + do { \ + _fcsr &= ~(FP_EX_ALL << FP_EX_CAUSE_SHIFT); \ + /* Also clear Unimplemented Operation. */ \ + _fcsr &= ~(1 << 17); \ + _fcsr |= _fex | (_fex << FP_EX_CAUSE_SHIFT); \ + __builtin_mips_set_fcsr (_fcsr); \ + } while (0); + +#else +#define FP_EX_INVALID (1 << 4) +#define FP_EX_DIVZERO (1 << 3) +#define FP_EX_OVERFLOW (1 << 2) +#define FP_EX_UNDERFLOW (1 << 1) +#define FP_EX_INEXACT (1 << 0) +#endif + +#define _FP_TININESS_AFTER_ROUNDING 1 + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#if defined _MIPSEB +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); diff --git a/gcc-4.9/libgcc/config/mips/t-crtstuff b/gcc-4.9/libgcc/config/mips/t-crtstuff new file mode 100644 index 000000000..d8ab43be2 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-crtstuff @@ -0,0 +1,2 @@ +# Don't let CTOR_LIST end up in sdata section. +CRTSTUFF_T_CFLAGS = -G 0 diff --git a/gcc-4.9/libgcc/config/mips/t-elf b/gcc-4.9/libgcc/config/mips/t-elf new file mode 100644 index 000000000..651f10a53 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-elf @@ -0,0 +1,3 @@ +# We must build libgcc2.a with -G 0, in case the user wants to link +# without the $gp register. +HOST_LIBGCC2_CFLAGS += -G 0 diff --git a/gcc-4.9/libgcc/config/mips/t-mips b/gcc-4.9/libgcc/config/mips/t-mips new file mode 100644 index 000000000..4fb8e1362 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-mips @@ -0,0 +1,9 @@ +LIB2_SIDITI_CONV_FUNCS = yes + +softfp_float_modes := +softfp_int_modes := si di +softfp_extensions := +softfp_truncations := +softfp_exclude_libgcc2 := n + +LIB2ADD_ST += $(srcdir)/config/mips/lib2funcs.c diff --git a/gcc-4.9/libgcc/config/mips/t-mips16 b/gcc-4.9/libgcc/config/mips/t-mips16 new file mode 100644 index 000000000..451ba9b81 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-mips16 @@ -0,0 +1,45 @@ +# Copyright (C) 2007-2014 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +LIB1ASMSRC = mips/mips16.S +LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \ + _m16eqsf2 _m16nesf2 _m16gtsf2 _m16gesf2 _m16lesf2 _m16ltsf2 \ + _m16unordsf2 \ + _m16fltsisf _m16fix_truncsfsi _m16fltunsisf \ + _m16adddf3 _m16subdf3 _m16muldf3 _m16divdf3 \ + _m16extsfdf2 _m16trdfsf2 \ + _m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \ + _m16unorddf2 \ + _m16fltsidf _m16fix_truncdfsi _m16fltunsidf \ + _m16retsf _m16retdf \ + _m16retsc _m16retdc \ + _m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \ + _m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \ + _m16stubsf9 _m16stubsf10 \ + _m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \ + _m16stubdf9 _m16stubdf10 \ + _m16stubsc0 _m16stubsc1 _m16stubsc2 _m16stubsc5 _m16stubsc6 \ + _m16stubsc9 _m16stubsc10 \ + _m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \ + _m16stubdc9 _m16stubdc10 + +SYNC = yes +SYNC_CFLAGS = -mno-mips16 + +# Version these symbols if building libgcc.so. +SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver diff --git a/gcc-4.9/libgcc/config/mips/t-mips64 b/gcc-4.9/libgcc/config/mips/t-mips64 new file mode 100644 index 000000000..a1e3513e2 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-mips64 @@ -0,0 +1 @@ +softfp_int_modes += ti diff --git a/gcc-4.9/libgcc/config/mips/t-sdemtk b/gcc-4.9/libgcc/config/mips/t-sdemtk new file mode 100644 index 000000000..a06e828b5 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-sdemtk @@ -0,0 +1,3 @@ +# Don't build FPBIT and DPBIT; we'll be using the SDE soft-float library. +FPBIT = +DPBIT = diff --git a/gcc-4.9/libgcc/config/mips/t-softfp-tf b/gcc-4.9/libgcc/config/mips/t-softfp-tf new file mode 100644 index 000000000..306677b12 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-softfp-tf @@ -0,0 +1,3 @@ +softfp_float_modes += tf +softfp_extensions += sftf dftf +softfp_truncations += tfsf tfdf diff --git a/gcc-4.9/libgcc/config/mips/t-vr b/gcc-4.9/libgcc/config/mips/t-vr new file mode 100644 index 000000000..601fbdece --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/t-vr @@ -0,0 +1,2 @@ +LIB2ADD_ST = $(srcdir)/config/mips/mips16.S \ + $(srcdir)/config/mips/vr4120-div.S diff --git a/gcc-4.9/libgcc/config/mips/vr4120-div.S b/gcc-4.9/libgcc/config/mips/vr4120-div.S new file mode 100644 index 000000000..76c4e7a45 --- /dev/null +++ b/gcc-4.9/libgcc/config/mips/vr4120-div.S @@ -0,0 +1,79 @@ +/* Support file for -mfix-vr4120. + Copyright (C) 2002-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +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/>. */ + +/* This file contains functions which implement divsi3 and modsi3 for + -mfix-vr4120. div and ddiv do not give the correct result when one + of the operands is negative. */ + + .set nomips16 + +#define DIV \ + xor $3,$4,$5 /* t = x ^ y */ ; \ + li $2,0x80000000; \ + .set noreorder; \ + bgez $4,1f /* x >= 0 */; \ + and $3,$3,$2 /* t = (x ^ y) & 0x80000000 in delay slot */ ;\ + .set reorder; \ + subu $4,$0,$4 /* x = -x */ ; \ +1:; \ + .set noreorder; \ + bgez $5,2f /* y >= 0 */ ; \ + nop; \ + subu $5,$0,$5 /* y = -y */ ; \ + .set reorder; \ +2:; \ + divu $0,$4,$5; /* we use divu because of INT_MIN */ \ + .set noreorder; \ + bne $5,$0,3f; \ + nop; \ + break 7 /* division on zero y */ ; \ +3:; \ + .set reorder; \ + mflo $2 /* r = x / y */ ; \ + .set noreorder; \ + beq $3,$0,4f /* t == 0 */ ; \ + nop; \ + subu $2,$0,$2 /* r = -r */ ; \ + .set reorder; \ +4: + + .globl __vr4120_divsi3 + .ent __vr4120_divsi3 +__vr4120_divsi3: + DIV + j $31 + .end __vr4120_divsi3 + + .globl __vr4120_modsi3 + .ent __vr4120_modsi3 +__vr4120_modsi3: + move $6,$4 # x1 = x + move $7,$5 # y1 = y + DIV + mult $2,$7 # r = r * y1 + mflo $2 + .set noreorder + j $31 + subu $2,$6,$2 # r = x1 - r in delay slot + .end __vr4120_modsi3 |