From 645d0312c2d6b6492cc4b3891bc1a91908dc24b7 Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Wed, 5 Feb 2014 18:51:43 -0800 Subject: [PATCH] [MIPS64] libc/libm support libc/libm support for MIPS64 targets Change-Id: I8271941d418612a286be55495f0e95822f90004f Signed-off-by: Chris Dearman Signed-off-by: Raghu Gandham --- libc/Android.mk | 9 +- libc/arch-mips/mips.mk | 1 - libc/arch-mips64/bionic/__bionic_clone.S | 99 ++++ libc/arch-mips64/bionic/__get_sp.S | 39 ++ .../bionic/__set_tls.c} | 19 +- .../bionic/_exit_with_stack_teardown.S | 48 ++ libc/arch-mips64/bionic/_setjmp.S | 188 ++++++++ libc/arch-mips64/bionic/atexit.h | 36 ++ libc/arch-mips64/bionic/bzero.S | 43 ++ libc/arch-mips64/bionic/cacheflush.cpp | 99 ++++ libc/arch-mips64/bionic/crtbegin.c | 94 ++++ libc/arch-mips64/bionic/crtbegin_so.c | 38 ++ libc/arch-mips64/bionic/futex_mips.S | 145 ++++++ libc/arch-mips64/bionic/getdents.cpp | 97 ++++ libc/arch-mips64/bionic/memcmp16.S | 53 +++ libc/arch-mips64/bionic/setjmp.S | 211 +++++++++ libc/arch-mips64/bionic/sigsetjmp.S | 77 ++++ libc/arch-mips64/bionic/syscall.S | 69 +++ libc/arch-mips64/bionic/vfork.S | 72 +++ libc/arch-mips64/include/machine/asm.h | 305 +++++++++++++ .../arch-mips64/include/machine/elf_machdep.h | 196 ++++++++ libc/arch-mips64/include/machine/endian.h | 70 +++ libc/arch-mips64/include/machine/exec.h | 188 ++++++++ libc/arch-mips64/include/machine/ieee.h | 169 +++++++ libc/arch-mips64/include/machine/limits.h | 62 +++ libc/arch-mips64/include/machine/regdef.h | 99 ++++ libc/arch-mips64/include/machine/regnum.h | 119 +++++ libc/arch-mips64/include/machine/setjmp.h | 10 + libc/arch-mips64/include/machine/signal.h | 53 +++ libc/arch-mips64/mips64.mk | 28 ++ libc/arch-mips64/string/memcpy.S | 423 ++++++++++++++++++ libc/arch-mips64/string/memset.S | 323 +++++++++++++ libc/arch-mips64/string/mips-string-ops.h | 148 ++++++ libc/arch-mips64/string/mips_strlen.c | 224 ++++++++++ libc/include/sys/stat.h | 28 +- libc/include/sys/vfs.h | 18 +- libm/Android.mk | 4 + libm/mips/_fpmath.h | 35 +- 38 files changed, 3901 insertions(+), 38 deletions(-) create mode 100644 libc/arch-mips64/bionic/__bionic_clone.S create mode 100644 libc/arch-mips64/bionic/__get_sp.S rename libc/{arch-mips/bionic/memmove.c => arch-mips64/bionic/__set_tls.c} (76%) create mode 100644 libc/arch-mips64/bionic/_exit_with_stack_teardown.S create mode 100644 libc/arch-mips64/bionic/_setjmp.S create mode 100644 libc/arch-mips64/bionic/atexit.h create mode 100644 libc/arch-mips64/bionic/bzero.S create mode 100644 libc/arch-mips64/bionic/cacheflush.cpp create mode 100644 libc/arch-mips64/bionic/crtbegin.c create mode 100644 libc/arch-mips64/bionic/crtbegin_so.c create mode 100644 libc/arch-mips64/bionic/futex_mips.S create mode 100644 libc/arch-mips64/bionic/getdents.cpp create mode 100644 libc/arch-mips64/bionic/memcmp16.S create mode 100644 libc/arch-mips64/bionic/setjmp.S create mode 100644 libc/arch-mips64/bionic/sigsetjmp.S create mode 100644 libc/arch-mips64/bionic/syscall.S create mode 100644 libc/arch-mips64/bionic/vfork.S create mode 100644 libc/arch-mips64/include/machine/asm.h create mode 100644 libc/arch-mips64/include/machine/elf_machdep.h create mode 100644 libc/arch-mips64/include/machine/endian.h create mode 100644 libc/arch-mips64/include/machine/exec.h create mode 100644 libc/arch-mips64/include/machine/ieee.h create mode 100644 libc/arch-mips64/include/machine/limits.h create mode 100644 libc/arch-mips64/include/machine/regdef.h create mode 100644 libc/arch-mips64/include/machine/regnum.h create mode 100644 libc/arch-mips64/include/machine/setjmp.h create mode 100644 libc/arch-mips64/include/machine/signal.h create mode 100644 libc/arch-mips64/mips64.mk create mode 100644 libc/arch-mips64/string/memcpy.S create mode 100644 libc/arch-mips64/string/memset.S create mode 100644 libc/arch-mips64/string/mips-string-ops.h create mode 100644 libc/arch-mips64/string/mips_strlen.c diff --git a/libc/Android.mk b/libc/Android.mk index 7edadd7d2..91f6cd193 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -481,10 +481,11 @@ libc_common_src_files += \ endif # arm64 -ifeq ($(TARGET_ARCH),mips) +ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64)) libc_common_src_files += \ bionic/memchr.c \ bionic/memcmp.c \ + bionic/memmove.c \ bionic/memrchr.c \ bionic/strchr.cpp \ bionic/strnlen.c \ @@ -507,7 +508,7 @@ libc_common_src_files += \ upstream-freebsd/lib/libc/string/wcsrchr.c \ upstream-freebsd/lib/libc/string/wmemcmp.c \ -endif # mips +endif # mips || mips64 ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86_64)) libc_common_src_files += \ @@ -618,7 +619,7 @@ ifeq ($(TARGET_ARCH),arm) libc_crt_target_cflags += -mthumb-interwork endif # arm -ifeq ($(TARGET_ARCH),mips) +ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64)) ifneq ($(ARCH_MIPS_HAS_FPU),true) libc_common_cflags += -DSOFTFLOAT endif @@ -683,7 +684,7 @@ ifeq ($(TARGET_ARCH),arm64) libc_crt_target_so_cflags := libc_crt_target_crtbegin_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.c endif -ifeq ($(TARGET_ARCH),mips) +ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64)) libc_crt_target_so_cflags := -fPIC libc_crt_target_crtbegin_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.c endif diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk index 1119a66be..6f5792c5b 100644 --- a/libc/arch-mips/mips.mk +++ b/libc/arch-mips/mips.mk @@ -6,7 +6,6 @@ _LIBC_ARCH_COMMON_SRC_FILES := \ arch-mips/bionic/futex_mips.S \ arch-mips/bionic/__get_sp.S \ arch-mips/bionic/memcmp16.S \ - arch-mips/bionic/memmove.c \ arch-mips/bionic/_setjmp.S \ arch-mips/bionic/setjmp.S \ arch-mips/bionic/__set_tls.c \ diff --git a/libc/arch-mips64/bionic/__bionic_clone.S b/libc/arch-mips64/bionic/__bionic_clone.S new file mode 100644 index 000000000..2a9a2b084 --- /dev/null +++ b/libc/arch-mips64/bionic/__bionic_clone.S @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) +FRAMESZ = MKFSIZ(NARGSAVE,0) +FRAME_ARG = 0*REGSZ +FRAME_FN = 1*REGSZ +#else +FRAMESZ = MKFSIZ(0,3) +FRAME_GP = FRAMESZ-1*REGSZ +FRAME_ARG = FRAMESZ-2*REGSZ +FRAME_FN = FRAMESZ-3*REGSZ +#endif + +// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg); + .text +LEAF(__bionic_clone,FRAMESZ) + PTR_SUBU sp, FRAMESZ # allocate stack frame + SETUP_GP64(FRAME_GP,__bionic_clone) + SAVE_GP(FRAME_GP) + + # set up child stack + PTR_SUBU a1,FRAMESZ +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_L t0,FRAMESZ+5*REGSZ(sp) # fn + PRL_L t1,FRAMESZ+6*REGSZ(sp) # arg + PTR_S t0,FRAME_FN(a1) # fn + PTR_S t1,FRAME_ARG(a1) # arg +#else + PTR_L t0,FRAME_GP(sp) # copy gp to child stack + PTR_S t0,FRAME_GP(a1) + PTR_S a5,FRAME_FN(a1) # fn + PTR_S a6,FRAME_ARG(a1) # arg +# endif + + # remainder of arguments are correct for clone system call + LI v0,__NR_clone + syscall + + move a0,v0 + bnez a3,.L__error_bc + + beqz v0,.L__thread_start_bc + + RESTORE_GP64 + PTR_ADDU sp,FRAMESZ + j ra + +.L__thread_start_bc: + # void __bionic_clone_entry(int (*func)(void*), void *arg) + PTR_L a0,FRAME_FN(sp) # fn + PTR_L a1,FRAME_ARG(sp) # arg + LA t9,__bionic_clone_entry + RESTORE_GP64 + /* + * For O32 etc the child stack must have space for a0..a3 to be stored + * For N64 etc, the child stack can be restored to the original value + */ +#if !((_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32)) + PTR_ADDU sp,FRAMESZ +#endif + j t9 + +.L__error_bc: + LA t9,__set_errno + RESTORE_GP64 + PTR_ADDU sp,FRAMESZ + j t9 + END(__bionic_clone) diff --git a/libc/arch-mips64/bionic/__get_sp.S b/libc/arch-mips64/bionic/__get_sp.S new file mode 100644 index 000000000..834c89d82 --- /dev/null +++ b/libc/arch-mips64/bionic/__get_sp.S @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + .text + +/* void *__get_sp(void) */ + + .type __get_sp, @function + .global __get_sp + .align 4 + .ent __get_sp +__get_sp: + move $v0, $sp + j $ra + .end __get_sp diff --git a/libc/arch-mips/bionic/memmove.c b/libc/arch-mips64/bionic/__set_tls.c similarity index 76% rename from libc/arch-mips/bionic/memmove.c rename to libc/arch-mips64/bionic/__set_tls.c index 1f4522b0c..38e3a505f 100644 --- a/libc/arch-mips/bionic/memmove.c +++ b/libc/arch-mips64/bionic/__set_tls.c @@ -25,20 +25,11 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include -#include +#include -void *memmove(void *dst, const void *src, size_t n) +extern int __set_thread_area(void *u_info); + +int __set_tls(void *ptr) { - const char *p = src; - char *q = dst; - /* We can use the optimized memcpy if the destination is completely below the - * source (i.e. q + n <= p), or if it is completely over it (i.e. q >= p+n). - */ - if (__builtin_expect((q + n < p) || (q >= p + n), 1)) { - return memcpy(dst, src, n); - } else { - bcopy(src, dst, n); - return dst; - } + return __set_thread_area(ptr); } diff --git a/libc/arch-mips64/bionic/_exit_with_stack_teardown.S b/libc/arch-mips64/bionic/_exit_with_stack_teardown.S new file mode 100644 index 000000000..8f624c324 --- /dev/null +++ b/libc/arch-mips64/bionic/_exit_with_stack_teardown.S @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + + .text + +// void _exit_with_stack_teardown(void* stackBase, size_t stackSize) + + .type _exit_with_stack_teardown, @function + .global _exit_with_stack_teardown + .align 4 + .ent _exit_with_stack_teardown +_exit_with_stack_teardown: + li $v0, __NR_munmap + syscall + // If munmap failed, we ignore the failure and exit anyway. + + li $a0, 0 + li $v0, __NR_exit + syscall + // The exit syscall does not return. + .end _exit_with_stack_teardown diff --git a/libc/arch-mips64/bionic/_setjmp.S b/libc/arch-mips64/bionic/_setjmp.S new file mode 100644 index 000000000..e7083ae29 --- /dev/null +++ b/libc/arch-mips64/bionic/_setjmp.S @@ -0,0 +1,188 @@ +/* $OpenBSD: _setjmp.S,v 1.4 2005/08/07 16:40:15 espie Exp $ */ + +/* + * Copyright (c) 2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opsycon AB nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +#include +#include + +/* + * _setjmp, _longjmp (not restoring signal state) + * + * XXX FPSET should probably be taken from SR setting. hmmm... + * GPOFF and FRAMESIZE must be the same for both _setjmp and _longjmp! + * + */ + +FRAMESZ= MKFSIZ(0,4) +GPOFF= FRAMESZ-2*REGSZ + +#define FPREG64_S(FPR, OFF, BASE) \ + swc1 FPR, OFF(BASE) ; \ + mfhc1 t0, FPR ; \ + sw t0, OFF+4(BASE) ; + +#define FPREG64_L(FPR, OFF, BASE) \ + lw t0, OFF+4(BASE) ; \ + lw t1, OFF(BASE) ; \ + mtc1 t1, FPR ; \ + mthc1 t0, FPR ; \ + +LEAF(_setjmp, FRAMESZ) + PTR_SUBU sp, FRAMESZ + SETUP_GP64(GPOFF, _setjmp) + SAVE_GP(GPOFF) + .set noreorder +#if defined(__mips64) + dli v0, 0xACEDBADE # sigcontext magic number +#else + li v0, 0xACEDBADE # sigcontext magic number +#endif + REG_S v0, SC_REGS+ZERO*REGSZ(a0) + REG_S s0, SC_REGS+S0*REGSZ(a0) + REG_S s1, SC_REGS+S1*REGSZ(a0) + REG_S s2, SC_REGS+S2*REGSZ(a0) + REG_S s3, SC_REGS+S3*REGSZ(a0) + REG_S s4, SC_REGS+S4*REGSZ(a0) + REG_S s5, SC_REGS+S5*REGSZ(a0) + REG_S s6, SC_REGS+S6*REGSZ(a0) + REG_S s7, SC_REGS+S7*REGSZ(a0) + REG_S s8, SC_REGS+S8*REGSZ(a0) + REG_L v0, GPOFF(sp) + REG_S v0, SC_REGS+GP*REGSZ(a0) + PTR_ADDU v0, sp, FRAMESZ + REG_S v0, SC_REGS+SP*REGSZ(a0) + REG_S ra, SC_PC(a0) + +#if !defined(SOFTFLOAT) + li v0, 1 # be nice if we could tell + REG_S v0, SC_FPUSED(a0) # sc_fpused = 1 + cfc1 v0, $31 +#if _MIPS_FPSET == 32 + FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0) + FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0) + FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0) + FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0) + FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0) + FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0) + FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0) + FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0) + FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0) + FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0) + FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0) + FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0) +#else + swc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0) + swc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0) + swc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0) + swc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0) + swc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0) + swc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0) + swc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0) + swc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0) + swc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0) + swc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0) + swc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0) + swc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0) +#endif + REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0) +#endif /* !SOFTFLOAT */ + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + j ra + move v0, zero +END(_setjmp) + +LEAF(_longjmp, FRAMESZ) + PTR_SUBU sp, FRAMESZ + SETUP_GP64(GPOFF, _longjmp) + SAVE_GP(GPOFF) + .set noreorder + REG_L v0, SC_REGS+ZERO*REGSZ(a0) + bne v0, 0xACEDBADE, botch # jump if error + REG_L ra, SC_PC(a0) + REG_L v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0) + REG_L s0, SC_REGS+S0*REGSZ(a0) + REG_L s1, SC_REGS+S1*REGSZ(a0) + REG_L s2, SC_REGS+S2*REGSZ(a0) + REG_L s3, SC_REGS+S3*REGSZ(a0) + REG_L s4, SC_REGS+S4*REGSZ(a0) + REG_L s5, SC_REGS+S5*REGSZ(a0) + REG_L s6, SC_REGS+S6*REGSZ(a0) + REG_L s7, SC_REGS+S7*REGSZ(a0) + REG_L s8, SC_REGS+S8*REGSZ(a0) + REG_L gp, SC_REGS+GP*REGSZ(a0) + REG_L sp, SC_REGS+SP*REGSZ(a0) +#if !defined(SOFTFLOAT) + ctc1 v0, $31 +#if _MIPS_FPSET == 32 + FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0) + FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0) + FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0) + FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0) + FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0) + FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0) + FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0) + FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0) + FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0) + FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0) + FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0) + FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0) +#else + lwc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0) + lwc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0) + lwc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0) + lwc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0) + lwc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0) + lwc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0) + lwc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0) + lwc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0) + lwc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0) + lwc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0) + lwc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0) + lwc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0) +#endif +#endif /* !SOFTFLOAT */ + bne a1, zero, 1f + nop + li a1, 1 # never return 0! +1: + j ra + move v0, a1 + +botch: + jal longjmperror + nop + jal abort + nop + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ +END(_longjmp) + diff --git a/libc/arch-mips64/bionic/atexit.h b/libc/arch-mips64/bionic/atexit.h new file mode 100644 index 000000000..759008c84 --- /dev/null +++ b/libc/arch-mips64/bionic/atexit.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +extern void *__dso_handle; +extern int __cxa_atexit(void (*func)(void *), void *arg, void *dso); + +__attribute__ ((visibility ("hidden"))) +int atexit(void (*func)(void)) +{ + return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle)); +} diff --git a/libc/arch-mips64/bionic/bzero.S b/libc/arch-mips64/bionic/bzero.S new file mode 100644 index 000000000..d0b5c847c --- /dev/null +++ b/libc/arch-mips64/bionic/bzero.S @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + .text + +#include + +/* + * void bzero(void *s, size_t n); + */ +LEAF(bzero,0) + SETUP_GP64(t0,bzero) + move a2,a1 + move a1,zero + LA t9,memset + RESTORE_GP64 + j t9 +END(bzero) + diff --git a/libc/arch-mips64/bionic/cacheflush.cpp b/libc/arch-mips64/bionic/cacheflush.cpp new file mode 100644 index 000000000..7955dd69d --- /dev/null +++ b/libc/arch-mips64/bionic/cacheflush.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +#include + +#ifdef DEBUG +#include "private/libc_logging.h" +#define XLOG(...) __libc_format_log(ANDROID_LOG_DEBUG,"libc-cacheflush",__VA_ARGS__) +#endif + +/* + * Linux historically defines a cacheflush(3) routine for MIPS + * with this signature: + * int cacheflush(char *addr, int nbytes, int cache); + * + * Android defines an alternate cacheflush routine which exposes the + * ARM system call interface: + * int cacheflush (long start, long end, long flags) + * + * This is an attempt to maintain compatibility between the historical MIPS + * usage for software previously ported to MIPS and Android specific + * uses of cacheflush() + * + * Use the gcc __clear_cache builtin if possible. This will generate inline synci + * instructions if available or call _flush_cache(start, len, BCACHE) directly + */ + +#if defined (__GNUC__) +#define GCC_VERSION ((__GNUC__*10000) + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif + +/* This is the Android signature */ +int cacheflush (long start, long end, long /*flags*/) { + if (end < start) { + /* + * It looks like this is really MIPS style cacheflush call + * start => addr + * end => nbytes + */ +#ifdef DEBUG + static int warned = 0; + if (!warned) { + XLOG("called with (start,len) instead of (start,end)"); + warned = 1; + } +#endif + end += start; + } + +#if !defined(ARCH_MIPS_USE_FLUSHCACHE_SYSCALL) && \ + defined(GCC_VERSION) && (GCC_VERSION >= 40300) + +#if (__mips_isa_rev >= 2) && (GCC_VERSION < 40403) + /* + * Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in + * mips_expand_synci_loop that may execute synci one more time. + * "start" points to the first byte of the cache line. + * "end" points to the last byte of the line before the last cache line. + * Because size is always a multiple of 4, this is safe to set + * "end" to the last byte. + */ + { + int lineSize; + asm("rdhwr %0, $1" : "=r" (lineSize)); + start = start & (-lineSize); + end = (end & (-lineSize)) - 1; + } +#endif + __builtin___clear_cache((char *)start, (char *)end); +#else + _flush_cache((char *)start, end-start, BCACHE); +#endif + return 0; +} diff --git a/libc/arch-mips64/bionic/crtbegin.c b/libc/arch-mips64/bionic/crtbegin.c new file mode 100644 index 000000000..2ea31ad64 --- /dev/null +++ b/libc/arch-mips64/bionic/crtbegin.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "../../bionic/libc_init_common.h" +#include +#include + +__attribute__ ((section (".preinit_array"))) +void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1; + +__attribute__ ((section (".init_array"))) +void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1; + +__attribute__ ((section (".fini_array"))) +void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1; + + +__LIBC_HIDDEN__ void do_mips_start(void *raw_args) { + structors_array_t array; + array.preinit_array = &__PREINIT_ARRAY__; + array.init_array = &__INIT_ARRAY__; + array.fini_array = &__FINI_ARRAY__; + + __libc_init(raw_args, NULL, &main, &array); +} + +/* + * This function prepares the return address with a branch-and-link + * instruction (bal) and then uses a .cpsetup to compute the Global + * Offset Table (GOT) pointer ($gp). The $gp is then used to load + * the address of _do_mips_start() into $t9 just before calling it. + * Terminating the stack with a NULL return address. + */ +__asm__ ( +" .set push \n" +" \n" +" .text \n" +" .align 4 \n" +" .type __start,@function \n" +" .globl __start \n" +" .globl _start \n" +" \n" +" .ent __start \n" +"__start: \n" +" _start: \n" +" .frame $sp,32,$0 \n" +" .mask 0x80000000,-8 \n" +" \n" +" move $a0, $sp \n" +" daddiu $sp, $sp, -32 \n" +" \n" +" .set noreorder \n" +" bal 1f \n" +" nop \n" +"1: \n" +" .cpsetup $ra,16,1b \n" +" .set reorder \n" +" \n" +" sd $0, 24($sp) \n" +" jal do_mips_start \n" +" \n" +"2: b 2b \n" +" .end __start \n" +" \n" +" .set pop \n" +); + +#include "../../arch-common/bionic/__dso_handle.h" +#include "atexit.h" diff --git a/libc/arch-mips64/bionic/crtbegin_so.c b/libc/arch-mips64/bionic/crtbegin_so.c new file mode 100644 index 000000000..d664ce64d --- /dev/null +++ b/libc/arch-mips64/bionic/crtbegin_so.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +extern void __cxa_finalize(void *); +extern void *__dso_handle; + +__attribute__((visibility("hidden"),destructor)) +void __on_dlclose() { + __cxa_finalize(&__dso_handle); +} + +#include "../../arch-common/bionic/__dso_handle_so.h" +#include "atexit.h" diff --git a/libc/arch-mips64/bionic/futex_mips.S b/libc/arch-mips64/bionic/futex_mips.S new file mode 100644 index 000000000..1a249a724 --- /dev/null +++ b/libc/arch-mips64/bionic/futex_mips.S @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) +FRAMESZ = MKFSIZ(NARGSAVE+2,0) +FRAME_A4 = 4*REGSZ +FRAME_A5 = 5*REGSZ +#else +FRAMESZ = 0 +#endif + +// int __futex_wait(volatile void* ftx, int val, const struct timespec* timeout) +LEAF(__futex_wait, FRAMESZ) +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_SUBU sp, FRAMESZ + REG_S $0,FRAME_A5(sp) /* val3 */ + REG_S $0,FRAME_A4(sp) /* addr2 */ +#else + move a5,$0 /* val3 */ + move a4,$0 /* addr2 */ +#endif + move a3,a2 /* timespec */ + move a2,a1 /* val */ + LI a1,FUTEX_WAIT /* op */ +# move a0,a0 /* ftx */ + LI v0,__NR_futex + syscall + neg v0 /* Negate errno */ + bnez a3,1f /* Check for error */ + move v0,$0 /* Return 0 if no error */ +1: +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_ADDU sp,FRAMESZ +#endif + j ra + END(__futex_wait) + +// int __futex_wake(volatile void* ftx, int count) +LEAF(__futex_wake,FRAMESZ) +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_SUBU sp, FRAMESZ + REG_S $0,FRAME_A5(sp) /* val3 */ + REG_S $0,FRAME_A4(sp) /* addr2 */ +#else + move a5,$0 /* val3 */ + move a4,$0 /* addr2 */ +#endif + move a3,$0 /* timespec */ + move a2,a1 /* val */ + LI a1,FUTEX_WAKE /* op */ +# move a0,a0 /* ftx */ + LI v0,__NR_futex + syscall + neg v0 /* Negate errno */ + bnez a3,1f /* Check for error */ + move v0,$0 /* Return 0 if no error */ +1: +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_ADDU sp,FRAMESZ +#endif + j ra + END(__futex_wake) + +// int __futex_syscall3(volatile void* ftx, int op, int count) +LEAF(__futex_syscall3,FRAMESZ) +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_SUBU sp, FRAMESZ + REG_S $0,FRAME_A5(sp) /* val3 */ + REG_S $0,FRAME_A4(sp) /* addr2 */ +#else + move a5,$0 /* val3 */ + move a4,$0 /* addr2 */ +#endif + move a3,$0 /* timespec */ +# move a2,a2 /* val */ +# move a1,a1 /* op */ +# move a0,a0 /* ftx */ + LI v0,__NR_futex + syscall + neg v0 /* Negate errno */ + bnez a3,1f /* Check for error */ + move v0,$0 /* Return 0 if no error */ +1: +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_ADDU sp,FRAMESZ +#endif + j ra + END(__futex_syscall3) + +// int __futex_syscall4(volatile void* ftx, int op, int val, const struct timespec* timeout) +LEAF(__futex_syscall4,FRAMESZ) +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_SUBU sp, FRAMESZ + REG_S $0,FRAME_A5(sp) /* val3 */ + REG_S $0,FRAME_A4(sp) /* addr2 */ +#else + move a5,$0 /* val3 */ + move a4,$0 /* addr2 */ +#endif +# move a3,a3 /* timespec */ +# move a2,a2 /* val */ +# move a1,a1 /* op */ +# move a0,a0 /* ftx */ + LI v0,__NR_futex + syscall + neg v0 /* Negate errno */ + bnez a3,1f /* Check for error */ + move v0,$0 /* Return 0 if no error */ +1: +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + PTR_ADDU sp,FRAMESZ +#endif + j ra + END(__futex_syscall4) diff --git a/libc/arch-mips64/bionic/getdents.cpp b/libc/arch-mips64/bionic/getdents.cpp new file mode 100644 index 000000000..66a61ec2f --- /dev/null +++ b/libc/arch-mips64/bionic/getdents.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The MIPS64 getdents64() system call is only present in 3.10+ kernels. + * If the getdents64() system call is not available fall back to using + * getdents() and modify the result to be compatible with getdents64(). + */ + +#include + +#include +#include +#include +#include +#include + + +/* The mips_getdents type is 64bit clean */ +struct mips_dirent { + uint64_t d_ino; /* Inode number */ + uint64_t d_off; /* Offset to next mips_dirent */ + uint16_t d_reclen; /* Length of this mips_dirent */ + char d_name[]; /* Filename (null-terminated) */ + /* length is actually (d_reclen - 2 - + offsetof(struct mips_dirent, d_name) */ + // char pad; /* Zero padding byte */ + // char d_type; /* File type (only since Linux 2.6.4; offset is (d_reclen - 1)) */ +}; + +extern "C" int __getdents64(unsigned int fd, struct dirent *dirp, unsigned int count); +extern "C" int __getdents(unsigned int fd, struct mips_dirent *dirp, unsigned int count); +int getdents(unsigned int fd, struct dirent *dirp, unsigned int count) +{ + int r; + int oerrno = errno; + + /* Use getdents64() if it is available */ + r = __getdents64(fd, dirp, count); + if (r >= 0 || errno != ENOSYS) + return r; + + /* Fallback to getdents() */ + errno = oerrno; + r = __getdents(fd, (struct mips_dirent *)dirp, count); + if (r > 0) { + char *p; + char type; + union dirents { + struct mips_dirent m; + struct dirent d; + } *u; + + p = (char *)dirp; + do { + u = (union dirents *)p; + + /* This should not happen, but just in case... */ + if (p + u->m.d_reclen > (char *)dirp + r) + break; + + /* shuffle the dirent */ + type = *(p + u->m.d_reclen - 1); + memmove(u->d.d_name, u->m.d_name, + u->m.d_reclen - 2 - offsetof(struct mips_dirent, d_name) + 1); + u->d.d_type = type; + + p += u->m.d_reclen; + } while (p < (char *)dirp + r); + } + return r; +} diff --git a/libc/arch-mips64/bionic/memcmp16.S b/libc/arch-mips64/bionic/memcmp16.S new file mode 100644 index 000000000..b70c078e7 --- /dev/null +++ b/libc/arch-mips64/bionic/memcmp16.S @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + .text + +#include + +/* + * u4 __memcmp16(const u2* s0, const u2* s1, size_t count); + */ +LEAF(__memcmp16,0) + move t0,$0 + move t1,$0 + beqz a2,.L_done /* 0 length string */ + beq a0,a1,.L_done /* strings are identical */ + + /* Unoptimised... */ +1: lhu t0,0(a0) + lhu t1,0(a1) + PTR_ADDU a1,2 + bne t0,t1,.L_done + PTR_ADDU a0,2 + SUBU a2,1 + bnez a2,1b + +.L_done: + SUBU v0,t0,t1 + j ra + END(__memcmp16) diff --git a/libc/arch-mips64/bionic/setjmp.S b/libc/arch-mips64/bionic/setjmp.S new file mode 100644 index 000000000..7c21195b6 --- /dev/null +++ b/libc/arch-mips64/bionic/setjmp.S @@ -0,0 +1,211 @@ +/* $OpenBSD: setjmp.S,v 1.5 2005/08/07 16:40:15 espie Exp $ */ + +/* + * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opsycon AB nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +#include +#include + +/* + * setjmp, longjmp implementation for libc. this code depends + * on the layout of the struct sigcontext in machine/signal.h. + * + */ + +FRAMESZ= MKFSIZ(2,6) +A1OFF= FRAMESZ-4*REGSZ +A0OFF= FRAMESZ-3*REGSZ +GPOFF= FRAMESZ-2*REGSZ +RAOFF= FRAMESZ-1*REGSZ + +#define FPREG64_S(FPR, OFF, BASE) \ + swc1 FPR, OFF(BASE) ; \ + mfhc1 t0, FPR ; \ + sw t0, OFF+4(BASE) ; + +#define FPREG64_L(FPR, OFF, BASE) \ + lw t0, OFF+4(BASE) ; \ + lw t1, OFF(BASE) ; \ + mtc1 t1, FPR ; \ + mthc1 t0, FPR ; \ + +NON_LEAF(setjmp, FRAMESZ, ra) + .mask 0x80000000, RAOFF + PTR_SUBU sp, FRAMESZ # allocate stack frame + SETUP_GP64(GPOFF, setjmp) + SAVE_GP(GPOFF) + .set reorder + REG_S ra, RAOFF(sp) # save state + REG_S a0, A0OFF(sp) + + move a0, zero # get current signal mask + jal sigblock + + REG_L v1, A0OFF(sp) # v1 = jmpbuf + REG_S v0, SC_MASK(v1) # save sc_mask = sigblock(0) + + REG_L a0, A0OFF(sp) # restore jmpbuf + REG_L ra, RAOFF(sp) + REG_S ra, SC_PC(a0) # sc_pc = return address +#if defined(__mips64) + dli v0, 0xACEDBADE # sigcontext magic number +#else + li v0, 0xACEDBADE # sigcontext magic number +#endif + REG_S v0, SC_REGS+ZERO*REGSZ(a0) + REG_S s0, SC_REGS+S0*REGSZ(a0) + REG_S s1, SC_REGS+S1*REGSZ(a0) + REG_S s2, SC_REGS+S2*REGSZ(a0) + REG_S s3, SC_REGS+S3*REGSZ(a0) + REG_S s4, SC_REGS+S4*REGSZ(a0) + REG_S s5, SC_REGS+S5*REGSZ(a0) + REG_S s6, SC_REGS+S6*REGSZ(a0) + REG_S s7, SC_REGS+S7*REGSZ(a0) + REG_S s8, SC_REGS+S8*REGSZ(a0) + REG_L v0, GPOFF(sp) + REG_S v0, SC_REGS+GP*REGSZ(a0) + PTR_ADDU v0, sp, FRAMESZ + REG_S v0, SC_REGS+SP*REGSZ(a0) + +#if !defined(SOFTFLOAT) + li v0, 1 # be nice if we could tell + REG_S v0, SC_FPUSED(a0) # sc_fpused = 1 + cfc1 v0, $31 +#if _MIPS_FPSET == 32 + FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0) + FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0) + FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0) + FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0) + FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0) + FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0) + FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0) + FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0) + FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0) + FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0) + FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0) + FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0) +#else + swc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0) + swc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0) + swc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0) + swc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0) + swc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0) + swc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0) + swc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0) + swc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0) + swc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0) + swc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0) + swc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0) + swc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0) +#endif + REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0) +#endif /* !SOFTFLOAT */ + move v0, zero + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + j ra + +botch: + jal longjmperror + jal abort + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ +END(setjmp) + + +LEAF(longjmp, FRAMESZ) + PTR_SUBU sp, FRAMESZ + SETUP_GP64(GPOFF, longjmp) + SAVE_GP(GPOFF) + .set reorder + sw a1, A1OFF(sp) + sw a0, A0OFF(sp) + + lw a0, SC_MASK(a0) + jal sigsetmask + + lw a0, A0OFF(sp) + lw a1, A1OFF(sp) + + .set noreorder + REG_L v0, SC_REGS+ZERO*REGSZ(a0) + bne v0, 0xACEDBADE, botch # jump if error + REG_L ra, SC_PC(a0) + REG_L s0, SC_REGS+S0*REGSZ(a0) + REG_L s1, SC_REGS+S1*REGSZ(a0) + REG_L s2, SC_REGS+S2*REGSZ(a0) + REG_L s3, SC_REGS+S3*REGSZ(a0) + REG_L s4, SC_REGS+S4*REGSZ(a0) + REG_L s5, SC_REGS+S5*REGSZ(a0) + REG_L s6, SC_REGS+S6*REGSZ(a0) + REG_L s7, SC_REGS+S7*REGSZ(a0) + REG_L s8, SC_REGS+S8*REGSZ(a0) + REG_L gp, SC_REGS+GP*REGSZ(a0) + REG_L sp, SC_REGS+SP*REGSZ(a0) + +#if !defined(SOFTFLOAT) + REG_L v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0) + ctc1 v0, $31 +#if _MIPS_FPSET == 32 + FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0) + FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0) + FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0) + FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0) + FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0) + FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0) + FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0) + FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0) + FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0) + FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0) + FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0) + FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0) +#else + lwc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0) + lwc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0) + lwc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0) + lwc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0) + lwc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0) + lwc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0) + lwc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0) + lwc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0) + lwc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0) + lwc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0) + lwc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0) + lwc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0) +#endif +#endif /* !SOFTFLOAT */ + bne a1, zero, 1f + nop + li a1, 1 # never return 0! +1: + j ra + move v0, a1 + +END(longjmp) diff --git a/libc/arch-mips64/bionic/sigsetjmp.S b/libc/arch-mips64/bionic/sigsetjmp.S new file mode 100644 index 000000000..b05454c28 --- /dev/null +++ b/libc/arch-mips64/bionic/sigsetjmp.S @@ -0,0 +1,77 @@ +/* $OpenBSD: sigsetjmp.S,v 1.5 2005/08/07 16:40:15 espie Exp $ */ +/*- + * Copyright (c) 1991, 1993, 1995, + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Havard Eidnes. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +/* + * trampolines for sigsetjmp and siglongjmp save and restore mask. + * + */ +FRAMESZ= MKFSIZ(1,1) +GPOFF= FRAMESZ-2*REGSZ + +LEAF(sigsetjmp, FRAMESZ) + PTR_SUBU sp, FRAMESZ + SETUP_GP64(GPOFF, sigsetjmp) + .set reorder + REG_S a1, (_JBLEN*REGSZ)(a0) # save "savemask" + bne a1, 0x0, 1f # do saving of signal mask? + LA t9, _setjmp + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + jr t9 + +1: LA t9, setjmp + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + jr t9 +END(sigsetjmp) + +LEAF(siglongjmp, FRAMESZ) + PTR_SUBU sp, FRAMESZ + SETUP_GP64(GPOFF, siglongjmp) + .set reorder + REG_L t0, (_JBLEN*REGSZ)(a0) # get "savemask" + bne t0, 0x0, 1f # restore signal mask? + LA t9, _longjmp + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + jr t9 +1: + LA t9, longjmp + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + jr t9 +END(siglongjmp) diff --git a/libc/arch-mips64/bionic/syscall.S b/libc/arch-mips64/bionic/syscall.S new file mode 100644 index 000000000..08aa7051a --- /dev/null +++ b/libc/arch-mips64/bionic/syscall.S @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) +FRAMESZ = MKFSIZ(6,0) +#else +FRAMESZ = MKFSIZ(0,1) +FRAME_GP = FRAMESZ-1*REGSZ +#endif + +LEAF(syscall,FRAMESZ) + PTR_SUBU sp, FRAMESZ # allocate stack frame + SETUP_GP64(FRAME_GP,syscall) + SAVE_GP(FRAME_GP) + move v0, a0 # syscall number to v0 + move a0, a1 # shift args down + move a1, a2 + move a2, a3 +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + REG_L a3, FRAMESZ+4*REGSZ(sp) + REG_L t0, FRAMESZ+5*REGSZ(sp) + REG_L t1, FRAMESZ+6*REGSZ(sp) + REG_S t0, 4*REGSZ(sp) + REG_S t1, 5*REGSZ(sp) +#else + move a3, a4 + move a4, a5 + REG_L a5, FRAMESZ(sp) +#endif + syscall + move a0, v0 + bnez a3, 1f + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + j ra +1: + LA t9,__set_errno + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + j t9 + END(syscall) diff --git a/libc/arch-mips64/bionic/vfork.S b/libc/arch-mips64/bionic/vfork.S new file mode 100644 index 000000000..c93694586 --- /dev/null +++ b/libc/arch-mips64/bionic/vfork.S @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__. +// #include +#define SIGCHLD 18 + + .text + +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) +FRAMESZ = MKFSIZ(5,0) +#else +FRAMESZ = MKFSIZ(0,0) +#endif + +LEAF(vfork,FRAMESZ) +#if FRAMESZ!=0 + PTR_SUBU sp, FRAMESZ +#endif + SETUP_GP64(a5,vfork) + LI a0, (CLONE_VM | CLONE_VFORK | SIGCHLD) + move a1, $0 + move a2, $0 + move a3, $0 +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + REG_S $0, 4*REGSZ(sp) +#else + move a4, $0 +#endif + LI v0, __NR_clone + syscall +#if FRAMESZ!=0 + PTR_ADDU sp,FRAMESZ +#endif + move a0, v0 + bnez a3, 1f + RESTORE_GP64 + j ra +1: + LA t9,__set_errno + RESTORE_GP64 + j t9 + END(vfork) diff --git a/libc/arch-mips64/include/machine/asm.h b/libc/arch-mips64/include/machine/asm.h new file mode 100644 index 000000000..eabb1bf4c --- /dev/null +++ b/libc/arch-mips64/include/machine/asm.h @@ -0,0 +1,305 @@ +/* $OpenBSD: asm.h,v 1.7 2004/10/20 12:49:15 pefo Exp $ */ + +/* + * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _MIPS64_ASM_H +#define _MIPS64_ASM_H + +#include + +#ifdef NEED_OLD_RM7KFIX +#define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; +#else +#define ITLBNOPFIX nop;nop;nop;nop +#endif + +#define _MIPS_ISA_MIPS1 1 /* R2000/R3000 */ +#define _MIPS_ISA_MIPS2 2 /* R4000/R6000 */ +#define _MIPS_ISA_MIPS3 3 /* R4000 */ +#define _MIPS_ISA_MIPS4 4 /* TFP (R1x000) */ +#ifdef __linux__ +#define _MIPS_ISA_MIPS5 5 +#define _MIPS_ISA_MIPS32 6 +#define _MIPS_ISA_MIPS64 7 +#else +#define _MIPS_ISA_MIPS32 32 /* MIPS32 */ +#endif + +#if !defined(ABICALLS) && !defined(_NO_ABICALLS) +#define ABICALLS .abicalls +#endif + +#if defined(ABICALLS) && !defined(_KERNEL) + ABICALLS +#endif + +#define _C_LABEL(x) x /* XXX Obsolete but keep for a while */ + +#if !defined(__MIPSEL__) && !defined(__MIPSEB__) +#error "__MIPSEL__ or __MIPSEB__ must be defined" +#endif +/* + * Define how to access unaligned data word + */ +#if defined(__MIPSEL__) +#define LWLO lwl +#define LWHI lwr +#define SWLO swl +#define SWHI swr +#define LDLO ldl +#define LDHI ldr +#define SDLO sdl +#define SDHI sdr +#endif +#if defined(__MIPSEB__) +#define LWLO lwr +#define LWHI lwl +#define SWLO swr +#define SWHI swl +#define LDLO ldr +#define LDHI ldl +#define SDLO sdr +#define SDHI sdl +#endif + +/* + * Define programming environment for ABI. + */ +#if defined(ABICALLS) && !defined(_KERNEL) && !defined(_STANDALONE) + +#ifndef _MIPS_SIM +#define _MIPS_SIM 1 +#define _ABIO32 1 +#endif +#ifndef _MIPS_ISA +#define _MIPS_ISA 2 +#define _MIPS_ISA_MIPS2 2 +#endif + +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) +#define NARGSAVE 4 + +#define SETUP_GP \ + .set noreorder; \ + .cpload t9; \ + .set reorder; + +#define SAVE_GP(x) \ + .cprestore x + +#define SETUP_GP64(gpoff, name) +#define RESTORE_GP64 +#endif + +#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) +#define NARGSAVE 0 + +#define SETUP_GP +#define SAVE_GP(x) +#define SETUP_GP64(gpoff, name) \ + .cpsetup t9, gpoff, name +#define RESTORE_GP64 \ + .cpreturn +#endif + +#define MKFSIZ(narg,locals) (((narg+locals)*REGSZ+31)&(~31)) + +#else /* defined(ABICALLS) && !defined(_KERNEL) */ + +#define NARGSAVE 4 +#define SETUP_GP +#define SAVE_GP(x) + +#define ALIGNSZ 16 /* Stack layout alignment */ +#define FRAMESZ(sz) (((sz) + (ALIGNSZ-1)) & ~(ALIGNSZ-1)) + +#endif + +/* + * Basic register operations based on selected ISA + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || _MIPS_ISA == _MIPS_ISA_MIPS32) +#define REGSZ 4 /* 32 bit mode register size */ +#define LOGREGSZ 2 /* log rsize */ +#define REG_S sw +#define REG_L lw +#define CF_SZ 24 /* Call frame size */ +#define CF_ARGSZ 16 /* Call frame arg size */ +#define CF_RA_OFFS 20 /* Call ra save offset */ +#endif + +#if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || _MIPS_ISA == _MIPS_ISA_MIPS64) +#define REGSZ 8 /* 64 bit mode register size */ +#define LOGREGSZ 3 /* log rsize */ +#define REG_S sd +#define REG_L ld +#define CF_SZ 48 /* Call frame size (multiple of ALIGNSZ) */ +#define CF_ARGSZ 32 /* Call frame arg size */ +#define CF_RA_OFFS 40 /* Call ra save offset */ +#endif + +#define REGSZ_FP 8 /* 64 bit FP register size */ + +#ifndef __LP64__ +#define PTR_L lw +#define PTR_S sw +#define PTR_SUB sub +#define PTR_ADD add +#define PTR_SUBU subu +#define PTR_ADDU addu +#define LI li +#define LA la +#define PTR_SLL sll +#define PTR_SRL srl +#define PTR_VAL .word +#else +#define PTR_L ld +#define PTR_S sd +#define PTR_ADD dadd +#define PTR_SUB dsub +#define PTR_SUBU dsubu +#define PTR_ADDU daddu +#define LI dli +#define LA dla +#define PTR_SLL dsll +#define PTR_SRL dsrl +#define PTR_VAL .dword +#endif + +/* + * Define -pg profile entry code. + */ +#if defined(XGPROF) || defined(XPROF) +#define MCOUNT \ + PTR_SUBU sp, sp, 64; \ + SAVE_GP(16); \ + sd ra, 56(sp); \ + sd gp, 48(sp); \ + .set noat; \ + .set noreorder; \ + move AT, ra; \ + jal _mcount; \ + PTR_SUBU sp, sp, 16; \ + ld ra, 56(sp); \ + PTR_ADDU sp, sp, 64; \ + .set reorder; \ + .set at; +#else +#define MCOUNT +#endif + +/* + * LEAF(x, fsize) + * + * Declare a leaf routine. + */ +#define LEAF(x, fsize) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, ra; \ + SETUP_GP \ + MCOUNT + +#define ALEAF(x) \ + .globl x; \ +x: + +/* + * NLEAF(x) + * + * Declare a non-profiled leaf routine. + */ +#define NLEAF(x, fsize) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, ra; \ + SETUP_GP + +/* + * NON_LEAF(x) + * + * Declare a non-leaf routine (a routine that makes other C calls). + */ +#define NON_LEAF(x, fsize, retpc) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, retpc; \ + SETUP_GP \ + MCOUNT + +/* + * NNON_LEAF(x) + * + * Declare a non-profiled non-leaf routine + * (a routine that makes other C calls). + */ +#define NNON_LEAF(x, fsize, retpc) \ + .align 3; \ + .globl x; \ + .ent x, 0; \ +x: ; \ + .frame sp, fsize, retpc \ + SETUP_GP + +/* + * END(x) + * + * Mark end of a procedure. + */ +#define END(x) \ + .end x + +/* + * Macros to panic and printf from assembly language. + */ +#define PANIC(msg) \ + LA a0, 9f; \ + jal panic; \ + nop ; \ + MSG(msg) + +#define PRINTF(msg) \ + LA a0, 9f; \ + jal printf; \ + nop ; \ + MSG(msg) + +#define MSG(msg) \ + .rdata; \ +9: .asciiz msg; \ + .text + +#define ASMSTR(str) \ + .asciiz str; \ + .align 3 + +#endif /* !_MIPS_ASM_H */ diff --git a/libc/arch-mips64/include/machine/elf_machdep.h b/libc/arch-mips64/include/machine/elf_machdep.h new file mode 100644 index 000000000..d27d43183 --- /dev/null +++ b/libc/arch-mips64/include/machine/elf_machdep.h @@ -0,0 +1,196 @@ +/* $NetBSD: elf_machdep.h,v 1.15 2011/03/15 07:39:22 matt Exp $ */ + +#ifndef _MIPS_ELF_MACHDEP_H_ +#define _MIPS_ELF_MACHDEP_H_ + +#ifdef _LP64 +#define ARCH_ELFSIZE 64 /* MD native binary size */ +#else +#define ARCH_ELFSIZE 32 /* MD native binary size */ +#endif + +#if ELFSIZE == 32 +#define ELF32_MACHDEP_ID_CASES \ + case EM_MIPS: \ + break; + +#define ELF32_MACHDEP_ID EM_MIPS +#elif ELFSIZE == 64 +#define ELF64_MACHDEP_ID_CASES \ + case EM_MIPS: \ + break; + +#define ELF64_MACHDEP_ID EM_MIPS +#endif + +/* mips relocs. */ + +#define R_MIPS_NONE 0 +#define R_MIPS_16 1 +#define R_MIPS_32 2 +#define R_MIPS_REL32 3 +#define R_MIPS_REL R_MIPS_REL32 +#define R_MIPS_26 4 +#define R_MIPS_HI16 5 /* high 16 bits of symbol value */ +#define R_MIPS_LO16 6 /* low 16 bits of symbol value */ +#define R_MIPS_GPREL16 7 /* GP-relative reference */ +#define R_MIPS_LITERAL 8 /* Reference to literal section */ +#define R_MIPS_GOT16 9 /* Reference to global offset table */ +#define R_MIPS_GOT R_MIPS_GOT16 +#define R_MIPS_PC16 10 /* 16 bit PC relative reference */ +#define R_MIPS_CALL16 11 /* 16 bit call thru glbl offset tbl */ +#define R_MIPS_CALL R_MIPS_CALL16 +#define R_MIPS_GPREL32 12 + +/* 13, 14, 15 are not defined at this point. */ +#define R_MIPS_UNUSED1 13 +#define R_MIPS_UNUSED2 14 +#define R_MIPS_UNUSED3 15 + +/* + * The remaining relocs are apparently part of the 64-bit Irix ELF ABI. + */ +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 + +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +/* TLS relocations */ + +#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ +#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ +#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ +#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ +#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ +#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ +#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ +#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ +#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ +#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ +#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ +#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ +#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ + +#define R_MIPS_max 51 + +#define R_TYPE(name) __CONCAT(R_MIPS_,name) + +#define R_MIPS16_min 100 +#define R_MIPS16_26 100 +#define R_MIPS16_GPREL 101 +#define R_MIPS16_GOT16 102 +#define R_MIPS16_CALL16 103 +#define R_MIPS16_HI16 104 +#define R_MIPS16_LO16 105 +#define R_MIPS16_max 106 + + +/* mips dynamic tags */ + +#define DT_MIPS_RLD_VERSION 0x70000001 +#define DT_MIPS_TIME_STAMP 0x70000002 +#define DT_MIPS_ICHECKSUM 0x70000003 +#define DT_MIPS_IVERSION 0x70000004 +#define DT_MIPS_FLAGS 0x70000005 +#define DT_MIPS_BASE_ADDRESS 0x70000006 +#define DT_MIPS_CONFLICT 0x70000008 +#define DT_MIPS_LIBLIST 0x70000009 +#define DT_MIPS_CONFLICTNO 0x7000000b +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* number of local got ents */ +#define DT_MIPS_LIBLISTNO 0x70000010 +#define DT_MIPS_SYMTABNO 0x70000011 /* number of .dynsym entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 +#define DT_MIPS_GOTSYM 0x70000013 /* first dynamic sym in got */ +#define DT_MIPS_HIPAGENO 0x70000014 +#define DT_MIPS_RLD_MAP 0x70000016 /* address of loader map */ + +/* + * ELF Flags + */ +#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */ +#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */ +#define EF_MIPS_ABI2 0x00000020 /* N32 */ + +#define EF_MIPS_ARCH_ASE 0x0f000000 /* Architectural extensions */ +#define EF_MIPS_ARCH_MDMX 0x08000000 /* MDMX multimedia extension */ +#define EF_MIPS_ARCH_M16 0x04000000 /* MIPS-16 ISA extensions */ + +#define EF_MIPS_ARCH 0xf0000000 /* Architecture field */ +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code */ +#define EF_MIPS_ARCH_32 0x50000000 /* -mips32 code */ +#define EF_MIPS_ARCH_64 0x60000000 /* -mips64 code */ +#define EF_MIPS_ARCH_32R2 0x70000000 /* -mips32r2 code */ +#define EF_MIPS_ARCH_64R2 0x80000000 /* -mips64r2 code */ + +#define EF_MIPS_ABI 0x0000f000 +#define EF_MIPS_ABI_O32 0x00001000 +#define EF_MIPS_ABI_O64 0x00002000 +#define EF_MIPS_ABI_EABI32 0x00003000 +#define EF_MIPS_ABI_EABI64 0x00004000 + +#if defined(__MIPSEB__) +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB +#define ELF64_MACHDEP_ENDIANNESS ELFDATA2MSB +#elif defined(__MIPSEL__) +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB +#define ELF64_MACHDEP_ENDIANNESS ELFDATA2LSB +#elif !defined(HAVE_NBTOOL_CONFIG_H) +#error neither __MIPSEL__ nor __MIPSEB__ are defined. +#endif + +#ifdef _KERNEL +#ifdef _KERNEL_OPT +#include "opt_compat_netbsd.h" +#endif +#ifdef COMPAT_16 +/* + * Up to 1.6, the ELF dynamic loader (ld.elf_so) was not relocatable. + * Tell the kernel ELF exec code not to try relocating the interpreter + * for dynamically-linked ELF binaries. + */ +#define ELF_INTERP_NON_RELOCATABLE +#endif /* COMPAT_16 */ + +/* + * We need to be able to include the ELF header so we can pick out the + * ABI being used. + */ +#ifdef ELFSIZE +#define ELF_MD_PROBE_FUNC ELFNAME2(mips_netbsd,probe) +#define ELF_MD_COREDUMP_SETUP ELFNAME2(coredump,setup) +#endif + +struct exec_package; + +int mips_netbsd_elf32_probe(struct lwp *, struct exec_package *, void *, char *, + vaddr_t *); +void coredump_elf32_setup(struct lwp *, void *); + +int mips_netbsd_elf64_probe(struct lwp *, struct exec_package *, void *, char *, + vaddr_t *); +void coredump_elf64_setup(struct lwp *, void *); +#endif /* _KERNEL */ + +#endif /* _MIPS_ELF_MACHDEP_H_ */ diff --git a/libc/arch-mips64/include/machine/endian.h b/libc/arch-mips64/include/machine/endian.h new file mode 100644 index 000000000..41a9004f4 --- /dev/null +++ b/libc/arch-mips64/include/machine/endian.h @@ -0,0 +1,70 @@ +/* $OpenBSD: endian.h,v 1.5 2006/02/27 23:35:59 miod Exp $ */ + +/* + * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_ENDIAN_H_ +#define _MIPS64_ENDIAN_H_ + +#ifdef __GNUC__ + +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) +#define __swap16md(x) ({ \ + register uint16_t _x = (x); \ + register uint16_t _r; \ + __asm volatile ("wsbh %0, %1" : "=r" (_r) : "r" (_x)); \ + _r; \ +}) + +#define __swap32md(x) ({ \ + register uint32_t _x = (x); \ + register uint32_t _r; \ + __asm volatile ("wsbh %0, %1; rotr %0, %0, 16" : "=r" (_r) : "r" (_x)); \ + _r; \ +}) + +#define __swap64md(x) ({ \ + uint64_t _swap64md_x = (x); \ + (uint64_t) __swap32md(_swap64md_x >> 32) | \ + (uint64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \ +}) + +/* Tell sys/endian.h we have MD variants of the swap macros. */ +#define MD_SWAP + +#endif /* __mips32r2__ */ +#endif /* __GNUC__ */ + +#if defined(__MIPSEB__) +#define _BYTE_ORDER _BIG_ENDIAN +#else +#define _BYTE_ORDER _LITTLE_ENDIAN +#endif +#define __STRICT_ALIGNMENT +#include +#include + +#endif /* _MIPS64_ENDIAN_H_ */ diff --git a/libc/arch-mips64/include/machine/exec.h b/libc/arch-mips64/include/machine/exec.h new file mode 100644 index 000000000..3c63f7435 --- /dev/null +++ b/libc/arch-mips64/include/machine/exec.h @@ -0,0 +1,188 @@ +/* $OpenBSD: exec.h,v 1.1 2004/10/18 19:05:36 grange Exp $ */ + +/* + * Copyright (c) 1996-2004 Per Fogelstrom, Opsycon AB + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_EXEC_H_ +#define _MIPS64_EXEC_H_ + +#define __LDPGSZ 4096 + +/* + * Define what exec "formats" we should handle. + */ +#define NATIVE_EXEC_ELF +#define NATIVE_ELFSIZE 64 +#define EXEC_SCRIPT + +/* + * If included from sys/exec.h define kernels ELF format. + */ +#ifdef __LP64__ +#define ARCH_ELFSIZE 64 +#define DB_ELFSIZE 64 +#define ELF_TARG_CLASS ELFCLASS64 +#else +#define ARCH_ELFSIZE 32 +#define DB_ELFSIZE 32 +#define ELF_TARG_CLASS ELFCLASS32 +#endif + +#if defined(__MIPSEB__) +#define ELF_TARG_DATA ELFDATA2MSB +#else +#define ELF_TARG_DATA ELFDATA2LSB +#endif +#define ELF_TARG_MACH EM_MIPS + +#define _NLIST_DO_ELF + +#if defined(_LP64) +#define _KERN_DO_ELF64 +#if defined(COMPAT_O32) +#define _KERN_DO_ELF +#endif +#else +#define _KERN_DO_ELF +#endif + +/* Information taken from MIPS ABI supplemental */ + +/* Architecture dependent Segment types - p_type */ +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ + +/* Architecture dependent d_tag field for Elf32_Dyn. */ +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime Linker Interface ID */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Cksum of ext. str. and com. sizes */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Segment base address */ +#define DT_MIPS_CONFLICT 0x70000008 /* Adr of .conflict section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of .liblist section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local .GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of .conflict entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of .liblist entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of .dynsym entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in .dynsym */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of debug map pointer */ + +#define DT_PROCNUM (DT_MIPS_RLD_MAP - DT_LOPROC + 1) + +/* + * Legal values for e_flags field of Elf32_Ehdr. + */ +#define EF_MIPS_NOREORDER 0x00000001 /* .noreorder was used */ +#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */ +#define EF_MIPS_CPIC 0x00000004 /* Uses PIC calling sequence */ +#define EF_MIPS_ABI2 0x00000020 /* -n32 on Irix 6 */ +#define EF_MIPS_32BITMODE 0x00000100 /* 64 bit in 32 bit mode... */ +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ +#define E_MIPS_ARCH_1 0x00000000 +#define E_MIPS_ARCH_2 0x10000000 +#define E_MIPS_ARCH_3 0x20000000 +#define E_MIPS_ARCH_4 0x30000000 +#define EF_MIPS_ABI 0x0000f000 /* ABI level */ +#define E_MIPS_ABI_NONE 0x00000000 /* ABI level not set */ +#define E_MIPS_ABI_O32 0x00001000 +#define E_MIPS_ABI_O64 0x00002000 +#define E_MIPS_ABI_EABI32 0x00004000 +#define E_MIPS_ABI_EABI64 0x00004000 + +/* + * Mips special sections. + */ +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* + * Legal values for sh_type field of Elf32_Shdr. + */ +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information */ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ + +/* + * Legal values for sh_flags field of Elf32_Shdr. + */ +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ + +#if 0 +/* + * Entries found in sections of type SHT_MIPS_GPTAB. + */ +typedef union { + struct { + Elf32_Word gt_current_g_value; /* -G val used in compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct { + Elf32_Word gt_g_value; /* If this val were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* + * Entry found in sections of type SHT_MIPS_REGINFO. + */ +typedef struct { + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; +#endif + + +/* + * Mips relocations. + */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#define R_MIPS_64 18 + +#define R_MIPS_REL32_64 ((R_MIPS_64 << 8) | R_MIPS_REL32) + + +#endif /* !_MIPS64_EXEC_H_ */ diff --git a/libc/arch-mips64/include/machine/ieee.h b/libc/arch-mips64/include/machine/ieee.h new file mode 100644 index 000000000..520a77b7c --- /dev/null +++ b/libc/arch-mips64/include/machine/ieee.h @@ -0,0 +1,169 @@ +/* $OpenBSD: ieee.h,v 1.4 2010/01/23 19:11:21 miod Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 112 + +#define EXT_IMPLICIT_NBIT + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_fraclm; \ + (a)[2] = (uint32_t)(p)->ext_frachm; \ + (a)[3] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { +#ifdef __MIPSEB__ + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +#else + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +#endif +}; + +struct ieee_double { +#ifdef __MIPSEB__ + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +#else + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +#endif +}; + +struct ieee_ext { +#ifdef __MIPSEB__ + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +#else + u_int ext_fracl; + u_int ext_fraclm; + u_int ext_frachm; + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; +#endif +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 diff --git a/libc/arch-mips64/include/machine/limits.h b/libc/arch-mips64/include/machine/limits.h new file mode 100644 index 000000000..339444dec --- /dev/null +++ b/libc/arch-mips64/include/machine/limits.h @@ -0,0 +1,62 @@ +/* $OpenBSD: limits.h,v 1.5 2007/05/07 20:51:07 kettenis Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + */ + +#ifndef _MIPS_LIMITS_H_ +#define _MIPS_LIMITS_H_ + +#include + +#define MB_LEN_MAX 6 /* Allow 31 bit UTF2 */ + +#ifndef SIZE_MAX +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#endif +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ + +#if __BSD_VISIBLE +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t (historic) */ + +/* Quads and longs are the same on mips64 */ +#define UQUAD_MAX (ULONG_MAX) /* max value for a uquad_t */ +#define QUAD_MAX (LONG_MAX) /* max value for a quad_t */ +#define QUAD_MIN (LONG_MIN) /* min value for a quad_t */ + +#endif /* __BSD_VISIBLE */ + + +#define LONGLONG_BIT 64 +#define LONGLONG_MIN (-9223372036854775807LL-1) +#define LONGLONG_MAX 9223372036854775807LL +#define ULONGLONG_MAX 18446744073709551615ULL + +#endif /* !_MIPS_LIMITS_H_ */ diff --git a/libc/arch-mips64/include/machine/regdef.h b/libc/arch-mips64/include/machine/regdef.h new file mode 100644 index 000000000..3a7cd687c --- /dev/null +++ b/libc/arch-mips64/include/machine/regdef.h @@ -0,0 +1,99 @@ +/* $OpenBSD: regdef.h,v 1.3 2005/08/07 07:29:44 miod Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. This file is derived from the MIPS RISC + * Architecture book by Gerry Kane. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regdef.h 8.1 (Berkeley) 6/10/93 + */ +#ifndef _MIPS_REGDEF_H_ +#define _MIPS_REGDEF_H_ + +#if (_MIPS_SIM == _ABI64) && !defined(__mips_n64) +#define __mips_n64 1 +#endif +#if (_MIPS_SIM == _ABIN32) && !defined(__mips_n32) +#define __mips_n32 1 +#endif + +#define zero $0 /* always zero */ +#define AT $at /* assembler temp */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#if defined(__mips_n32) || defined(__mips_n64) +#define a4 $8 /* expanded register arguments */ +#define a5 $9 +#define a6 $10 +#define a7 $11 +#define ta0 $8 /* alias */ +#define ta1 $9 +#define ta2 $10 +#define ta3 $11 +#define t0 $12 /* temp registers (not saved across subroutine calls) */ +#define t1 $13 +#define t2 $14 +#define t3 $15 +#else +#define t0 $8 /* temp registers (not saved across subroutine calls) */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define ta0 $12 /* alias */ +#define ta1 $13 +#define ta2 $14 +#define ta3 $15 +#endif +#define s0 $16 /* saved across subroutine calls (callee saved) */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* two more temp registers */ +#define t9 $25 +#define k0 $26 /* kernel temporary */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define s8 $30 /* one more callee saved */ +#define ra $31 /* return address */ + +#endif /* !_MIPS_REGDEF_H_ */ diff --git a/libc/arch-mips64/include/machine/regnum.h b/libc/arch-mips64/include/machine/regnum.h new file mode 100644 index 000000000..bfe128047 --- /dev/null +++ b/libc/arch-mips64/include/machine/regnum.h @@ -0,0 +1,119 @@ +/* $OpenBSD: regnum.h,v 1.3 2004/08/10 20:28:13 deraadt Exp $ */ + +/* + * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _MIPS64_REGNUM_H_ +#define _MIPS64_REGNUM_H_ + +/* + * Location of the saved registers relative to ZERO. + * Usage is p->p_regs[XX]. + */ +#define ZERO 0 +#define AST 1 +#define V0 2 +#define V1 3 +#define A0 4 +#define A1 5 +#define A2 6 +#define A3 7 +#define T0 8 +#define T1 9 +#define T2 10 +#define T3 11 +#define T4 12 +#define T5 13 +#define T6 14 +#define T7 15 +#define S0 16 +#define S1 17 +#define S2 18 +#define S3 19 +#define S4 20 +#define S5 21 +#define S6 22 +#define S7 23 +#define T8 24 +#define T9 25 +#define K0 26 +#define K1 27 +#define GP 28 +#define SP 29 +#define S8 30 +#define RA 31 +#define SR 32 +#define PS SR /* alias for SR */ +#define MULLO 33 +#define MULHI 34 +#define BADVADDR 35 +#define CAUSE 36 +#define PC 37 +#define IC 38 +#define CPL 39 + +#define NUMSAVEREGS 40 /* Number of registers saved in trap */ + +#define FPBASE NUMSAVEREGS +#define F0 (FPBASE+0) +#define F1 (FPBASE+1) +#define F2 (FPBASE+2) +#define F3 (FPBASE+3) +#define F4 (FPBASE+4) +#define F5 (FPBASE+5) +#define F6 (FPBASE+6) +#define F7 (FPBASE+7) +#define F8 (FPBASE+8) +#define F9 (FPBASE+9) +#define F10 (FPBASE+10) +#define F11 (FPBASE+11) +#define F12 (FPBASE+12) +#define F13 (FPBASE+13) +#define F14 (FPBASE+14) +#define F15 (FPBASE+15) +#define F16 (FPBASE+16) +#define F17 (FPBASE+17) +#define F18 (FPBASE+18) +#define F19 (FPBASE+19) +#define F20 (FPBASE+20) +#define F21 (FPBASE+21) +#define F22 (FPBASE+22) +#define F23 (FPBASE+23) +#define F24 (FPBASE+24) +#define F25 (FPBASE+25) +#define F26 (FPBASE+26) +#define F27 (FPBASE+27) +#define F28 (FPBASE+28) +#define F29 (FPBASE+29) +#define F30 (FPBASE+30) +#define F31 (FPBASE+31) +#define FSR (FPBASE+32) + +#define NUMFPREGS 33 + +#define NREGS (NUMSAVEREGS + NUMFPREGS) + +#endif /* !_MIPS64_REGNUM_H_ */ diff --git a/libc/arch-mips64/include/machine/setjmp.h b/libc/arch-mips64/include/machine/setjmp.h new file mode 100644 index 000000000..55ba7bebb --- /dev/null +++ b/libc/arch-mips64/include/machine/setjmp.h @@ -0,0 +1,10 @@ +/* $OpenBSD: setjmp.h,v 1.2 2004/08/10 21:10:56 pefo Exp $ */ + +/* Public domain */ + +#ifndef _MIPS_SETJMP_H_ +#define _MIPS_SETJMP_H_ + +#define _JBLEN 157 /* size, in longs, of a jmp_buf */ + +#endif /* !_MIPS_SETJMP_H_ */ diff --git a/libc/arch-mips64/include/machine/signal.h b/libc/arch-mips64/include/machine/signal.h new file mode 100644 index 000000000..f02ec0d22 --- /dev/null +++ b/libc/arch-mips64/include/machine/signal.h @@ -0,0 +1,53 @@ +/* $OpenBSD: signal.h,v 1.8 2006/01/09 18:18:37 millert Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MIPS_SIGNAL_H_ +#define _MIPS_SIGNAL_H_ + +#include + +#define SC_REGMASK (0*REGSZ) +#define SC_STATUS (1*REGSZ) +#define SC_PC (2*REGSZ) +#define SC_REGS (SC_PC+8) +#define SC_FPREGS (SC_REGS+32*8) +#define SC_ACX (SC_FPREGS+32*REGSZ_FP) +#define SC_USED_MATH (SC_ACX+3*REGSZ) +/* OpenBSD compatibility */ +#define SC_MASK SC_REGMASK +#define SC_FPUSED SC_USED_MATH + +#endif /* !_MIPS_SIGNAL_H_ */ diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk new file mode 100644 index 000000000..fa09caa5f --- /dev/null +++ b/libc/arch-mips64/mips64.mk @@ -0,0 +1,28 @@ +_LIBC_ARCH_COMMON_SRC_FILES := \ + arch-mips64/bionic/__bionic_clone.S \ + arch-mips64/bionic/bzero.S \ + arch-mips64/bionic/cacheflush.cpp \ + arch-mips64/bionic/_exit_with_stack_teardown.S \ + arch-mips64/bionic/futex_mips.S \ + arch-mips64/bionic/__get_sp.S \ + arch-mips64/bionic/getdents.cpp \ + arch-mips64/bionic/memcmp16.S \ + arch-mips64/bionic/_setjmp.S \ + arch-mips64/bionic/setjmp.S \ + arch-mips64/bionic/__set_tls.c \ + arch-mips64/bionic/sigsetjmp.S \ + arch-mips64/bionic/syscall.S \ + arch-mips64/bionic/vfork.S \ + +# FIXME TODO +## _LIBC_ARCH_COMMON_SRC_FILES += arch-mips64/string/memcpy.S +## _LIBC_ARCH_COMMON_SRC_FILES += arch-mips64/string/memset.S +## _LIBC_ARCH_COMMON_SRC_FILES += arch-mips64/string/mips_strlen.c +_LIBC_ARCH_COMMON_SRC_FILES += bionic/memcpy.c +_LIBC_ARCH_COMMON_SRC_FILES += bionic/memset.c +_LIBC_ARCH_COMMON_SRC_FILES += string/strlen.c + +_LIBC_ARCH_STATIC_SRC_FILES := \ + bionic/dl_iterate_phdr_static.c \ + +_LIBC_ARCH_DYNAMIC_SRC_FILES := diff --git a/libc/arch-mips64/string/memcpy.S b/libc/arch-mips64/string/memcpy.S new file mode 100644 index 000000000..aabdfcfdc --- /dev/null +++ b/libc/arch-mips64/string/memcpy.S @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2009 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/************************************************************************ + * + * memcpy.S + * Version: "043009" + * + ************************************************************************/ + + +/************************************************************************ + * Include files + ************************************************************************/ + +#include "machine/asm.h" + + +/* + * This routine could be optimized for MIPS64. The current code only + * uses MIPS32 instructions. + */ +#if defined(__MIPSEB__) +# define LWHI lwl /* high part is left in big-endian */ +# define SWHI swl /* high part is left in big-endian */ +# define LWLO lwr /* low part is right in big-endian */ +# define SWLO swr /* low part is right in big-endian */ +#endif + +#if defined(__MIPSEL__) +# define LWHI lwr /* high part is right in little-endian */ +# define SWHI swr /* high part is right in little-endian */ +# define LWLO lwl /* low part is left in big-endian */ +# define SWLO swl /* low part is left in big-endian */ +#endif + +LEAF(memcpy,0) + + .set noreorder + .set noat +/* + * Below we handle the case where memcpy is called with overlapping src and dst. + * Although memcpy is not required to handle this case, some parts of Android like Skia + * rely on such usage. We call memmove to handle such cases. + */ + subu t0,a0,a1 + sra AT,t0,31 + xor t1,t0,AT + subu t0,t1,AT + sltu AT,t0,a2 + beq AT,zero,.Lmemcpy + la t9,memmove + jr t9 + nop +.Lmemcpy: + slti AT,a2,8 + bne AT,zero,.Llast8 + move v0,a0 # memcpy returns the dst pointer + +# Test if the src and dst are word-aligned, or can be made word-aligned + xor t8,a1,a0 + andi t8,t8,0x3 # t8 is a0/a1 word-displacement + + bne t8,zero,.Lunaligned + negu a3,a0 + + andi a3,a3,0x3 # we need to copy a3 bytes to make a0/a1 aligned + beq a3,zero,.Lchk16w # when a3=0 then the dst (a0) is word-aligned + subu a2,a2,a3 # now a2 is the remining bytes count + + LWHI t8,0(a1) + addu a1,a1,a3 + SWHI t8,0(a0) + addu a0,a0,a3 + +# Now the dst/src are mutually word-aligned with word-aligned addresses +.Lchk16w: + andi t8,a2,0x3f # any whole 64-byte chunks? + # t8 is the byte count after 64-byte chunks + + beq a2,t8,.Lchk8w # if a2==t8, no 64-byte chunks + # There will be at most 1 32-byte chunk after it + subu a3,a2,t8 # subtract from a2 the reminder + # Here a3 counts bytes in 16w chunks + addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks + + addu t0,a0,a2 # t0 is the "past the end" address + +# When in the loop we exercise "pref 30,x(a0)", the a0+x should not be past +# the "t0-32" address +# This means: for x=128 the last "safe" a0 address is "t0-160" +# Alternatively, for x=64 the last "safe" a0 address is "t0-96" +# In the current version we will use "pref 30,128(a0)", so "t0-160" is the limit + subu t9,t0,160 # t9 is the "last safe pref 30,128(a0)" address + + pref 0,0(a1) # bring the first line of src, addr 0 + pref 0,32(a1) # bring the second line of src, addr 32 + pref 0,64(a1) # bring the third line of src, addr 64 + pref 30,32(a0) # safe, as we have at least 64 bytes ahead +# In case the a0 > t9 don't use "pref 30" at all + sgtu v1,a0,t9 + bgtz v1,.Lloop16w # skip "pref 30,64(a0)" for too short arrays + nop +# otherwise, start with using pref30 + pref 30,64(a0) +.Lloop16w: + pref 0,96(a1) + lw t0,0(a1) + bgtz v1,.Lskip_pref30_96 # skip "pref 30,96(a0)" + lw t1,4(a1) + pref 30,96(a0) # continue setting up the dest, addr 96 +.Lskip_pref30_96: + lw t2,8(a1) + lw t3,12(a1) + lw t4,16(a1) + lw t5,20(a1) + lw t6,24(a1) + lw t7,28(a1) + pref 0,128(a1) # bring the next lines of src, addr 128 + + sw t0,0(a0) + sw t1,4(a0) + sw t2,8(a0) + sw t3,12(a0) + sw t4,16(a0) + sw t5,20(a0) + sw t6,24(a0) + sw t7,28(a0) + + lw t0,32(a1) + bgtz v1,.Lskip_pref30_128 # skip "pref 30,128(a0)" + lw t1,36(a1) + pref 30,128(a0) # continue setting up the dest, addr 128 +.Lskip_pref30_128: + lw t2,40(a1) + lw t3,44(a1) + lw t4,48(a1) + lw t5,52(a1) + lw t6,56(a1) + lw t7,60(a1) + pref 0, 160(a1) # bring the next lines of src, addr 160 + + sw t0,32(a0) + sw t1,36(a0) + sw t2,40(a0) + sw t3,44(a0) + sw t4,48(a0) + sw t5,52(a0) + sw t6,56(a0) + sw t7,60(a0) + + addiu a0,a0,64 # adding 64 to dest + sgtu v1,a0,t9 + bne a0,a3,.Lloop16w + addiu a1,a1,64 # adding 64 to src + move a2,t8 + +# Here we have src and dest word-aligned but less than 64-bytes to go + +.Lchk8w: + pref 0, 0x0(a1) + andi t8,a2,0x1f # is there a 32-byte chunk? + # the t8 is the reminder count past 32-bytes + beq a2,t8,.Lchk1w # when a2=t8, no 32-byte chunk + nop + + lw t0,0(a1) + lw t1,4(a1) + lw t2,8(a1) + lw t3,12(a1) + lw t4,16(a1) + lw t5,20(a1) + lw t6,24(a1) + lw t7,28(a1) + addiu a1,a1,32 + + sw t0,0(a0) + sw t1,4(a0) + sw t2,8(a0) + sw t3,12(a0) + sw t4,16(a0) + sw t5,20(a0) + sw t6,24(a0) + sw t7,28(a0) + addiu a0,a0,32 + +.Lchk1w: + andi a2,t8,0x3 # now a2 is the reminder past 1w chunks + beq a2,t8,.Llast8 + subu a3,t8,a2 # a3 is count of bytes in 1w chunks + addu a3,a0,a3 # now a3 is the dst address past the 1w chunks + +# copying in words (4-byte chunks) +.LwordCopy_loop: + lw t3,0(a1) # the first t3 may be equal t0 ... optimize? + addiu a1,a1,4 + addiu a0,a0,4 + bne a0,a3,.LwordCopy_loop + sw t3,-4(a0) + +# For the last (<8) bytes +.Llast8: + blez a2,.Lleave + addu a3,a0,a2 # a3 is the last dst address +.Llast8loop: + lb v1,0(a1) + addiu a1,a1,1 + addiu a0,a0,1 + bne a0,a3,.Llast8loop + sb v1,-1(a0) + +.Lleave: + j ra + nop + +# +# UNALIGNED case +# + +.Lunaligned: + # got here with a3="negu a0" + andi a3,a3,0x3 # test if the a0 is word aligned + beqz a3,.Lua_chk16w + subu a2,a2,a3 # bytes left after initial a3 bytes + + LWHI v1,0(a1) + LWLO v1,3(a1) + addu a1,a1,a3 # a3 may be here 1, 2 or 3 + SWHI v1,0(a0) + addu a0,a0,a3 # below the dst will be word aligned (NOTE1) + +.Lua_chk16w: + andi t8,a2,0x3f # any whole 64-byte chunks? + # t8 is the byte count after 64-byte chunks + beq a2,t8,.Lua_chk8w # if a2==t8, no 64-byte chunks + # There will be at most 1 32-byte chunk after it + subu a3,a2,t8 # subtract from a2 the reminder + # Here a3 counts bytes in 16w chunks + addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks + + addu t0,a0,a2 # t0 is the "past the end" address + + subu t9,t0,160 # t9 is the "last safe pref 30,128(a0)" address + + pref 0,0(a1) # bring the first line of src, addr 0 + pref 0,32(a1) # bring the second line of src, addr 32 + pref 0,64(a1) # bring the third line of src, addr 64 + pref 30,32(a0) # safe, as we have at least 64 bytes ahead +# In case the a0 > t9 don't use "pref 30" at all + sgtu v1,a0,t9 + bgtz v1,.Lua_loop16w # skip "pref 30,64(a0)" for too short arrays + nop +# otherwise, start with using pref30 + pref 30,64(a0) +.Lua_loop16w: + pref 0,96(a1) + LWHI t0,0(a1) + LWLO t0,3(a1) + LWHI t1,4(a1) + bgtz v1,.Lua_skip_pref30_96 + LWLO t1,7(a1) + pref 30,96(a0) # continue setting up the dest, addr 96 +.Lua_skip_pref30_96: + LWHI t2,8(a1) + LWLO t2,11(a1) + LWHI t3,12(a1) + LWLO t3,15(a1) + LWHI t4,16(a1) + LWLO t4,19(a1) + LWHI t5,20(a1) + LWLO t5,23(a1) + LWHI t6,24(a1) + LWLO t6,27(a1) + LWHI t7,28(a1) + LWLO t7,31(a1) + pref 0,128(a1) # bring the next lines of src, addr 128 + + sw t0,0(a0) + sw t1,4(a0) + sw t2,8(a0) + sw t3,12(a0) + sw t4,16(a0) + sw t5,20(a0) + sw t6,24(a0) + sw t7,28(a0) + + LWHI t0,32(a1) + LWLO t0,35(a1) + LWHI t1,36(a1) + bgtz v1,.Lua_skip_pref30_128 + LWLO t1,39(a1) + pref 30,128(a0) # continue setting up the dest, addr 128 +.Lua_skip_pref30_128: + LWHI t2,40(a1) + LWLO t2,43(a1) + LWHI t3,44(a1) + LWLO t3,47(a1) + LWHI t4,48(a1) + LWLO t4,51(a1) + LWHI t5,52(a1) + LWLO t5,55(a1) + LWHI t6,56(a1) + LWLO t6,59(a1) + LWHI t7,60(a1) + LWLO t7,63(a1) + pref 0, 160(a1) # bring the next lines of src, addr 160 + + sw t0,32(a0) + sw t1,36(a0) + sw t2,40(a0) + sw t3,44(a0) + sw t4,48(a0) + sw t5,52(a0) + sw t6,56(a0) + sw t7,60(a0) + + addiu a0,a0,64 # adding 64 to dest + sgtu v1,a0,t9 + bne a0,a3,.Lua_loop16w + addiu a1,a1,64 # adding 64 to src + move a2,t8 + +# Here we have src and dest word-aligned but less than 64-bytes to go + +.Lua_chk8w: + pref 0, 0x0(a1) + andi t8,a2,0x1f # is there a 32-byte chunk? + # the t8 is the reminder count + beq a2,t8,.Lua_chk1w # when a2=t8, no 32-byte chunk + nop + + LWHI t0,0(a1) + LWLO t0,3(a1) + LWHI t1,4(a1) + LWLO t1,7(a1) + LWHI t2,8(a1) + LWLO t2,11(a1) + LWHI t3,12(a1) + LWLO t3,15(a1) + LWHI t4,16(a1) + LWLO t4,19(a1) + LWHI t5,20(a1) + LWLO t5,23(a1) + LWHI t6,24(a1) + LWLO t6,27(a1) + LWHI t7,28(a1) + LWLO t7,31(a1) + addiu a1,a1,32 + + sw t0,0(a0) + sw t1,4(a0) + sw t2,8(a0) + sw t3,12(a0) + sw t4,16(a0) + sw t5,20(a0) + sw t6,24(a0) + sw t7,28(a0) + addiu a0,a0,32 + +.Lua_chk1w: + andi a2,t8,0x3 # now a2 is the reminder past 1w chunks + beq a2,t8,.Lua_smallCopy + subu a3,t8,a2 # a3 is count of bytes in 1w chunks + addu a3,a0,a3 # now a3 is the dst address past the 1w chunks + +# copying in words (4-byte chunks) +.Lua_wordCopy_loop: + LWHI v1,0(a1) + LWLO v1,3(a1) + addiu a1,a1,4 + addiu a0,a0,4 # note: dst=a0 is word aligned here, see NOTE1 + bne a0,a3,.Lua_wordCopy_loop + sw v1,-4(a0) + +# Now less than 4 bytes (value in a2) left to copy +.Lua_smallCopy: + beqz a2,.Lleave + addu a3,a0,a2 # a3 is the last dst address +.Lua_smallCopy_loop: + lb v1,0(a1) + addiu a1,a1,1 + addiu a0,a0,1 + bne a0,a3,.Lua_smallCopy_loop + sb v1,-1(a0) + + j ra + nop + + .set at + .set reorder + +END(memcpy) + + +/************************************************************************ + * Implementation : Static functions + ************************************************************************/ diff --git a/libc/arch-mips64/string/memset.S b/libc/arch-mips64/string/memset.S new file mode 100644 index 000000000..a1c5055c4 --- /dev/null +++ b/libc/arch-mips64/string/memset.S @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2009 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/************************************************************************ + * + * memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops + * Version: "043009" + * + ************************************************************************/ + + +/************************************************************************ + * Include files + ************************************************************************/ + +#include "machine/asm.h" + +/* + * This routine could be optimized for MIPS64. The current code only + * uses MIPS32 instructions. + */ + +#if defined(__MIPSEB__) +# define SWHI swl /* high part is left in big-endian */ +# define SWLO swr /* low part is right in big-endian */ +#endif + +#if defined(__MIPSEL__) +# define SWHI swr /* high part is right in little-endian */ +# define SWLO swl /* low part is left in little-endian */ +#endif + +#if !(defined(XGPROF) || defined(XPROF)) +#undef SETUP_GP +#define SETUP_GP +#endif + +#ifdef NDEBUG +#define DBG # +#else +#define DBG +#endif + +/* + * void _memset16(uint16_t* dst, uint16_t value, size_t size); + */ + +LEAF(_memset16,0) + .set noreorder +DBG /* Check parameters */ +DBG andi t0,a0,1 # a0 must be halfword aligned +DBG tne t0,zero +DBG andi t2,a2,1 # a2 must be even +DBG tne t2,zero + +#ifdef FIXARGS + # ensure count is even +#if (__mips==32) && (__mips_isa_rev>=2) + ins a2,zero,0,1 +#else + ori a2,1 + xori a2,1 +#endif +#endif + +#if (__mips==32) && (__mips_isa_rev>=2) + ins a1,a1,16,16 +#else + andi a1,0xffff + sll t3,a1,16 + or a1,t3 +#endif + + beqz a2,.Ldone + andi t1,a0,2 + beqz t1,.Lalignok + addu t0,a0,a2 # t0 is the "past the end" address + sh a1,0(a0) # store one halfword to get aligned + addu a0,2 + subu a2,2 +.Lalignok: + slti t1,a2,4 # .Laligned for 4 or more bytes + beqz t1,.Laligned + sne t1,a2,2 # one more halfword? + bnez t1,.Ldone + nop + sh a1,0(a0) +.Ldone: + j ra + nop + .set reorder +END(_memset16) + +/* + * void _memset32(uint32_t* dst, uint32_t value, size_t size); + */ + +LEAF(_memset32,0) + .set noreorder +DBG /* Check parameters */ +DBG andi t0,a0,3 # a0 must be word aligned +DBG tne t0,zero +DBG andi t2,a2,3 # a2 must be a multiple of 4 bytes +DBG tne t2,zero + +#ifdef FIXARGS + # ensure count is a multiple of 4 +#if (__mips==32) && (__mips_isa_rev>=2) + ins $a2,$0,0,2 +#else + ori a2,3 + xori a2,3 +#endif +#endif + + bnez a2,.Laligned # any work to do? + addu t0,a0,a2 # t0 is the "past the end" address + + j ra + nop + .set reorder +END(_memset32) + +LEAF(memset,0) + + .set noreorder + .set noat + + addu t0,a0,a2 # t0 is the "past the end" address + slti AT,a2,4 # is a2 less than 4? + bne AT,zero,.Llast4 # if yes, go to last4 + move v0,a0 # memset returns the dst pointer + + beq a1,zero,.Lset0 + subu v1,zero,a0 + + # smear byte into 32 bit word +#if (__mips==32) && (__mips_isa_rev>=2) + ins a1, a1, 8, 8 # Replicate fill byte into half-word. + ins a1, a1, 16, 16 # Replicate fill byte into word. +#else + and a1,0xff + sll AT,a1,8 + or a1,AT + sll AT,a1,16 + or a1,AT +#endif + +.Lset0: + andi v1,v1,0x3 # word-unaligned address? + beq v1,zero,.Laligned # v1 is the unalignment count + subu a2,a2,v1 + SWHI a1,0(a0) + addu a0,a0,v1 + +# Here we have the "word-aligned" a0 (until the "last4") +.Laligned: + andi t8,a2,0x3f # any 64-byte chunks? + # t8 is the byte count past 64-byte chunks + beq a2,t8,.Lchk8w # when a2==t8, no 64-byte chunks + # There will be at most 1 32-byte chunk then + subu a3,a2,t8 # subtract from a2 the reminder + # Here a3 counts bytes in 16w chunks + addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks + +# Find out, if there are any 64-byte chunks after which will be still at least +# 96 bytes left. The value "96" is calculated as needed buffer for +# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after +# incrementing "a0" by 64. +# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk. +# + sltiu v1,a2,160 + bgtz v1,.Lloop16w_nopref30 # skip "pref 30,0(a0)" + subu t7,a2,96 # subtract "pref 30 unsafe" region + # below we have at least 1 64-byte chunk which is "pref 30 safe" + andi t6,t7,0x3f # t6 is past "64-byte safe chunks" reminder + subu t5,t7,t6 # subtract from t7 the reminder + # Here t5 counts bytes in 16w "safe" chunks + addu t4,a0,t5 # Now t4 is the dst after 64-byte "safe" chunks + +# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line +# pref 30,0(a0) +# Here we are in the region, where it is safe to use "pref 30,64(a0)" +.Lloop16w: + addiu a0,a0,64 + pref 30,-32(a0) # continue setting up the dest, addr 64-32 + sw a1,-64(a0) + sw a1,-60(a0) + sw a1,-56(a0) + sw a1,-52(a0) + sw a1,-48(a0) + sw a1,-44(a0) + sw a1,-40(a0) + sw a1,-36(a0) + nop + nop # the extra nop instructions help to balance + nop # cycles needed for "store" + "fill" + "evict" + nop # For 64byte store there are needed 8 fill + nop # and 8 evict cycles, i.e. at least 32 instr. + nop + nop + pref 30,0(a0) # continue setting up the dest, addr 64-0 + sw a1,-32(a0) + sw a1,-28(a0) + sw a1,-24(a0) + sw a1,-20(a0) + sw a1,-16(a0) + sw a1,-12(a0) + sw a1,-8(a0) + sw a1,-4(a0) + nop + nop + nop + nop # NOTE: adding 14 nop-s instead of 12 nop-s + nop # gives better results for "fast" memory + nop + bne a0,t4,.Lloop16w + nop + + beq a0,a3,.Lchk8w # maybe no more 64-byte chunks? + nop # this "delayed slot" is useless ... + +.Lloop16w_nopref30: # there could be up to 3 "64-byte nopref30" chunks + addiu a0,a0,64 + sw a1,-64(a0) + sw a1,-60(a0) + sw a1,-56(a0) + sw a1,-52(a0) + sw a1,-48(a0) + sw a1,-44(a0) + sw a1,-40(a0) + sw a1,-36(a0) + sw a1,-32(a0) + sw a1,-28(a0) + sw a1,-24(a0) + sw a1,-20(a0) + sw a1,-16(a0) + sw a1,-12(a0) + sw a1,-8(a0) + bne a0,a3,.Lloop16w_nopref30 + sw a1,-4(a0) + +.Lchk8w: # t8 here is the byte count past 64-byte chunks + + andi t7,t8,0x1f # is there a 32-byte chunk? + # the t7 is the reminder count past 32-bytes + beq t8,t7,.Lchk1w # when t8==t7, no 32-byte chunk + move a2,t7 + + sw a1,0(a0) + sw a1,4(a0) + sw a1,8(a0) + sw a1,12(a0) + sw a1,16(a0) + sw a1,20(a0) + sw a1,24(a0) + sw a1,28(a0) + addiu a0,a0,32 + +.Lchk1w: + andi t8,a2,0x3 # now t8 is the reminder past 1w chunks + beq a2,t8,.Llast4aligned + subu a3,a2,t8 # a3 is the count of bytes in 1w chunks + addu a3,a0,a3 # now a3 is the dst address past the 1w chunks + +# copying in words (4-byte chunks) +.LwordCopy_loop: + addiu a0,a0,4 + bne a0,a3,.LwordCopy_loop + sw a1,-4(a0) + +# store last 0-3 bytes +# this will repeat the last store if the memset finishes on a word boundary +.Llast4aligned: + j ra + SWLO a1,-1(t0) + +.Llast4: + beq a0,t0,.Llast4e +.Llast4l: + addiu a0,a0,1 + bne a0,t0,.Llast4l + sb a1,-1(a0) +.Llast4e: + j ra + nop + + .set at + .set reorder + +END(memset) + + +/************************************************************************ + * Implementation : Static functions + ************************************************************************/ + diff --git a/libc/arch-mips64/string/mips-string-ops.h b/libc/arch-mips64/string/mips-string-ops.h new file mode 100644 index 000000000..e635ba178 --- /dev/null +++ b/libc/arch-mips64/string/mips-string-ops.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2010 MIPS Technologies, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with + * the distribution. + * * Neither the name of MIPS Technologies Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MIPS_STRING_OPS_H +#define __MIPS_STRING_OPS_H + /* This definition of the byte bitfields uses the + assumption that the layout of the bitfields is + equivalent to the layout in memory. Generally, + for the MIPS ABIs, this is true. If you compile + the strcmp.c file with -DSMOKE_TEST_NEW_STRCMP, + this assumption will be tested. + + Also, regardless of char signedness, ANSI C dictates that + strcmp() treats each character as unsigned char. For + strlen and the like, signedness doesn't matter. + + Also, this code assumes that there are 8-bits per 'char'. */ + +#if __mips64 +typedef struct bits +{ + unsigned long B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8; +} bits_t; +#else +typedef struct bits +{ + unsigned long B0:8, B1:8, B2:8, B3:8; +} bits_t; +#endif + +#ifndef _ULW + /* for MIPS GCC, there is no unaligned builtins - so this code forces + the compiler to treat the pointer access as unaligned. */ +struct ulw +{ + unsigned long b; +} __attribute__ ((packed)); + +#define _ULW(__x) ((struct ulw *) ((char *)(&__x)))->b; +#endif + +/* This union assumes that small structures can be in registers. If + not, then memory accesses will be done - not optimal, but ok. */ +typedef union +{ + unsigned long v; + bits_t b; +} bitfields_t; + +#ifndef detect_zero +/* __mips_dsp, __mips_dspr2, and __mips64 are predefined by + the compiler, based on command line options. */ +#if (__mips_dsp || __mips_dspr2) && !__mips64 +#define __mips_using_dsp 1 + +/* DSP 4-lane (8 unsigned bits per line) subtract and saturate + * Intrinsic operation. How this works: + * Given a 4-byte string of "ABC\0", subtract this as + * an unsigned integer from 0x01010101: + * 0x01010101 + * - 0x41424300 + * ----------- + ( 0xbfbebe01 <-- answer without saturation + * 0x00000001 <-- answer with saturation + * When this 4-lane vector is treated as an unsigned int value, + * a non-zero answer indicates the presence of a zero in the + * original 4-byte argument. */ + +typedef signed char v4i8 __attribute__ ((vector_size (4))); + +#define detect_zero(__x,__y,__01s,__80s)\ + ((unsigned) __builtin_mips_subu_s_qb((v4i8) __01s,(v4i8) __x)) + + /* sets all 4 lanes to requested byte. */ +#define set_byte_lanes(__x) ((unsigned) __builtin_mips_repl_qb(__x)) + + /* sets all 4 lanes to 0x01. */ +#define def_and_set_01(__x) unsigned long __x = (unsigned) __builtin_mips_repl_qb(0x01) + + /* sets all 4 lanes to 0x80. Not needed when subu_s.qb used. */ +#define def_and_set_80(__x) /* do nothing */ + +#else + /* this version, originally published in the 80's, uses + a reverse-carry-set like determination of the zero byte. + The steps are, for __x = 0x31ff0001: + __x - _01s = 0x30fdff00 + ~__x = 0xce00fffe + ((__x - _01s) & ~__x) = 0x0000ff00 + x & _80s = 0x00008000 <- byte 3 was zero + Some implementaions naively assume that characters are + always 7-bit unsigned ASCII. With that assumption, the + "& ~x" is usually discarded. Since character strings + are 8-bit, the and is needed to catch the case of + a false positive when the byte is 0x80. */ + +#define detect_zero(__x,__y,_01s,_80s)\ + ((unsigned) (((__x) - _01s) & ~(__x)) & _80s) + +#if __mips64 +#define def_and_set_80(__x) unsigned long __x = 0x8080808080808080ul +#define def_and_set_01(__x) unsigned long __x = 0x0101010101010101ul +#else +#define def_and_set_80(__x) unsigned long __x = 0x80808080ul +#define def_and_set_01(__x) unsigned long __x = 0x01010101ul +#endif + +#endif +#endif + +/* dealing with 'void *' conversions without using extra variables. */ +#define get_byte(__x,__idx) (((unsigned char *) (__x))[__idx]) +#define set_byte(__x,__idx,__fill) ((unsigned char *) (__x))[__idx] = (__fill) +#define get_word(__x,__idx) (((unsigned long *) (__x))[__idx]) +#define set_word(__x,__idx,__fill) ((unsigned long *) (__x))[__idx] = (__fill) +#define inc_ptr_as(__type,__x,__inc) __x = (void *) (((__type) __x) + (__inc)) +#define cvt_ptr_to(__type,__x) ((__type) (__x)) + +#endif diff --git a/libc/arch-mips64/string/mips_strlen.c b/libc/arch-mips64/string/mips_strlen.c new file mode 100644 index 000000000..37e586588 --- /dev/null +++ b/libc/arch-mips64/string/mips_strlen.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2010 MIPS Technologies, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with + * the distribution. + * * Neither the name of MIPS Technologies Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "mips-string-ops.h" + +#define do_strlen_word(__av) {\ + if (detect_zero(x,x,_01s,_80s)) break;\ + x = __av;\ + cnt += sizeof (unsigned);\ + } + +#define do_strlen_byte(__x) {\ + if ((bx.b.B##__x) == 0) break;\ + ++cnt;\ + } + +#if SMOKE_TEST_MIPS_STRLEN +#define strlen my_strlen +#endif + +size_t +strlen (const char *_a) +{ + int cnt = 0; + unsigned long x; + + /* align the string to word boundary so we can do word at a time. */ + if ((cvt_ptr_to (unsigned long, _a) & (sizeof (unsigned long) - 1)) != 0) + { + if ((cvt_ptr_to (unsigned long, _a) & 1) != 0) + { + if (get_byte (_a, 0) == 0) + return cnt; + /* set bit 1 so 2-bytes are checked and incremented. */ + inc_ptr_as (char *, _a, 1); + ++cnt; + } + if ((cvt_ptr_to (unsigned long, _a) & 2) != 0) + { + if (get_byte (_a, 0) == 0) + return cnt + 0; + if (get_byte (_a, 1) == 0) + return cnt + 1; + inc_ptr_as (char *, _a, 2); + cnt += 2; + } + } + +#if __mips64 +#error strlen: mips64 check for 4-byte alignment not implemented. +#endif + + if (1) + { + def_and_set_01 (_01s); + def_and_set_80 (_80s); + + /* as advantagous as it is to performance, this code cannot pre-load + the following word, nor can it prefetch the next line at the start + of the loop since the string can be at the end of a page with the + following page unmapped. There are tests in the suite to catch + any attempt to go beyond the current word. */ + x = get_word (_a, 0); + while (1) + { + /* doing 8 words should cover most strings. */ + do_strlen_word (get_word (_a, 1)); + do_strlen_word (get_word (_a, 2)); + do_strlen_word (get_word (_a, 3)); + do_strlen_word (get_word (_a, 4)); + do_strlen_word (get_word (_a, 5)); + do_strlen_word (get_word (_a, 6)); + do_strlen_word (get_word (_a, 7)); + do_strlen_word (get_word (_a, 8)); + inc_ptr_as (unsigned long*, _a, 8); + } + } + while (1) + { + /* pull apart the last word processed and find the zero. */ + bitfields_t bx; + bx.v = x; +#if __mips64 + do_strlen_byte (0); + do_strlen_byte (1); + do_strlen_byte (2); + do_strlen_byte (3); + do_strlen_byte (4); + do_strlen_byte (5); + do_strlen_byte (6); +#else + do_strlen_byte (0); + do_strlen_byte (1); + do_strlen_byte (2); +#endif + /* last byte is zero */ + break; + } + return cnt; +} + +#undef do_strlen_byte +#undef do_strlen_word + +#if SMOKE_TEST_MIPS_STRLEN +#include +char str1[] = "DHRYSTONE PROGRAM, 1'ST STRING"; +char str2[] = "DHRYSTONE PROGRAM, 2'ST STRING"; + +char str3[] = "another string"; +char str4[] = "another"; + +char str5[] = "somes tring"; +char str6[] = "somes_tring"; + +char str7[16], str8[16]; + +static char * +chk (unsigned long mine, unsigned long libs, int *errors) +{ + static char answer[1024]; + char *result = mine == libs ? "PASS" : "FAIL"; + sprintf (answer, "new_strlen=%d: lib_strlen=%d: %s!", mine, libs, result); + if (mine != libs) + (*errors)++; + return answer; +} + +int +main (int argc, char **argv) +{ + int errors = 0; + /* set -1 in one position */ + str6[5] = 0xff; + /* set zero in same position with junk in following 3 */ + str7[0] = str8[0] = 0; + str7[1] = 0xff; + str7[2] = 'a'; + str7[3] = 2; + str8[1] = 's'; + str8[2] = -2; + str8[3] = 0; + + fprintf (stderr, "========== mips_strlen%s test...\n", + argv[0] ? argv[0] : "unknown strlen"); +#define P(__x,__y) {\ + int a = my_strlen(__x + __y);\ + int b = (strlen)(__x + __y) /* library version */;\ + fprintf(stderr,"%s+%d: %s\n",#__x,__y,chk(a,b,&errors));\ + } + + P (str1, 0); + P (str1, 1); + P (str1, 2); + P (str1, 3); + + P (str2, 0); + P (str2, 1); + P (str2, 2); + P (str2, 3); + + P (str3, 0); + P (str3, 1); + P (str3, 2); + P (str3, 3); + + P (str4, 0); + P (str4, 1); + P (str4, 2); + P (str4, 3); + + P (str5, 0); + P (str5, 1); + P (str5, 2); + P (str5, 3); + + P (str6, 0); + P (str6, 1); + P (str6, 2); + P (str6, 3); + + P (str7, 0); + P (str7, 1); + P (str7, 2); + P (str7, 3); + + P (str8, 0); + P (str8, 1); + P (str8, 2); + P (str8, 3); + + return errors; +} +#endif diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h index 3d754c058..37b8dc2c8 100644 --- a/libc/include/sys/stat.h +++ b/libc/include/sys/stat.h @@ -62,24 +62,24 @@ struct stat { }; #elif defined(__mips__) struct stat { - unsigned long st_dev; - unsigned long __pad0[3]; + unsigned int st_dev; + unsigned int __pad0[3]; unsigned long long st_ino; unsigned int st_mode; unsigned int st_nlink; - unsigned long st_uid; - unsigned long st_gid; - unsigned long st_rdev; - unsigned long __pad1[3]; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + unsigned int __pad1[3]; long long st_size; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; - unsigned long st_blksize; - unsigned long __pad2; + unsigned int st_atime; + unsigned int st_atime_nsec; + unsigned int st_mtime; + unsigned int st_mtime_nsec; + unsigned int st_ctime; + unsigned int st_ctime_nsec; + unsigned int st_blksize; + unsigned int __pad2; unsigned long long st_blocks; }; #elif defined(__x86_64__) diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h index 10fe5029b..10afbc329 100644 --- a/libc/include/sys/vfs.h +++ b/libc/include/sys/vfs.h @@ -38,7 +38,7 @@ __BEGIN_DECLS typedef struct { int __val[2]; } __fsid_t; typedef __fsid_t fsid_t; -#if defined(__LP64__) +#if defined(__aarch64__) || defined(__x86_64__) struct statfs { uint64_t f_type; uint64_t f_bsize; @@ -53,6 +53,22 @@ struct statfs { uint64_t f_flags; uint64_t f_spare[4]; }; +#elif defined(__mips__) && defined(__LP64__) +/* 64-bit MIPS. */ +struct statfs { + uint64_t f_type; + uint64_t f_bsize; + uint64_t f_frsize; /* Fragment size - unsupported. */ + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_files; + uint64_t f_ffree; + uint64_t f_bavail; + fsid_t f_fsid; + uint64_t f_namelen; + uint64_t f_flags; + uint64_t f_spare[5]; +}; #elif defined(__mips__) /* 32-bit MIPS (corresponds to the kernel's statfs64 type). */ struct statfs { diff --git a/libm/Android.mk b/libm/Android.mk index 64a40e4fa..d06088b9f 100644 --- a/libm/Android.mk +++ b/libm/Android.mk @@ -254,6 +254,10 @@ LOCAL_CFLAGS_mips := -fno-builtin-rintf -fno-builtin-rint LOCAL_C_INCLUDES_mips := $(LOCAL_PATH)/mips LOCAL_SRC_FILES_mips := mips/fenv.c +LOCAL_CFLAGS_mips64 := -fno-builtin-rintf -fno-builtin-rint +LOCAL_C_INCLUDES_mips64 := $(LOCAL_PATH)/mips +LOCAL_SRC_FILES_mips64 := mips/fenv.c + include $(BUILD_STATIC_LIBRARY) # diff --git a/libm/mips/_fpmath.h b/libm/mips/_fpmath.h index f006a583b..f759639eb 100644 --- a/libm/mips/_fpmath.h +++ b/libm/mips/_fpmath.h @@ -30,23 +30,49 @@ union IEEEl2bits { long double e; struct { #ifndef __MIPSEB__ +#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) + unsigned long manl :64; + unsigned long manh :48; + unsigned int exp :15; + unsigned int sign :1; +#else unsigned int manl :32; unsigned int manh :20; unsigned int exp :11; unsigned int sign :1; +#endif #else - unsigned int sign :1; - unsigned int exp :11; - unsigned int manh :20; - unsigned int manl :32; +#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) + unsigned int sign :1; + unsigned int exp :15; + unsigned long manh :48; + unsigned long manl :64; +#else + unsigned int sign :1; + unsigned int exp :11; + unsigned int manh :20; + unsigned int manl :32; +#endif #endif } bits; + }; #define LDBL_NBIT 0 #define mask_nbit_l(u) ((void)0) #define LDBL_IMPLICIT_NBIT +#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) +#define LDBL_MANH_SIZE 48 +#define LDBL_MANL_SIZE 64 + +#define LDBL_TO_ARRAY32(u, a) do { \ + (a)[0] = (uint32_t)(u).bits.manl; \ + (a)[1] = (uint32_t)((u).bits.manl >> 32); \ + (a)[2] = (uint32_t)(u).bits.manh; \ + (a)[3] = (uint32_t)((u).bits.manh >> 32); \ +} while(0) +#else #define LDBL_MANH_SIZE 20 #define LDBL_MANL_SIZE 32 @@ -54,3 +80,4 @@ union IEEEl2bits { (a)[0] = (uint32_t)(u).bits.manl; \ (a)[1] = (uint32_t)(u).bits.manh; \ } while(0) +#endif