Add support for building as MIPS16 code.
authorMaciej W. Rozycki <macro@codesourcery.com>
Wed, 27 Feb 2013 23:45:07 +0000 (23:45 +0000)
committerMaciej W. Rozycki <macro@codesourcery.com>
Wed, 27 Feb 2013 23:45:07 +0000 (23:45 +0000)
62 files changed:
ports/ChangeLog.mips
ports/sysdeps/mips/__longjmp.c
ports/sysdeps/mips/abort-instr.h
ports/sysdeps/mips/bits/atomic.h
ports/sysdeps/mips/bsd-_setjmp.S
ports/sysdeps/mips/bsd-setjmp.S
ports/sysdeps/mips/dl-machine.h
ports/sysdeps/mips/dl-trampoline.c
ports/sysdeps/mips/fpu/e_sqrt.c
ports/sysdeps/mips/fpu/e_sqrtf.c
ports/sysdeps/mips/fpu_control.h
ports/sysdeps/mips/machine-gmon.h
ports/sysdeps/mips/memset.S
ports/sysdeps/mips/mips32/crti.S
ports/sysdeps/mips/mips32/crtn.S
ports/sysdeps/mips/mips32/fpu/Versions [new file with mode: 0644]
ports/sysdeps/mips/mips32/fpu/fpu_control.c [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/add_n.c [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/addmul_1.c [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/fpu/Makefile [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/lshift.c [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/mul_1.c [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/rshift.c [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/sub_n.c [new file with mode: 0644]
ports/sysdeps/mips/mips32/mips16/submul_1.c [new file with mode: 0644]
ports/sysdeps/mips/mips64/n32/crti.S
ports/sysdeps/mips/mips64/n32/crtn.S
ports/sysdeps/mips/mips64/n64/crti.S
ports/sysdeps/mips/mips64/n64/crtn.S
ports/sysdeps/mips/nptl/tls.h
ports/sysdeps/mips/preconfigure
ports/sysdeps/mips/setjmp.S
ports/sysdeps/mips/setjmp_aux.c
ports/sysdeps/mips/start.S
ports/sysdeps/mips/sys/tas.h
ports/sysdeps/mips/tls-macros.h
ports/sysdeps/unix/mips/mips32/sysdep.h
ports/sysdeps/unix/mips/mips64/n32/sysdep.h
ports/sysdeps/unix/mips/mips64/n64/sysdep.h
ports/sysdeps/unix/mips/sysdep.S
ports/sysdeps/unix/mips/sysdep.h
ports/sysdeps/unix/sysv/linux/mips/brk.c
ports/sysdeps/unix/sysv/linux/mips/clone.S
ports/sysdeps/unix/sysv/linux/mips/getcontext.S
ports/sysdeps/unix/sysv/linux/mips/makecontext.S
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c [new file with mode: 0644]
ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist
ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h
ports/sysdeps/unix/sysv/linux/mips/setcontext.S
ports/sysdeps/unix/sysv/linux/mips/swapcontext.S
ports/sysdeps/unix/sysv/linux/mips/vfork.S

index f06c986..2518065 100644 (file)
@@ -1,3 +1,109 @@
+2013-02-27  Chung-Lin Tang  <cltang@codesourcery.com>
+            Maciej W. Rozycki  <macro@codesourcery.com>
+            Maxim Kuvyrkov  <maxim@codesourcery.com>
+
+       * sysdeps/mips/abort-instr.h (ABORT_INSTRUCTION) [__mips16]:
+       New macro.
+       * sysdeps/mips/dl-machine.h (elf_machine_load_address): Add
+       MIPS16 version of assembly code.
+       (RTLD_START) [__mips16]: New macro.
+       * sysdeps/mips/fpu_control.h (__mips_fpu_getcw): New prototype.
+       (__mips_fpu_setcw): Likewise.
+       (_FPU_GETCW) [__mips16]: New macro.
+       (_FPU_SETCW) [__mips16]: Likewise.
+       * sysdeps/mips/machine-gmon.h (MCOUNT): Add `.set nomips16'.
+       * sysdeps/mips/tls-macros.h (LOAD_GP) [__mips16]: New macro.
+       (TLS_GD, TLS_LD, TLS_IE, TLS_LE) [__mips16]: Likewise.
+       * sysdeps/mips/bits/atomic.h: Also use __atomic_* builtins with
+       GCC 4.7 in MIPS16 code.
+       (atomic_compare_and_exchange_val_acq) [__mips16]: New macro.
+       (atomic_compare_and_exchange_bool_acq) [__mips16]: Likewise.
+       (atomic_exchange_acq) [__mips16]: Likewise.
+       (atomic_exchange_and_add) [__mips16]: Likewise.
+       (atomic_bit_test_set) [__mips16]: Likewise.
+       (atomic_and, atomic_and_val) [__mips16]: Likewise.
+       (atomic_or, atomic_or_val) [__mips16]: Likewise.
+       (atomic_full_barrier) [__mips16]: Likewise.
+       * sysdeps/mips/nptl/tls.h (READ_THREAD_POINTER) [__mips16]:
+       Likewise.
+       * sysdeps/mips/sys/tas.h (_test_and_set): Add `__nomips16__'
+       attribute.
+       * sysdeps/unix/mips/sysdep.h (PSEUDO_NOERRNO): Add
+       `.set nomips16'.
+       (PSEUDO_ERRVAL): Likewise.
+       * sysdeps/unix/mips/mips32/sysdep.h (PSEUDO): Likewise.
+       * sysdeps/unix/mips/mips64/n32/sysdep.h (PSEUDO): Likewise.
+       * sysdeps/unix/mips/mips64/n64/sysdep.h (PSEUDO): Likewise.
+       * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
+       (INTERNAL_SYSCALL, INTERNAL_SYSCALL_NCS) [__mips16]: New macros.
+       (INTERNAL_SYSCALL_MIPS16) [__mips16]: Likewise.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h (PSEUDO):
+       Add `.set nomips16'.
+       * sysdeps/mips/bsd-_setjmp.S (_setjmp): Likewise.
+       * sysdeps/mips/bsd-setjmp.S (setjmp): Likewise.
+       * sysdeps/mips/memset.S (memset): Likewise.
+       * sysdeps/mips/setjmp.S (__sigsetjmp): Likewise.
+       * sysdeps/mips/start.S (ENTRY_POINT) [__mips16]: New function.
+       * sysdeps/mips/mips32/crti.S: Add `.set nomips16'.
+       * sysdeps/mips/mips32/crtn.S: Likewise.
+       * sysdeps/mips/mips64/n32/crti.S: Likewise.
+       * sysdeps/mips/mips64/n32/crtn.S: Likewise.
+       * sysdeps/mips/mips64/n64/crti.S: Likewise.
+       * sysdeps/mips/mips64/n64/crtn.S: Likewise.
+       * sysdeps/unix/mips/sysdep.S: Likewise.
+       * sysdeps/unix/sysv/linux/mips/clone.S: Likewise.
+       * sysdeps/unix/sysv/linux/mips/getcontext.S: Likewise.
+       * sysdeps/unix/sysv/linux/mips/makecontext.S: Likewise.
+       * sysdeps/unix/sysv/linux/mips/setcontext.S: Likewise.
+       * sysdeps/unix/sysv/linux/mips/swapcontext.S: Likewise.
+       * sysdeps/unix/sysv/linux/mips/vfork.S: Likewise.
+       * sysdeps/mips/__longjmp.c (__longjmp): Rename function to...
+       (____longjmp): ... this.  Make static and add `nomips16'
+       attribute.
+       (__longjmp): New alias.
+       * sysdeps/mips/dl-trampoline.c (_dl_runtime_resolve) [__mips16]:
+       New function.
+       (_dl_runtime_pltresolve): Likewise.
+       * sysdeps/mips/setjmp_aux.c (__sigsetjmp_aux): Add `nomips16'
+       attribute.
+       * sysdeps/mips/fpu/e_sqrt.c (__ieee754_sqrt): Likewise.
+       * sysdeps/mips/fpu/e_sqrtf.c (__ieee754_sqrtf): Likewise.
+       * sysdeps/unix/sysv/linux/mips/brk.c (__brk): Rewrite in terms
+       of INTERNAL_SYSCALL.
+       * sysdeps/mips/mips32/fpu/fpu_control.c: New file.
+       * sysdeps/mips/mips32/mips16/add_n.c: New file.
+       * sysdeps/mips/mips32/mips16/addmul_1.c: New file.
+       * sysdeps/mips/mips32/mips16/lshift.c: New file.
+       * sysdeps/mips/mips32/mips16/mul_1.c: New file.
+       * sysdeps/mips/mips32/mips16/rshift.c: New file.
+       * sysdeps/mips/mips32/mips16/sub_n.c: New file.
+       * sysdeps/mips/mips32/mips16/submul_1.c: New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c:
+       New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c:
+       New file.
+       * sysdeps/mips/mips32/fpu/Versions: New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions: New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist: New
+       file.
+       * sysdeps/mips/mips32/mips16/fpu/Makefile: New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile: New file.
+       * sysdeps/mips/preconfigure: Handle o32 MIPS16 compilation.
+
 2013-02-20  Thomas Schwinge  <thomas@codesourcery.com>
 
        * sysdeps/mips/bits/nan.h [!__GNUC__] (__nan_union): Change
index a9efb0d..67bdb86 100644 (file)
@@ -23,8 +23,8 @@
   #error This file uses GNU C extensions; you must compile with GCC.
 #endif
 
-void
-__longjmp (env_arg, val_arg)
+static void __attribute__ ((nomips16))
+____longjmp (env_arg, val_arg)
      __jmp_buf env_arg;
      int val_arg;
 {
@@ -86,3 +86,5 @@ __longjmp (env_arg, val_arg)
   /* Avoid `volatile function does return' warnings.  */
   for (;;);
 }
+
+strong_alias (____longjmp, __longjmp);
index d7d8d50..7ccae57 100644 (file)
@@ -1,2 +1,6 @@
 /* An instruction which should crash any program is a breakpoint.  */
-#define ABORT_INSTRUCTION asm ("break 255")
+#ifdef __mips16
+# define ABORT_INSTRUCTION asm ("break 63")
+#else
+# define ABORT_INSTRUCTION asm ("break 255")
+#endif
index 566b3dd..bdc3ace 100644 (file)
@@ -78,9 +78,12 @@ typedef uintmax_t uatomic_max_t;
 #define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X)
 #define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC)
 
-#if __GNUC_PREREQ (4, 8)
+#if __GNUC_PREREQ (4, 8) || (defined __mips16 && __GNUC_PREREQ (4, 7))
 /* The __atomic_* builtins are available in GCC 4.7 and later, but MIPS
-   support for their efficient implementation was added only in GCC 4.8.  */
+   support for their efficient implementation was added only in GCC 4.8.
+   We still want to use them even with GCC 4.7 for MIPS16 code where we
+   have no assembly alternative available and want to avoid the __sync_*
+   if at all possible.  */
 
 /* Compare and exchange.
    For all "bool" routines, we return FALSE if exchange succesful.  */
@@ -200,7 +203,33 @@ typedef uintmax_t uatomic_max_t;
 # define atomic_exchange_and_add_rel(mem, value)                       \
   __atomic_val_bysize (__arch_exchange_and_add, int, mem, value,       \
                       __ATOMIC_RELEASE)
-#else /* !__GNUC_PREREQ (4, 8) */
+
+#elif defined __mips16 /* !__GNUC_PREREQ (4, 7) */
+/* This implementation using __sync* builtins will be removed once glibc
+   requires GCC 4.7 or later to build.  */
+
+# define atomic_compare_and_exchange_val_acq(mem, newval, oldval)      \
+  __sync_val_compare_and_swap ((mem), (oldval), (newval))
+# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval)     \
+  (!__sync_bool_compare_and_swap ((mem), (oldval), (newval)))
+
+# define atomic_exchange_acq(mem, newval)                              \
+  __sync_lock_test_and_set ((mem), (newval))
+
+# define atomic_exchange_and_add(mem, val)                             \
+  __sync_fetch_and_add ((mem), (val))
+
+# define atomic_bit_test_set(mem, bit)                                 \
+  ({ __typeof (bit) __bit = (bit);                                     \
+     (__sync_fetch_and_or ((mem), 1 << (__bit)) & (1 << (__bit))); })
+
+# define atomic_and(mem, mask) (void) __sync_fetch_and_and ((mem), (mask))
+# define atomic_and_val(mem, mask) __sync_fetch_and_and ((mem), (mask))
+
+# define atomic_or(mem, mask) (void) __sync_fetch_and_or ((mem), (mask))
+# define atomic_or_val(mem, mask) __sync_fetch_and_or ((mem), (mask))
+
+#else /* !__mips16 && !__GNUC_PREREQ (4, 8) */
 /* This implementation using inline assembly will be removed once glibc
    requires GCC 4.8 or later to build.  */
 
@@ -443,15 +472,21 @@ typedef uintmax_t uatomic_max_t;
 # define atomic_exchange_and_add_rel(mem, value)                       \
   __atomic_val_bysize (__arch_exchange_and_add, int, mem, value,       \
                       MIPS_SYNC_STR, "")
-#endif /* __GNUC_PREREQ (4, 8) */
+
+#endif /* !__mips16 && !__GNUC_PREREQ (4, 8) */
 
 /* TODO: More atomic operations could be implemented efficiently; only the
    basic requirements are done.  */
 
-#define atomic_full_barrier() \
+#ifdef __mips16
+# define atomic_full_barrier() __sync_synchronize ()
+
+#else /* !__mips16 */
+# define atomic_full_barrier() \
   __asm__ __volatile__ (".set push\n\t"                                              \
                        MIPS_PUSH_MIPS2                                       \
                        MIPS_SYNC_STR "\n\t"                                  \
                        ".set pop" : : : "memory")
+#endif /* !__mips16 */
 
 #endif /* bits/atomic.h */
index 1974e4b..50cce7e 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <sysdep.h>
 
+       .set    nomips16
+
 #ifdef __PIC__
        .option pic2
 #endif
index 5eedcdd..18e8b0f 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <sysdep.h>
 
+       .set    nomips16
+
 #ifdef __PIC__
        .option pic2
 #endif
index 91f7a7b..a7c784f 100644 (file)
@@ -119,6 +119,7 @@ static inline ElfW(Addr)
 elf_machine_load_address (void)
 {
   ElfW(Addr) addr;
+#ifndef __mips16
   asm ("       .set noreorder\n"
        "       " STRINGXP (PTR_LA) " %0, 0f\n"
        "       bltzal $0, 0f\n"
@@ -128,6 +129,19 @@ elf_machine_load_address (void)
        :       "=r" (addr)
        :       /* No inputs */
        :       "$31");
+#else
+  ElfW(Addr) tmp;
+  asm ("       .set noreorder\n"
+       "       move %1,$gp\n"
+       "       lw %1,%%got(0f)(%1)\n"
+       "0:     .fill 0\n"              /* Clear the ISA bit on 0:.  */
+       "       la %0,0b\n"
+       "       addiu %1,%%lo(0b)\n"
+       "       subu %0,%1\n"
+       "       .set reorder\n"
+       :       "=d" (addr), "=d" (tmp)
+       :       /* No inputs */);
+#endif
   return addr;
 }
 
@@ -210,7 +224,8 @@ do {                                                                        \
    2) That under Unix the entry is named __start
       and not just plain _start.  */
 
-#define RTLD_START asm (\
+#ifndef __mips16
+# define RTLD_START asm (\
        ".text\n\
        " _RTLD_PROLOGUE(ENTRY_POINT) "\
        " STRINGXV(SETUP_GPX($25)) "\n\
@@ -283,6 +298,91 @@ do {                                                                       \
        ".previous"\
 );
 
+#else /* __mips16 */
+/* MIPS16 version.  We currently only support O32 under MIPS16; the proper
+   assembly preprocessor abstractions will need to be added if other ABIs
+   are to be supported.  */
+
+# define RTLD_START asm (\
+       ".text\n\
+       .set mips16\n\
+       " _RTLD_PROLOGUE (ENTRY_POINT) "\
+       # Construct GP value in $3.\n\
+       li $3, %hi(_gp_disp)\n\
+       addiu $4, $pc, %lo(_gp_disp)\n\
+       sll $3, 16\n\
+       addu $3, $4\n\
+       move $28, $3\n\
+       lw $4, %got(_DYNAMIC)($3)\n\
+       sw $4, -0x7ff0($3)\n\
+       move $4, $sp\n\
+       addiu $sp, -16\n\
+       # _dl_start() is sufficiently near to use pc-relative\n\
+       # load address.\n\
+       la $3, _dl_start\n\
+       move $25, $3\n\
+       jalr $3\n\
+       addiu $sp, 16\n\
+       " _RTLD_EPILOGUE (ENTRY_POINT) "\
+       \n\
+       \n\
+       " _RTLD_PROLOGUE (_dl_start_user) "\
+       li $16, %hi(_gp_disp)\n\
+       addiu $4, $pc, %lo(_gp_disp)\n\
+       sll $16, 16\n\
+       addu $16, $4\n\
+       move $17, $2\n\
+       move $28, $16\n\
+       lw $4, %got(_dl_skip_args)($16)\n\
+       lw $4, 0($4)\n\
+       beqz $4, 1f\n\
+       # Load the original argument count.\n\
+       lw $5, 0($sp)\n\
+       # Subtract _dl_skip_args from it.\n\
+       subu $5, $4\n\
+       # Adjust the stack pointer to skip _dl_skip_args words.\n\
+       sll $4, " STRINGXP (PTRLOG) "\n\
+       move $6, $sp\n\
+       addu $6, $4\n\
+       move $sp, $6\n\
+       # Save back the modified argument count.\n\
+       sw $5, 0($sp)\n\
+1:     # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
+       lw $4, %got(_rtld_local)($16)\n\
+       lw $4, 0($4)\n\
+       lw $5, 0($sp)\n\
+       addiu $6, $sp, " STRINGXP (PTRSIZE) "\n\
+       sll $7, $5, " STRINGXP (PTRLOG) "\n\
+       addu $7, $6\n\
+       addu $7, " STRINGXP (PTRSIZE) "\n\
+       # Make sure the stack pointer is aligned for _dl_init_internal.\n\
+       li $2, 2 * " STRINGXP (SZREG) "\n\
+       neg $2, $2\n\
+       move $3, $sp\n\
+       and $2, $3\n\
+       sw $3, -" STRINGXP (SZREG) "($2)\n\
+       addiu $2, -32\n\
+       move $sp, $2\n\
+       sw $16, 16($sp)\n\
+       # Call the function to run the initializers.\n\
+       lw $2, %call16(_dl_init_internal)($16)\n\
+       move $25, $2\n\
+       jalr $2\n\
+       # Restore the stack pointer for _start.\n\
+       lw $2, 32-" STRINGXP (SZREG) "($sp)\n\
+       move $sp, $2\n\
+       move $28, $16\n\
+       # Pass our finalizer function to the user in $2 as per ELF ABI.\n\
+       lw $2, %call16(_dl_fini)($16)\n\
+       # Jump to the user entry point.\n\
+       move $25, $17\n\
+       jr $17\n\t"\
+       _RTLD_EPILOGUE (_dl_start_user)\
+       ".previous"\
+);
+
+#endif /* __mips16 */
+
 /* Names of the architecture-specific auditing callback functions.  */
 # if _MIPS_SIM == _ABIO32
 #  define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
index 57fb05b..605e44e 100644 (file)
@@ -292,9 +292,11 @@ __dl_runtime_resolve (ElfW(Word) sym_index,
 
 #endif
 
+#ifndef __mips16
 asm ("\n\
        .text\n\
        .align  2\n\
+       .set    nomips16\n\
        .globl  _dl_runtime_resolve\n\
        .type   _dl_runtime_resolve,@function\n\
        .ent    _dl_runtime_resolve\n\
@@ -351,6 +353,7 @@ _dl_runtime_resolve:\n\
 asm ("\n\
        .text\n\
        .align  2\n\
+       .set    nomips16\n\
        .globl  _dl_runtime_pltresolve\n\
        .type   _dl_runtime_pltresolve,@function\n\
        .ent    _dl_runtime_pltresolve\n\
@@ -381,3 +384,130 @@ _dl_runtime_pltresolve:\n\
        .previous\n\
 ");
 
+#elif _MIPS_SIM == _ABIO32 /* __mips16 */
+/* MIPS16 version, O32 only.  */
+asm ("\n\
+       .text\n\
+       .align  2\n\
+       .set    mips16\n\
+       .globl  _dl_runtime_resolve\n\
+       .type   _dl_runtime_resolve,@function\n\
+       .ent    _dl_runtime_resolve\n\
+_dl_runtime_resolve:\n\
+       .frame  $29, " STRINGXP (ELF_DL_FRAME_SIZE) ", $31\n\
+       # Save arguments and sp value in stack.\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+       "save   " STRINGXP (ELF_DL_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+       "addiu  $sp, -" STRINGXP (ELF_DL_FRAME_SIZE) "\n\
+       sw      $7, 32($sp)\n\
+       sw      $6, 28($sp)\n\
+       sw      $5, 24($sp)\n\
+       sw      $4, 20($sp)\n\t"
+# endif
+       "# Preserve caller's $ra, for RESTORE instruction below.\n\
+       move    $5, $15\n\
+       sw      $5, 36($sp)\n\
+       # Compute GP into $2.\n\
+       li      $2, %hi(_gp_disp)\n\
+       addiu   $3, $pc, %lo(_gp_disp)\n\
+       sll     $2, 16\n\
+       addu    $2, $3\n\
+       lw      $3, %got(__dl_runtime_resolve)($2)\n\
+       move    $4, $24\n\
+       addiu   $3, %lo(__dl_runtime_resolve)\n\
+       move    $7, $ra\n\
+       move    $6, $28\n\
+       move    $25, $3\n\
+       jalr    $3\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+       "restore " STRINGXP(ELF_DL_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+       "# Restore $ra, move placed further down to hide latency.\n\
+       lw      $4, 36($sp)\n\
+       lw      $5, 24($sp)\n\
+       lw      $6, 28($sp)\n\
+       lw      $7, 32($sp)\n\
+       move    $ra, $4\n\
+       lw      $4, 20($sp)\n\
+       addiu   $sp, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\t"
+# endif
+       "move   $25, $2\n\
+       jr      $2\n\
+       .end    _dl_runtime_resolve\n\
+       .previous\n\
+");
+
+asm ("\n\
+       .text\n\
+       .align  2\n\
+       .set    mips16\n\
+       .globl  _dl_runtime_pltresolve\n\
+       .type   _dl_runtime_pltresolve,@function\n\
+       .ent    _dl_runtime_pltresolve\n\
+_dl_runtime_pltresolve:\n\
+       .frame  $29, " STRINGXP(ELF_DL_PLT_FRAME_SIZE) ", $31\n\
+       # Save arguments and sp value in stack.\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+       "save   " STRINGXP(ELF_DL_PLT_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+       "addiu  $sp, -" STRINGXP(ELF_DL_PLT_FRAME_SIZE) "\n\
+       sw      $7, 40($sp)\n\
+       sw      $6, 36($sp)\n\
+       sw      $5, 32($sp)\n\
+       sw      $4, 28($sp)\n\t"
+# endif
+       "# Preserve MIPS16 stub function arguments.\n\
+       sw      $3, 20($sp)\n\
+       sw      $2, 16($sp)\n\
+       # Preserve caller's $ra, for RESTORE instruction below.\n\
+       move    $3, $15\n\
+       sw      $3, 44($sp)\n\
+       # Compute GP into $2.\n\
+       li      $2, %hi(_gp_disp)\n\
+       addiu   $3, $pc, %lo(_gp_disp)\n\
+       sll     $2, 16\n\
+       addu    $2, $3\n\
+       # Save GP value in slot.\n\
+       sw      $2, 24($sp)\n\
+       # Load _dl_fixup address.\n\
+       lw      $6, %call16(_dl_fixup)($2)\n\
+       # Load link map address.\n\
+       move    $3, $28\n\
+       lw      $4, " STRINGXP (PTRSIZE) "($3)\n\
+       move    $5, $24\n\
+       sll     $5, " STRINGXP (PTRLOG) " + 1\n\
+       # Call _dl_fixup.\n\
+       move    $25, $6\n\
+       jalr    $6\n\
+       move    $25, $2\n\
+       # Reload GP value into $28.\n\
+       lw      $3, 24($sp)\n\
+       move    $28, $3\n\
+       lw      $3, 16($sp)\n\
+       move    $15, $3\n\
+       lw      $3, 20($sp)\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+       "restore " STRINGXP (ELF_DL_PLT_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+       "# Restore $ra, move placed further down to hide latency.\n\
+       lw      $4, 44($sp)\n\
+       lw      $5, 32($sp)\n\
+       lw      $6, 36($sp)\n\
+       lw      $7, 40($sp)\n\
+       move    $ra, $4\n\
+       lw      $4, 28($sp)\n\
+       addiu   $sp, " STRINGXP (ELF_DL_PLT_FRAME_SIZE) "\n\t"
+# endif
+       ".set   noreorder\n\
+       jr      $2\n\
+        move   $2, $15\n\
+       .set    reorder\n\
+       .end    _dl_runtime_pltresolve\n\
+       .previous\n\
+");
+
+#else /* __mips16 && _MIPS_SIM != _ABIO32 */
+# error "MIPS16 support for N32/N64 not implemented"
+
+#endif /* __mips16 */
index cff9cec..26314b0 100644 (file)
@@ -22,7 +22,7 @@
 
 #if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
 
-double
+double __attribute__ ((nomips16))
 __ieee754_sqrt (double x)
 {
   double z;
index 87d242d..0f7bfd9 100644 (file)
@@ -22,7 +22,7 @@
 
 #if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
 
-float
+float __attribute__ ((nomips16))
 __ieee754_sqrtf (float x)
 {
   float z;
index 30e54f9..6aecb3b 100644 (file)
@@ -99,8 +99,15 @@ extern fpu_control_t __fpu_control;
 typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
 
 /* Macros for accessing the hardware control word.  */
-#define _FPU_GETCW(cw) __asm__ volatile ("cfc1 %0,$31" : "=r" (cw))
-#define _FPU_SETCW(cw) __asm__ volatile ("ctc1 %0,$31" : : "r" (cw))
+extern fpu_control_t __mips_fpu_getcw (void) __THROW;
+extern void __mips_fpu_setcw (fpu_control_t) __THROW;
+#ifdef __mips16
+# define _FPU_GETCW(cw) do { (cw) = __mips_fpu_getcw (); } while (0)
+# define _FPU_SETCW(cw) __mips_fpu_setcw (cw)
+#else
+# define _FPU_GETCW(cw) __asm__ volatile ("cfc1 %0,$31" : "=r" (cw))
+# define _FPU_SETCW(cw) __asm__ volatile ("ctc1 %0,$31" : : "r" (cw))
+#endif
 
 /* Default control word set at startup.  */
 extern fpu_control_t __fpu_control;
index 8c62d84..144c044 100644 (file)
@@ -37,6 +37,8 @@ static void __attribute_used__ __mcount (u_long frompc, u_long selfpc)
 #define MCOUNT asm(\
        ".globl _mcount;\n\t" \
        ".align 2;\n\t" \
+       ".set push;\n\t" \
+       ".set nomips16;\n\t" \
        ".type _mcount,@function;\n\t" \
        ".ent _mcount\n\t" \
         "_mcount:\n\t" \
@@ -67,9 +69,8 @@ static void __attribute_used__ __mcount (u_long frompc, u_long selfpc)
         "addu $29,$29,56;\n\t" \
         "j $31;\n\t" \
         "move $31,$1;\n\t" \
-        ".set reorder;\n\t" \
-        ".set at\n\t" \
-        ".end _mcount");
+       ".end _mcount;\n\t" \
+       ".set pop");
 
 #else
 
@@ -94,6 +95,8 @@ static void __attribute_used__ __mcount (u_long frompc, u_long selfpc)
 #define MCOUNT asm(\
        ".globl _mcount;\n\t" \
        ".align 3;\n\t" \
+       ".set push;\n\t" \
+       ".set nomips16;\n\t" \
        ".type _mcount,@function;\n\t" \
        ".ent _mcount\n\t" \
         "_mcount:\n\t" \
@@ -132,8 +135,7 @@ static void __attribute_used__ __mcount (u_long frompc, u_long selfpc)
         PTR_ADDU_STRING " $29,$29,96;\n\t" \
         "j $31;\n\t" \
         "move $31,$1;\n\t" \
-        ".set reorder;\n\t" \
-        ".set at\n\t" \
-        ".end _mcount");
+       ".end _mcount;\n\t" \
+       ".set pop");
 
 #endif
index 8c8606c..78dab48 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <sysdep.h>
 
+       .set    nomips16
 
 /* void *memset(void *s, int c, size_t n).  */
 
index 5b46279..5f3e9ba 100644 (file)
@@ -54,6 +54,8 @@
        .hidden PREINIT_FUNCTION
 #endif
 
+       .set nomips16
+
        .section .init,"ax",@progbits
        .p2align 2
        .globl _init
index 44cdff0..42381c5 100644 (file)
@@ -36,6 +36,8 @@
 /* crtn.S puts function epilogues in the .init and .fini sections
    corresponding to the prologues in crti.S. */
 
+       .set nomips16
+
        .section .init,"ax",@progbits
        lw $31,28($sp)
        .set noreorder
diff --git a/ports/sysdeps/mips/mips32/fpu/Versions b/ports/sysdeps/mips/mips32/fpu/Versions
new file mode 100644 (file)
index 0000000..91bbf56
--- /dev/null
@@ -0,0 +1,5 @@
+libc {
+  GLIBC_2.18 {
+    __mips_fpu_getcw; __mips_fpu_setcw;
+  }
+}
diff --git a/ports/sysdeps/mips/mips32/fpu/fpu_control.c b/ports/sysdeps/mips/mips32/fpu/fpu_control.c
new file mode 100644 (file)
index 0000000..cd107c5
--- /dev/null
@@ -0,0 +1,34 @@
+/* FPU control word handling, MIPS version, needed by MIPS16 callers.
+   Copyright (C) 1996-2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <math/fpu_control.c>
+
+fpu_control_t
+__mips_fpu_getcw (void)
+{
+  fpu_control_t cw;
+
+  _FPU_GETCW (cw);
+  return cw;
+}
+
+void
+__mips_fpu_setcw (fpu_control_t cw)
+{
+  _FPU_SETCW (cw);
+}
diff --git a/ports/sysdeps/mips/mips32/mips16/add_n.c b/ports/sysdeps/mips/mips32/mips16/add_n.c
new file mode 100644 (file)
index 0000000..fbb4120
--- /dev/null
@@ -0,0 +1 @@
+#include <stdlib/add_n.c>
diff --git a/ports/sysdeps/mips/mips32/mips16/addmul_1.c b/ports/sysdeps/mips/mips32/mips16/addmul_1.c
new file mode 100644 (file)
index 0000000..c0e4a0b
--- /dev/null
@@ -0,0 +1 @@
+#include <stdlib/addmul_1.c>
diff --git a/ports/sysdeps/mips/mips32/mips16/fpu/Makefile b/ports/sysdeps/mips/mips32/mips16/fpu/Makefile
new file mode 100644 (file)
index 0000000..b58c4ee
--- /dev/null
@@ -0,0 +1,5 @@
+# Building hard-float libm as MIPS16 actually produces larger code size,
+# so avoid doing so.
+ifeq ($(subdir),math)
+sysdep-CFLAGS += -mno-mips16
+endif
diff --git a/ports/sysdeps/mips/mips32/mips16/lshift.c b/ports/sysdeps/mips/mips32/mips16/lshift.c
new file mode 100644 (file)
index 0000000..2f945d2
--- /dev/null
@@ -0,0 +1 @@
+#include <stdlib/lshift.c>
diff --git a/ports/sysdeps/mips/mips32/mips16/mul_1.c b/ports/sysdeps/mips/mips32/mips16/mul_1.c
new file mode 100644 (file)
index 0000000..8e758d6
--- /dev/null
@@ -0,0 +1 @@
+#include <stdlib/mul_1.c>
diff --git a/ports/sysdeps/mips/mips32/mips16/rshift.c b/ports/sysdeps/mips/mips32/mips16/rshift.c
new file mode 100644 (file)
index 0000000..4e350a0
--- /dev/null
@@ -0,0 +1 @@
+#include <stdlib/rshift.c>
diff --git a/ports/sysdeps/mips/mips32/mips16/sub_n.c b/ports/sysdeps/mips/mips32/mips16/sub_n.c
new file mode 100644 (file)
index 0000000..d8b5492
--- /dev/null
@@ -0,0 +1 @@
+#include <stdlib/sub_n.c>
diff --git a/ports/sysdeps/mips/mips32/mips16/submul_1.c b/ports/sysdeps/mips/mips32/mips16/submul_1.c
new file mode 100644 (file)
index 0000000..44cadf5
--- /dev/null
@@ -0,0 +1 @@
+#include <stdlib/submul_1.c>
index d9066b2..ddcc9cc 100644 (file)
@@ -54,6 +54,8 @@
        .hidden PREINIT_FUNCTION
 #endif
 
+       .set nomips16
+
        .section .init,"ax",@progbits
        .p2align 2
        .globl _init
index daf7d42..5eb2b4f 100644 (file)
@@ -36,6 +36,8 @@
 /* crtn.S puts function epilogues in the .init and .fini sections
    corresponding to the prologues in crti.S. */
 
+       .set nomips16
+
        .section .init,"ax",@progbits
        ld $31,8($sp)
        ld $28,0($sp)
index 2111ba5..0c66d0d 100644 (file)
@@ -54,6 +54,8 @@
        .hidden PREINIT_FUNCTION
 #endif
 
+       .set nomips16
+
        .section .init,"ax",@progbits
        .p2align 2
        .globl _init
index c66a2e5..4c014b7 100644 (file)
@@ -36,6 +36,8 @@
 /* crtn.S puts function epilogues in the .init and .fini sections
    corresponding to the prologues in crti.S. */
 
+       .set nomips16
+
        .section .init,"ax",@progbits
        ld $31,8($sp)
        ld $28,0($sp)
index 0c91995..2529408 100644 (file)
@@ -37,12 +37,17 @@ typedef union dtv
   } pointer;
 } dtv_t;
 
+#ifdef __mips16
+/* MIPS16 uses GCC builtin to access the TP.  */
+# define READ_THREAD_POINTER() (__builtin_thread_pointer ())
+#else
 /* Note: rd must be $v1 to be ABI-conformant.  */
 # define READ_THREAD_POINTER() \
     ({ void *__result;                                                       \
        asm volatile (".set\tpush\n\t.set\tmips32r2\n\t"                              \
                     "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result));        \
        __result; })
+#endif
 
 #else /* __ASSEMBLER__ */
 # include <tcb-offsets.h>
index 9190eee..b215eb2 100644 (file)
@@ -25,5 +25,10 @@ mips64*)     base_machine=mips64
                  CPPFLAGS="$CPPFLAGS -mabi=$mips_config_abi"
                fi
                ;;
-mips*)         base_machine=mips machine=mips/mips32/$machine ;;
+mips*)         base_machine=mips
+               case "$CC $CFLAGS $CPPFLAGS " in
+               *" -mips16 "*) machine=mips/mips32/mips16/$machine ;;
+               *) machine=mips/mips32/$machine ;;
+               esac
+               ;;
 esac
index 3f923fb..f014b73 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <sysdep.h>
 
+       .set    nomips16
+
 /* The function __sigsetjmp_aux saves all the registers, but it can't
    reliably access the stack or frame pointers, so we pass them in as
    extra arguments.  */
index a955a4f..cb9ea24 100644 (file)
@@ -23,7 +23,7 @@
    pointer.  We do things this way because it's difficult to reliably
    access them in C.  */
 
-int
+int __attribute__ ((nomips16))
 __sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp)
 {
 #ifdef __mips_hard_float
index 82b7a22..83a6895 100644 (file)
        .text
        .globl ENTRY_POINT
        .type ENTRY_POINT,@function
+#ifndef __mips16
 ENTRY_POINT:
-#ifdef __PIC__
+# ifdef __PIC__
        SETUP_GPX($0)
        SETUP_GPX64($25,$0)
-#else
+# else
        PTR_LA $28, _gp         /* Setup GP correctly if we're non-PIC.  */
        move $31, $0
-#endif
+# endif
 
        PTR_LA $4, main         /* main */
        PTR_L $5, 0($29)                /* argc */
@@ -92,22 +93,85 @@ ENTRY_POINT:
           on o32 and quad words (16 bytes) on n32 and n64.  */
        
        and $29, -2 * SZREG
-#if _MIPS_SIM == _ABIO32
+# if _MIPS_SIM == _ABIO32
        PTR_SUBIU $29, 32
-#endif
+# endif
        PTR_LA $7, __libc_csu_init              /* init */
        PTR_LA $8, __libc_csu_fini
-#if _MIPS_SIM == _ABIO32
+# if _MIPS_SIM == _ABIO32
        PTR_S $8, 16($29)               /* fini */
        PTR_S $2, 20($29)               /* rtld_fini */
        PTR_S $29, 24($29)              /* stack_end */
-#else
+# else
        move $9, $2             /* rtld_fini */
        move $10, $29           /* stack_end */
-#endif
+# endif
        jal __libc_start_main
 hlt:   b hlt                   /* Crash if somehow it does return.  */
 
+#elif _MIPS_SIM == _ABIO32 /* __mips16 */
+       /* MIPS16 entry point.  */
+       .set    mips16
+ENTRY_POINT:
+# ifdef __PIC__
+       li      $3, %hi(_gp_disp)
+       addiu   $4, $pc, %lo(_gp_disp)
+       sll     $3, 16
+       addu    $3, $4
+       move    $gp, $3
+# else
+       li      $3, %hi(_gp)
+       sll     $3, 16
+       addiu   $3, %lo(_gp)
+       move    $gp, $3
+# endif
+       /* Tie end of stack frames.  */
+       li      $4, 0
+       move    $31, $4
+       /* Create new SP value in $7, including alignment.  */
+       li      $4, 2 * SZREG
+       neg     $4, $4
+       move    $7, $sp
+       and     $7, $4
+       addiu   $7, -32
+       /* Load arguments with original SP.  */
+       lw      $5, 0($sp)
+       addiu   $6, $sp, PTRSIZE
+       /* Update SP.  */
+       move    $sp, $7
+       /* Lay out last arguments, and call __libc_start_main().  */
+# ifdef __PIC__
+       sw      $7, 24($sp)                     /* stack_end */
+       lw      $4, %got(__libc_csu_fini)($3)
+       lw      $7, %got(__libc_csu_init)($3)   /* init */
+       sw      $4, 16($sp)                     /* fini */
+       lw      $4, %got(main)($3)              /* main */
+       lw      $3, %call16(__libc_start_main)($3)
+       sw      $2, 20($sp)                     /* rtld_fini */
+       move    $25, $3
+       jalr    $3
+# else
+       lw      $4, 1f
+       sw      $7, 24($sp)                     /* stack_end */
+       lw      $7, 2f                          /* init */
+       sw      $4, 16($sp)                     /* fini */
+       lw      $4, 3f                          /* main */
+       sw      $2, 20($sp)                     /* rtld_fini */
+       jal     __libc_start_main
+# endif
+hlt:   b       hlt             /* Crash if somehow it does return.  */
+# ifndef __PIC__
+       .align  2
+1:     .word   __libc_csu_fini
+2:     .word   __libc_csu_init
+3:     .word   main
+# endif
+
+#else /* __mips16 && _MIPS_SIM != _ABIO32 */
+# error "MIPS16 support for N32/N64 not implemented"
+
+#endif /* __mips16 */
+
 /* Define a symbol for the first piece of initialized data.  */
        .data
        .globl __data_start
index 603346a..8718185 100644 (file)
@@ -24,7 +24,8 @@
 
 __BEGIN_DECLS
 
-extern int _test_and_set (int *__p, int __v) __THROW;
+extern int _test_and_set (int *__p, int __v)
+     __THROW __attribute__ ((__nomips16__));
 
 #ifdef __USE_EXTERN_INLINES
 
@@ -32,7 +33,7 @@ extern int _test_and_set (int *__p, int __v) __THROW;
 #  define _EXTERN_INLINE __extern_inline
 # endif
 
-_EXTERN_INLINE int
+_EXTERN_INLINE int __attribute__ ((__nomips16__))
 __NTH (_test_and_set (int *__p, int __v))
 {
   int __r, __t;
index 8fe2e4a..3e87e42 100644 (file)
    (abicalls pic0) function.  */
 #ifndef __PIC__
 # if _MIPS_SIM != _ABI64
-#  define LOAD_GP "move %[tmp], $28\n\tla $28, __gnu_local_gp\n\t"
+#  ifndef __mips16
+#   define LOAD_GP "move %[tmp], $28\n\tla $28, __gnu_local_gp\n\t"
+#  else
+#   define LOAD_GP                                     \
+           "li %[tmp], %%hi(__gnu_local_gp)\n\t"       \
+           "sll %[tmp], 16\n\t"                                \
+           "addiu %[tmp], %%lo(__gnu_local_gp)\n\t"
+#  endif
 # else
 #  define LOAD_GP "move %[tmp], $28\n\tdla $28, __gnu_local_gp\n\t"
 # endif
 # define UNLOAD_GP "\n\tmove $28, %[tmp]"
 #else
-# define LOAD_GP
+/* MIPS16 (re)creates the GP value using PC-relative instructions.  */
+# ifdef __mips16
+#  define LOAD_GP                                      \
+           "li %[tmp], %%hi(_gp_disp)\n\t"             \
+           "addiu %0, $pc, %%lo(_gp_disp)\n\t"         \
+           "sll %[tmp], 16\n\t"                                \
+           "addu %[tmp], %0\n\t"
+# else
+#  define LOAD_GP
+# endif
 # define UNLOAD_GP
 #endif
 
+#ifndef __mips16
 # define TLS_GD(x)                                     \
   ({ void *__result, *__tmp;                           \
      extern void *__tls_get_addr (void *);             \
          ADDU " %0,%0,$3"                              \
          : "+r" (__result) : : "$3");                  \
      __result; })
+
+#else /* __mips16 */
+/* MIPS16 version.  */
+# define TLS_GD(x)                                     \
+  ({ void *__result, *__tmp;                           \
+     extern void *__tls_get_addr (void *);             \
+     asm (LOAD_GP ADDIU " %1, %%tlsgd(" #x ")"         \
+         "\n\tmove %0, %1"                             \
+         : "=d" (__result), [tmp] "=&d" (__tmp));      \
+     (int *) __tls_get_addr (__result); })
+# define TLS_LD(x)                                     \
+  ({ void *__result, *__tmp;                           \
+     extern void *__tls_get_addr (void *);             \
+     asm (LOAD_GP ADDIU " %1, %%tlsldm(" #x ")"                \
+         "\n\tmove %0, %1"                             \
+         : "=d" (__result), [tmp] "=&d" (__tmp));      \
+     __result = __tls_get_addr (__result);             \
+     asm ("li $3,%%dtprel_hi(" #x ")\n\t"              \
+         "sll $3,16\n\t"                               \
+         "addiu $3,%%dtprel_lo(" #x ")\n\t"            \
+         ADDU " %0,%0,$3"                              \
+         : "+d" (__result) : : "$3");                  \
+     __result; })
+# define TLS_IE(x)                                     \
+  ({ void *__result, *__tmp, *__tp;                    \
+     __tp = __builtin_thread_pointer ();               \
+     asm (LOAD_GP LW " $3,%%gottprel(" #x ")(%1)\n\t"  \
+         ADDU " %0,%[tp],$3"                           \
+         : "=&d" (__result), [tmp] "=&d" (__tmp)       \
+         : [tp] "d" (__tp) : "$3");                    \
+     __result; })
+# define TLS_LE(x)                                     \
+  ({ void *__result, *__tp;                            \
+     __tp = __builtin_thread_pointer ();               \
+     asm ("li $3,%%tprel_hi(" #x ")\n\t"               \
+         "sll $3,16\n\t"                               \
+         "addiu $3,%%tprel_lo(" #x ")\n\t"             \
+         ADDU " %0,%[tp],$3"                           \
+         : "=d" (__result) : [tp] "d" (__tp) : "$3");  \
+     __result; })
+
+#endif /* __mips16 */
index 5c5d769..5d96d05 100644 (file)
@@ -24,6 +24,7 @@
 #ifdef __PIC__
 #define PSEUDO(name, syscall_name, args) \
   .align 2;                                                                  \
+  .set nomips16;                                                             \
   cfi_startproc;                                                             \
   99: la t9,__syscall_error;                                                 \
   jr t9;                                                                     \
@@ -39,6 +40,7 @@ L(syse1):
 #else
 #define PSEUDO(name, syscall_name, args) \
   .set noreorder;                                                            \
+  .set nomips16;                                                             \
   .align 2;                                                                  \
   cfi_startproc;                                                             \
   99: j __syscall_error;                                                     \
index 49ae769..c55b95c 100644 (file)
@@ -26,6 +26,7 @@
 #ifdef __PIC__
 #define PSEUDO(name, syscall_name, args) \
   .align 2;                                                                  \
+  .set nomips16;                                                             \
   cfi_startproc;                                                             \
   99:;                                                                       \
   .set noat;                                                                 \
@@ -46,6 +47,7 @@ L(syse1):
 #define PSEUDO(name, syscall_name, args) \
   .set noreorder;                                                            \
   .align 2;                                                                  \
+  .set nomips16;                                                             \
   cfi_startproc;                                                             \
   99: j __syscall_error;                                                     \
   nop;                                                                        \
index 2670c68..445e6ff 100644 (file)
@@ -26,6 +26,7 @@
 #ifdef __PIC__
 #define PSEUDO(name, syscall_name, args) \
   .align 2;                                                                  \
+  .set nomips16;                                                             \
   cfi_startproc;                                                             \
   99:;                                                                       \
   .set noat;                                                                 \
@@ -46,6 +47,7 @@ L(syse1):
 #define PSEUDO(name, syscall_name, args) \
   .set noreorder;                                                            \
   .align 2;                                                                  \
+  .set nomips16;                                                             \
   cfi_startproc;                                                             \
   99: j __syscall_error;                                                     \
   nop;                                                                        \
index e778918..e27aada 100644 (file)
@@ -21,6 +21,8 @@
 #include <bits/errno.h>
 #include <sys/asm.h>
 
+       .set    nomips16
+
 #ifdef _LIBC_REENTRANT
 
 LOCALSZ= 3
index ef5c089..4d7667e 100644 (file)
@@ -44,6 +44,7 @@
 #define PSEUDO_NOERRNO(name, syscall_name, args)       \
   .align 2;                                            \
   ENTRY(name)                                          \
+  .set nomips16;                                       \
   .set noreorder;                                      \
   li v0, SYS_ify(syscall_name);                                \
   syscall
@@ -56,6 +57,7 @@
 #define PSEUDO_ERRVAL(name, syscall_name, args)        \
   .align 2;                                            \
   ENTRY(name)                                          \
+  .set nomips16;                                       \
   .set noreorder;                                      \
   li v0, SYS_ify(syscall_name);                                \
   syscall
index 9bd6d94..07c8a96 100644 (file)
@@ -30,19 +30,10 @@ weak_alias (__curbrk, ___brk_addr)
 int
 __brk (void *addr)
 {
+  INTERNAL_SYSCALL_DECL (err);
   void *newbrk;
 
-  {
-    register long int res __asm__ ("$2");
-
-    asm ("move\t$4,%2\n\t"
-        "li\t%0,%1\n\t"
-        "syscall"              /* Perform the system call.  */
-        : "=r" (res)
-        : "I" (SYS_ify (brk)), "r" (addr)
-        : "$4", "$7", __SYSCALL_CLOBBERS);
-    newbrk = (void *) res;
-  }
+  newbrk = (void *) INTERNAL_SYSCALL (brk, err, 1, addr);
   __curbrk = newbrk;
 
   if (newbrk < addr)
index ef80188..f6f2f05 100644 (file)
@@ -34,6 +34,7 @@
             void *parent_tidptr, void *tls, void *child_tidptr) */
 
        .text
+       .set            nomips16
 #if _MIPS_SIM == _ABIO32
 # define EXTRA_LOCALS 1
 #else
index 7af6825..268098c 100644 (file)
@@ -27,6 +27,7 @@
 /* int getcontext (ucontext_t *ucp) */
 
        .text
+       .set    nomips16
 LOCALSZ = 0
 MASK = 0x00000000
 #ifdef __PIC__
index d89db01..a8bbebb 100644 (file)
@@ -27,6 +27,7 @@
 /* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */
 
        .text
+       .set    nomips16
 LOCALSZ = 0
 ARGSZ = 0
 MASK = 0x00000000
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile
new file mode 100644 (file)
index 0000000..fa9fcb7
--- /dev/null
@@ -0,0 +1,13 @@
+ifeq ($(subdir),misc)
+sysdep_routines += mips16-syscall0 mips16-syscall1 mips16-syscall2
+sysdep_routines += mips16-syscall3 mips16-syscall4 mips16-syscall5
+sysdep_routines += mips16-syscall6 mips16-syscall7
+CFLAGS-mips16-syscall0.c += -fexceptions
+CFLAGS-mips16-syscall1.c += -fexceptions
+CFLAGS-mips16-syscall2.c += -fexceptions
+CFLAGS-mips16-syscall3.c += -fexceptions
+CFLAGS-mips16-syscall4.c += -fexceptions
+CFLAGS-mips16-syscall5.c += -fexceptions
+CFLAGS-mips16-syscall6.c += -fexceptions
+CFLAGS-mips16-syscall7.c += -fexceptions
+endif
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions
new file mode 100644 (file)
index 0000000..73bcfb5
--- /dev/null
@@ -0,0 +1,6 @@
+libc {
+  GLIBC_PRIVATE {
+    __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3;
+    __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7;
+  }
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h
new file mode 100644 (file)
index 0000000..8449836
--- /dev/null
@@ -0,0 +1,89 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef MIPS16_SYSCALL_H
+#define MIPS16_SYSCALL_H 1
+
+#define __nomips16 __attribute__ ((nomips16))
+
+union __mips16_syscall_return
+  {
+    long long val;
+    struct
+      {
+       long v0;
+       long v1;
+      }
+    reg;
+  };
+
+long long __nomips16 __mips16_syscall0 (long number);
+#define __mips16_syscall0(dummy, number)                               \
+       __mips16_syscall0 ((long) (number))
+
+long long __nomips16 __mips16_syscall1 (long a0,
+                                       long number);
+#define __mips16_syscall1(a0, number)                                  \
+       __mips16_syscall1 ((long) (a0),                                 \
+                          (long) (number))
+
+long long __nomips16 __mips16_syscall2 (long a0, long a1,
+                                       long number);
+#define __mips16_syscall2(a0, a1, number)                              \
+       __mips16_syscall2 ((long) (a0), (long) (a1),                    \
+                          (long) (number))
+
+long long __nomips16 __mips16_syscall3 (long a0, long a1, long a2,
+                                       long number);
+#define __mips16_syscall3(a0, a1, a2, number)                          \
+       __mips16_syscall3 ((long) (a0), (long) (a1), (long) (a2),       \
+                          (long) (number))
+
+long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3,
+                                       long number);
+#define __mips16_syscall4(a0, a1, a2, a3, number)                      \
+       __mips16_syscall4 ((long) (a0), (long) (a1), (long) (a2),       \
+                          (long) (a3),                                 \
+                          (long) (number))
+
+long long __nomips16 __mips16_syscall5 (long a0, long a1, long a2, long a3,
+                                       long a4,
+                                       long number);
+#define __mips16_syscall5(a0, a1, a2, a3, a4, number)                  \
+       __mips16_syscall5 ((long) (a0), (long) (a1), (long) (a2),       \
+                          (long) (a3), (long) (a4),                    \
+                          (long) (number))
+
+long long __nomips16 __mips16_syscall6 (long a0, long a1, long a2, long a3,
+                                       long a4, long a5,
+                                       long number);
+#define __mips16_syscall6(a0, a1, a2, a3, a4, a5, number)              \
+       __mips16_syscall6 ((long) (a0), (long) (a1), (long) (a2),       \
+                          (long) (a3), (long) (a4), (long) (a5),       \
+                          (long) (number))
+
+long long __nomips16 __mips16_syscall7 (long a0, long a1, long a2, long a3,
+                                       long a4, long a5, long a6,
+                                       long number);
+#define __mips16_syscall7(a0, a1, a2, a3, a4, a5, a6, number)          \
+       __mips16_syscall7 ((long) (a0), (long) (a1), (long) (a2),       \
+                          (long) (a3), (long) (a4), (long) (a5),       \
+                          (long) (a6),                                 \
+                          (long) (number))
+
+#endif
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c
new file mode 100644 (file)
index 0000000..0cdf94c
--- /dev/null
@@ -0,0 +1,30 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall0
+
+long long __nomips16
+__mips16_syscall0 (long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0);
+  return ret.val;
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c
new file mode 100644 (file)
index 0000000..5e60a59
--- /dev/null
@@ -0,0 +1,32 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall1
+
+long long __nomips16
+__mips16_syscall1 (long a0,
+                  long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1,
+                                       a0);
+  return ret.val;
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c
new file mode 100644 (file)
index 0000000..7750c51
--- /dev/null
@@ -0,0 +1,32 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall2
+
+long long __nomips16
+__mips16_syscall2 (long a0, long a1,
+                  long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2,
+                                       a0, a1);
+  return ret.val;
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c
new file mode 100644 (file)
index 0000000..7fc1c4e
--- /dev/null
@@ -0,0 +1,32 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall3
+
+long long __nomips16
+__mips16_syscall3 (long a0, long a1, long a2,
+                  long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3,
+                                       a0, a1, a2);
+  return ret.val;
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c
new file mode 100644 (file)
index 0000000..b8b4198
--- /dev/null
@@ -0,0 +1,32 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall4
+
+long long __nomips16
+__mips16_syscall4 (long a0, long a1, long a2, long a3,
+                  long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4,
+                                       a0, a1, a2, a3);
+  return ret.val;
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c
new file mode 100644 (file)
index 0000000..e1322d1
--- /dev/null
@@ -0,0 +1,33 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall5
+
+long long __nomips16
+__mips16_syscall5 (long a0, long a1, long a2, long a3,
+                  long a4,
+                  long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 5,
+                                       a0, a1, a2, a3, a4);
+  return ret.val;
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c
new file mode 100644 (file)
index 0000000..a9e5cd9
--- /dev/null
@@ -0,0 +1,33 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall6
+
+long long __nomips16
+__mips16_syscall6 (long a0, long a1, long a2, long a3,
+                  long a4, long a5,
+                  long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 6,
+                                       a0, a1, a2, a3, a4, a5);
+  return ret.val;
+}
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c
new file mode 100644 (file)
index 0000000..d87b5ba
--- /dev/null
@@ -0,0 +1,33 @@
+/* MIPS16 syscall wrappers.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <mips16-syscall.h>
+
+#undef __mips16_syscall7
+
+long long __nomips16
+__mips16_syscall7 (long a0, long a1, long a2, long a3,
+                  long a4, long a5, long a6,
+                  long number)
+{
+  union __mips16_syscall_return ret;
+  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 7,
+                                       a0, a1, a2, a3, a4, a5, a6);
+  return ret.val;
+}
index 2c2cd54..f01278e 100644 (file)
@@ -1401,6 +1401,8 @@ GLIBC_2.17
 GLIBC_2.18
  GLIBC_2.18 A
  __cxa_thread_atexit_impl F
+ __mips_fpu_getcw F
+ __mips_fpu_setcw F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
index c8bfe5d..0faf68c 100644 (file)
 #endif
 
 #undef INTERNAL_SYSCALL
-#define INTERNAL_SYSCALL(name, err, nr, args...)                       \
+#undef INTERNAL_SYSCALL_NCS
+
+#ifdef __mips16
+/* There's no MIPS16 syscall instruction, so we go through out-of-line
+   standard MIPS wrappers.  These do use inline snippets below though,
+   through INTERNAL_SYSCALL_MIPS16.  Spilling the syscall number to
+   memory gives the best code in that case, avoiding the need to save
+   and restore a static register.  */
+
+# include <mips16-syscall.h>
+
+# define INTERNAL_SYSCALL(name, err, nr, args...)                      \
+       INTERNAL_SYSCALL_NCS (SYS_ify (name), err, nr, args)
+
+# define INTERNAL_SYSCALL_NCS(number, err, nr, args...)                        \
+({                                                                     \
+       union __mips16_syscall_return ret;                              \
+       ret.val = __mips16_syscall##nr (args, number);                  \
+       err = ret.reg.v1;                                               \
+       ret.reg.v0;                                                     \
+})
+
+# define INTERNAL_SYSCALL_MIPS16(number, err, nr, args...)             \
+       internal_syscall##nr ("lw\t%0, %2\n\t",                         \
+                             "R" (number),                             \
+                             0, err, args)
+
+#else /* !__mips16 */
+# define INTERNAL_SYSCALL(name, err, nr, args...)                      \
        internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t",        \
                              "IK" (SYS_ify (name)),                    \
                              0, err, args)
 
