diff options
Diffstat (limited to 'sysdeps/i386')
-rw-r--r-- | sysdeps/i386/Implies | 1 | ||||
-rw-r--r-- | sysdeps/i386/Makefile | 3 | ||||
-rw-r--r-- | sysdeps/i386/__longjmp.c | 66 | ||||
-rw-r--r-- | sysdeps/i386/abort.c | 28 | ||||
-rw-r--r-- | sysdeps/i386/add_n.S | 94 | ||||
-rw-r--r-- | sysdeps/i386/addmul_1.S | 75 | ||||
-rw-r--r-- | sysdeps/i386/asm-syntax.h | 64 | ||||
-rw-r--r-- | sysdeps/i386/bsd-_setjmp.S | 32 | ||||
-rw-r--r-- | sysdeps/i386/bsd-setjmp.S | 32 | ||||
-rw-r--r-- | sysdeps/i386/bytesex.h | 3 | ||||
-rw-r--r-- | sysdeps/i386/bzero.c | 81 | ||||
-rw-r--r-- | sysdeps/i386/ffs.c | 45 | ||||
-rw-r--r-- | sysdeps/i386/i586/memcopy.h | 94 | ||||
-rw-r--r-- | sysdeps/i386/jmp_buf.h | 9 | ||||
-rw-r--r-- | sysdeps/i386/lshift.S | 84 | ||||
-rw-r--r-- | sysdeps/i386/memchr.c | 48 | ||||
-rw-r--r-- | sysdeps/i386/memcopy.h | 86 | ||||
-rw-r--r-- | sysdeps/i386/memset.c | 83 | ||||
-rw-r--r-- | sysdeps/i386/mul_1.S | 74 | ||||
-rw-r--r-- | sysdeps/i386/rshift.S | 86 | ||||
-rw-r--r-- | sysdeps/i386/setjmp.c | 55 | ||||
-rw-r--r-- | sysdeps/i386/strlen.c | 36 | ||||
-rw-r--r-- | sysdeps/i386/sub_n.S | 94 | ||||
-rw-r--r-- | sysdeps/i386/submul_1.S | 75 |
24 files changed, 1348 insertions, 0 deletions
diff --git a/sysdeps/i386/Implies b/sysdeps/i386/Implies new file mode 100644 index 0000000000..1610bfdc5b --- /dev/null +++ b/sysdeps/i386/Implies @@ -0,0 +1 @@ +ieee754 diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile new file mode 100644 index 0000000000..29676784a2 --- /dev/null +++ b/sysdeps/i386/Makefile @@ -0,0 +1,3 @@ +# The mpn functions need a #define for asm syntax flavor. +# Every i386 port in use uses gas syntax (I think). +asm-CPPFLAGS := $(asm-CPPFLAGS) -DGAS_SYNTAX diff --git a/sysdeps/i386/__longjmp.c b/sysdeps/i386/__longjmp.c new file mode 100644 index 0000000000..65d6ec18ec --- /dev/null +++ b/sysdeps/i386/__longjmp.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef __GNUC__ + #error This file uses GNU C extensions; you must compile with GCC. +#endif + +/* Put these global register declarations first, because we get an error if + they come after any function definition, including inlines which might + be in some header. */ + +#define REGS \ + REG (bx);\ + REG (si);\ + REG (di);\ + REG (bp);\ + REG (sp) + +#define REG(xx) register long int xx asm (#xx) +REGS; +#undef REG + +#include <ansidecl.h> +#include <errno.h> +#include <setjmp.h> +#include <stdlib.h> + +/* Jump to the position specified by ENV, causing the + setjmp call there to return VAL, or 1 if VAL is 0. */ +void +DEFUN(__longjmp, (env, val), + __jmp_buf env AND int val) +{ + /* We specify explicit registers because, when not optimizing, + the compiler will generate code that uses the frame pointer + after it's been munged. */ + + register CONST __typeof (env[0]) *e asm ("cx"); + register int v asm ("ax"); + + e = env; + v = val == 0 ? 1 : val; + +#define REG(xx) xx = (long int) e->__##xx + REGS; + + asm volatile ("jmp %*%0" : : "g" (e->__pc), "a" (v)); + + /* NOTREACHED */ + abort (); +} diff --git a/sysdeps/i386/abort.c b/sysdeps/i386/abort.c new file mode 100644 index 0000000000..28513fd1ec --- /dev/null +++ b/sysdeps/i386/abort.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdlib.h> + +/* Cause an abnormal program termination with core-dump. */ +void +DEFUN_VOID(abort) +{ + while (1) + asm ("hlt"); +} diff --git a/sysdeps/i386/add_n.S b/sysdeps/i386/add_n.S new file mode 100644 index 0000000000..f528976866 --- /dev/null +++ b/sysdeps/i386/add_n.S @@ -0,0 +1,94 @@ +/* i80386 __mpn_add_n -- Add two limb vectors of the same length > 0 and store +sum in a third limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + s2_ptr (sp + 12) + size (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_add_n) +C_SYMBOL_NAME(__mpn_add_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ + leal (Loop - 3)(%eax,%eax,8),%eax /* calc start addr in loop */ + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + adcl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + adcl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + adcl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + adcl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + adcl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + adcl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + adcl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + adcl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret diff --git a/sysdeps/i386/addmul_1.S b/sysdeps/i386/addmul_1.S new file mode 100644 index 0000000000..3e166ec38b --- /dev/null +++ b/sysdeps/i386/addmul_1.S @@ -0,0 +1,75 @@ +/* i80386 __mpn_addmul_1 -- Multiply a limb vector with a limb and add + the result to a second limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_addmul_1) +C_SYMBOL_NAME(__mpn_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/sysdeps/i386/asm-syntax.h b/sysdeps/i386/asm-syntax.h new file mode 100644 index 0000000000..6e287764dc --- /dev/null +++ b/sysdeps/i386/asm-syntax.h @@ -0,0 +1,64 @@ +/* asm.h -- Definitions for x86 syntax variations. + +Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#undef ALIGN + +#ifdef GAS_SYNTAX +#define R(r) %r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)displacement(R(base)) +#define MEM_INDEX(base,index,size)(R(base),R(index),size) +#ifdef __STDC__ +#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst +#else +#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst +#endif +#define TEXT .text +#define ALIGN(log) .align log +#define GLOBL .globl +#endif + +#ifdef INTEL_SYNTAX +#define R(r) r +#define MEM(base)[base] +#define MEM_DISP(base,displacement)[base+(displacement)] +#define MEM_INDEX(base,index,size)[base+index*size] +#define INSN1(mnemonic,size_suffix,dst)mnemonic dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic dst,src +#define TEXT .text +#define ALIGN(log) .align log +#define GLOBL .globl +#endif + +#ifdef BROKEN_ALIGN +#undef ALIGN +#define ALIGN(log) .align log,0x90 +#endif + +#if !defined (NOLOG_ALIGN) && defined (HAVE_ELF) +#define NOLOG_ALIGN +#endif + +#ifdef NOLOG_ALIGN +#undef ALIGN +#define ALIGN(log) .align 1<<log +#endif diff --git a/sysdeps/i386/bsd-_setjmp.S b/sysdeps/i386/bsd-_setjmp.S new file mode 100644 index 0000000000..372fc242b2 --- /dev/null +++ b/sysdeps/i386/bsd-_setjmp.S @@ -0,0 +1,32 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. i386 version. +Copyright (C) 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include <sysdep.h> + +ENTRY (setjmp) + popl %eax /* Pop return PC. */ + popl %ecx /* Pop jmp_buf argument. */ + pushl $0 /* Push second argument of zero. */ + pushl %ecx /* Push back first argument. */ + pushl %eax /* Push back return PC. */ + jmp C_SYMBOL_NAME (__sigsetjmp) diff --git a/sysdeps/i386/bsd-setjmp.S b/sysdeps/i386/bsd-setjmp.S new file mode 100644 index 0000000000..238f0307ad --- /dev/null +++ b/sysdeps/i386/bsd-setjmp.S @@ -0,0 +1,32 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. i386 version. +Copyright (C) 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include <sysdep.h> + +ENTRY (setjmp) + popl %eax /* Pop return PC. */ + popl %ecx /* Pop jmp_buf argument. */ + pushl $1 /* Push second argument of one. */ + pushl %ecx /* Push back first argument. */ + pushl %eax /* Push back return PC. */ + jmp C_SYMBOL_NAME (__sigsetjmp) diff --git a/sysdeps/i386/bytesex.h b/sysdeps/i386/bytesex.h new file mode 100644 index 0000000000..a5d6c5ea92 --- /dev/null +++ b/sysdeps/i386/bytesex.h @@ -0,0 +1,3 @@ +/* i386 is little-endian. */ + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/sysdeps/i386/bzero.c b/sysdeps/i386/bzero.c new file mode 100644 index 0000000000..659e54df22 --- /dev/null +++ b/sysdeps/i386/bzero.c @@ -0,0 +1,81 @@ +/* bzero -- set a block of memory to zero. + For Intel 80x86, x>=3. + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +The GNU C Library 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. + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <string.h> +#include <memcopy.h> + +#undef bzero + +#ifdef __GNUC__ + +void +DEFUN(bzero, (dstpp, len), + PTR dstpp AND size_t len) +{ + /* N.B.: This code is almost verbatim from memset.c. */ + + unsigned long int dstp = (unsigned long int) dstpp; + + /* This explicit register allocation + improves code very much indeed. */ + register op_t x asm("ax"); + + x = 0; + + /* Clear the direction flag, so filling will move forward. */ + asm volatile("cld"); + + /* This threshold value is optimal. */ + if (len >= 12) + { + /* Adjust LEN for the bytes handled in the first loop. */ + len -= (-dstp) % OPSIZ; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + + /* Fill bytes until DSTP is aligned on a longword boundary. */ + asm volatile("rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp) : + "0" (dstp), "c" ((-dstp) % OPSIZ), "a" (x) : + "cx"); + + /* Fill longwords. */ + asm volatile("rep\n" + "stosl" /* %0, %2, %3 */ : + "=D" (dstp) : + "0" (dstp), "c" (len / OPSIZ), "a" (x) : + "cx"); + len %= OPSIZ; + } + + /* Write the last few bytes. */ + asm volatile("rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp) : + "0" (dstp), "c" (len), "a" (x) : + "cx"); +} + +#else +#include <sysdeps/generic/bzero.c> +#endif diff --git a/sysdeps/i386/ffs.c b/sysdeps/i386/ffs.c new file mode 100644 index 0000000000..1e21585874 --- /dev/null +++ b/sysdeps/i386/ffs.c @@ -0,0 +1,45 @@ +/* ffs -- find first set bit in a word, counted from least significant end. + For Intel 80x86, x>=3. + Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +The GNU C Library 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. + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <string.h> + +#undef ffs + +#ifdef __GNUC__ + +int +DEFUN(ffs, (x), int x) +{ + int cnt; + int tmp; + + asm ("xorl %0,%0\n" /* Set CNT to zero. */ + "bsfl %2,%1\n" /* Count low bits in X and store in %1. */ + "jz nonzero\n" /* Jump if OK, i.e. X was non-zero. */ + "leal 1(%1),%0\n" /* Return bsfl-result plus one on %0. */ + "nonzero:" : "=&a" (cnt), "=r" (tmp) : "rm" (x)); + + return cnt; +} + +#else +#include <sysdeps/generic/ffs.c> +#endif diff --git a/sysdeps/i386/i586/memcopy.h b/sysdeps/i386/i586/memcopy.h new file mode 100644 index 0000000000..a9bb9e7a40 --- /dev/null +++ b/sysdeps/i386/i586/memcopy.h @@ -0,0 +1,94 @@ +/* memcopy.h -- definitions for memory copy functions. Pentium version. + Copyright (C) 1994 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Get the i386 definitions. We will override some of them below. */ +#include_next <memcopy.h> + + +/* Written like this, the Pentium pipeline can execute the loop at a + sustained rate of 2 instructions/clock, or asymptotically 480 + Mbytes/second at 60Mhz. */ + +#undef WORD_COPY_FWD +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + asm volatile ("subl $32,%2\n" \ + "js 2f\n" \ + "1:\n" \ + "movl 0(%1),%%eax\n" \ + "movl 4(%1),%%edx\n" \ + "movl %%eax,0(%0)\n" \ + "movl %%edx,4(%0)\n" \ + "movl 8(%1),%%eax\n" \ + "movl 12(%1),%%edx\n" \ + "movl %%eax,8(%0)\n" \ + "movl %%edx,12(%0)\n" \ + "movl 16(%1),%%eax\n" \ + "movl 20(%1),%%edx\n" \ + "movl %%eax,16(%0)\n" \ + "movl %%edx,20(%0)\n" \ + "movl 24(%1),%%eax\n" \ + "movl 28(%1),%%edx\n" \ + "movl %%eax,24(%0)\n" \ + "movl %%edx,28(%0)\n" \ + "addl $32,%1\n" \ + "addl $32,%0\n" \ + "subl $32,%2\n" \ + "jns 1b\n" \ + "2: addl $32,%2" : \ + "=r" (dst_bp), "=r" (src_bp), "=r" (nbytes_left) : \ + "0" (dst_bp), "1" (src_bp), "2" (nbytes) : \ + "ax", "dx"); \ + } while (0) + +#undef WORD_COPY_BWD +#define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes) \ + do \ + { \ + asm volatile ("subl $32,%2\n" \ + "js 2f\n" \ + "1:\n" \ + "movl -4(%1),%%eax\n" \ + "movl -8(%1),%%edx\n" \ + "movl %%eax,-4(%0)\n" \ + "movl %%edx,-8(%0)\n" \ + "movl -12(%1),%%eax\n" \ + "movl -16(%1),%%edx\n" \ + "movl %%eax,-12(%0)\n" \ + "movl %%edx,-16(%0)\n" \ + "movl -20(%1),%%eax\n" \ + "movl -24(%1),%%edx\n" \ + "movl %%eax,-20(%0)\n" \ + "movl %%edx,-24(%0)\n" \ + "movl -28(%1),%%eax\n" \ + "movl -32(%1),%%edx\n" \ + "movl %%eax,-28(%0)\n" \ + "movl %%edx,-32(%0)\n" \ + "subl $32,%1\n" \ + "subl $32,%0\n" \ + "subl $32,%2\n" \ + "jns 1b\n" \ + "2: addl $32,%2" : \ + "=r" (dst_bp), "=r" (src_bp), "=r" (nbytes_left) : \ + "0" (dst_bp), "1" (src_bp), "2" (nbytes) : \ + "ax", "dx"); \ + } while (0) diff --git a/sysdeps/i386/jmp_buf.h b/sysdeps/i386/jmp_buf.h new file mode 100644 index 0000000000..7686c4d278 --- /dev/null +++ b/sysdeps/i386/jmp_buf.h @@ -0,0 +1,9 @@ +/* Define the machine-dependent type `jmp_buf'. Intel 386 version. */ + +typedef struct + { + long int __bx, __si, __di; + __ptr_t __bp; + __ptr_t __sp; + __ptr_t __pc; + } __jmp_buf[1]; diff --git a/sysdeps/i386/lshift.S b/sysdeps/i386/lshift.S new file mode 100644 index 0000000000..ca48eda8ce --- /dev/null +++ b/sysdeps/i386/lshift.S @@ -0,0 +1,84 @@ +/* i80386 __mpn_lshift -- + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s_ptr (sp + 8) + size (sp + 12) + cnt (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_lshift) +C_SYMBOL_NAME(__mpn_lshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* res_ptr */ + movl 20(%esp),%esi /* s_ptr */ + movl 24(%esp),%edx /* size */ + movl 28(%esp),%ecx /* cnt */ + + subl $4,%esi /* adjust s_ptr */ + + movl (%esi,%edx,4),%ebx /* read most significant limb */ + xorl %eax,%eax + shldl %cl,%ebx,%eax /* compute carry limb */ + decl %edx + jz Lend + pushl %eax /* push carry limb onto stack */ + testb $1,%edx + jnz L1 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop: movl (%esi,%edx,4),%ebx /* load next lower limb */ + shldl %cl,%ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + decl %edx +L1: movl (%esi,%edx,4),%eax + shldl %cl,%eax,%ebx + movl %ebx,(%edi,%edx,4) + decl %edx + jnz Loop + + shll %cl,%eax /* compute least significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend: shll %cl,%ebx /* compute least significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret diff --git a/sysdeps/i386/memchr.c b/sysdeps/i386/memchr.c new file mode 100644 index 0000000000..ff0f8d9044 --- /dev/null +++ b/sysdeps/i386/memchr.c @@ -0,0 +1,48 @@ +/* memchr (str, ch, n) -- Return pointer to first occurrence of CH in STR less + than N. + For Intel 80x86, x>=3. + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +The GNU C Library 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. + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <string.h> + +#ifdef __GNUC__ + +PTR +DEFUN(memchr, (str, c, len), + CONST PTR str AND int c AND size_t len) +{ + PTR retval; + asm("cld\n" /* Search forward. */ + "testl %1,%1\n" /* Clear Z flag, to handle LEN == 0. */ + /* Some old versions of gas need `repne' instead of `repnz'. */ + "repnz\n" /* Search for C in al. */ + "scasb\n" + "movl %2,%0\n" /* Set %0 to 0 (without affecting Z flag). */ + "jnz done\n" /* Jump if we found nothing equal to C. */ + "leal -1(%1),%0\n" /* edi has been incremented. Return edi-1. */ + "done:" : + "=a" (retval), "=D" (str), "=c" (len) : + "0" (c), "1" (str), "2" (len)); + return retval; +} + +#else +#include <sysdeps/generic/memchr.c> +#endif diff --git a/sysdeps/i386/memcopy.h b/sysdeps/i386/memcopy.h new file mode 100644 index 0000000000..506d3ea54d --- /dev/null +++ b/sysdeps/i386/memcopy.h @@ -0,0 +1,86 @@ +/* memcopy.h -- definitions for memory copy functions. i386 version. + Copyright (C) 1991 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +The GNU C Library 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. + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdeps/generic/memcopy.h> + +#undef OP_T_THRES +#define OP_T_THRES 8 + +#undef BYTE_COPY_FWD +#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \ + asm volatile(/* Clear the direction flag, so copying goes forward. */ \ + "cld\n" \ + /* Copy bytes. */ \ + "rep\n" \ + "movsb" : \ + "=D" (dst_bp), "=S" (src_bp) : \ + "0" (dst_bp), "1" (src_bp), "c" (nbytes) : \ + "cx") + +#undef BYTE_COPY_BWD +#define BYTE_COPY_BWD(dst_ep, src_ep, nbytes) \ + do \ + { \ + asm volatile(/* Set the direction flag, so copying goes backwards. */ \ + "std\n" \ + /* Copy bytes. */ \ + "rep\n" \ + "movsb\n" \ + /* Clear the dir flag. Convention says it should be 0. */ \ + "cld" : \ + "=D" (dst_ep), "=S" (src_ep) : \ + "0" (dst_ep - 1), "1" (src_ep - 1), "c" (nbytes) : \ + "cx"); \ + dst_ep += 1; \ + src_ep += 1; \ + } while (0) + +#undef WORD_COPY_FWD +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + asm volatile(/* Clear the direction flag, so copying goes forward. */ \ + "cld\n" \ + /* Copy longwords. */ \ + "rep\n" \ + "movsl" : \ + "=D" (dst_bp), "=S" (src_bp) : \ + "0" (dst_bp), "1" (src_bp), "c" ((nbytes) / 4) : \ + "cx"); \ + (nbytes_left) = (nbytes) % 4; \ + } while (0) + +#undef WORD_COPY_BWD +#define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes) \ + do \ + { \ + asm volatile(/* Set the direction flag, so copying goes backwards. */ \ + "std\n" \ + /* Copy longwords. */ \ + "rep\n" \ + "movsl\n" \ + /* Clear the dir flag. Convention says it should be 0. */ \ + "cld" : \ + "=D" (dst_ep), "=S" (src_ep) : \ + "0" (dst_ep - 4), "1" (src_ep - 4), "c" ((nbytes) / 4) : \ + "cx"); \ + dst_ep += 4; \ + src_ep += 4; \ + (nbytes_left) = (nbytes) % 4; \ + } while (0) diff --git a/sysdeps/i386/memset.c b/sysdeps/i386/memset.c new file mode 100644 index 0000000000..2987445d4f --- /dev/null +++ b/sysdeps/i386/memset.c @@ -0,0 +1,83 @@ +/* memset -- set a block of memory to some byte value. + For Intel 80x86, x>=3. + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +The GNU C Library 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. + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <string.h> +#include <memcopy.h> + +#ifdef __GNUC__ + +PTR +DEFUN(memset, (dstpp, c, len), + PTR dstpp AND int c AND size_t len) +{ + unsigned long int dstp = (unsigned long int) dstpp; + + /* This explicit register allocation + improves code very much indeed. */ + register op_t x asm("ax"); + + x = (unsigned char) c; + + /* Clear the direction flag, so filling will move forward. */ + asm volatile("cld"); + + /* This threshold value is optimal. */ + if (len >= 12) + { + /* Fill X with four copies of the char we want to fill with. */ + x |= (x << 8); + x |= (x << 16); + + /* Adjust LEN for the bytes handled in the first loop. */ + len -= (-dstp) % OPSIZ; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + + /* Fill bytes until DSTP is aligned on a longword boundary. */ + asm volatile("rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp) : + "0" (dstp), "c" ((-dstp) % OPSIZ), "a" (x) : + "cx"); + + /* Fill longwords. */ + asm volatile("rep\n" + "stosl" /* %0, %2, %3 */ : + "=D" (dstp) : + "0" (dstp), "c" (len / OPSIZ), "a" (x) : + "cx"); + len %= OPSIZ; + } + + /* Write the last few bytes. */ + asm volatile("rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp) : + "0" (dstp), "c" (len), "a" (x) : + "cx"); + + return dstpp; +} + +#else +#include <sysdeps/generic/memset.c> +#endif diff --git a/sysdeps/i386/mul_1.S b/sysdeps/i386/mul_1.S new file mode 100644 index 0000000000..303a940f0b --- /dev/null +++ b/sysdeps/i386/mul_1.S @@ -0,0 +1,74 @@ +/* i80386 __mpn_mul_1 -- Multiply a limb vector with a limb and store + the result in a second limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_mul_1) +C_SYMBOL_NAME(__mpn_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/sysdeps/i386/rshift.S b/sysdeps/i386/rshift.S new file mode 100644 index 0000000000..d4aa0b93e6 --- /dev/null +++ b/sysdeps/i386/rshift.S @@ -0,0 +1,86 @@ +/* i80386 __mpn_rshift -- + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s_ptr (sp + 8) + size (sp + 12) + cnt (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_rshift) +C_SYMBOL_NAME(__mpn_rshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* res_ptr */ + movl 20(%esp),%esi /* s_ptr */ + movl 24(%esp),%edx /* size */ + movl 28(%esp),%ecx /* cnt */ + + leal -4(%edi,%edx,4),%edi + leal (%esi,%edx,4),%esi + negl %edx + + movl (%esi,%edx,4),%ebx /* read least significant limb */ + xorl %eax,%eax + shrdl %cl,%ebx,%eax /* compute carry limb */ + incl %edx + jz Lend + pushl %eax /* push carry limb onto stack */ + testb $1,%edx + jnz L1 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop: movl (%esi,%edx,4),%ebx /* load next higher limb */ + shrdl %cl,%ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + incl %edx +L1: movl (%esi,%edx,4),%eax + shrdl %cl,%eax,%ebx + movl %ebx,(%edi,%edx,4) + incl %edx + jnz Loop + + shrl %cl,%eax /* compute most significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend: shrl %cl,%ebx /* compute most significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret diff --git a/sysdeps/i386/setjmp.c b/sysdeps/i386/setjmp.c new file mode 100644 index 0000000000..fb8fc98659 --- /dev/null +++ b/sysdeps/i386/setjmp.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Put these global register declarations first, because we get an error if + they come after any function definition, including inlines which might + be in some header. */ + +#define REGS \ + REG (bx);\ + REG (si);\ + REG (di) + +#define REG(xx) register long int xx asm (#xx) +REGS; +#undef REG + +#include <errno.h> +#include <setjmp.h> + +/* Save the current program position in ENV and return 0. */ +int +__sigsetjmp (jmp_buf env, int savemask) +{ + /* Save the general registers. */ +#define REG(xx) env[0].__jmpbuf[0].__##xx = xx + REGS; +#undef REG + + /* Save the return PC. */ + env[0].__jmpbuf[0].__pc = ((void **) &env)[-1]; + + /* Save caller's FP, not our own. */ + env[0].__jmpbuf[0].__bp = ((void **) &env)[-2]; + + /* Save caller's SP, not our own. */ + env[0].__jmpbuf[0].__sp = (void *) &env; + + /* Save the signal mask if requested. */ + return __sigjmp_save (env, savemask); +} diff --git a/sysdeps/i386/strlen.c b/sysdeps/i386/strlen.c new file mode 100644 index 0000000000..3c1398b461 --- /dev/null +++ b/sysdeps/i386/strlen.c @@ -0,0 +1,36 @@ +/* strlen -- determine the length of a string. + For Intel 80x86, x>=3. + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +The GNU C Library 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. + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <string.h> + +size_t +DEFUN(strlen, (str), CONST char *str) +{ + int cnt; + + asm("cld\n" /* Search forward. */ + /* Some old versions of gas need `repne' instead of `repnz'. */ + "repnz\n" /* Look for a zero byte. */ + "scasb" /* %0, %1, %3 */ : + "=c" (cnt) : "D" (str), "0" (-1), "a" (0)); + + return -2 - cnt; +} diff --git a/sysdeps/i386/sub_n.S b/sysdeps/i386/sub_n.S new file mode 100644 index 0000000000..a1630d4562 --- /dev/null +++ b/sysdeps/i386/sub_n.S @@ -0,0 +1,94 @@ +/* i80386 __mpn_sub_n -- Add two limb vectors of the same length > 0 and store + sum in a third limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + s2_ptr (sp + 12) + size (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_sub_n) +C_SYMBOL_NAME(__mpn_sub_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ + leal (Loop - 3)(%eax,%eax,8),%eax /* calc start addr in loop */ + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + sbbl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + sbbl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + sbbl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + sbbl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + sbbl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + sbbl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + sbbl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + sbbl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret diff --git a/sysdeps/i386/submul_1.S b/sysdeps/i386/submul_1.S new file mode 100644 index 0000000000..5ab78f6846 --- /dev/null +++ b/sysdeps/i386/submul_1.S @@ -0,0 +1,75 @@ +/* i80386 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract + the result from a second limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library 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. + +The GNU MP 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 Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_submul_1) +C_SYMBOL_NAME(__mpn_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret |