* [PATCH 0/2] MIPS16: MIPS16 support @ 2013-01-23 4:41 Maciej W. Rozycki 2013-01-23 4:41 ` [PATCH 1/2] MIPS16: Allocate GLIBC_2.18 Maciej W. Rozycki 2013-01-23 4:42 ` [PATCH 2/2] MIPS16: MIPS16 support proper Maciej W. Rozycki 0 siblings, 2 replies; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-23 4:41 UTC (permalink / raw) To: libc-alpha, libc-ports; +Cc: Chung-Lin Tang Hi, This patch mini-series adds MIPS16 support to glibc. It's been split into two parts per patch submission guidelines. The first part applies to glibc proper and the second one to the ports add-on. Full descriptions are included with the patches themselves. Maciej ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 1/2] MIPS16: Allocate GLIBC_2.18 2013-01-23 4:41 [PATCH 0/2] MIPS16: MIPS16 support Maciej W. Rozycki @ 2013-01-23 4:41 ` Maciej W. Rozycki 2013-01-23 4:42 ` [PATCH 2/2] MIPS16: MIPS16 support proper Maciej W. Rozycki 1 sibling, 0 replies; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-23 4:41 UTC (permalink / raw) To: libc-alpha, libc-ports; +Cc: Chung-Lin Tang Hi, This change adds GLIBC_2.18 to the list of defined versions. It is needed for newly-defined functions required for MIPS16 support. Please apply. 2013-01-23 Maciej W. Rozycki <macro@codesourcery.com> * Versions.def (libc): Add GLIBC_2.18. Maciej Index: glibc-fsf-trunk-quilt/Versions.def =================================================================== --- glibc-fsf-trunk-quilt.orig/Versions.def 2012-11-21 23:51:43.000000000 +0000 +++ glibc-fsf-trunk-quilt/Versions.def 2013-01-20 22:12:01.457025518 +0000 @@ -34,6 +34,7 @@ libc { GLIBC_2.15 GLIBC_2.16 GLIBC_2.17 + GLIBC_2.18 HURD_CTHREADS_0.3 %ifdef EXPORT_UNWIND_FIND_FDE GCC_3.0 ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-23 4:41 [PATCH 0/2] MIPS16: MIPS16 support Maciej W. Rozycki 2013-01-23 4:41 ` [PATCH 1/2] MIPS16: Allocate GLIBC_2.18 Maciej W. Rozycki @ 2013-01-23 4:42 ` Maciej W. Rozycki 2013-01-23 17:22 ` Joseph S. Myers 2013-01-24 18:08 ` [PATCH 2/2] MIPS16: MIPS16 support proper Ellcey, Steve 1 sibling, 2 replies; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-23 4:42 UTC (permalink / raw) To: libc-alpha, libc-ports; +Cc: Chung-Lin Tang Hi, This change adds support for building the MIPS port of glibc as MIPS16 code, for the o32 ABI. The MIPS16 instruction set has several limitations that required adjustments in the library. The benefit is a smaller footprint of pieces that can actually be compiled to MIPS16 code. The execution mode can be freely switched between the standard MIPS and the MIPS16 mode by flipping the ISA bit, that is exposed to the programmer as bit #0 of the PC and supported by the relevant jump instructions. Standard MIPS and MIPS16 code can be mixed in a single program both at the static-link and at the dynamic-load time. Please note that owing to that property MIPS16 dynamic executables are supported by glibc already, barring the issue of _FPU_GETCW and _FPU_SETCW described below, simply by linking and loading such programs with standard-MIPS glibc binaries; it's just building the library itself that is not. Here is how individual issues have been addressed by the change proposed: 1. There are no floating-point MIPS16 instructions nor ones to access floating-point registers. That required all the affected functions to be marked with the nomips16 attribute. This applies to functions like setjmp/longjmp, setcontext/getcontext/etc. that requires access tothe floating-point register stack. Further, all the math functions are compiled with the -mno-mips16 compiler option, so that they do not have to be individually marked. The overhead to factor out individual low-level floating-point operations, such as addition or multiplication, as standard MIPS code and call the respective functions as appropriate would be prohibitive and no code size gain would result. Finally, the _FPU_GETCW and _FPU_SETCW user-accessible macros have been rewritten to refer to new helpers so that they can be called in the MIPS16 mode. This code is surrounded by an __mips16 macro check that is only going to work for code built with -mips16 as the preprocessor does not know the actual mode selected by the compiler. A different solution, such as a __builtin_mips16 compiler function, would be required for the macros to work even for functions marked with the mips16 attribute or compiled to MIPS16 code due to the -mflip-mips16 compiler option. The solution chosen is I believe the best that we can get and works for the common case. I have decided to export prototypes for the new helpers, but I have no strong preference to do that -- we may well keep them as an internal implementation detail instead, i.e.: #define _FPU_GETCW(cw) \ do \ { \ extern fpu_control_t __fpu_getcw (void) __THROW; \ (cw) = __fpu_getcw (); \ } \ while (0) -- and likewise for _FPU_SETCW. Suggestions? 2. The MIPS16 BREAK instruction has a limited range of its immediate code compared to its standard MIPS counterpart. Therefore 63, the maximum value supported, has been chosen for ABORT_INSTRUCTION. 3. There are no MIPS16 atomic LL or SC instructions. GCC has, since 4.1, supported suitable built-ins and this change relies on them. In practice the built-ins produce small snippets of out-of-line standard MIPS code called from where requested. 4. Several handcoded assembly sequences have been rewritten as corresponding MIPS16 code. Where there would be no gain from switching to the MIPS16 mode the existing pieces have been marked with the ".set nomips16" GAS directive so that they are built as standard MIPS code. 5. New MIPS16 constructor and destructor prologue and epilogue assembly code has been added. This code is lumped together with all the individual constructor and destructor call fragments. This works as long as all the code involved has been built for the same ISA, either the standard MIPS or the MIPS16 one. This will break if individual pieces have been built for different ISAs. To address this properly the MIPS port would have to switch to using constructor and destructor arrays rather than lumped code (i.e. DT_INIT_ARRAY and DT_FINI_ARRAY rather than DT_INIT and DT_FINI, respectively). In this case the ISA bit of the individual array entries would select the execution mode as appropriate for each call. To the best of my knowledge the GNU toolchain has supported these arrays since forever, so this is probably the right moment to switch. NB mixed standard MIPS/microMIPS binaries suffer from the same problem. For the time being the change proposed here is the best we can do to support the common case I believe. 6. There is no MIPS16 RDHWR instruction. To implement the READ_THREAD_POINTER macro we use the __builtin_thread_pointer GCC builtin instead. In practice if called from MIPS16 code, this expands to a call to __mips16_rdhwr that is a small piece of standard MIPS code that executes RDHWR with the right arguments. 7. There is no MIPS16 SYSCALL instruction. Internal inline syscall wrappers have been rewritten to small snippets of out-of-line standard MIPS code where called from MIPS16 code. The snippets have been designed such as to avoid unnecessary argument shuffling -- hence the syscall number is passed last. Consequently __brk is rewritten in terms of INTERNAL_SYSCALL too. The change was regression-tested successfully for the following configurations (compiler flag/multilib options), for both endiannesses each (the -EB and -EL compiler option, respectively): * standard MIPS ISA, o32 (-mabi=32), * standard MIPS ISA, n64 (-mabi=64), * standard MIPS ISA, n32 (-mabi=n32), * standard MIPS ISA, o32, soft-float (-mabi=32 -msoft-float), * standard MIPS ISA, n64, soft-float (-mabi=64 -msoft-float), * standard MIPS ISA, n32, soft-float (-mabi=n32 -msoft-float), * microMIPS ISA, o32 (-mmicromips -mabi=32), * microMIPS ISA, o32, soft-float (-mmicromips -mabi=32 -msoft-float), with the MIPS32r2 or MIPS64r2 ISA level selected as applicable. Likewise new functionality has been tested for: * MIPS16 ISA, o32 (-mips16 -mabi=32), * MIPS16 ISA, o32, soft-float (-mips16 -mabi=32 -msoft-float), producing no failures other to ones already present for the standard MIPS and microMIPS ISAs. Questions and comments are welcome; otherwise please apply. 2013-01-23 Chung-Lin Tang <cltang@codesourcery.com> Maciej W. Rozycki <macro@codesourcery.com> Maxim Kuvyrkov <maxim@codesourcery.com> ports/ * sysdeps/mips/abort-instr.h (ABORT_INSTRUCTION) [__mips16]: New macro. * sysdeps/mips/dl-machine.h (elf_machine_load_address): Add MIPS16 version. (RTLD_START): Likewise. * sysdeps/mips/fpu_control.h (__fpu_getcw) [__mips16]: New prototype. (__fpu_setcw) [__mips16]: 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. * sysdeps/mips/bits/atomic.h (atomic_compare_and_exchange_val_acq) [__mips16]: Likewise. (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. (TLS_GD, TLS_LD, TLS_IE, TLS_LE) [__mips16]: Likewise. * sysdeps/mips/sys/tas.h (_test_and_set): Add ".set nomips16". * sysdeps/unix/mips/sysdep.h (PSEUDO_NOERRNO): Likewise. (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/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): Add MIPS16 version. * sysdeps/unix/mips/sysdep.S: Add ".set nomips16". * 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 nomips16. (__longjmp): New alias. * sysdeps/mips/dl-trampoline.c (_dl_runtime_resolve): Add MIPS16 version. (_dl_runtime_pltresolve): Likewise. * sysdeps/mips/setjmp_aux.c (__sigsetjmp_aux): Add nomips16 attribute. * sysdeps/mips/fpu/e_sqrt.c (__ieee754_sqrt): Add nomips16 attribute. * sysdeps/mips/fpu/e_sqrtf.c (__ieee754_sqrtf): Likewise. * sysdeps/unix/sysv/linux/mips/brk.c (__brk): Replace inline asm with INTERNAL_SYSCALL. * sysdeps/mips/mips32/fpu/Implies: New file. * sysdeps/mips/mips32/fpu/fpu_control.c: New file. * sysdeps/mips/mips32/mips16/crti.S: New file. * sysdeps/mips/mips32/mips16/crtn.S: 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/mips/mips32/mips16/Makefile: New file. * sysdeps/mips/mips32/mips16/fpu/Makefile: New file. * sysdeps/mips/mips32/mips16/fpu/Versions: New file. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h: 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/unix/sysv/linux/mips/mips32/mips16/Makefile: New file. * sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions: New file. * sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist (GLIBC_2.18): New. Add __fpu_getcw and __fpu_setcw. * sysdeps/mips/preconfigure: Handle o32 MIPS16 compilation. Maciej glibc-mips16.diff Index: ports/sysdeps/mips/__longjmp.c =================================================================== --- ports/sysdeps/mips/__longjmp.c 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/__longjmp.c 2013-01-20 19:40:57.097753716 +0000 @@ -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: ports/sysdeps/mips/abort-instr.h =================================================================== --- ports/sysdeps/mips/abort-instr.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/abort-instr.h 2013-01-20 19:40:57.097753716 +0000 @@ -1,2 +1,6 @@ /* An instruction which should crash any program is a breakpoint. */ +#ifdef __mips16 +#define ABORT_INSTRUCTION asm ("break 63") +#else #define ABORT_INSTRUCTION asm ("break 255") +#endif Index: ports/sysdeps/mips/bits/atomic.h =================================================================== --- ports/sysdeps/mips/bits/atomic.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/bits/atomic.h 2013-01-20 19:40:57.117793511 +0000 @@ -37,6 +37,40 @@ typedef uintptr_t uatomicptr_t; typedef intmax_t atomic_max_t; typedef uintmax_t uatomic_max_t; +/* MIPS16 uses GCC __sync_* builtins to implement the required atomic + operations, to abstract out the unsupported assembly instructions. + ??? Maybe eventually use them for 32-bit MIPS too? */ +#ifdef __mips16 +# if __GNUC_PREREQ (4, 1) + +# 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)) + +# define atomic_full_barrier() __sync_synchronize () + +# else +# error "MIPS16 requires GCC with __sync_* builtins" +# endif +#else /* !__mips16 */ + #if _MIPS_SIM == _ABIO32 #define MIPS_PUSH_MIPS2 ".set mips2\n\t" #else @@ -454,4 +488,5 @@ typedef uintmax_t uatomic_max_t; MIPS_SYNC_STR "\n\t" \ ".set pop" : : : "memory") +#endif /* !__mips16 */ #endif /* bits/atomic.h */ Index: ports/sysdeps/mips/bsd-_setjmp.S =================================================================== --- ports/sysdeps/mips/bsd-_setjmp.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/bsd-_setjmp.S 2013-01-20 19:40:57.137753861 +0000 @@ -26,6 +26,7 @@ .option pic2 #endif ENTRY (_setjmp) + .set nomips16 #ifdef __PIC__ .set noreorder .cpload t9 Index: ports/sysdeps/mips/bsd-setjmp.S =================================================================== --- ports/sysdeps/mips/bsd-setjmp.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/bsd-setjmp.S 2013-01-20 19:40:57.156841347 +0000 @@ -26,6 +26,7 @@ .option pic2 #endif ENTRY (setjmp) + .set nomips16 .set noreorder #ifdef __PIC__ .cpload t9 Index: ports/sysdeps/mips/dl-machine.h =================================================================== --- ports/sysdeps/mips/dl-machine.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/dl-machine.h 2013-01-20 19:40:57.176855918 +0000 @@ -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,6 +224,7 @@ do { \ 2) That under Unix the entry is named __start and not just plain _start. */ +#ifndef __mips16 #define RTLD_START asm (\ ".text\n\ " _RTLD_PROLOGUE(ENTRY_POINT) "\ @@ -283,6 +298,91 @@ do { \ ".previous"\ ); +#else + +/* 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 + /* Names of the architecture-specific auditing callback functions. */ # if _MIPS_SIM == _ABIO32 # define ARCH_LA_PLTENTER mips_o32_gnu_pltenter Index: ports/sysdeps/mips/dl-trampoline.c =================================================================== --- ports/sysdeps/mips/dl-trampoline.c 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/dl-trampoline.c 2013-01-20 19:40:57.196878136 +0000 @@ -292,8 +292,11 @@ __dl_runtime_resolve (ElfW(Word) sym_ind #endif +#ifndef __mips16 + asm ("\n\ .text\n\ + .set nomips16\n\ .align 2\n\ .globl _dl_runtime_resolve\n\ .type _dl_runtime_resolve,@function\n\ @@ -350,6 +353,7 @@ _dl_runtime_resolve:\n\ asm ("\n\ .text\n\ + .set nomips16\n\ .align 2\n\ .globl _dl_runtime_pltresolve\n\ .type _dl_runtime_pltresolve,@function\n\ @@ -381,3 +385,131 @@ _dl_runtime_pltresolve:\n\ .previous\n\ "); +#elif _MIPS_SIM == _ABIO32 + +/* MIPS16 version, O32 only. */ + +asm ("\n\ + .text\n\ + .set mips16\n\ + .align 2\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\ + .set mips16\n\ + .align 2\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 +#error "MIPS16 support for N32/N64 not implemented" +#endif /* __mips16 */ Index: ports/sysdeps/mips/fpu/e_sqrt.c =================================================================== --- ports/sysdeps/mips/fpu/e_sqrt.c 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/fpu/e_sqrt.c 2013-01-20 19:40:57.216896761 +0000 @@ -22,7 +22,7 @@ #if (_MIPS_ISA >= _MIPS_ISA_MIPS2) -double +double __attribute__ ((nomips16)) __ieee754_sqrt (double x) { double z; Index: ports/sysdeps/mips/fpu/e_sqrtf.c =================================================================== --- ports/sysdeps/mips/fpu/e_sqrtf.c 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/fpu/e_sqrtf.c 2013-01-20 19:40:57.236875700 +0000 @@ -22,7 +22,7 @@ #if (_MIPS_ISA >= _MIPS_ISA_MIPS2) -float +float __attribute__ ((nomips16)) __ieee754_sqrtf (float x) { float z; Index: ports/sysdeps/mips/fpu_control.h =================================================================== --- ports/sysdeps/mips/fpu_control.h 2013-01-16 00:04:04.000000000 +0000 +++ ports/sysdeps/mips/fpu_control.h 2013-01-23 01:25:04.047168836 +0000 @@ -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. */ +extern fpu_control_t __fpu_getcw (void) __THROW; +extern void __fpu_setcw (fpu_control_t) __THROW; +#ifdef __mips16 +#define _FPU_GETCW(cw) do { (cw) = __fpu_getcw (); } while (0) +#define _FPU_SETCW(cw) __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: ports/sysdeps/mips/machine-gmon.h =================================================================== --- ports/sysdeps/mips/machine-gmon.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/machine-gmon.h 2013-01-20 19:40:57.256890706 +0000 @@ -35,6 +35,8 @@ static void __attribute_used__ __mcount #endif #define MCOUNT asm(\ + ".set push;\n\t" \ + ".set nomips16;\n\t" \ ".globl _mcount;\n\t" \ ".align 2;\n\t" \ ".type _mcount,@function;\n\t" \ @@ -67,9 +69,8 @@ static void __attribute_used__ __mcount "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 @@ -92,6 +93,8 @@ static void __attribute_used__ __mcount #endif #define MCOUNT asm(\ + ".set push;\n\t" \ + ".set nomips16;\n\t" \ ".globl _mcount;\n\t" \ ".align 3;\n\t" \ ".type _mcount,@function;\n\t" \ @@ -132,8 +135,7 @@ static void __attribute_used__ __mcount 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: ports/sysdeps/mips/memset.S =================================================================== --- ports/sysdeps/mips/memset.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/memset.S 2013-01-20 19:40:57.276543548 +0000 @@ -28,6 +28,7 @@ #endif ENTRY (memset) + .set nomips16 .set noreorder slti t1, a2, 8 # Less than 8? Index: ports/sysdeps/mips/mips32/fpu/fpu_control.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/fpu/fpu_control.c 2013-01-20 23:16:11.026712794 +0000 @@ -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 +__fpu_getcw (void) +{ + fpu_control_t cw; + + _FPU_GETCW(cw); + return cw; +} + +void +__fpu_setcw (fpu_control_t cw) +{ + _FPU_SETCW(cw); +} Index: ports/sysdeps/mips/mips32/mips16/add_n.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/add_n.c 2013-01-20 19:40:57.296892628 +0000 @@ -0,0 +1 @@ +#include <stdlib/add_n.c> Index: ports/sysdeps/mips/mips32/mips16/addmul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/addmul_1.c 2013-01-20 19:40:57.296892628 +0000 @@ -0,0 +1 @@ +#include <stdlib/addmul_1.c> Index: ports/sysdeps/mips/mips32/mips16/crti.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/crti.S 2013-01-20 20:05:43.816556531 +0000 @@ -0,0 +1,111 @@ +/* Special .init and .fini section support for MIPS16 (o32). + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* crti.S puts a function prologue at the beginning of the .init and + .fini sections and defines global symbols for those addresses, so + they can be called as functions. The symbols _init and _fini are + magic and cause the linker to emit DT_INIT and DT_FINI. */ + +#include <libc-symbols.h> + +#ifndef PREINIT_FUNCTION +# define PREINIT_FUNCTION __gmon_start__ +#endif + +#ifndef PREINIT_FUNCTION_WEAK +# define PREINIT_FUNCTION_WEAK 1 +#endif + +#if PREINIT_FUNCTION_WEAK + weak_extern (PREINIT_FUNCTION) +#else + .hidden PREINIT_FUNCTION +#endif + + .section .init, "ax", @progbits + .p2align 2 + .globl _init + .type _init, @function +_init: + li $2, %hi(_gp_disp) + addiu $3, $pc, %lo(_gp_disp) + sll $2, 16 + addu $2, $3 +#if _MIPS_ISA >= _MIPS_ISA_MIPS32 + save 32, $31 +#else + addiu $sp, -32 + sw $31, 28($sp) +#endif + move $28, $2 + sw $2, 16($sp) +#if PREINIT_FUNCTION_WEAK + lw $3, %got(PREINIT_FUNCTION)($2) + beqz $3, .Lno_weak_fn + lw $2, %call16(PREINIT_FUNCTION)($2) + .set noreorder + .set nomacro + jalr $2 + move $25, $2 + .set macro + .set reorder +.Lno_weak_fn: +#else + lw $2, %got(PREINIT_FUNCTION)($2) + .set noreorder + .set nomacro + jalr $2 + move $25, $2 + .set macro + .set reorder +#endif + + .section .fini, "ax", @progbits + .p2align 2 + .globl _fini + .type _fini, @function +_fini: + li $2, %hi(_gp_disp) + addiu $3, $pc, %lo(_gp_disp) + sll $2, 16 + addu $2, $3 +#if _MIPS_ISA >= _MIPS_ISA_MIPS32 + save 32, $31 +#else + addiu $sp, -32 + sw $31, 28($sp) +#endif + move $28, $2 + sw $2, 16($sp) Index: ports/sysdeps/mips/mips32/mips16/crtn.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/crtn.S 2013-01-20 20:00:38.716871098 +0000 @@ -0,0 +1,57 @@ +/* Special .init and .fini section support for MIPS16 (o32). + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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/>. */ + +/* crtn.S puts function epilogues in the .init and .fini sections + corresponding to the prologues in crti.S. */ + + .section .init, "ax", @progbits +#if _MIPS_ISA >= _MIPS_ISA_MIPS32 + restore 32, $31 + j $31 +#else + lw $7, 28($sp) + addiu $sp, 32 + j $7 +#endif + + .section .fini, "ax", @progbits +#if _MIPS_ISA >= _MIPS_ISA_MIPS32 + restore 32, $31 + j $31 +#else + lw $7, 28($sp) + addiu $sp, 32 + j $7 +#endif Index: ports/sysdeps/mips/mips32/mips16/fpu/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/fpu/Makefile 2013-01-20 19:40:57.296892628 +0000 @@ -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 Index: ports/sysdeps/mips/mips32/mips16/fpu/Versions =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/fpu/Versions 2013-01-20 22:11:01.057025227 +0000 @@ -0,0 +1,5 @@ +libc { + GLIBC_2.18 { + __fpu_getcw; __fpu_getcw; + } +} Index: ports/sysdeps/mips/mips32/mips16/lshift.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/lshift.c 2013-01-20 19:40:57.296892628 +0000 @@ -0,0 +1 @@ +#include <stdlib/lshift.c> Index: ports/sysdeps/mips/mips32/mips16/mul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/mul_1.c 2013-01-20 19:40:57.296892628 +0000 @@ -0,0 +1 @@ +#include <stdlib/mul_1.c> Index: ports/sysdeps/mips/mips32/mips16/rshift.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/rshift.c 2013-01-20 19:40:57.296892628 +0000 @@ -0,0 +1 @@ +#include <stdlib/rshift.c> Index: ports/sysdeps/mips/mips32/mips16/sub_n.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/sub_n.c 2013-01-20 19:40:57.296892628 +0000 @@ -0,0 +1 @@ +#include <stdlib/sub_n.c> Index: ports/sysdeps/mips/mips32/mips16/submul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/submul_1.c 2013-01-20 19:40:57.296892628 +0000 @@ -0,0 +1 @@ +#include <stdlib/submul_1.c> Index: ports/sysdeps/mips/nptl/tls.h =================================================================== --- ports/sysdeps/mips/nptl/tls.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/nptl/tls.h 2013-01-20 19:40:57.296892628 +0000 @@ -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: ports/sysdeps/mips/preconfigure =================================================================== --- ports/sysdeps/mips/preconfigure 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/preconfigure 2013-01-20 19:40:57.306553118 +0000 @@ -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: ports/sysdeps/mips/setjmp.S =================================================================== --- ports/sysdeps/mips/setjmp.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/setjmp.S 2013-01-20 19:40:57.326814470 +0000 @@ -24,6 +24,7 @@ .option pic2 #endif ENTRY (__sigsetjmp) + .set nomips16 #ifdef __PIC__ .set noreorder .cpload t9 Index: ports/sysdeps/mips/setjmp_aux.c =================================================================== --- ports/sysdeps/mips/setjmp_aux.c 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/setjmp_aux.c 2013-01-20 19:40:57.346890569 +0000 @@ -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: ports/sysdeps/mips/start.S =================================================================== --- ports/sysdeps/mips/start.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/start.S 2013-01-20 19:40:57.366883392 +0000 @@ -74,6 +74,7 @@ .text .globl ENTRY_POINT .type ENTRY_POINT,@function +#ifndef __mips16 ENTRY_POINT: #ifdef __PIC__ SETUP_GPX($0) @@ -108,6 +109,68 @@ jal __libc_start_main hlt: b hlt /* Crash if somehow it does return. */ +#elif _MIPS_SIM == _ABIO32 + /* MIPS16 entry point. */ +ENTRY_POINT: + .set mips16 +#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 +#error "MIPS16 support for N32/N64 not implemented" +#endif + /* Define a symbol for the first piece of initialized data. */ .data .globl __data_start Index: ports/sysdeps/mips/sys/tas.h =================================================================== --- ports/sysdeps/mips/sys/tas.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/sys/tas.h 2013-01-20 19:40:57.376549265 +0000 @@ -24,7 +24,7 @@ __BEGIN_DECLS -extern int _test_and_set (int *__p, int __v) __THROW; +extern int __attribute__((nomips16)) test_and_set (int *__p, int __v) __THROW; #ifdef __USE_EXTERN_INLINES @@ -32,7 +32,7 @@ extern int _test_and_set (int *__p, int # 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: ports/sysdeps/mips/tls-macros.h =================================================================== --- ports/sysdeps/mips/tls-macros.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/mips/tls-macros.h 2013-01-20 19:40:57.406635785 +0000 @@ -12,16 +12,33 @@ (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 *); \ @@ -62,3 +79,46 @@ ADDU " %0,%0,$3" \ : "+r" (__result) : : "$3"); \ __result; }) + +#else + +/* 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 Index: ports/sysdeps/unix/mips/mips32/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/mips32/sysdep.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/mips/mips32/sysdep.h 2013-01-20 19:40:57.406635785 +0000 @@ -23,6 +23,7 @@ backwards into the previous fn. */ #ifdef __PIC__ #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .align 2; \ 99: la t9,__syscall_error; \ jr t9; \ @@ -36,6 +37,7 @@ L(syse1): #else #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .set noreorder; \ .align 2; \ 99: j __syscall_error; \ Index: ports/sysdeps/unix/mips/mips64/n32/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/mips64/n32/sysdep.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/mips/mips64/n32/sysdep.h 2013-01-20 19:40:57.426877081 +0000 @@ -25,6 +25,7 @@ backwards into the previous fn. */ #ifdef __PIC__ #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .align 2; \ 99:; \ .set noat; \ @@ -40,6 +41,7 @@ L(syse1): #else #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .set noreorder; \ .align 2; \ 99: j __syscall_error; \ Index: ports/sysdeps/unix/mips/mips64/n64/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/mips64/n64/sysdep.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/mips/mips64/n64/sysdep.h 2013-01-20 19:40:57.446887899 +0000 @@ -25,6 +25,7 @@ backwards into the previous fn. */ #ifdef __PIC__ #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .align 2; \ 99:; \ .set noat; \ @@ -40,6 +41,7 @@ L(syse1): #else #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .set noreorder; \ .align 2; \ 99: j __syscall_error; \ Index: ports/sysdeps/unix/mips/sysdep.S =================================================================== --- ports/sysdeps/unix/mips/sysdep.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/mips/sysdep.S 2013-01-20 19:40:57.466877139 +0000 @@ -21,6 +21,9 @@ #include <bits/errno.h> #include <sys/asm.h> + /* Not MIPS16 code. */ + .set nomips16 + #ifdef _LIBC_REENTRANT LOCALSZ= 3 Index: ports/sysdeps/unix/mips/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/sysdep.h 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/mips/sysdep.h 2013-01-20 19:40:57.486831430 +0000 @@ -42,6 +42,7 @@ #define PSEUDO_NOERRNO(name, syscall_name, args) \ .align 2; \ ENTRY(name) \ + .set nomips16; \ .set noreorder; \ li v0, SYS_ify(syscall_name); \ syscall @@ -54,6 +55,7 @@ #define PSEUDO_ERRVAL(name, syscall_name, args) \ .align 2; \ ENTRY(name) \ + .set nomips16; \ .set noreorder; \ li v0, SYS_ify(syscall_name); \ syscall Index: ports/sysdeps/unix/sysv/linux/mips/brk.c =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/brk.c 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/brk.c 2013-01-20 19:40:57.506879197 +0000 @@ -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: ports/sysdeps/unix/sysv/linux/mips/clone.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/clone.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/clone.S 2013-01-20 19:40:57.526854098 +0000 @@ -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: ports/sysdeps/unix/sysv/linux/mips/getcontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/getcontext.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/getcontext.S 2013-01-20 19:40:57.546859991 +0000 @@ -27,6 +27,7 @@ /* int getcontext (ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 MASK = 0x00000000 #ifdef __PIC__ Index: ports/sysdeps/unix/sysv/linux/mips/makecontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/makecontext.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/makecontext.S 2013-01-20 19:40:57.546859991 +0000 @@ -27,6 +27,7 @@ /* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2013-01-20 19:40:57.546859991 +0000 @@ -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 Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2013-01-20 19:40:57.546859991 +0000 @@ -0,0 +1,6 @@ +libc { + GLIBC_PRIVATE { + __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3; + __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7; + } +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2013-01-20 19:40:57.546859991 +0000 @@ -0,0 +1,91 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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 Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2013-01-20 19:40:57.546859991 +0000 @@ -0,0 +1,32 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2013-01-20 19:40:57.546859991 +0000 @@ -0,0 +1,34 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2013-01-20 19:40:57.546859991 +0000 @@ -0,0 +1,35 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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; +} +//libc_hidden_def (__mips16_syscall2) Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2013-01-20 19:40:57.546859991 +0000 @@ -0,0 +1,34 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2013-01-20 19:40:57.546859991 +0000 @@ -0,0 +1,34 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c 2013-01-20 19:40:57.556541697 +0000 @@ -0,0 +1,35 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c 2013-01-20 19:40:57.556541697 +0000 @@ -0,0 +1,35 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c 2013-01-20 19:40:57.556541697 +0000 @@ -0,0 +1,35 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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: ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist 2012-11-21 23:51:44.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist 2013-01-20 23:50:55.947782276 +0000 @@ -2250,3 +2250,7 @@ GLIBC_2.17 clock_nanosleep F clock_settime F secure_getenv F +GLIBC_2.18 + GLIBC_2.18 A + __fpu_getcw F + __fpu_setcw F Index: ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-01-19 19:25:30.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-01-20 19:40:57.556541697 +0000 @@ -84,17 +84,47 @@ #endif #undef INTERNAL_SYSCALL +#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...) \ 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: ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h 2013-01-17 01:18:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h 2013-01-20 19:40:57.576858974 +0000 @@ -45,6 +45,7 @@ # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .align 2; \ + .set nomips16; \ L(pseudo_start): \ cfi_startproc; \ 99: PSEUDO_ERRJMP \ Index: ports/sysdeps/unix/sysv/linux/mips/setcontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/setcontext.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/setcontext.S 2013-01-20 19:40:57.596908144 +0000 @@ -27,6 +27,7 @@ /* int setcontext (const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: ports/sysdeps/unix/sysv/linux/mips/swapcontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/swapcontext.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/swapcontext.S 2013-01-20 19:40:57.616906450 +0000 @@ -27,6 +27,7 @@ /* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: ports/sysdeps/unix/sysv/linux/mips/vfork.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/vfork.S 2013-01-17 00:55:17.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/vfork.S 2013-01-20 19:40:57.646908672 +0000 @@ -34,6 +34,7 @@ /* int vfork() */ .text + .set nomips16 LOCALSZ= 1 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK GPOFF= FRAMESZ-(1*SZREG) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-23 4:42 ` [PATCH 2/2] MIPS16: MIPS16 support proper Maciej W. Rozycki @ 2013-01-23 17:22 ` Joseph S. Myers 2013-01-24 10:10 ` Chung-Lin Tang 2013-02-20 16:19 ` [PATCH v2] MIPS: MIPS16 support Maciej W. Rozycki 2013-01-24 18:08 ` [PATCH 2/2] MIPS16: MIPS16 support proper Ellcey, Steve 1 sibling, 2 replies; 26+ messages in thread From: Joseph S. Myers @ 2013-01-23 17:22 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: libc-ports, Chung-Lin Tang On Wed, 23 Jan 2013, Maciej W. Rozycki wrote: > Index: ports/sysdeps/mips/__longjmp.c > =================================================================== > --- ports/sysdeps/mips/__longjmp.c 2013-01-17 00:55:17.000000000 +0000 > +++ ports/sysdeps/mips/__longjmp.c 2013-01-20 19:40:57.097753716 +0000 > @@ -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); Why is the renaming / alias needed? > Index: ports/sysdeps/mips/abort-instr.h > =================================================================== > --- ports/sysdeps/mips/abort-instr.h 2013-01-17 00:55:17.000000000 +0000 > +++ ports/sysdeps/mips/abort-instr.h 2013-01-20 19:40:57.097753716 +0000 > @@ -1,2 +1,6 @@ > /* An instruction which should crash any program is a breakpoint. */ > +#ifdef __mips16 > +#define ABORT_INSTRUCTION asm ("break 63") > +#else > #define ABORT_INSTRUCTION asm ("break 255") > +#endif Indentation inside #if, "# define". > +/* MIPS16 uses GCC __sync_* builtins to implement the required atomic > + operations, to abstract out the unsupported assembly instructions. > + ??? Maybe eventually use them for 32-bit MIPS too? */ > +#ifdef __mips16 > +# if __GNUC_PREREQ (4, 1) glibc requires at least 4.3 to build, so no such condition is needed in an internal header. However, __sync_* are obsolete; the __atomic_* built-in functions (supported in 4.7 and later, well-optimized for MIPS in 4.8 and later) are preferred because they allow more precise specification of the barrier semantics in particular cases. So if building with 4.8 or later, you should use the existing definitions in terms of __atomic_* that are already used in those circumstances for MIPS - and probably use them for the (4.7 and MIPS16) combination, since they won't be any worse than __sync_*. Fallbacks using __sync_* should only be for the (older GCC, MIPS16) combination. So the logic in the file should be: #if (4.8 or later, or 4.7 and MIPS16) existing implementation using __atomic_* #elif (MIPS16) implementation using __sync_*, for older GCC and MIPS16 #else existing implementation using inline asm #endif > +#else > + > +/* 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 (\ Indentation, "# define". Many further cases in this patch as well, not individually pointed out. > /* Macros for accessing the hardware control word. */ > +extern fpu_control_t __fpu_getcw (void) __THROW; > +extern void __fpu_setcw (fpu_control_t) __THROW; > +#ifdef __mips16 > +#define _FPU_GETCW(cw) do { (cw) = __fpu_getcw (); } while (0) > +#define _FPU_SETCW(cw) __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 Names __mips_fpu_getcw and __mips_fpu_setcw might reduce any risk of conflicts with any future architecture-independent internal function? > + _FPU_GETCW(cw); > + _FPU_SETCW(cw); Missing space before '('. > Index: ports/sysdeps/mips/mips32/mips16/fpu/Versions > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ports/sysdeps/mips/mips32/mips16/fpu/Versions 2013-01-20 22:11:01.057025227 +0000 > @@ -0,0 +1,5 @@ > +libc { > + GLIBC_2.18 { > + __fpu_getcw; __fpu_getcw; > + } > +} The public ABI exported by glibc should not depend on whether glibc itself was built as MIPS16; remember that these functions will be needed by MIPS16 code linked with a MIPS32 glibc. So this Versions file should not be in a mips16 sysdeps directory. > Index: ports/sysdeps/mips/sys/tas.h > =================================================================== > --- ports/sysdeps/mips/sys/tas.h 2013-01-17 00:55:17.000000000 +0000 > +++ ports/sysdeps/mips/sys/tas.h 2013-01-20 19:40:57.376549265 +0000 > @@ -24,7 +24,7 @@ > > __BEGIN_DECLS > > -extern int _test_and_set (int *__p, int __v) __THROW; > +extern int __attribute__((nomips16)) test_and_set (int *__p, int __v) __THROW; > > #ifdef __USE_EXTERN_INLINES > > @@ -32,7 +32,7 @@ extern int _test_and_set (int *__p, int > # 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; This is an installed header, so you need to use __nomips16__ rather than just plain nomips16. > Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2013-01-20 19:40:57.546859991 +0000 > @@ -0,0 +1,91 @@ > +/* MIPS16 syscall wrappers. > + Copyright (C) 2013 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + Contributed by Maciej W. Rozycki <macro@codesourcery.com>. We don't put "Contributed by" lines in new files in glibc. > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, write to the Free > + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA > + 02111-1307 USA. */ All files in glibc should now use a URL instead of an FSF postal address. These points apply similarly to other new files. Please send a revised patch for review. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-23 17:22 ` Joseph S. Myers @ 2013-01-24 10:10 ` Chung-Lin Tang 2013-01-24 13:13 ` Maciej W. Rozycki 2013-02-20 16:19 ` [PATCH v2] MIPS: MIPS16 support Maciej W. Rozycki 1 sibling, 1 reply; 26+ messages in thread From: Chung-Lin Tang @ 2013-01-24 10:10 UTC (permalink / raw) To: Joseph S. Myers; +Cc: Maciej W. Rozycki, libc-ports On 2013/1/24 01:22 AM, Joseph S. Myers wrote: >> >> > -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); > Why is the renaming / alias needed? > This was because the declaration of __longjmp() in setjmp.h prohibited us from tagging it directly with __attribute__ ((nomips16)) locally; there will be a declaration inconsistent with header error. Chung-Lin ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-24 10:10 ` Chung-Lin Tang @ 2013-01-24 13:13 ` Maciej W. Rozycki 2013-01-24 13:56 ` Richard Sandiford 0 siblings, 1 reply; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-24 13:13 UTC (permalink / raw) To: Richard Sandiford, Chung-Lin Tang; +Cc: Joseph S. Myers, libc-ports On Thu, 24 Jan 2013, Chung-Lin Tang wrote: > >> > -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); > > Why is the renaming / alias needed? > > > > This was because the declaration of __longjmp() in setjmp.h prohibited > us from tagging it directly with __attribute__ ((nomips16)) locally; > there will be a declaration inconsistent with header error. Indeed, GCC goes through a great pain to enforce consistency between a function's prototype and the corresponding definition as far as the mips16 and nomips16 attributes are concerned. On the other hand it is possible to provide a prototype with neither attribute and freely choose the instruction encoding used for the definition with either of the -mips16 and -mno-mips16 command line options applied when building the relevant source file. I have no idea where this dichotomy comes from -- Richard, do you happen to know? I'd be happy to get enlightened. Maciej ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-24 13:13 ` Maciej W. Rozycki @ 2013-01-24 13:56 ` Richard Sandiford 0 siblings, 0 replies; 26+ messages in thread From: Richard Sandiford @ 2013-01-24 13:56 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: Chung-Lin Tang, Joseph S. Myers, libc-ports "Maciej W. Rozycki" <macro@codesourcery.com> writes: > On Thu, 24 Jan 2013, Chung-Lin Tang wrote: > >> >> > -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); >> > Why is the renaming / alias needed? >> > >> >> This was because the declaration of __longjmp() in setjmp.h prohibited >> us from tagging it directly with __attribute__ ((nomips16)) locally; >> there will be a declaration inconsistent with header error. > > Indeed, GCC goes through a great pain to enforce consistency between a > function's prototype and the corresponding definition as far as the mips16 > and nomips16 attributes are concerned. On the other hand it is possible > to provide a prototype with neither attribute and freely choose the > instruction encoding used for the definition with either of the -mips16 > and -mno-mips16 command line options applied when building the relevant > source file. > > I have no idea where this dichotomy comes from -- Richard, do you happen > to know? I'd be happy to get enlightened. As it happens, this very topic was raised on the GCC list recently: http://gcc.gnu.org/ml/gcc/2013-01/msg00133.html http://gcc.gnu.org/ml/gcc/2013-01/msg00229.html Richard ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v2] MIPS: MIPS16 support 2013-01-23 17:22 ` Joseph S. Myers 2013-01-24 10:10 ` Chung-Lin Tang @ 2013-02-20 16:19 ` Maciej W. Rozycki 2013-02-20 16:29 ` Joseph S. Myers 1 sibling, 1 reply; 26+ messages in thread From: Maciej W. Rozycki @ 2013-02-20 16:19 UTC (permalink / raw) To: Joseph S. Myers Cc: libc-ports, Chung-Lin Tang, Steve Ellcey, Richard Sandiford Joseph, Here's an updated version of the change to add MIPS16 support to GNU libc. I hope I have addressed all your concerns to your satisfaction. MIPS16 CRT files have now been dropped and likewise the GCC change I used for MIPS16 support there and I have bootstrapped the whole toolchain to make sure the new arrangement still works as expected. Also GLIBC_2.18 has been defined meanwhile, so I dropped the Versions.def change, and consequently the patch does not require any attention at the libc-alpha list anymore. Like the original the update was regression-tested successfully for the following configurations (compiler flag/multilib options), for both endiannesses each (the -EB and -EL compiler option, respectively): * standard MIPS ISA, o32 (-mabi=32), * standard MIPS ISA, n64 (-mabi=64), * standard MIPS ISA, n32 (-mabi=n32), * standard MIPS ISA, o32, soft-float (-mabi=32 -msoft-float), * standard MIPS ISA, n64, soft-float (-mabi=64 -msoft-float), * standard MIPS ISA, n32, soft-float (-mabi=n32 -msoft-float), * microMIPS ISA, o32 (-mmicromips -mabi=32), * microMIPS ISA, o32, soft-float (-mmicromips -mabi=32 -msoft-float), with the MIPS32r2 or MIPS64r2 ISA level selected as applicable. Likewise new functionality has been tested for: * MIPS16 ISA, o32 (-mips16 -mabi=32), * MIPS16 ISA, o32, soft-float (-mips16 -mabi=32 -msoft-float), producing no failures other to ones already present for the standard MIPS and microMIPS ISAs. OK to apply? 2013-02-20 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. (RTLD_START): Likewise. * sysdeps/mips/fpu_control.h (__fpu_getcw) [__mips16]: New prototype. (__fpu_setcw) [__mips16]: 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. * sysdeps/mips/bits/atomic.h (atomic_compare_and_exchange_val_acq) [__mips16]: Likewise. (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. (TLS_GD, TLS_LD, TLS_IE, TLS_LE) [__mips16]: Likewise. * sysdeps/mips/sys/tas.h (_test_and_set): Add `.set nomips16'. * sysdeps/unix/mips/sysdep.h (PSEUDO_NOERRNO): Likewise. (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/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): Add MIPS16 version. * 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 nomips16. (__longjmp): New alias. * sysdeps/mips/dl-trampoline.c (_dl_runtime_resolve): Add MIPS16 version. (_dl_runtime_pltresolve): Likewise. * sysdeps/mips/setjmp_aux.c (__sigsetjmp_aux): Add nomips16 attribute. * sysdeps/mips/fpu/e_sqrt.c (__ieee754_sqrt): Add nomips16 attribute. * sysdeps/mips/fpu/e_sqrtf.c (__ieee754_sqrtf): Likewise. * sysdeps/unix/sysv/linux/mips/brk.c (__brk): Replace inline asm with INTERNAL_SYSCALL. * sysdeps/mips/mips32/fpu/Implies: New file. * 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/mips/mips32/mips16/Makefile: New file. * sysdeps/mips/mips32/mips16/fpu/Makefile: New file. * sysdeps/mips/mips32/mips16/fpu/Versions: New file. * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h: 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/unix/sysv/linux/mips/mips32/mips16/Makefile: New file. * sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions: New file. * sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist (GLIBC_2.18): Add __fpu_getcw and __fpu_setcw. * sysdeps/mips/preconfigure: Handle o32 MIPS16 compilation. Maciej glibc-mips16-upstream.diff Index: ports/sysdeps/mips/__longjmp.c =================================================================== --- ports/sysdeps/mips/__longjmp.c 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/__longjmp.c 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/abort-instr.h =================================================================== --- ports/sysdeps/mips/abort-instr.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/abort-instr.h 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/bits/atomic.h =================================================================== --- ports/sysdeps/mips/bits/atomic.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/bits/atomic.h 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/bsd-_setjmp.S =================================================================== --- ports/sysdeps/mips/bsd-_setjmp.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/bsd-_setjmp.S 2013-02-19 22:23:55.317751073 +0000 @@ -26,6 +26,7 @@ .option pic2 #endif ENTRY (_setjmp) + .set nomips16 #ifdef __PIC__ .set noreorder .cpload t9 Index: ports/sysdeps/mips/bsd-setjmp.S =================================================================== --- ports/sysdeps/mips/bsd-setjmp.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/bsd-setjmp.S 2013-02-19 22:23:55.317751073 +0000 @@ -26,6 +26,7 @@ .option pic2 #endif ENTRY (setjmp) + .set nomips16 .set noreorder #ifdef __PIC__ .cpload t9 Index: ports/sysdeps/mips/dl-machine.h =================================================================== --- ports/sysdeps/mips/dl-machine.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/dl-machine.h 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/dl-trampoline.c =================================================================== --- ports/sysdeps/mips/dl-trampoline.c 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/dl-trampoline.c 2013-02-19 22:23:55.317751073 +0000 @@ -292,8 +292,10 @@ __dl_runtime_resolve (ElfW(Word) sym_ind #endif +#ifndef __mips16 asm ("\n\ .text\n\ + .set nomips16\n\ .align 2\n\ .globl _dl_runtime_resolve\n\ .type _dl_runtime_resolve,@function\n\ @@ -350,6 +352,7 @@ _dl_runtime_resolve:\n\ asm ("\n\ .text\n\ + .set nomips16\n\ .align 2\n\ .globl _dl_runtime_pltresolve\n\ .type _dl_runtime_pltresolve,@function\n\ @@ -381,3 +384,130 @@ _dl_runtime_pltresolve:\n\ .previous\n\ "); +#elif _MIPS_SIM == _ABIO32 /* __mips16 */ +/* MIPS16 version, O32 only. */ +asm ("\n\ + .text\n\ + .set mips16\n\ + .align 2\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\ + .set mips16\n\ + .align 2\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: ports/sysdeps/mips/fpu/e_sqrt.c =================================================================== --- ports/sysdeps/mips/fpu/e_sqrt.c 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/fpu/e_sqrt.c 2013-02-19 22:23:55.317751073 +0000 @@ -22,7 +22,7 @@ #if (_MIPS_ISA >= _MIPS_ISA_MIPS2) -double +double __attribute__ ((nomips16)) __ieee754_sqrt (double x) { double z; Index: ports/sysdeps/mips/fpu/e_sqrtf.c =================================================================== --- ports/sysdeps/mips/fpu/e_sqrtf.c 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/fpu/e_sqrtf.c 2013-02-19 22:23:55.317751073 +0000 @@ -22,7 +22,7 @@ #if (_MIPS_ISA >= _MIPS_ISA_MIPS2) -float +float __attribute__ ((nomips16)) __ieee754_sqrtf (float x) { float z; Index: ports/sysdeps/mips/fpu_control.h =================================================================== --- ports/sysdeps/mips/fpu_control.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/fpu_control.h 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/machine-gmon.h =================================================================== --- ports/sysdeps/mips/machine-gmon.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/machine-gmon.h 2013-02-19 22:23:55.317751073 +0000 @@ -35,6 +35,8 @@ static void __attribute_used__ __mcount #endif #define MCOUNT asm(\ + ".set push;\n\t" \ + ".set nomips16;\n\t" \ ".globl _mcount;\n\t" \ ".align 2;\n\t" \ ".type _mcount,@function;\n\t" \ @@ -67,9 +69,8 @@ static void __attribute_used__ __mcount "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 @@ -92,6 +93,8 @@ static void __attribute_used__ __mcount #endif #define MCOUNT asm(\ + ".set push;\n\t" \ + ".set nomips16;\n\t" \ ".globl _mcount;\n\t" \ ".align 3;\n\t" \ ".type _mcount,@function;\n\t" \ @@ -132,8 +135,7 @@ static void __attribute_used__ __mcount 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: ports/sysdeps/mips/memset.S =================================================================== --- ports/sysdeps/mips/memset.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/memset.S 2013-02-19 22:23:55.317751073 +0000 @@ -28,6 +28,7 @@ #endif ENTRY (memset) + .set nomips16 .set noreorder slti t1, a2, 8 # Less than 8? Index: ports/sysdeps/mips/mips32/crti.S =================================================================== --- ports/sysdeps/mips/mips32/crti.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/mips32/crti.S 2013-02-19 22:23:55.317751073 +0000 @@ -54,6 +54,8 @@ .hidden PREINIT_FUNCTION #endif + .set nomips16 + .section .init,"ax",@progbits .p2align 2 .globl _init Index: ports/sysdeps/mips/mips32/crtn.S =================================================================== --- ports/sysdeps/mips/mips32/crtn.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/mips32/crtn.S 2013-02-19 22:23:55.317751073 +0000 @@ -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 Index: ports/sysdeps/mips/mips32/fpu/Versions =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/fpu/Versions 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1,5 @@ +libc { + GLIBC_2.18 { + __fpu_getcw; __fpu_getcw; + } +} Index: ports/sysdeps/mips/mips32/fpu/fpu_control.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/fpu/fpu_control.c 2013-02-19 22:23:55.317751073 +0000 @@ -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); +} Index: ports/sysdeps/mips/mips32/mips16/add_n.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/add_n.c 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1 @@ +#include <stdlib/add_n.c> Index: ports/sysdeps/mips/mips32/mips16/addmul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/addmul_1.c 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1 @@ +#include <stdlib/addmul_1.c> Index: ports/sysdeps/mips/mips32/mips16/fpu/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/fpu/Makefile 2013-02-19 22:23:55.317751073 +0000 @@ -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 Index: ports/sysdeps/mips/mips32/mips16/lshift.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/lshift.c 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1 @@ +#include <stdlib/lshift.c> Index: ports/sysdeps/mips/mips32/mips16/mul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/mul_1.c 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1 @@ +#include <stdlib/mul_1.c> Index: ports/sysdeps/mips/mips32/mips16/rshift.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/rshift.c 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1 @@ +#include <stdlib/rshift.c> Index: ports/sysdeps/mips/mips32/mips16/sub_n.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/sub_n.c 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1 @@ +#include <stdlib/sub_n.c> Index: ports/sysdeps/mips/mips32/mips16/submul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/mips/mips32/mips16/submul_1.c 2013-02-19 22:23:55.317751073 +0000 @@ -0,0 +1 @@ +#include <stdlib/submul_1.c> Index: ports/sysdeps/mips/mips64/n32/crti.S =================================================================== --- ports/sysdeps/mips/mips64/n32/crti.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/mips64/n32/crti.S 2013-02-19 22:23:55.317751073 +0000 @@ -54,6 +54,8 @@ .hidden PREINIT_FUNCTION #endif + .set nomips16 + .section .init,"ax",@progbits .p2align 2 .globl _init Index: ports/sysdeps/mips/mips64/n32/crtn.S =================================================================== --- ports/sysdeps/mips/mips64/n32/crtn.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/mips64/n32/crtn.S 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/mips64/n64/crti.S =================================================================== --- ports/sysdeps/mips/mips64/n64/crti.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/mips64/n64/crti.S 2013-02-19 22:23:55.317751073 +0000 @@ -54,6 +54,8 @@ .hidden PREINIT_FUNCTION #endif + .set nomips16 + .section .init,"ax",@progbits .p2align 2 .globl _init Index: ports/sysdeps/mips/mips64/n64/crtn.S =================================================================== --- ports/sysdeps/mips/mips64/n64/crtn.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/mips64/n64/crtn.S 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/nptl/tls.h =================================================================== --- ports/sysdeps/mips/nptl/tls.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/nptl/tls.h 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/preconfigure =================================================================== --- ports/sysdeps/mips/preconfigure 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/preconfigure 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/setjmp.S =================================================================== --- ports/sysdeps/mips/setjmp.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/setjmp.S 2013-02-19 22:23:55.317751073 +0000 @@ -24,6 +24,7 @@ .option pic2 #endif ENTRY (__sigsetjmp) + .set nomips16 #ifdef __PIC__ .set noreorder .cpload t9 Index: ports/sysdeps/mips/setjmp_aux.c =================================================================== --- ports/sysdeps/mips/setjmp_aux.c 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/setjmp_aux.c 2013-02-19 22:23:55.317751073 +0000 @@ -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: ports/sysdeps/mips/start.S =================================================================== --- ports/sysdeps/mips/start.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/start.S 2013-02-19 22:23:55.327333248 +0000 @@ -74,14 +74,15 @@ .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 @@ 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. */ +ENTRY_POINT: + .set mips16 +# 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: ports/sysdeps/mips/sys/tas.h =================================================================== --- ports/sysdeps/mips/sys/tas.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/sys/tas.h 2013-02-19 22:23:55.327333248 +0000 @@ -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 # 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: ports/sysdeps/mips/tls-macros.h =================================================================== --- ports/sysdeps/mips/tls-macros.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/mips/tls-macros.h 2013-02-19 22:23:55.327333248 +0000 @@ -12,16 +12,33 @@ (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 *); \ @@ -62,3 +79,45 @@ 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: ports/sysdeps/unix/mips/mips32/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/mips32/sysdep.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/mips/mips32/sysdep.h 2013-02-19 22:23:55.327333248 +0000 @@ -23,6 +23,7 @@ backwards into the previous fn. */ #ifdef __PIC__ #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .align 2; \ cfi_startproc; \ 99: la t9,__syscall_error; \ @@ -38,6 +39,7 @@ L(syse1): #else #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .set noreorder; \ .align 2; \ cfi_startproc; \ Index: ports/sysdeps/unix/mips/mips64/n32/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/mips64/n32/sysdep.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/mips/mips64/n32/sysdep.h 2013-02-19 22:23:55.327333248 +0000 @@ -25,6 +25,7 @@ backwards into the previous fn. */ #ifdef __PIC__ #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .align 2; \ cfi_startproc; \ 99:; \ @@ -44,6 +45,7 @@ L(syse1): #else #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .set noreorder; \ .align 2; \ cfi_startproc; \ Index: ports/sysdeps/unix/mips/mips64/n64/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/mips64/n64/sysdep.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/mips/mips64/n64/sysdep.h 2013-02-19 22:23:55.327333248 +0000 @@ -25,6 +25,7 @@ backwards into the previous fn. */ #ifdef __PIC__ #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .align 2; \ cfi_startproc; \ 99:; \ @@ -44,6 +45,7 @@ L(syse1): #else #define PSEUDO(name, syscall_name, args) \ + .set nomips16; \ .set noreorder; \ .align 2; \ cfi_startproc; \ Index: ports/sysdeps/unix/mips/sysdep.S =================================================================== --- ports/sysdeps/unix/mips/sysdep.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/mips/sysdep.S 2013-02-19 22:23:55.327333248 +0000 @@ -21,6 +21,8 @@ #include <bits/errno.h> #include <sys/asm.h> + .set nomips16 + #ifdef _LIBC_REENTRANT LOCALSZ= 3 Index: ports/sysdeps/unix/mips/sysdep.h =================================================================== --- ports/sysdeps/unix/mips/sysdep.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/mips/sysdep.h 2013-02-19 22:23:55.327333248 +0000 @@ -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: ports/sysdeps/unix/sysv/linux/mips/brk.c =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/brk.c 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/brk.c 2013-02-19 22:23:55.327333248 +0000 @@ -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: ports/sysdeps/unix/sysv/linux/mips/clone.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/clone.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/clone.S 2013-02-19 22:23:55.327333248 +0000 @@ -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: ports/sysdeps/unix/sysv/linux/mips/getcontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/getcontext.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/getcontext.S 2013-02-19 22:23:55.327333248 +0000 @@ -27,6 +27,7 @@ /* int getcontext (ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 MASK = 0x00000000 #ifdef __PIC__ Index: ports/sysdeps/unix/sysv/linux/mips/makecontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/makecontext.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/makecontext.S 2013-02-19 22:23:55.327333248 +0000 @@ -27,6 +27,7 @@ /* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2013-02-19 22:23:55.327333248 +0000 @@ -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 Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2013-02-19 22:23:55.327333248 +0000 @@ -0,0 +1,6 @@ +libc { + GLIBC_PRIVATE { + __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3; + __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7; + } +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2013-02-19 22:23:55.327333248 +0000 @@ -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 Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2013-02-19 22:23:55.327333248 +0000 @@ -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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2013-02-19 22:23:55.327333248 +0000 @@ -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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2013-02-19 22:23:55.327333248 +0000 @@ -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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2013-02-19 22:23:55.327333248 +0000 @@ -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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2013-02-19 22:23:55.327333248 +0000 @@ -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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c 2013-02-19 22:23:55.327333248 +0000 @@ -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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c 2013-02-19 22:23:55.327333248 +0000 @@ -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; +} Index: ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c 2013-02-19 22:23:55.327333248 +0000 @@ -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: ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist 2013-02-19 22:23:55.327333248 +0000 @@ -2253,3 +2253,5 @@ GLIBC_2.17 GLIBC_2.18 GLIBC_2.18 A __cxa_thread_atexit_impl F + __fpu_getcw F + __fpu_setcw F Index: ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-02-19 22:23:55.327333248 +0000 @@ -95,17 +95,46 @@ #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: ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h 2013-02-19 22:23:55.327333248 +0000 @@ -45,6 +45,7 @@ # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .align 2; \ + .set nomips16; \ L(pseudo_start): \ cfi_startproc; \ 99: PSEUDO_ERRJMP \ Index: ports/sysdeps/unix/sysv/linux/mips/setcontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/setcontext.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/setcontext.S 2013-02-19 22:23:55.327333248 +0000 @@ -27,6 +27,7 @@ /* int setcontext (const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: ports/sysdeps/unix/sysv/linux/mips/swapcontext.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/swapcontext.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/swapcontext.S 2013-02-19 22:23:55.327333248 +0000 @@ -27,6 +27,7 @@ /* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: ports/sysdeps/unix/sysv/linux/mips/vfork.S =================================================================== --- ports/sysdeps/unix/sysv/linux/mips/vfork.S 2013-02-19 22:23:49.556613890 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/vfork.S 2013-02-19 22:23:55.327333248 +0000 @@ -34,6 +34,7 @@ /* int vfork() */ .text + .set nomips16 LOCALSZ= 1 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK GPOFF= FRAMESZ-(1*SZREG) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2] MIPS: MIPS16 support 2013-02-20 16:19 ` [PATCH v2] MIPS: MIPS16 support Maciej W. Rozycki @ 2013-02-20 16:29 ` Joseph S. Myers 2013-02-27 1:38 ` [PATCH v3] " Maciej W. Rozycki 0 siblings, 1 reply; 26+ messages in thread From: Joseph S. Myers @ 2013-02-20 16:29 UTC (permalink / raw) To: Maciej W. Rozycki Cc: libc-ports, Chung-Lin Tang, Steve Ellcey, Richard Sandiford On Wed, 20 Feb 2013, Maciej W. Rozycki wrote: > * sysdeps/mips/fpu_control.h (__fpu_getcw) [__mips16]: New > prototype. > (__fpu_setcw) [__mips16]: Likewise. Since you've renamed the functions to __mips_fpu_getcw and __mips_fpu_setcw, you need to update the ChangeLog entry accordingly. The ChangeLog entries may also need updates for other changes in this patch version. > * sysdeps/mips/mips32/mips16/fpu/Versions: New file. Actually you moved the Versions file to the correct place for the symbol versions not to depend on whether glibc itself is built as MIPS16. But the contents of the file - and of the libc.abilist changes - need updating for the new symbol names. (Given these inconsistencies, I haven't fully reviewed the rest of the patch contents.) -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v3] MIPS: MIPS16 support 2013-02-20 16:29 ` Joseph S. Myers @ 2013-02-27 1:38 ` Maciej W. Rozycki 2013-02-27 17:50 ` Joseph S. Myers 0 siblings, 1 reply; 26+ messages in thread From: Maciej W. Rozycki @ 2013-02-27 1:38 UTC (permalink / raw) To: Joseph S. Myers Cc: libc-ports, Chung-Lin Tang, Steve Ellcey, Richard Sandiford On Wed, 20 Feb 2013, Joseph S. Myers wrote: > (Given these inconsistencies, I haven't fully reviewed the rest of the > patch contents.) I apologise about the inconsistencies you found, I missed them somehow even though I thought I had adjusted all the ChangeLog entries as I had been making the respective source changes. I have therefore went over the whole change again and verified all ChangeLog data is accurate. And while doing that I actually discovered some issues with the getcw/setcw symbols themselves, so I have corrected them. I have also decided to put as much consistency as possible among all the .set nomips16 pseudo-ops added. Their exact placement has a marginal significance as any .align pseudo-op following that actually emits padding will use the NOP encoding correct for the newly-selected ISA mode. However the absence of any symbol between .set and .align will cause `objdump' to decode that instruction stream according to the old mode, producing garbled output. On the other hand for assembly sources where .set nomips16 applies throughout I think it's most readable if the pseudo-op is located at the top rather than being buried somewhere within the first function defined. Unfortunately our assembly sources lack formatting consistency, but I tried my best. Given I made changes I pushed this new version, as the original, through a full regression test cycle across the following multilibs (both endiannesses each): * standard MIPS ISA, o32 (-mabi=32), * standard MIPS ISA, n64 (-mabi=64), * standard MIPS ISA, n32 (-mabi=n32), * standard MIPS ISA, o32, soft-float (-mabi=32 -msoft-float), * standard MIPS ISA, n64, soft-float (-mabi=64 -msoft-float), * standard MIPS ISA, n32, soft-float (-mabi=n32 -msoft-float), * microMIPS ISA, o32 (-mmicromips -mabi=32), * microMIPS ISA, o32, soft-float (-mmicromips -mabi=32 -msoft-float), * MIPS16 ISA, o32 (-mips16 -mabi=32), * MIPS16 ISA, o32, soft-float (-mips16 -mabi=32 -msoft-float). OK to apply? 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. Maciej glibc-mips16.diff Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/__longjmp.c =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/__longjmp.c 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/__longjmp.c 2013-02-26 22:32:04.447786638 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/abort-instr.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/abort-instr.h 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/abort-instr.h 2013-02-26 22:32:04.447786638 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/bits/atomic.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/bits/atomic.h 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/bits/atomic.h 2013-02-26 22:32:04.447786638 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/bsd-_setjmp.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/bsd-_setjmp.S 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/bsd-_setjmp.S 2013-02-26 22:32:04.457754330 +0000 @@ -22,6 +22,8 @@ #include <sysdep.h> + .set nomips16 + #ifdef __PIC__ .option pic2 #endif Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/bsd-setjmp.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/bsd-setjmp.S 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/bsd-setjmp.S 2013-02-26 22:32:04.457754330 +0000 @@ -22,6 +22,8 @@ #include <sysdep.h> + .set nomips16 + #ifdef __PIC__ .option pic2 #endif Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/dl-machine.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/dl-machine.h 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/dl-machine.h 2013-02-26 22:32:04.457754330 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/dl-trampoline.c =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/dl-trampoline.c 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/dl-trampoline.c 2013-02-26 22:32:04.457754330 +0000 @@ -292,9 +292,11 @@ __dl_runtime_resolve (ElfW(Word) sym_ind #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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/fpu/e_sqrt.c =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/fpu/e_sqrt.c 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/fpu/e_sqrt.c 2013-02-26 22:32:04.457754330 +0000 @@ -22,7 +22,7 @@ #if (_MIPS_ISA >= _MIPS_ISA_MIPS2) -double +double __attribute__ ((nomips16)) __ieee754_sqrt (double x) { double z; Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/fpu/e_sqrtf.c =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/fpu/e_sqrtf.c 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/fpu/e_sqrtf.c 2013-02-26 22:32:04.457754330 +0000 @@ -22,7 +22,7 @@ #if (_MIPS_ISA >= _MIPS_ISA_MIPS2) -float +float __attribute__ ((nomips16)) __ieee754_sqrtf (float x) { float z; Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/fpu_control.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/fpu_control.h 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/fpu_control.h 2013-02-26 22:32:04.457754330 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/machine-gmon.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/machine-gmon.h 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/machine-gmon.h 2013-02-26 22:32:04.457754330 +0000 @@ -37,6 +37,8 @@ static void __attribute_used__ __mcount #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 "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 #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 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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/memset.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/memset.S 2013-02-26 21:08:22.197807296 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/memset.S 2013-02-26 22:32:04.457754330 +0000 @@ -18,6 +18,7 @@ #include <sysdep.h> + .set nomips16 /* void *memset(void *s, int c, size_t n). */ Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/crti.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/mips32/crti.S 2013-02-26 21:08:22.206574592 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/crti.S 2013-02-26 22:32:04.457754330 +0000 @@ -54,6 +54,8 @@ .hidden PREINIT_FUNCTION #endif + .set nomips16 + .section .init,"ax",@progbits .p2align 2 .globl _init Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/crtn.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/mips32/crtn.S 2013-02-26 21:08:22.206574592 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/crtn.S 2013-02-26 22:32:04.457754330 +0000 @@ -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 Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/fpu/Versions =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/fpu/Versions 2013-02-26 22:32:04.457754330 +0000 @@ -0,0 +1,5 @@ +libc { + GLIBC_2.18 { + __mips_fpu_getcw; __mips_fpu_setcw; + } +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/fpu/fpu_control.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/fpu/fpu_control.c 2013-02-26 22:32:04.457754330 +0000 @@ -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); +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/add_n.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/add_n.c 2013-02-26 22:32:04.457754330 +0000 @@ -0,0 +1 @@ +#include <stdlib/add_n.c> Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/addmul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/addmul_1.c 2013-02-26 22:32:04.467753501 +0000 @@ -0,0 +1 @@ +#include <stdlib/addmul_1.c> Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/fpu/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/fpu/Makefile 2013-02-26 22:32:04.467753501 +0000 @@ -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 Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/lshift.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/lshift.c 2013-02-26 22:32:04.467753501 +0000 @@ -0,0 +1 @@ +#include <stdlib/lshift.c> Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/mul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/mul_1.c 2013-02-26 22:32:04.467753501 +0000 @@ -0,0 +1 @@ +#include <stdlib/mul_1.c> Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/rshift.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/rshift.c 2013-02-26 22:32:04.467753501 +0000 @@ -0,0 +1 @@ +#include <stdlib/rshift.c> Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/sub_n.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/sub_n.c 2013-02-26 22:32:04.467753501 +0000 @@ -0,0 +1 @@ +#include <stdlib/sub_n.c> Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/submul_1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips32/mips16/submul_1.c 2013-02-26 22:32:04.467753501 +0000 @@ -0,0 +1 @@ +#include <stdlib/submul_1.c> Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n32/crti.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/mips64/n32/crti.S 2013-02-26 21:08:22.206574592 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n32/crti.S 2013-02-26 22:32:04.467753501 +0000 @@ -54,6 +54,8 @@ .hidden PREINIT_FUNCTION #endif + .set nomips16 + .section .init,"ax",@progbits .p2align 2 .globl _init Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n32/crtn.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/mips64/n32/crtn.S 2013-02-26 21:08:22.206574592 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n32/crtn.S 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n64/crti.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/mips64/n64/crti.S 2013-02-26 21:08:22.206574592 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n64/crti.S 2013-02-26 22:32:04.477753462 +0000 @@ -54,6 +54,8 @@ .hidden PREINIT_FUNCTION #endif + .set nomips16 + .section .init,"ax",@progbits .p2align 2 .globl _init Index: glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n64/crtn.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/mips64/n64/crtn.S 2013-02-26 21:08:22.206574592 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/mips64/n64/crtn.S 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/nptl/tls.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/nptl/tls.h 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/nptl/tls.h 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/preconfigure =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/preconfigure 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/preconfigure 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/setjmp.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/setjmp.S 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/setjmp.S 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/setjmp_aux.c =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/setjmp_aux.c 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/setjmp_aux.c 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/start.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/start.S 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/start.S 2013-02-26 22:32:04.477753462 +0000 @@ -74,14 +74,15 @@ .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 @@ 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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/sys/tas.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/sys/tas.h 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/sys/tas.h 2013-02-26 22:32:04.477753462 +0000 @@ -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 # 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: glibc-fsf-trunk-quilt/ports/sysdeps/mips/tls-macros.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/mips/tls-macros.h 2013-02-26 21:08:22.186821407 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/mips/tls-macros.h 2013-02-26 22:32:04.477753462 +0000 @@ -12,16 +12,33 @@ (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 *); \ @@ -62,3 +79,45 @@ 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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/mips32/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/mips/mips32/sysdep.h 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/mips32/sysdep.h 2013-02-26 22:32:04.477753462 +0000 @@ -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 @@ #else #define PSEUDO(name, syscall_name, args) \ .set noreorder; \ + .set nomips16; \ .align 2; \ cfi_startproc; \ 99: j __syscall_error; \ Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/mips64/n32/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/mips/mips64/n32/sysdep.h 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/mips64/n32/sysdep.h 2013-02-26 22:32:04.477753462 +0000 @@ -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 @@ #define PSEUDO(name, syscall_name, args) \ .set noreorder; \ .align 2; \ + .set nomips16; \ cfi_startproc; \ 99: j __syscall_error; \ nop; \ Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/mips64/n64/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/mips/mips64/n64/sysdep.h 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/mips64/n64/sysdep.h 2013-02-26 22:32:04.477753462 +0000 @@ -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 @@ #define PSEUDO(name, syscall_name, args) \ .set noreorder; \ .align 2; \ + .set nomips16; \ cfi_startproc; \ 99: j __syscall_error; \ nop; \ Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/sysdep.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/mips/sysdep.S 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/sysdep.S 2013-02-26 22:32:04.477753462 +0000 @@ -21,6 +21,8 @@ #include <bits/errno.h> #include <sys/asm.h> + .set nomips16 + #ifdef _LIBC_REENTRANT LOCALSZ= 3 Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/mips/sysdep.h 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/mips/sysdep.h 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/brk.c =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/brk.c 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/brk.c 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/clone.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/clone.S 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/clone.S 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/getcontext.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/getcontext.S 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/getcontext.S 2013-02-26 22:32:04.477753462 +0000 @@ -27,6 +27,7 @@ /* int getcontext (ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 MASK = 0x00000000 #ifdef __PIC__ Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/makecontext.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/makecontext.S 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/makecontext.S 2013-02-26 22:32:04.477753462 +0000 @@ -27,6 +27,7 @@ /* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2013-02-26 22:32:04.477753462 +0000 @@ -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 Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2013-02-26 22:32:04.477753462 +0000 @@ -0,0 +1,6 @@ +libc { + GLIBC_PRIVATE { + __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3; + __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7; + } +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2013-02-26 22:32:04.477753462 +0000 @@ -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 Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2013-02-26 22:32:04.477753462 +0000 @@ -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; +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2013-02-26 22:32:04.477753462 +0000 @@ -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; +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2013-02-26 22:32:04.477753462 +0000 @@ -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; +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2013-02-26 22:32:04.477753462 +0000 @@ -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; +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2013-02-26 22:32:04.477753462 +0000 @@ -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; +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c 2013-02-26 22:32:04.477753462 +0000 @@ -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; +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c 2013-02-26 22:32:04.477753462 +0000 @@ -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; +} Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-02-26 22:32:04.477753462 +0000 @@ -95,17 +95,46 @@ #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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h 2013-02-26 21:08:22.397776709 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h 2013-02-26 22:32:04.477753462 +0000 @@ -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: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/setcontext.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/setcontext.S 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/setcontext.S 2013-02-26 22:32:04.477753462 +0000 @@ -27,6 +27,7 @@ /* int setcontext (const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/swapcontext.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/swapcontext.S 2013-02-26 21:08:22.176752232 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/swapcontext.S 2013-02-26 22:32:04.487753065 +0000 @@ -27,6 +27,7 @@ /* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 Index: glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/vfork.S =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/vfork.S 2013-02-26 21:08:22.166795198 +0000 +++ glibc-fsf-trunk-quilt/ports/sysdeps/unix/sysv/linux/mips/vfork.S 2013-02-26 22:32:04.497752188 +0000 @@ -34,6 +34,7 @@ /* int vfork() */ .text + .set nomips16 LOCALSZ= 1 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK GPOFF= FRAMESZ-(1*SZREG) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v3] MIPS: MIPS16 support 2013-02-27 1:38 ` [PATCH v3] " Maciej W. Rozycki @ 2013-02-27 17:50 ` Joseph S. Myers 2013-02-27 23:54 ` Maciej W. Rozycki 0 siblings, 1 reply; 26+ messages in thread From: Joseph S. Myers @ 2013-02-27 17:50 UTC (permalink / raw) To: Maciej W. Rozycki Cc: libc-ports, Chung-Lin Tang, Steve Ellcey, Richard Sandiford On Wed, 27 Feb 2013, Maciej W. Rozycki wrote: > OK to apply? This patch version is OK. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v3] MIPS: MIPS16 support 2013-02-27 17:50 ` Joseph S. Myers @ 2013-02-27 23:54 ` Maciej W. Rozycki 0 siblings, 0 replies; 26+ messages in thread From: Maciej W. Rozycki @ 2013-02-27 23:54 UTC (permalink / raw) To: Joseph S. Myers Cc: libc-ports, Chung-Lin Tang, Steve Ellcey, Richard Sandiford On Wed, 27 Feb 2013, Joseph S. Myers wrote: > > OK to apply? > > This patch version is OK. Applied now, thanks for going through this review. Maciej ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-23 4:42 ` [PATCH 2/2] MIPS16: MIPS16 support proper Maciej W. Rozycki 2013-01-23 17:22 ` Joseph S. Myers @ 2013-01-24 18:08 ` Ellcey, Steve 2013-01-25 5:14 ` Maciej W. Rozycki 1 sibling, 1 reply; 26+ messages in thread From: Ellcey, Steve @ 2013-01-24 18:08 UTC (permalink / raw) To: Maciej W. Rozycki, libc-alpha, libc-ports; +Cc: Chung-Lin Tang Maciej, I was able to apply your patches and build a MIPS16 glibc (multiple ones actually for mips32, mips32r2, big & little endian, soft & hard float), so that was great. I am having trouble running executables that I link with those libraries though. I am using qemu for my testing and the same qemu that runs mips32r2 binaries just fine won't run something compiled with -mips32r2 -mips16 and linked with the mips16 glibc that I built. After some poking around I think the problem is not the glibc that I built but with crti.o and crtn.o. If I use regular mips32 versions of these crt files and mips16 built versions of everything else (main program, glibc, libgcc, etc.) then I can run a simple hello world program, if I use the mips16 versions of crti and crtn I get: mips-mti-linux-gnu-gcc -mips32r2 -mips16 '-Wl,--dynamic-linker=/local/home/sellcey/gcc/mips16/sysroot-mips-mti-linux-gnu/mips16/usr/lib/ld-2.17.90.so' '-Wl,-rpath=/local/home/sellcey/gcc/mips16/sysroot-mips-mti-linux-gnu/mips16/usr/lib:/local/home/sellcey/gcc/mips16/install-mips-mti-linux-gnu/mips-mti-linux-gnu/lib/mips16' hi.c -o x mips-mti-linux-gnu-qemu -r 2.6.38 ./x hi qemu: uncaught target signal 11 (Segmentation fault) - core dumped Note that it did print 'hi' before getting the signal. If I try adding '-static' then I get: mips-mti-linux-gnu-gcc -static -mips32r2 -mips16 hi.c -o x mips-mti-linux-gnu-qemu -r 2.6.38 ./x qemu: uncaught target signal 4 (Illegal instruction) - core dumped I was wondering if you have any idea what could be causing this. Should the standard qemu be able to run mips16 executables with no changes? Steve Ellcey sellcey@mips.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-24 18:08 ` [PATCH 2/2] MIPS16: MIPS16 support proper Ellcey, Steve @ 2013-01-25 5:14 ` Maciej W. Rozycki 2013-01-25 13:59 ` Richard Sandiford 2013-01-25 22:10 ` Steve Ellcey 0 siblings, 2 replies; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-25 5:14 UTC (permalink / raw) To: Ellcey, Steve; +Cc: libc-alpha, libc-ports, Chung-Lin Tang Steve, > After some poking around I think the problem is not the glibc that I built but with crti.o and crtn.o. If I use > regular mips32 versions of these crt files and mips16 built versions of everything else (main program, glibc, > libgcc, etc.) then I can run a simple hello world program, if I use the mips16 versions of crti and crtn I get: > > > mips-mti-linux-gnu-gcc -mips32r2 -mips16 '-Wl,--dynamic-linker=/local/home/sellcey/gcc/mips16/sysroot-mips-mti-linux-gnu/mips16/usr/lib/ld-2.17.90.so' '-Wl,-rpath=/local/home/sellcey/gcc/mips16/sysroot-mips-mti-linux-gnu/mips16/usr/lib:/local/home/sellcey/gcc/mips16/install-mips-mti-linux-gnu/mips-mti-linux-gnu/lib/mips16' hi.c -o x > > mips-mti-linux-gnu-qemu -r 2.6.38 ./x > hi > qemu: uncaught target signal 11 (Segmentation fault) - core dumped > > Note that it did print 'hi' before getting the signal. > > If I try adding '-static' then I get: > > mips-mti-linux-gnu-gcc -static -mips32r2 -mips16 hi.c -o x > mips-mti-linux-gnu-qemu -r 2.6.38 ./x > qemu: uncaught target signal 4 (Illegal instruction) - core dumped > > > > I was wondering if you have any idea what could be causing this. Should the standard qemu be able > to run mips16 executables with no changes? I am fairly sure QEMU has issues with MIPS16 code, and I wouldn't be surprised if user-mode emulation actually required porting QEMU, rather than merely fixing bugs, to support MIPS16 binaries -- it may not be prepared to handle the ISA bit at all. Have you tried running your code on actual hardware? This is how we did testing of all these changes. Please also note that as I mentioned along the patch submission mixing execution modes in static constructors or destructors installed as single lumps of code (that is with the use of the DT_INIT or DT_FINI dynamic tags) cannot be supported. Can you run `objdump -j .init -j .fini -d' on your binary and make sure the disassembly looks right? Here's an example of correct MIPS16 code from one of the test cases: Disassembly of section .init: 00400a2c <_init>: 400a2c: f000 6a02 li v0,2 400a30: f692 0b10 la v1,3fa0c0 <_DYNAMIC-0x60dc> 400a34: f400 3240 sll v0,16 400a38: e269 addu v0,v1 400a3a: 64c4 save 32,ra 400a3c: 659a move gp,v0 400a3e: d204 sw v0,16(sp) 400a40: f030 9a6c lw v1,-32724(v0) 400a44: 2304 beqz v1,400a4e <_init+0x22> 400a46: f030 9a4c lw v0,-32724(v0) 400a4a: ea40 jalr v0 400a4c: 653a move t9,v0 400a4e: 6500 nop 400a50: 1a00 036e jal 400db8 <frame_dummy> 400a54: 6500 nop 400a56: 1a00 0400 jal 401000 <__do_global_ctors_aux> 400a5a: 6500 nop 400a5c: 6444 restore 32,ra 400a5e: e8a0 jrc ra Disassembly of section .fini: 00401050 <_fini>: 401050: f000 6a02 li v0,2 401054: f072 0b0c la v1,3fa0c0 <_DYNAMIC-0x60dc> 401058: f400 3240 sll v0,16 40105c: e269 addu v0,v1 40105e: 64c4 save 32,ra 401060: 659a move gp,v0 401062: d204 sw v0,16(sp) 401064: 1a00 035a jal 400d68 <__do_global_dtors_aux> 401068: 6500 nop 40106a: 6444 restore 32,ra 40106c: e8a0 jrc ra Maciej ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-25 5:14 ` Maciej W. Rozycki @ 2013-01-25 13:59 ` Richard Sandiford 2013-01-28 22:18 ` Steve Ellcey 2013-01-25 22:10 ` Steve Ellcey 1 sibling, 1 reply; 26+ messages in thread From: Richard Sandiford @ 2013-01-25 13:59 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: Ellcey, Steve, libc-alpha, libc-ports, Chung-Lin Tang "Maciej W. Rozycki" <macro@codesourcery.com> writes: >> After some poking around I think the problem is not the glibc that I >> built but with crti.o and crtn.o. If I use >> regular mips32 versions of these crt files and mips16 built versions >> of everything else (main program, glibc, >> libgcc, etc.) then I can run a simple hello world program, if I use >> the mips16 versions of crti and crtn I get: >> >> >> mips-mti-linux-gnu-gcc -mips32r2 -mips16 >> -Wl,--dynamic-linker=/local/home/sellcey/gcc/mips16/sysroot-mips-mti-linux-gnu/mips16/usr/lib/ld-2.17.90.so' >> -Wl,-rpath=/local/home/sellcey/gcc/mips16/sysroot-mips-mti-linux-gnu/mips16/usr/lib:/local/home/sellcey/gcc/mips16/install-mips-mti-linux-gnu/mips-mti-linux-gnu/lib/mips16' >> hi.c -o x >> >> mips-mti-linux-gnu-qemu -r 2.6.38 ./x >> hi >> qemu: uncaught target signal 11 (Segmentation fault) - core dumped >> >> Note that it did print 'hi' before getting the signal. >> >> If I try adding '-static' then I get: >> >> mips-mti-linux-gnu-gcc -static -mips32r2 -mips16 hi.c -o x >> mips-mti-linux-gnu-qemu -r 2.6.38 ./x >> qemu: uncaught target signal 4 (Illegal instruction) - core dumped >> >> >> >> I was wondering if you have any idea what could be causing this. >> Should the standard qemu be able >> to run mips16 executables with no changes? > > I am fairly sure QEMU has issues with MIPS16 code, and I wouldn't be > surprised if user-mode emulation actually required porting QEMU, rather > than merely fixing bugs, to support MIPS16 binaries -- it may not be > prepared to handle the ISA bit at all. Never tried user-mode emulation either, but FWIW... > Have you tried running your code on actual hardware? This is how we did > testing of all these changes. ...QEMU 1.2 system emulation seems to handle MIPS16 pretty well, so that might be another alternative. See: http://gcc.gnu.org/ml/gcc-testresults/2013-01/msg02626.html http://gcc.gnu.org/ml/gcc-testresults/2013-01/msg02550.html for some recent results. Richard ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-25 13:59 ` Richard Sandiford @ 2013-01-28 22:18 ` Steve Ellcey 0 siblings, 0 replies; 26+ messages in thread From: Steve Ellcey @ 2013-01-28 22:18 UTC (permalink / raw) To: Richard Sandiford Cc: Maciej W. Rozycki, libc-alpha, libc-ports, Chung-Lin Tang On Fri, 2013-01-25 at 13:59 +0000, Richard Sandiford wrote: > "Maciej W. Rozycki" <macro@codesourcery.com> writes: > > Never tried user-mode emulation either, but FWIW... > > > Have you tried running your code on actual hardware? This is how we did > > testing of all these changes. > > ...QEMU 1.2 system emulation seems to handle MIPS16 pretty well, > so that might be another alternative. See: > > http://gcc.gnu.org/ml/gcc-testresults/2013-01/msg02626.html > http://gcc.gnu.org/ml/gcc-testresults/2013-01/msg02550.html > > for some recent results. > > Richard FYI: Now that I got my .init section straightened out with a patch to GCC I was able to use qemu to test mips16. I ran the entire GCC testsuite with -mips16 and the only failure I saw that didn't look familiar to me was: FAIL: gcc.c-torture/execute/ieee/compare-fp-1.c compilation, -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects This is a segfault coming from the linker, I haven't investigated it anymore then that yet, but in general the testing looks very good now. Steve Ellcey sellcey@mips.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-25 5:14 ` Maciej W. Rozycki 2013-01-25 13:59 ` Richard Sandiford @ 2013-01-25 22:10 ` Steve Ellcey 2013-01-26 0:32 ` Maciej W. Rozycki 1 sibling, 1 reply; 26+ messages in thread From: Steve Ellcey @ 2013-01-25 22:10 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: libc-alpha, libc-ports, Chung-Lin Tang On Fri, 2013-01-25 at 05:13 +0000, Maciej W. Rozycki wrote: > Have you tried running your code on actual hardware? This is how we did > testing of all these changes. I thought I had a simple program working on my 74K, but I just tried a test case (hello world compiled statically) and it gave me a bus error. > Please also note that as I mentioned along the patch submission mixing > execution modes in static constructors or destructors installed as single > lumps of code (that is with the use of the DT_INIT or DT_FINI dynamic > tags) cannot be supported. Can you run `objdump -j .init -j .fini -d' on > your binary and make sure the disassembly looks right? Mine looks a bit different, this is the .init and .fini from a dynamically linked big endian hello world program, I am not sure where the addiu instructions are coming from. x: file format elf32-tradbigmips Disassembly of section .init: 004004d0 <_init>: 4004d0: f000 6a02 li v0,2 4004d4: f2f0 0b0c la v1,3f87c0 <_DYNAMIC-0x7a08> 4004d8: f400 3240 sll v0,16 4004dc: e269 addu v0,v1 4004de: 64c4 save 32,ra 4004e0: 659a move gp,v0 4004e2: d204 sw v0,16(sp) 4004e4: f030 9a64 lw v1,-32732(v0) 4004e8: 2304 beqz v1,4004f2 <_init+0x22> 4004ea: f030 9a44 lw v0,-32732(v0) 4004ee: ea40 jalr v0 4004f0: 653a move t9,v0 4004f2: 6500 nop 4004f4: 0411 addiu a0,sp,68 4004f6: 0001 addiu s0,sp,4 4004f8: 0000 addiu s0,sp,0 4004fa: 0000 addiu s0,sp,0 4004fc: 7410 cmpi a0,16 4004fe: 0196 addiu s1,sp,600 400500: 0000 addiu s0,sp,0 400502: 0000 addiu s0,sp,0 400504: 0411 addiu a0,sp,68 400506: 0001 addiu s0,sp,4 400508: 0000 addiu s0,sp,0 40050a: 0000 addiu s0,sp,0 40050c: 7410 cmpi a0,16 40050e: 01c0 addiu s1,sp,768 400510: 0000 addiu s0,sp,0 400512: 0000 addiu s0,sp,0 400514: 6444 restore 32,ra 400516: e8a0 jrc ra Disassembly of section .fini: 00400730 <_fini>: 400730: f000 6a02 li v0,2 400734: f090 0b0c la v1,3f87c0 <_DYNAMIC-0x7a08> 400738: f400 3240 sll v0,16 40073c: e269 addu v0,v1 40073e: 64c4 save 32,ra 400740: 659a move gp,v0 400742: d204 sw v0,16(sp) 400744: 0411 addiu a0,sp,68 400746: 0001 addiu s0,sp,4 400748: 0000 addiu s0,sp,0 40074a: 0000 addiu s0,sp,0 40074c: 7410 cmpi a0,16 40074e: 0182 addiu s1,sp,520 400750: 0000 addiu s0,sp,0 400752: 0000 addiu s0,sp,0 400754: 6444 restore 32,ra 400756: e8a0 jrc ra Steve Ellcey sellcey@mips.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-25 22:10 ` Steve Ellcey @ 2013-01-26 0:32 ` Maciej W. Rozycki 2013-01-28 17:36 ` Steve Ellcey 0 siblings, 1 reply; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-26 0:32 UTC (permalink / raw) To: Steve Ellcey; +Cc: libc-alpha, libc-ports, Chung-Lin Tang On Fri, 25 Jan 2013, Steve Ellcey wrote: > > Please also note that as I mentioned along the patch submission mixing > > execution modes in static constructors or destructors installed as single > > lumps of code (that is with the use of the DT_INIT or DT_FINI dynamic > > tags) cannot be supported. Can you run `objdump -j .init -j .fini -d' on > > your binary and make sure the disassembly looks right? > > Mine looks a bit different, this is the .init and .fini from a > dynamically linked big endian hello world program, I am not sure where > the addiu instructions are coming from. You have some standard MIPS code there, this is not ever going to work unless we switch to DT_INIT_ARRAY and DT_FINI_ARRAY constructors/destructors. Until then you need to rebuild the relevant sources as MIPS16 code. > x: file format elf32-tradbigmips > > > Disassembly of section .init: > > 004004d0 <_init>: > 4004d0: f000 6a02 li v0,2 > 4004d4: f2f0 0b0c la v1,3f87c0 <_DYNAMIC-0x7a08> > 4004d8: f400 3240 sll v0,16 > 4004dc: e269 addu v0,v1 > 4004de: 64c4 save 32,ra > 4004e0: 659a move gp,v0 > 4004e2: d204 sw v0,16(sp) > 4004e4: f030 9a64 lw v1,-32732(v0) > 4004e8: 2304 beqz v1,4004f2 <_init+0x22> > 4004ea: f030 9a44 lw v0,-32732(v0) > 4004ee: ea40 jalr v0 > 4004f0: 653a move t9,v0 > 4004f2: 6500 nop > 4004f4: 0411 addiu a0,sp,68 > 4004f6: 0001 addiu s0,sp,4 > 4004f8: 0000 addiu s0,sp,0 > 4004fa: 0000 addiu s0,sp,0 > 4004fc: 7410 cmpi a0,16 > 4004fe: 0196 addiu s1,sp,600 > 400500: 0000 addiu s0,sp,0 > 400502: 0000 addiu s0,sp,0 > 400504: 0411 addiu a0,sp,68 > 400506: 0001 addiu s0,sp,4 > 400508: 0000 addiu s0,sp,0 > 40050a: 0000 addiu s0,sp,0 > 40050c: 7410 cmpi a0,16 > 40050e: 01c0 addiu s1,sp,768 > 400510: 0000 addiu s0,sp,0 > 400512: 0000 addiu s0,sp,0 > 400514: 6444 restore 32,ra > 400516: e8a0 jrc ra > > Disassembly of section .fini: > > 00400730 <_fini>: > 400730: f000 6a02 li v0,2 > 400734: f090 0b0c la v1,3f87c0 <_DYNAMIC-0x7a08> > 400738: f400 3240 sll v0,16 > 40073c: e269 addu v0,v1 > 40073e: 64c4 save 32,ra > 400740: 659a move gp,v0 > 400742: d204 sw v0,16(sp) > 400744: 0411 addiu a0,sp,68 > 400746: 0001 addiu s0,sp,4 > 400748: 0000 addiu s0,sp,0 > 40074a: 0000 addiu s0,sp,0 > 40074c: 7410 cmpi a0,16 > 40074e: 0182 addiu s1,sp,520 > 400750: 0000 addiu s0,sp,0 > 400752: 0000 addiu s0,sp,0 > 400754: 6444 restore 32,ra > 400756: e8a0 jrc ra The odd instructions disassemble as follows when interpreted as standard MIPS code: 0: 04110001 bal 8 4: 00000000 nop 8: 74100196 jalx 400658 c: 00000000 nop 10: 04110001 bal 18 14: 00000000 nop 18: 741001c0 jalx 400700 1c: 00000000 nop and: 0: 04110001 bal 8 4: 00000000 nop 8: 74100182 jalx 400608 c: 00000000 nop Make sure that you've got your GCC pieces of the MIPS16 multilib right (crtbegin.o and crtend.o files). Maciej ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-26 0:32 ` Maciej W. Rozycki @ 2013-01-28 17:36 ` Steve Ellcey 2013-01-28 17:56 ` Steve Ellcey 2013-01-28 18:58 ` Richard Henderson 0 siblings, 2 replies; 26+ messages in thread From: Steve Ellcey @ 2013-01-28 17:36 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: libc-alpha, libc-ports, Chung-Lin Tang On Sat, 2013-01-26 at 00:31 +0000, Maciej W. Rozycki wrote: > On Fri, 25 Jan 2013, Steve Ellcey wrote: > > > > Please also note that as I mentioned along the patch submission mixing > > > execution modes in static constructors or destructors installed as single > > > lumps of code (that is with the use of the DT_INIT or DT_FINI dynamic > > > tags) cannot be supported. Can you run `objdump -j .init -j .fini -d' on > > > your binary and make sure the disassembly looks right? > > > > Mine looks a bit different, this is the .init and .fini from a > > dynamically linked big endian hello world program, I am not sure where > > the addiu instructions are coming from. > > You have some standard MIPS code there, this is not ever going to work > unless we switch to DT_INIT_ARRAY and DT_FINI_ARRAY > constructors/destructors. Until then you need to rebuild the relevant > sources as MIPS16 code. OK, I see where this is happening now. crti (from glibc) is mips16 and crtbegin (from gcc) is mips32. crtbegin is mips32 because it uses CRT_CALL_STATIC_FUNCTION and that has '.nomips16' in it. I am not sure how to rewrite CRT_CALL_STATIC_FUNCTION in mips16 to avoid this and it looks like the codesourcery version of GCC is handling this by making all .init/.fini code mips32 instead of mips16. So, should I try to make crti use a mips32 .init or make crtbegin use a mips16 .init? I am not sure which is better. Steve Ellcey sellcey@mips.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-28 17:36 ` Steve Ellcey @ 2013-01-28 17:56 ` Steve Ellcey 2013-01-28 21:08 ` Maciej W. Rozycki 2013-01-28 18:58 ` Richard Henderson 1 sibling, 1 reply; 26+ messages in thread From: Steve Ellcey @ 2013-01-28 17:56 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: libc-alpha, libc-ports, Chung-Lin Tang On Mon, 2013-01-28 at 09:35 -0800, Steve Ellcey wrote: > OK, I see where this is happening now. crti (from glibc) is mips16 and > crtbegin (from gcc) is mips32. crtbegin is mips32 because it uses > CRT_CALL_STATIC_FUNCTION and that has '.nomips16' in it. I am not sure > how to rewrite CRT_CALL_STATIC_FUNCTION in mips16 to avoid this and it > looks like the codesourcery version of GCC is handling this by making > all .init/.fini code mips32 instead of mips16. So, should I try to make > crti use a mips32 .init or make crtbegin use a mips16 .init? I am not > sure which is better. > > Steve Ellcey > sellcey@mips.com Following up to my own email, I think I was wrong about codesourcery using mips32 code in .init/.fini, it looks like they have a GCC patch to define CRT_CALL_STATIC_FUNCTION differently for mips16/mips32. I am going to try and apply that patch to my ToT GCC and see what happens. Steve Ellcey sellcey@mips.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-28 17:56 ` Steve Ellcey @ 2013-01-28 21:08 ` Maciej W. Rozycki 0 siblings, 0 replies; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-28 21:08 UTC (permalink / raw) To: Steve Ellcey; +Cc: libc-alpha, libc-ports, Chung-Lin Tang On Mon, 28 Jan 2013, Steve Ellcey wrote: > Following up to my own email, I think I was wrong about codesourcery > using mips32 code in .init/.fini, it looks like they have a GCC patch > to define CRT_CALL_STATIC_FUNCTION differently for mips16/mips32. I am > going to try and apply that patch to my ToT GCC and see what happens. Indeed, I wasn't aware there was an outstanding change there. Sorry about that. I think for now our best option is to follow Richard's suggestion. I'll take it into account with the upcoming patch update. Maciej ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-28 17:36 ` Steve Ellcey 2013-01-28 17:56 ` Steve Ellcey @ 2013-01-28 18:58 ` Richard Henderson 2013-01-28 21:06 ` Maciej W. Rozycki 1 sibling, 1 reply; 26+ messages in thread From: Richard Henderson @ 2013-01-28 18:58 UTC (permalink / raw) To: Steve Ellcey; +Cc: Maciej W. Rozycki, libc-alpha, libc-ports, Chung-Lin Tang On 01/28/2013 09:35 AM, Steve Ellcey wrote: > OK, I see where this is happening now. crti (from glibc) is mips16 and > crtbegin (from gcc) is mips32. crtbegin is mips32 because it uses > CRT_CALL_STATIC_FUNCTION and that has '.nomips16' in it. I am not sure > how to rewrite CRT_CALL_STATIC_FUNCTION in mips16 to avoid this and it > looks like the codesourcery version of GCC is handling this by making > all .init/.fini code mips32 instead of mips16. So, should I try to make > crti use a mips32 .init or make crtbegin use a mips16 .init? I am not > sure which is better. FWIW, I think you're better off considering the .init section to be mips32 code always, as a part of the ABI. That way stuff that worked before continues to work, and no one has to worry about how the installed toolchain itself is configured. And of course as you note elsewhere, this is an excellent time to have new toolchains stop using .init, as DT_INIT_ARRAY has none of these problems. r~ ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-28 18:58 ` Richard Henderson @ 2013-01-28 21:06 ` Maciej W. Rozycki 2013-01-28 21:17 ` Steve Ellcey 0 siblings, 1 reply; 26+ messages in thread From: Maciej W. Rozycki @ 2013-01-28 21:06 UTC (permalink / raw) To: Richard Henderson; +Cc: Steve Ellcey, libc-alpha, libc-ports, Chung-Lin Tang On Mon, 28 Jan 2013, Richard Henderson wrote: > > OK, I see where this is happening now. crti (from glibc) is mips16 and > > crtbegin (from gcc) is mips32. crtbegin is mips32 because it uses > > CRT_CALL_STATIC_FUNCTION and that has '.nomips16' in it. I am not sure > > how to rewrite CRT_CALL_STATIC_FUNCTION in mips16 to avoid this and it > > looks like the codesourcery version of GCC is handling this by making > > all .init/.fini code mips32 instead of mips16. So, should I try to make > > crti use a mips32 .init or make crtbegin use a mips16 .init? I am not > > sure which is better. > > FWIW, I think you're better off considering the .init section to be > mips32 code always, as a part of the ABI. That way stuff that worked > before continues to work, and no one has to worry about how the > installed toolchain itself is configured. That may work as a temporary measure for MIPS16 code only, as any processor that supports MIPS16 execution must also support standard MIPS execution. However we have the very same problem with microMIPS code -- that glibc supports out of the box thanks to the high level of source compatibility the ISA provides and GCC support for which is currently under review. There we cannot agree upon using standard MIPS code in .init/.fini because we have conflicting objectives to choose from: 1. We want to support mixing standard MIPS and microMIPS code, so we cannot assume all binary modules in a static link will use the same encoding. 2. We want to support processors that only support either instruction encoding, so the encoding of .init/.fini code has to match the encoding of the remaining parts of the module concerned. And regardless of the scenario chosen we want to keep the same binary modules built for either ISA without the need to rebuild any parts of them. > And of course as you note elsewhere, this is an excellent time to > have new toolchains stop using .init, as DT_INIT_ARRAY has none of > these problems. Given the above I think we need it sooner rather than later. Who's got the power to make it happen? Maciej ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-28 21:06 ` Maciej W. Rozycki @ 2013-01-28 21:17 ` Steve Ellcey 2013-01-29 16:24 ` Richard Henderson 0 siblings, 1 reply; 26+ messages in thread From: Steve Ellcey @ 2013-01-28 21:17 UTC (permalink / raw) To: Maciej W. Rozycki Cc: Richard Henderson, libc-alpha, libc-ports, Chung-Lin Tang, rdsandiford On Mon, 2013-01-28 at 21:06 +0000, Maciej W. Rozycki wrote: > On Mon, 28 Jan 2013, Richard Henderson wrote: > > > And of course as you note elsewhere, this is an excellent time to > > have new toolchains stop using .init, as DT_INIT_ARRAY has none of > > these problems. > > Given the above I think we need it sooner rather than later. Who's got > the power to make it happen? > > Maciej Would switching from .init to DT_INIT_ARRAY be an incompatible ABI change? I think I remember the GNU linker can handle mixing both types of sections in one executable but I am not sure if that is right. I added Richard Sandiford to this email in case he hasn't seen it on the libc mailing lists. Steve Ellcey sellcey@mips.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-28 21:17 ` Steve Ellcey @ 2013-01-29 16:24 ` Richard Henderson 2013-01-29 19:27 ` Joseph S. Myers 0 siblings, 1 reply; 26+ messages in thread From: Richard Henderson @ 2013-01-29 16:24 UTC (permalink / raw) To: Steve Ellcey Cc: Maciej W. Rozycki, libc-alpha, libc-ports, Chung-Lin Tang, rdsandiford On 01/28/2013 01:17 PM, Steve Ellcey wrote: > On Mon, 2013-01-28 at 21:06 +0000, Maciej W. Rozycki wrote: >> On Mon, 28 Jan 2013, Richard Henderson wrote: >> >>> And of course as you note elsewhere, this is an excellent time to >>> have new toolchains stop using .init, as DT_INIT_ARRAY has none of >>> these problems. >> >> Given the above I think we need it sooner rather than later. Who's got >> the power to make it happen? >> >> Maciej > > Would switching from .init to DT_INIT_ARRAY be an incompatible ABI > change? I think I remember the GNU linker can handle mixing both types > of sections in one executable but I am not sure if that is right. > > I added Richard Sandiford to this email in case he hasn't seen it on the > libc mailing lists. Both gcc and ld have an --enable-initfini-array configuration switch. Both programs can autodetect the current host setting during native builds to preserve the system setting. I don't believe there's currently a way to force the setting on based on a configuration triple, but it ought not be hard to add. r~ ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] MIPS16: MIPS16 support proper 2013-01-29 16:24 ` Richard Henderson @ 2013-01-29 19:27 ` Joseph S. Myers 0 siblings, 0 replies; 26+ messages in thread From: Joseph S. Myers @ 2013-01-29 19:27 UTC (permalink / raw) To: Richard Henderson Cc: Steve Ellcey, Maciej W. Rozycki, libc-alpha, libc-ports, Chung-Lin Tang, rdsandiford On Tue, 29 Jan 2013, Richard Henderson wrote: > Both gcc and ld have an --enable-initfini-array configuration switch. > > Both programs can autodetect the current host setting during native builds to > preserve the system setting. > > I don't believe there's currently a way to force the setting on based on a > configuration triple, but it ought not be hard to add. FWIW, ARM EABI has used init_array/fini_array for a long time (probably since before this configure option existed, and maybe not using the same mechanism as the configure option), following an EABI requirement (which might have been motivated by Thumb causing the same issues for .init/.fini as MIPS16 and microMIPS). -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2013-02-27 23:54 UTC | newest] Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-01-23 4:41 [PATCH 0/2] MIPS16: MIPS16 support Maciej W. Rozycki 2013-01-23 4:41 ` [PATCH 1/2] MIPS16: Allocate GLIBC_2.18 Maciej W. Rozycki 2013-01-23 4:42 ` [PATCH 2/2] MIPS16: MIPS16 support proper Maciej W. Rozycki 2013-01-23 17:22 ` Joseph S. Myers 2013-01-24 10:10 ` Chung-Lin Tang 2013-01-24 13:13 ` Maciej W. Rozycki 2013-01-24 13:56 ` Richard Sandiford 2013-02-20 16:19 ` [PATCH v2] MIPS: MIPS16 support Maciej W. Rozycki 2013-02-20 16:29 ` Joseph S. Myers 2013-02-27 1:38 ` [PATCH v3] " Maciej W. Rozycki 2013-02-27 17:50 ` Joseph S. Myers 2013-02-27 23:54 ` Maciej W. Rozycki 2013-01-24 18:08 ` [PATCH 2/2] MIPS16: MIPS16 support proper Ellcey, Steve 2013-01-25 5:14 ` Maciej W. Rozycki 2013-01-25 13:59 ` Richard Sandiford 2013-01-28 22:18 ` Steve Ellcey 2013-01-25 22:10 ` Steve Ellcey 2013-01-26 0:32 ` Maciej W. Rozycki 2013-01-28 17:36 ` Steve Ellcey 2013-01-28 17:56 ` Steve Ellcey 2013-01-28 21:08 ` Maciej W. Rozycki 2013-01-28 18:58 ` Richard Henderson 2013-01-28 21:06 ` Maciej W. Rozycki 2013-01-28 21:17 ` Steve Ellcey 2013-01-29 16:24 ` Richard Henderson 2013-01-29 19:27 ` Joseph S. Myers
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).