Update the in-tree GMP; fixes trac #832
[ghc-hetmet.git] / rts / gmp / mpn / x86 / p6 / sqr_basecase.asm
diff --git a/rts/gmp/mpn/x86/p6/sqr_basecase.asm b/rts/gmp/mpn/x86/p6/sqr_basecase.asm
deleted file mode 100644 (file)
index 174c784..0000000
+++ /dev/null
@@ -1,641 +0,0 @@
-dnl  Intel P6 mpn_sqr_basecase -- square an mpn number.
-dnl 
-dnl  P6: approx 4.0 cycles per cross product, or 7.75 cycles per triangular
-dnl  product (measured on the speed difference between 20 and 40 limbs,
-dnl  which is the Karatsuba recursing range).
-
-
-dnl  Copyright (C) 1999, 2000 Free Software Foundation, Inc.
-dnl 
-dnl  This file is part of the GNU MP Library.
-dnl 
-dnl  The GNU MP Library is free software; you can redistribute it and/or
-dnl  modify it under the terms of the GNU Lesser General Public License as
-dnl  published by the Free Software Foundation; either version 2.1 of the
-dnl  License, or (at your option) any later version.
-dnl 
-dnl  The GNU MP Library is distributed in the hope that it will be useful,
-dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-dnl  Lesser General Public License for more details.
-dnl 
-dnl  You should have received a copy of the GNU Lesser General Public
-dnl  License along with the GNU MP Library; see the file COPYING.LIB.  If
-dnl  not, write to the Free Software Foundation, Inc., 59 Temple Place -
-dnl  Suite 330, Boston, MA 02111-1307, USA.
-
-
-include(`../config.m4')
-
-
-dnl  These are the same as in mpn/x86/k6/sqr_basecase.asm, see that file for
-dnl  a description.  The only difference here is that UNROLL_COUNT can go up
-dnl  to 64 (not 63) making KARATSUBA_SQR_THRESHOLD_MAX 67.
-
-deflit(KARATSUBA_SQR_THRESHOLD_MAX, 67)
-
-ifdef(`KARATSUBA_SQR_THRESHOLD_OVERRIDE',
-`define(`KARATSUBA_SQR_THRESHOLD',KARATSUBA_SQR_THRESHOLD_OVERRIDE)')
-
-m4_config_gmp_mparam(`KARATSUBA_SQR_THRESHOLD')
-deflit(UNROLL_COUNT, eval(KARATSUBA_SQR_THRESHOLD-3))
-
-
-C void mpn_sqr_basecase (mp_ptr dst, mp_srcptr src, mp_size_t size);
-C
-C The algorithm is basically the same as mpn/generic/sqr_basecase.c, but a
-C lot of function call overheads are avoided, especially when the given size
-C is small.
-C
-C The code size might look a bit excessive, but not all of it is executed so
-C it won't all get into the code cache.  The 1x1, 2x2 and 3x3 special cases
-C clearly apply only to those sizes; mid sizes like 10x10 only need part of
-C the unrolled addmul; and big sizes like 40x40 that do use the full
-C unrolling will least be making good use of it, because 40x40 will take
-C something like 7000 cycles.
-
-defframe(PARAM_SIZE,12)
-defframe(PARAM_SRC, 8)
-defframe(PARAM_DST, 4)
-
-       .text
-       ALIGN(32)
-PROLOGUE(mpn_sqr_basecase)
-deflit(`FRAME',0)
-
-       movl    PARAM_SIZE, %edx
-
-       movl    PARAM_SRC, %eax
-
-       cmpl    $2, %edx
-       movl    PARAM_DST, %ecx
-       je      L(two_limbs)
-
-       movl    (%eax), %eax
-       ja      L(three_or_more)
-
-
-C -----------------------------------------------------------------------------
-C one limb only
-       C eax   src limb
-       C ebx
-       C ecx   dst
-       C edx
-
-       mull    %eax
-
-       movl    %eax, (%ecx)
-       movl    %edx, 4(%ecx)
-
-       ret
-
-
-C -----------------------------------------------------------------------------
-L(two_limbs):
-       C eax   src
-       C ebx
-       C ecx   dst
-       C edx
-
-defframe(SAVE_ESI, -4)
-defframe(SAVE_EBX, -8)
-defframe(SAVE_EDI, -12)
-defframe(SAVE_EBP, -16)
-deflit(`STACK_SPACE',16)
-
-       subl    $STACK_SPACE, %esp
-deflit(`FRAME',STACK_SPACE)
-
-       movl    %esi, SAVE_ESI
-       movl    %eax, %esi
-       movl    (%eax), %eax
-
-       mull    %eax            C src[0]^2
-
-       movl    %eax, (%ecx)    C dst[0]
-       movl    4(%esi), %eax
-
-       movl    %ebx, SAVE_EBX
-       movl    %edx, %ebx      C dst[1]
-
-       mull    %eax            C src[1]^2
-
-       movl    %edi, SAVE_EDI
-       movl    %eax, %edi      C dst[2]
-       movl    (%esi), %eax
-
-       movl    %ebp, SAVE_EBP
-       movl    %edx, %ebp      C dst[3]
-
-       mull    4(%esi)         C src[0]*src[1]
-
-       addl    %eax, %ebx
-       movl    SAVE_ESI, %esi
-
-       adcl    %edx, %edi
-
-       adcl    $0, %ebp
-       addl    %ebx, %eax
-       movl    SAVE_EBX, %ebx
-
-       adcl    %edi, %edx
-       movl    SAVE_EDI, %edi
-
-       adcl    $0, %ebp
-
-       movl    %eax, 4(%ecx)
-
-       movl    %ebp, 12(%ecx)
-       movl    SAVE_EBP, %ebp
-
-       movl    %edx, 8(%ecx)
-       addl    $FRAME, %esp
-
-       ret
-
-
-C -----------------------------------------------------------------------------
-L(three_or_more):
-       C eax   src low limb
-       C ebx
-       C ecx   dst
-       C edx   size
-deflit(`FRAME',0)
-
-       pushl   %esi    defframe_pushl(`SAVE_ESI')
-       cmpl    $4, %edx
-
-       movl    PARAM_SRC, %esi
-       jae     L(four_or_more)
-
-
-C -----------------------------------------------------------------------------
-C three limbs
-
-       C eax   src low limb
-       C ebx
-       C ecx   dst
-       C edx
-       C esi   src
-       C edi
-       C ebp
-
-       pushl   %ebp    defframe_pushl(`SAVE_EBP')
-       pushl   %edi    defframe_pushl(`SAVE_EDI')
-
-       mull    %eax            C src[0] ^ 2
-
-       movl    %eax, (%ecx)
-       movl    %edx, 4(%ecx)
-
-       movl    4(%esi), %eax
-       xorl    %ebp, %ebp
-
-       mull    %eax            C src[1] ^ 2
-
-       movl    %eax, 8(%ecx)
-       movl    %edx, 12(%ecx)
-       movl    8(%esi), %eax
-
-       pushl   %ebx    defframe_pushl(`SAVE_EBX')
-
-       mull    %eax            C src[2] ^ 2
-
-       movl    %eax, 16(%ecx)
-       movl    %edx, 20(%ecx)
-
-       movl    (%esi), %eax
-
-       mull    4(%esi)         C src[0] * src[1]
-
-       movl    %eax, %ebx
-       movl    %edx, %edi
-
-       movl    (%esi), %eax
-
-       mull    8(%esi)         C src[0] * src[2]
-
-       addl    %eax, %edi
-       movl    %edx, %ebp
-
-       adcl    $0, %ebp
-       movl    4(%esi), %eax
-
-       mull    8(%esi)         C src[1] * src[2]
-
-       xorl    %esi, %esi
-       addl    %eax, %ebp
-
-       C eax
-       C ebx   dst[1]
-       C ecx   dst
-       C edx   dst[4]
-       C esi   zero, will be dst[5]
-       C edi   dst[2]
-       C ebp   dst[3]
-
-       adcl    $0, %edx
-       addl    %ebx, %ebx
-
-       adcl    %edi, %edi
-
-       adcl    %ebp, %ebp
-
-       adcl    %edx, %edx
-       movl    4(%ecx), %eax
-
-       adcl    $0, %esi
-       addl    %ebx, %eax
-
-       movl    %eax, 4(%ecx)
-       movl    8(%ecx), %eax
-
-       adcl    %edi, %eax
-       movl    12(%ecx), %ebx
-
-       adcl    %ebp, %ebx
-       movl    16(%ecx), %edi
-
-       movl    %eax, 8(%ecx)
-       movl    SAVE_EBP, %ebp
-
-       movl    %ebx, 12(%ecx)
-       movl    SAVE_EBX, %ebx
-
-       adcl    %edx, %edi
-       movl    20(%ecx), %eax
-
-       movl    %edi, 16(%ecx)
-       movl    SAVE_EDI, %edi
-
-       adcl    %esi, %eax      C no carry out of this
-       movl    SAVE_ESI, %esi
-
-       movl    %eax, 20(%ecx)
-       addl    $FRAME, %esp
-
-       ret
-
-
-
-C -----------------------------------------------------------------------------
-defframe(VAR_COUNTER,-20)
-defframe(VAR_JMP,    -24)
-deflit(`STACK_SPACE',24)
-
-L(four_or_more):
-       C eax   src low limb
-       C ebx
-       C ecx
-       C edx   size
-       C esi   src
-       C edi
-       C ebp
-deflit(`FRAME',4)  dnl  %esi already pushed
-
-C First multiply src[0]*src[1..size-1] and store at dst[1..size].
-       subl    $STACK_SPACE-FRAME, %esp
-deflit(`FRAME',STACK_SPACE)
-       movl    $1, %ecx
-
-       movl    %edi, SAVE_EDI
-       movl    PARAM_DST, %edi
-
-       movl    %ebx, SAVE_EBX
-       subl    %edx, %ecx              C -(size-1)
-
-       movl    %ebp, SAVE_EBP
-       movl    $0, %ebx                C initial carry
-
-       leal    (%esi,%edx,4), %esi     C &src[size]
-       movl    %eax, %ebp              C multiplier
-
-       leal    -4(%edi,%edx,4), %edi   C &dst[size-1]
-
-
-C This loop runs at just over 6 c/l.
-
-L(mul_1):
-       C eax   scratch
-       C ebx   carry
-       C ecx   counter, limbs, negative, -(size-1) to -1
-       C edx   scratch
-       C esi   &src[size]
-       C edi   &dst[size-1]
-       C ebp   multiplier
-
-       movl    %ebp, %eax
-
-       mull    (%esi,%ecx,4)
-
-       addl    %ebx, %eax
-       movl    $0, %ebx
-
-       adcl    %edx, %ebx
-       movl    %eax, 4(%edi,%ecx,4)
-
-       incl    %ecx
-       jnz     L(mul_1)
-
-
-       movl    %ebx, 4(%edi)
-
-
-C Addmul src[n]*src[n+1..size-1] at dst[2*n-1...], for each n=1..size-2.
-C
-C The last two addmuls, which are the bottom right corner of the product
-C triangle, are left to the end.  These are src[size-3]*src[size-2,size-1]
-C and src[size-2]*src[size-1].  If size is 4 then it's only these corner
-C cases that need to be done.
-C
-C The unrolled code is the same as mpn_addmul_1(), see that routine for some
-C comments.
-C
-C VAR_COUNTER is the outer loop, running from -(size-4) to -1, inclusive.
-C
-C VAR_JMP is the computed jump into the unrolled code, stepped by one code
-C chunk each outer loop.
-
-dnl  This is also hard-coded in the address calculation below.
-deflit(CODE_BYTES_PER_LIMB, 15)
-
-dnl  With &src[size] and &dst[size-1] pointers, the displacements in the
-dnl  unrolled code fit in a byte for UNROLL_COUNT values up to 32, but above
-dnl  that an offset must be added to them.
-deflit(OFFSET,
-ifelse(eval(UNROLL_COUNT>32),1,
-eval((UNROLL_COUNT-32)*4),
-0))
-
-       C eax
-       C ebx   carry
-       C ecx
-       C edx
-       C esi   &src[size]
-       C edi   &dst[size-1]
-       C ebp
-
-       movl    PARAM_SIZE, %ecx
-
-       subl    $4, %ecx
-       jz      L(corner)
-
-       movl    %ecx, %edx
-       negl    %ecx
-
-       shll    $4, %ecx
-ifelse(OFFSET,0,,`subl $OFFSET, %esi')
-
-ifdef(`PIC',`
-       call    L(pic_calc)
-L(here):
-',`
-       leal    L(unroll_inner_end)-eval(2*CODE_BYTES_PER_LIMB)(%ecx,%edx), %ecx
-')
-       negl    %edx
-
-ifelse(OFFSET,0,,`subl $OFFSET, %edi')
-
-       C The calculated jump mustn't be before the start of the available
-       C code.  This is the limit that UNROLL_COUNT puts on the src operand
-       C size, but checked here using the jump address directly.
-
-       ASSERT(ae,
-       `movl_text_address( L(unroll_inner_start), %eax)
-       cmpl    %eax, %ecx')
-
-
-C -----------------------------------------------------------------------------
-       ALIGN(16)
-L(unroll_outer_top):
-       C eax
-       C ebx   high limb to store
-       C ecx   VAR_JMP
-       C edx   VAR_COUNTER, limbs, negative
-       C esi   &src[size], constant
-       C edi   dst ptr, second highest limb of last addmul
-       C ebp
-
-       movl    -12+OFFSET(%esi,%edx,4), %ebp   C multiplier
-       movl    %edx, VAR_COUNTER
-
-       movl    -8+OFFSET(%esi,%edx,4), %eax    C first limb of multiplicand
-
-       mull    %ebp
-
-define(cmovX,`ifelse(eval(UNROLL_COUNT%2),1,`cmovz($@)',`cmovnz($@)')')
-
-       testb   $1, %cl
-
-       movl    %edx, %ebx      C high carry
-       leal    4(%edi), %edi
-
-       movl    %ecx, %edx      C jump
-
-       movl    %eax, %ecx      C low carry
-       leal    CODE_BYTES_PER_LIMB(%edx), %edx
-
-       cmovX(  %ebx, %ecx)     C high carry reverse
-       cmovX(  %eax, %ebx)     C low carry reverse
-       movl    %edx, VAR_JMP
-       jmp     *%edx
-
-
-       C Must be on an even address here so the low bit of the jump address
-       C will indicate which way around ecx/ebx should start.
-
-       ALIGN(2)
-
-L(unroll_inner_start):
-       C eax   scratch
-       C ebx   carry high
-       C ecx   carry low
-       C edx   scratch
-       C esi   src pointer
-       C edi   dst pointer
-       C ebp   multiplier
-       C
-       C 15 code bytes each limb
-       C ecx/ebx reversed on each chunk
-
-forloop(`i', UNROLL_COUNT, 1, `
-       deflit(`disp_src', eval(-i*4 + OFFSET))
-       deflit(`disp_dst', eval(disp_src))
-
-       m4_assert(`disp_src>=-128 && disp_src<128')
-       m4_assert(`disp_dst>=-128 && disp_dst<128')
-
-ifelse(eval(i%2),0,`
-Zdisp( movl,   disp_src,(%esi), %eax)
-       mull    %ebp
-Zdisp( addl,   %ebx, disp_dst,(%edi))
-       adcl    %eax, %ecx
-       movl    %edx, %ebx
-       adcl    $0, %ebx
-',`
-       dnl  this one comes out last
-Zdisp( movl,   disp_src,(%esi), %eax)
-       mull    %ebp
-Zdisp( addl,   %ecx, disp_dst,(%edi))
-       adcl    %eax, %ebx
-       movl    %edx, %ecx
-       adcl    $0, %ecx
-')
-')
-L(unroll_inner_end):
-
-       addl    %ebx, m4_empty_if_zero(OFFSET)(%edi)
-
-       movl    VAR_COUNTER, %edx
-       adcl    $0, %ecx
-
-       movl    %ecx, m4_empty_if_zero(OFFSET+4)(%edi)
-       movl    VAR_JMP, %ecx
-
-       incl    %edx
-       jnz     L(unroll_outer_top)
-       
-
-ifelse(OFFSET,0,,`
-       addl    $OFFSET, %esi
-       addl    $OFFSET, %edi
-')
-
-
-C -----------------------------------------------------------------------------
-       ALIGN(16)
-L(corner):
-       C eax
-       C ebx
-       C ecx
-       C edx
-       C esi   &src[size]
-       C edi   &dst[2*size-5]
-       C ebp
-
-       movl    -12(%esi), %eax
-
-       mull    -8(%esi)
-
-       addl    %eax, (%edi)
-       movl    -12(%esi), %eax
-       movl    $0, %ebx
-
-       adcl    %edx, %ebx
-
-       mull    -4(%esi)
-
-       addl    %eax, %ebx
-       movl    -8(%esi), %eax
-
-       adcl    $0, %edx
-
-       addl    %ebx, 4(%edi)
-       movl    $0, %ebx
-
-       adcl    %edx, %ebx
-
-       mull    -4(%esi)
-
-       movl    PARAM_SIZE, %ecx
-       addl    %ebx, %eax
-
-       adcl    $0, %edx
-
-       movl    %eax, 8(%edi)
-
-       movl    %edx, 12(%edi)
-       movl    PARAM_DST, %edi
-
-
-C Left shift of dst[1..2*size-2], the bit shifted out becomes dst[2*size-1].
-
-       subl    $1, %ecx                C size-1
-       xorl    %eax, %eax              C ready for final adcl, and clear carry
-
-       movl    %ecx, %edx
-       movl    PARAM_SRC, %esi
-
-
-L(lshift):
-       C eax
-       C ebx
-       C ecx   counter, size-1 to 1
-       C edx   size-1 (for later use)
-       C esi   src (for later use)
-       C edi   dst, incrementing
-       C ebp
-
-       rcll    4(%edi)
-       rcll    8(%edi)
-
-       leal    8(%edi), %edi
-       decl    %ecx
-       jnz     L(lshift)
-
-
-       adcl    %eax, %eax
-
-       movl    %eax, 4(%edi)           C dst most significant limb
-       movl    (%esi), %eax            C src[0]
-
-       leal    4(%esi,%edx,4), %esi    C &src[size]
-       subl    %edx, %ecx              C -(size-1)
-
-
-C Now add in the squares on the diagonal, src[0]^2, src[1]^2, ...,
-C src[size-1]^2.  dst[0] hasn't yet been set at all yet, and just gets the
-C low limb of src[0]^2.
-
-
-       mull    %eax
-
-       movl    %eax, (%edi,%ecx,8)     C dst[0]
-
-
-L(diag):
-       C eax   scratch
-       C ebx   scratch
-       C ecx   counter, negative
-       C edx   carry
-       C esi   &src[size]
-       C edi   dst[2*size-2]
-       C ebp
-
-       movl    (%esi,%ecx,4), %eax
-       movl    %edx, %ebx
-
-       mull    %eax
-
-       addl    %ebx, 4(%edi,%ecx,8)
-       adcl    %eax, 8(%edi,%ecx,8)
-       adcl    $0, %edx
-
-       incl    %ecx
-       jnz     L(diag)
-
-
-       movl    SAVE_ESI, %esi
-       movl    SAVE_EBX, %ebx
-
-       addl    %edx, 4(%edi)           C dst most significant limb
-
-       movl    SAVE_EDI, %edi
-       movl    SAVE_EBP, %ebp
-       addl    $FRAME, %esp
-       ret
-
-
-
-C -----------------------------------------------------------------------------
-ifdef(`PIC',`
-L(pic_calc):
-       addl    (%esp), %ecx
-       addl    $L(unroll_inner_end)-L(here)-eval(2*CODE_BYTES_PER_LIMB), %ecx
-       addl    %edx, %ecx
-       ret
-')
-
-
-EPILOGUE()