github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/powerpc32/mode1o.asm (about)

     1  dnl  PowerPC-32 mpn_modexact_1_odd -- mpn by limb exact remainder.
     2  
     3  dnl  Copyright 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
     4  
     5  dnl  This file is part of the GNU MP Library.
     6  dnl
     7  dnl  The GNU MP Library is free software; you can redistribute it and/or modify
     8  dnl  it under the terms of either:
     9  dnl
    10  dnl    * the GNU Lesser General Public License as published by the Free
    11  dnl      Software Foundation; either version 3 of the License, or (at your
    12  dnl      option) any later version.
    13  dnl
    14  dnl  or
    15  dnl
    16  dnl    * the GNU General Public License as published by the Free Software
    17  dnl      Foundation; either version 2 of the License, or (at your option) any
    18  dnl      later version.
    19  dnl
    20  dnl  or both in parallel, as here.
    21  dnl
    22  dnl  The GNU MP Library is distributed in the hope that it will be useful, but
    23  dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    24  dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    25  dnl  for more details.
    26  dnl
    27  dnl  You should have received copies of the GNU General Public License and the
    28  dnl  GNU Lesser General Public License along with the GNU MP Library.  If not,
    29  dnl  see https://www.gnu.org/licenses/.
    30  
    31  include(`../config.m4')
    32  
    33  
    34  C                cycles/limb
    35  C 603e:             ?
    36  C 604e:             6.0
    37  C 75x (G3):         6.0-13.0, depending on divisor
    38  C 7400,7410 (G4):   6.0-13.0, depending on divisor
    39  C 744x,745x (G4+):  8.0-10.0, depending on divisor
    40  C power4/ppc970:   12.0
    41  C power5:          12.0
    42  
    43  
    44  C mp_limb_t mpn_modexact_1_odd (mp_srcptr src, mp_size_t size,
    45  C                               mp_limb_t divisor);
    46  C mp_limb_t mpn_modexact_1c_odd (mp_srcptr src, mp_size_t size,
    47  C                                mp_limb_t divisor, mp_limb_t carry);
    48  C
    49  C For PIC, the inverse is established arithmetically since it measures about
    50  C 5 cycles faster than the nonsense needed to access binvert_limb_table in
    51  C SVR4 or Darwin style PIC.  AIX might be better, since it avoids bl/mflr to
    52  C get at the GOT/TOC/whatever.
    53  C
    54  C Using divwu for size==1 measured about 10 cycles slower on 604e, or about
    55  C 3-5 cycles faster on 750.  For now it doesn't seem worth bothering with.
    56  C
    57  C The loop allows an early-out on mullw for the inverse, and on mulhwu for
    58  C the divisor.  So the fastest is for instance divisor==1 (inverse==-1), and
    59  C the slowest is anything giving a full 32-bits in both, such as
    60  C divisor==0xDEADBEEF (inverse==0x904B300F).  These establish the stated
    61  C range above for 750 and 7400.
    62  
    63  
    64  ASM_START()
    65  
    66  EXTERN(binvert_limb_table)
    67  
    68  PROLOGUE(mpn_modexact_1_odd)
    69  	li	r6, 0
    70  
    71  PROLOGUE(mpn_modexact_1c_odd)
    72  
    73  	mtctr	r4			C size
    74  
    75  ifdef(`PIC_SLOW',`
    76  C Load from our table with PIC is so slow on Linux and Darwin that we avoid it
    77  	rlwinm	r7, r5, 1,28,28		C (divisor << 1) & 8
    78  	rlwinm	r8, r5, 2,28,28		C (divisor << 2) & 8
    79  	xor	r7, r7, r8		C ((divisor << 1) ^ (divisor << 2)) & 8
    80  	rlwinm	r4, r5, 0,28,31		C divisor low 4 bits, speedup mullw
    81  	xor	r4, r4, r7		C inverse, 4 bits
    82  	mullw	r7, r4, r4		C i*i
    83  	slwi	r4, r4, 1		C 2*i
    84  	rlwinm	r8, r5, 0,24,31		C divisor low 8 bits, speedup mullw
    85  	mullw	r7, r7, r8		C i*i*d
    86  	sub	r4, r4, r7		C inverse, 8 bits
    87  ',`
    88  	LEA(	r7, binvert_limb_table)
    89  	rlwinm	r4, r5, 31,25,31	C (divisor/2) & 0x7F
    90  	lbzx	r4, r4,r7		C inverse, 8 bits
    91  ')
    92  
    93  	mullw	r7, r4, r4		C i*i
    94  	slwi	r4, r4, 1		C 2*i
    95  	mullw	r7, r5, r7		C i*i*d   [i*i is 16 bits, so second operand]
    96  	sub	r4, r4, r7		C inverse, 16 bits
    97  	mullw	r7, r4, r4		C i*i
    98  	slwi	r4, r4, 1		C 2*i
    99  	mullw	r7, r7, r5		C i*i*d
   100  	lwz	r0, 0(r3)		C src[0]
   101  	sub	r4, r4, r7		C inverse, 32 bits
   102  	subfc	r7, r6, r0		C l = src[0] - carry
   103  
   104  	mullw	r7, r7, r4		C q = l * inverse
   105  	bdz	L(one)
   106  
   107  	lwzu	r0, 4(r3)		C src[1]
   108  	mulhwu	r6, r7, r5		C carry = high(q*divisor)
   109  	subfe	r7, r6, r0		C l = src[1] - carry
   110  	bdz	L(two)
   111  
   112  L(top):
   113  	mullw	r7, r7, r4		C q = l * inverse
   114  	lwzu	r0, 4(r3)		C src[i]
   115  	mulhwu	r6, r7, r5		C carry = high(q*divisor)
   116  	subfe	r7, r6, r0		C l = src[i] - carry
   117  	bdnz	L(top)
   118  
   119  L(two):	mullw	r7, r7, r4		C q = l * inverse
   120  L(one):	subfe	r3, r3, r3		C ca 0 or -1
   121  	mulhwu	r6, r7, r5		C carry = high(q*divisor)
   122  	subf	r3, r3, r6		C carry + ca
   123  	blr
   124  
   125  EPILOGUE(mpn_modexact_1c_odd)
   126  EPILOGUE(mpn_modexact_1_odd)
   127  ASM_END()