[MIPS64] libc/libm support
libc/libm support for MIPS64 targets
Change-Id: I8271941d418612a286be55495f0e95822f90004f
Signed-off-by: Chris Dearman <chris.dearman@imgtec.com>
Signed-off-by: Raghu Gandham <raghu.gandham@imgtec.com>
diff --git a/libc/arch-mips64/bionic/__bionic_clone.S b/libc/arch-mips64/bionic/__bionic_clone.S
new file mode 100644
index 0000000..2a9a2b0
--- /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 <machine/asm.h>
+#include <asm/unistd.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+#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 0000000..834c89d
--- /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-mips64/bionic/__set_tls.c b/libc/arch-mips64/bionic/__set_tls.c
new file mode 100644
index 0000000..38e3a50
--- /dev/null
+++ b/libc/arch-mips64/bionic/__set_tls.c
@@ -0,0 +1,35 @@
+/*
+ * 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 <pthread.h>
+
+extern int __set_thread_area(void *u_info);
+
+int __set_tls(void *ptr)
+{
+ 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 0000000..8f624c3
--- /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 <asm/unistd.h>
+
+ .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 0000000..e7083ae
--- /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 <machine/asm.h>
+#include <machine/regnum.h>
+#include <machine/signal.h>
+
+/*
+ * _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 0000000..759008c
--- /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 0000000..d0b5c84
--- /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 <machine/asm.h>
+
+/*
+ * 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 0000000..7955dd6
--- /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 <unistd.h>
+#include <sys/cachectl.h>
+
+#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 0000000..2ea31ad
--- /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 <stddef.h>
+#include <stdint.h>
+
+__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 0000000..d664ce6
--- /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 0000000..1a249a7
--- /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 <machine/asm.h>
+#include <private/bionic_asm.h>
+
+#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 0000000..66a61ec
--- /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 <dirent.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+/* 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 0000000..b70c078
--- /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 <machine/asm.h>
+
+/*
+ * 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 0000000..7c21195
--- /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 <machine/asm.h>
+#include <machine/regnum.h>
+#include <machine/signal.h>
+
+/*
+ * 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 0000000..b05454c
--- /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 <machine/asm.h>
+#include <machine/regnum.h>
+#include <machine/setjmp.h>
+
+/*
+ * 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 0000000..08aa705
--- /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 <machine/asm.h>
+#include <asm/unistd.h>
+
+#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 0000000..c936945
--- /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 <machine/asm.h>
+#include <asm/unistd.h>
+#include <linux/sched.h>
+
+// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__.
+// #include <asm/signal.h>
+#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)