-#undef INTERNAL_SYSCALL_NCS
-#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)                 \
+# define INTERNAL_SYSCALL_NCS(number, err, nr, args...)                        \
        internal_syscall##nr (MOVE32 "\t%0, %2\n\t",                    \
                              "r" (__s0),                               \
                              number, err, args)
 
+#endif /* !__mips16 */
+
 #define internal_syscall0(v0_init, input, number, err, dummy...)       \
 ({                                                                     \
        long _sys_result;                                               \
index 1e0bfed..3b0eccc 100644 (file)
@@ -39,6 +39,7 @@
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)                                    \
       .align 2;                                                                      \
+      .set nomips16;                                                         \
   L(pseudo_start):                                                           \
       cfi_startproc;                                                         \
   99: PSEUDO_ERRJMP                                                          \
index 6ed355c..2d5aee0 100644 (file)
@@ -27,6 +27,7 @@
 /* int setcontext (const ucontext_t *ucp) */
 
        .text
+       .set    nomips16
 LOCALSZ = 0
 ARGSZ = 0
 MASK = 0x00000000
index ddd3b28..ec271b0 100644 (file)
@@ -27,6 +27,7 @@
 /* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
 
        .text
+       .set    nomips16
 LOCALSZ = 0
 ARGSZ = 0
 MASK = 0x00000000
index d627923..ae76a91 100644 (file)
@@ -34,6 +34,7 @@
 /* int vfork() */
 
        .text
+       .set            nomips16
 LOCALSZ= 1
 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
 GPOFF= FRAMESZ-(1*SZREG)