From bec90733b9de6e7d75b8bda19b3f0a7117e6b78d Mon Sep 17 00:00:00 2001 From: Manuel Novoa III Date: Thu, 2 Sep 2004 14:39:38 +0000 Subject: Add a couple of mips-specific string funcs. Port the generic optimized string funcs from glibc, with some tweaks to cut their size a little. The main change is making memmove call memcpy for forward copying to trim redundant code. Make use of both the generic and arch-specific speed-optimized string funcs configurable. Arch-specific take precedence over generic, and generic takes precedence over basic size-optimized uClibc funcs. --- libc/string/mips/Makefile | 38 +++++++++++++ libc/string/mips/memcpy.S | 140 ++++++++++++++++++++++++++++++++++++++++++++++ libc/string/mips/memset.S | 90 +++++++++++++++++++++++++++++ libc/string/mips/sysdep.h | 51 +++++++++++++++++ 4 files changed, 319 insertions(+) create mode 100644 libc/string/mips/Makefile create mode 100644 libc/string/mips/memcpy.S create mode 100644 libc/string/mips/memset.S create mode 100644 libc/string/mips/sysdep.h (limited to 'libc/string/mips') diff --git a/libc/string/mips/Makefile b/libc/string/mips/Makefile new file mode 100644 index 000000000..a17826ea5 --- /dev/null +++ b/libc/string/mips/Makefile @@ -0,0 +1,38 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2003 Erik Andersen +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +TOPDIR=../../../ +include $(TOPDIR)Rules.mak + +SSRC= memcpy.S memset.S +SOBJS=$(patsubst %.S,%.o, $(SSRC)) + +all: $(SOBJS) $(LIBC) + +$(LIBC): ar-target + +ar-target: $(SOBJS) + $(AR) $(ARFLAGS) $(LIBC) $(SOBJS) + +$(SOBJS): %.o : %.S + $(CC) $(CFLAGS) -c $< -o $@ + $(STRIPTOOL) -x -R .note -R .comment $*.o + +clean: + $(RM) *.[oa] *~ core + diff --git a/libc/string/mips/memcpy.S b/libc/string/mips/memcpy.S new file mode 100644 index 000000000..369c82f39 --- /dev/null +++ b/libc/string/mips/memcpy.S @@ -0,0 +1,140 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Hartvig Ekner , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/*#include */ +#include +#include "sysdep.h" + +#ifdef __mips64 +#error mips32 code being compiled for mips64! +#endif + +/* void *memcpy(void *s1, const void *s2, size_t n); */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# 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 */ +#else +# 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 little-endian */ +# define SWLO swl /* low part is left in little-endian */ +#endif + +ENTRY (memcpy) + .set noreorder + + slti t0, a2, 8 # Less than 8? + bne t0, zero, L(last8) + move v0, a0 # Setup exit value before too late + + xor t0, a1, a0 # Find a0/a1 displacement + andi t0, 0x3 + bne t0, zero, L(shift) # Go handle the unaligned case + subu t1, zero, a1 + andi t1, 0x3 # a0/a1 are aligned, but are we + beq t1, zero, L(chk8w) # starting in the middle of a word? + subu a2, t1 + LWHI t0, 0(a1) # Yes we are... take care of that + addu a1, t1 + SWHI t0, 0(a0) + addu a0, t1 + +L(chk8w): + andi t0, a2, 0x1f # 32 or more bytes left? + beq t0, a2, L(chk1w) + subu a3, a2, t0 # Yes + addu a3, a1 # a3 = end address of loop + move a2, t0 # a2 = what will be left after loop +L(lop8w): + lw t0, 0(a1) # Loop taking 8 words at a time + 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 a0, 32 + addiu a1, 32 + sw t0, -32(a0) + sw t1, -28(a0) + sw t2, -24(a0) + sw t3, -20(a0) + sw t4, -16(a0) + sw t5, -12(a0) + sw t6, -8(a0) + bne a1, a3, L(lop8w) + sw t7, -4(a0) + +L(chk1w): + andi t0, a2, 0x3 # 4 or more bytes left? + beq t0, a2, L(last8) + subu a3, a2, t0 # Yes, handle them one word at a time + addu a3, a1 # a3 again end address + move a2, t0 +L(lop1w): + lw t0, 0(a1) + addiu a0, 4 + addiu a1, 4 + bne a1, a3, L(lop1w) + sw t0, -4(a0) + +L(last8): + blez a2, L(lst8e) # Handle last 8 bytes, one at a time + addu a3, a2, a1 +L(lst8l): + lb t0, 0(a1) + addiu a0, 1 + addiu a1, 1 + bne a1, a3, L(lst8l) + sb t0, -1(a0) +L(lst8e): + jr ra # Bye, bye + nop + +L(shift): + subu a3, zero, a0 # Src and Dest unaligned + andi a3, 0x3 # (unoptimized case...) + beq a3, zero, L(shft1) + subu a2, a3 # a2 = bytes left + LWHI t0, 0(a1) # Take care of first odd part + LWLO t0, 3(a1) + addu a1, a3 + SWHI t0, 0(a0) + addu a0, a3 +L(shft1): + andi t0, a2, 0x3 + subu a3, a2, t0 + addu a3, a1 +L(shfth): + LWHI t1, 0(a1) # Limp through, word by word + LWLO t1, 3(a1) + addiu a0, 4 + addiu a1, 4 + bne a1, a3, L(shfth) + sw t1, -4(a0) + b L(last8) # Handle anything which may be left + move a2, t0 + + .set reorder +END (memcpy) +libc_hidden_builtin_def (memcpy) diff --git a/libc/string/mips/memset.S b/libc/string/mips/memset.S new file mode 100644 index 000000000..0919fb82e --- /dev/null +++ b/libc/string/mips/memset.S @@ -0,0 +1,90 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Hartvig Ekner , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/*#include */ +#include +#include "sysdep.h" + +#ifdef __mips64 +#error mips32 code being compiled for mips64! +#endif + +/* void *memset(void *s, int c, size_t n). */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define SWHI swl /* high part is left in big-endian */ +#else +# define SWHI swr /* high part is right in little-endian */ +#endif + +ENTRY (memset) + .set noreorder + + slti t1, a2, 8 # Less than 8? + bne t1, zero, L(last8) + move v0, a0 # Setup exit value before too late + + beq a1, zero, L(ueven) # If zero pattern, no need to extend + andi a1, 0xff # Avoid problems with bogus arguments + sll t0, a1, 8 + or a1, t0 + sll t0, a1, 16 + or a1, t0 # a1 is now pattern in full word + +L(ueven): + subu t0, zero, a0 # Unaligned address? + andi t0, 0x3 + beq t0, zero, L(chkw) + subu a2, t0 + SWHI a1, 0(a0) # Yes, handle first unaligned part + addu a0, t0 # Now both a0 and a2 are updated + +L(chkw): + andi t0, a2, 0x7 # Enough left for one loop iteration? + beq t0, a2, L(chkl) + subu a3, a2, t0 + addu a3, a0 # a3 is last loop address +1 + move a2, t0 # a2 is now # of bytes left after loop +L(loopw): + addiu a0, 8 # Handle 2 words pr. iteration + sw a1, -8(a0) + bne a0, a3, L(loopw) + sw a1, -4(a0) + +L(chkl): + andi t0, a2, 0x4 # Check if there is at least a full + beq t0, zero, L(last8) # word remaining after the loop + subu a2, t0 + sw a1, 0(a0) # Yes... + addiu a0, 4 + +L(last8): + blez a2, L(exit) # Handle last 8 bytes (if cnt>0) + addu a3, a2, a0 # a3 is last address +1 +L(lst8l): + addiu a0, 1 + bne a0, a3, L(lst8l) + sb a1, -1(a0) +L(exit): + j ra # Bye, bye + nop + + .set reorder +END (memset) +libc_hidden_builtin_def (memset) diff --git a/libc/string/mips/sysdep.h b/libc/string/mips/sysdep.h new file mode 100644 index 000000000..2c96ced0d --- /dev/null +++ b/libc/string/mips/sysdep.h @@ -0,0 +1,51 @@ +/* Adapted from glibc's sysdeps/unix/mips/sysdep.h */ + +/* Copyright (C) 1992, 1995, 1997, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __ASSEMBLER__ + +#include +#include + +#define ENTRY(name) \ + .globl name; \ + .align 2; \ + .ent name,0; \ + name##: + +#undef END +#define END(function) \ + .end function; \ + .size function,.-function + +#if _MIPS_SIM == _MIPS_SIM_ABI32 || _MIPS_SIM == _MIPS_SIM_ABIO64 +# define L(label) $L ## label +#else +# define L(label) .L ## label +#endif + +#ifdef libc_hidden_builtin_def +#error WHOA!!! libc_hidden_builtin_def is defined +#else +#define libc_hidden_builtin_def(name) +#endif + +#endif -- cgit v1.2.3