[BACK]Return to rshift.asm CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpn / x86 / k7 / mmx

Annotation of OpenXM_contrib/gmp/mpn/x86/k7/mmx/rshift.asm, Revision 1.1.1.1

1.1       maekawa     1: dnl  AMD K7 mpn_rshift -- mpn right shift.
                      2: dnl
                      3: dnl  K7: 1.21 cycles/limb (at 16 limbs/loop).
                      4:
                      5:
                      6: dnl  Copyright (C) 1999, 2000 Free Software Foundation, Inc.
                      7: dnl
                      8: dnl  This file is part of the GNU MP Library.
                      9: dnl
                     10: dnl  The GNU MP Library is free software; you can redistribute it and/or
                     11: dnl  modify it under the terms of the GNU Lesser General Public License as
                     12: dnl  published by the Free Software Foundation; either version 2.1 of the
                     13: dnl  License, or (at your option) any later version.
                     14: dnl
                     15: dnl  The GNU MP Library is distributed in the hope that it will be useful,
                     16: dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     18: dnl  Lesser General Public License for more details.
                     19: dnl
                     20: dnl  You should have received a copy of the GNU Lesser General Public
                     21: dnl  License along with the GNU MP Library; see the file COPYING.LIB.  If
                     22: dnl  not, write to the Free Software Foundation, Inc., 59 Temple Place -
                     23: dnl  Suite 330, Boston, MA 02111-1307, USA.
                     24:
                     25:
                     26: include(`../config.m4')
                     27:
                     28:
                     29: dnl  K7: UNROLL_COUNT cycles/limb
                     30: dnl           4           1.51
                     31: dnl           8           1.26
                     32: dnl          16           1.21
                     33: dnl          32           1.2
                     34: dnl  Maximum possible with the current code is 64.
                     35:
                     36: deflit(UNROLL_COUNT, 16)
                     37:
                     38:
                     39: C mp_limb_t mpn_rshift (mp_ptr dst, mp_srcptr src, mp_size_t size,
                     40: C                       unsigned shift);
                     41: C
                     42: C Shift src,size right by shift many bits and store the result in dst,size.
                     43: C Zeros are shifted in at the left.  The bits shifted out at the right are
                     44: C the return value.
                     45: C
                     46: C This code uses 64-bit MMX operations, which makes it possible to handle
                     47: C two limbs at a time, for a theoretical 1.0 cycles/limb.  Plain integer
                     48: C code, on the other hand, suffers from shrd being a vector path decode and
                     49: C running at 3 cycles back-to-back.
                     50: C
                     51: C Full speed depends on source and destination being aligned, and some hairy
                     52: C setups and finish-ups are done to arrange this for the loop.
                     53:
                     54: ifdef(`PIC',`
                     55: deflit(UNROLL_THRESHOLD, 10)
                     56: ',`
                     57: deflit(UNROLL_THRESHOLD, 10)
                     58: ')
                     59:
                     60: defframe(PARAM_SHIFT,16)
                     61: defframe(PARAM_SIZE, 12)
                     62: defframe(PARAM_SRC,  8)
                     63: defframe(PARAM_DST,  4)
                     64:
                     65: defframe(SAVE_EDI, -4)
                     66: defframe(SAVE_ESI, -8)
                     67: defframe(SAVE_EBX, -12)
                     68: deflit(SAVE_SIZE, 12)
                     69:
                     70:        .text
                     71:        ALIGN(32)
                     72:
                     73: PROLOGUE(mpn_rshift)
                     74: deflit(`FRAME',0)
                     75:
                     76:        movl    PARAM_SIZE, %eax
                     77:        movl    PARAM_SRC, %edx
                     78:        subl    $SAVE_SIZE, %esp
                     79: deflit(`FRAME',SAVE_SIZE)
                     80:
                     81:        movl    PARAM_SHIFT, %ecx
                     82:        movl    %edi, SAVE_EDI
                     83:
                     84:        movl    PARAM_DST, %edi
                     85:        decl    %eax
                     86:        jnz     L(more_than_one_limb)
                     87:
                     88:        movl    (%edx), %edx            C src limb
                     89:
                     90:        shrdl(  %cl, %edx, %eax)        C eax was decremented to zero
                     91:
                     92:        shrl    %cl, %edx
                     93:
                     94:        movl    %edx, (%edi)            C dst limb
                     95:        movl    SAVE_EDI, %edi
                     96:        addl    $SAVE_SIZE, %esp
                     97:
                     98:        ret
                     99:
                    100:
                    101: C -----------------------------------------------------------------------------
                    102: L(more_than_one_limb):
                    103:        C eax   size-1
                    104:        C ebx
                    105:        C ecx   shift
                    106:        C edx   src
                    107:        C esi
                    108:        C edi   dst
                    109:        C ebp
                    110:
                    111:        movd    PARAM_SHIFT, %mm6       C rshift
                    112:        movd    (%edx), %mm5            C src low limb
                    113:        cmp     $UNROLL_THRESHOLD-1, %eax
                    114:
                    115:        jae     L(unroll)
                    116:        leal    (%edx,%eax,4), %edx     C &src[size-1]
                    117:        leal    -4(%edi,%eax,4), %edi   C &dst[size-2]
                    118:
                    119:        movd    (%edx), %mm4            C src high limb
                    120:        negl    %eax
                    121:
                    122:
                    123: L(simple_top):
                    124:        C eax   loop counter, limbs, negative
                    125:        C ebx
                    126:        C ecx   shift
                    127:        C edx   carry
                    128:        C edx   &src[size-1]
                    129:        C edi   &dst[size-2]
                    130:        C ebp
                    131:        C
                    132:        C mm0   scratch
                    133:        C mm4   src high limb
                    134:        C mm5   src low limb
                    135:        C mm6   shift
                    136:
                    137:        movq    (%edx,%eax,4), %mm0
                    138:        incl    %eax
                    139:
                    140:        psrlq   %mm6, %mm0
                    141:
                    142:        movd    %mm0, (%edi,%eax,4)
                    143:        jnz     L(simple_top)
                    144:
                    145:
                    146:        psllq   $32, %mm5
                    147:        psrlq   %mm6, %mm4
                    148:
                    149:        psrlq   %mm6, %mm5
                    150:        movd    %mm4, 4(%edi)           C dst high limb
                    151:
                    152:        movd    %mm5, %eax              C return value
                    153:
                    154:        movl    SAVE_EDI, %edi
                    155:        addl    $SAVE_SIZE, %esp
                    156:        emms
                    157:
                    158:        ret
                    159:
                    160:
                    161: C -----------------------------------------------------------------------------
                    162:        ALIGN(16)
                    163: L(unroll):
                    164:        C eax   size-1
                    165:        C ebx
                    166:        C ecx   shift
                    167:        C edx   src
                    168:        C esi
                    169:        C edi   dst
                    170:        C ebp
                    171:        C
                    172:        C mm5   src low limb
                    173:        C mm6   rshift
                    174:
                    175:        testb   $4, %dl
                    176:        movl    %esi, SAVE_ESI
                    177:        movl    %ebx, SAVE_EBX
                    178:
                    179:        psllq   $32, %mm5
                    180:        jz      L(start_src_aligned)
                    181:
                    182:
                    183:        C src isn't aligned, process low limb separately (marked xxx) and
                    184:        C step src and dst by one limb, making src aligned.
                    185:        C
                    186:        C source                  edx
                    187:        C --+-------+-------+-------+
                    188:        C           |          xxx  |
                    189:        C --+-------+-------+-------+
                    190:        C         4mod8   0mod8   4mod8
                    191:        C
                    192:        C         dest            edi
                    193:        C         --+-------+-------+
                    194:        C           |       |  xxx  |
                    195:        C         --+-------+-------+
                    196:
                    197:        movq    (%edx), %mm0            C src low two limbs
                    198:        addl    $4, %edx
                    199:        movl    %eax, PARAM_SIZE        C size-1
                    200:
                    201:        addl    $4, %edi
                    202:        decl    %eax                    C size-2 is new size-1
                    203:
                    204:        psrlq   %mm6, %mm0
                    205:        movl    %edi, PARAM_DST         C new dst
                    206:
                    207:        movd    %mm0, -4(%edi)
                    208: L(start_src_aligned):
                    209:
                    210:
                    211:        movq    (%edx), %mm1            C src low two limbs
                    212:        decl    %eax                    C size-2, two last limbs handled at end
                    213:        testl   $4, %edi
                    214:
                    215:        psrlq   %mm6, %mm5
                    216:        jz      L(start_dst_aligned)
                    217:
                    218:
                    219:        C dst isn't aligned, add 4 to make it so, and pretend the shift is
                    220:        C 32 bits extra.  Low limb of dst (marked xxx) handled here separately.
                    221:        C
                    222:        C          source          edx
                    223:        C          --+-------+-------+
                    224:        C            |      mm1      |
                    225:        C          --+-------+-------+
                    226:        C                  4mod8   0mod8
                    227:        C
                    228:        C  dest                    edi
                    229:        C  --+-------+-------+-------+
                    230:        C                    |  xxx  |
                    231:        C  --+-------+-------+-------+
                    232:        C          4mod8   0mod8   4mod8
                    233:
                    234:        movq    %mm1, %mm0
                    235:        psrlq   %mm6, %mm1
                    236:        addl    $32, %ecx               C shift+32
                    237:
                    238:        movd    %mm1, (%edi)
                    239:        movq    %mm0, %mm1
                    240:        addl    $4, %edi                C new dst
                    241:
                    242:        movd    %ecx, %mm6
                    243: L(start_dst_aligned):
                    244:
                    245:
                    246:        movq    %mm1, %mm2              C copy of src low two limbs
                    247:        negl    %ecx
                    248:        andl    $-2, %eax               C round size down to even
                    249:
                    250:        movl    %eax, %ebx
                    251:        negl    %eax
                    252:        addl    $64, %ecx
                    253:
                    254:        andl    $UNROLL_MASK, %eax
                    255:        decl    %ebx
                    256:
                    257:        shll    %eax
                    258:
                    259:        movd    %ecx, %mm7              C lshift = 64-rshift
                    260:
                    261: ifdef(`PIC',`
                    262:        call    L(pic_calc)
                    263: L(here):
                    264: ',`
                    265:        leal    L(entry) (%eax,%eax,4), %esi
                    266:        negl    %eax
                    267: ')
                    268:        shrl    $UNROLL_LOG2, %ebx      C loop counter
                    269:
                    270:        leal    ifelse(UNROLL_BYTES,256,128+) 8(%edx,%eax,2), %edx
                    271:        leal    ifelse(UNROLL_BYTES,256,128) (%edi,%eax,2), %edi
                    272:        movl    PARAM_SIZE, %eax        C for use at end
                    273:
                    274:        jmp     *%esi
                    275:
                    276:
                    277: ifdef(`PIC',`
                    278: L(pic_calc):
                    279:        C See README.family about old gas bugs
                    280:        leal    (%eax,%eax,4), %esi
                    281:        addl    $L(entry)-L(here), %esi
                    282:        addl    (%esp), %esi
                    283:        negl    %eax
                    284:
                    285:        ret
                    286: ')
                    287:
                    288:
                    289: C -----------------------------------------------------------------------------
                    290:        ALIGN(64)
                    291: L(top):
                    292:        C eax   size, for use at end
                    293:        C ebx   loop counter
                    294:        C ecx   lshift
                    295:        C edx   src
                    296:        C esi   was computed jump
                    297:        C edi   dst
                    298:        C ebp
                    299:        C
                    300:        C mm0   scratch
                    301:        C mm1   \ carry (alternating)
                    302:        C mm2   /
                    303:        C mm6   rshift
                    304:        C mm7   lshift
                    305:        C
                    306:        C 10 code bytes/limb
                    307:        C
                    308:        C The two chunks differ in whether mm1 or mm2 hold the carry.
                    309:        C The computed jump puts the initial carry in both mm1 and mm2.
                    310:
                    311: L(entry):
                    312: deflit(CHUNK_COUNT, 4)
                    313: forloop(i, 0, UNROLL_COUNT/CHUNK_COUNT-1, `
                    314:        deflit(`disp0', eval(i*CHUNK_COUNT*4 ifelse(UNROLL_BYTES,256,-128)))
                    315:        deflit(`disp1', eval(disp0 + 8))
                    316:
                    317:        movq    disp0(%edx), %mm0
                    318:        psrlq   %mm6, %mm2
                    319:
                    320:        movq    %mm0, %mm1
                    321:        psllq   %mm7, %mm0
                    322:
                    323:        por     %mm2, %mm0
                    324:        movq    %mm0, disp0(%edi)
                    325:
                    326:
                    327:        movq    disp1(%edx), %mm0
                    328:        psrlq   %mm6, %mm1
                    329:
                    330:        movq    %mm0, %mm2
                    331:        psllq   %mm7, %mm0
                    332:
                    333:        por     %mm1, %mm0
                    334:        movq    %mm0, disp1(%edi)
                    335: ')
                    336:
                    337:        addl    $UNROLL_BYTES, %edx
                    338:        addl    $UNROLL_BYTES, %edi
                    339:        decl    %ebx
                    340:
                    341:        jns     L(top)
                    342:
                    343:
                    344: deflit(`disp0', ifelse(UNROLL_BYTES,256,-128))
                    345: deflit(`disp1', eval(disp0-0 + 8))
                    346:
                    347:        testb   $1, %al
                    348:        psrlq   %mm6, %mm2      C wanted rshifted in all cases below
                    349:        movl    SAVE_ESI, %esi
                    350:
                    351:        movd    %mm5, %eax              C return value
                    352:
                    353:        movl    SAVE_EBX, %ebx
                    354:        jz      L(end_even)
                    355:
                    356:
                    357:        C Size odd, destination was aligned.
                    358:        C
                    359:        C source
                    360:        C       edx
                    361:        C +-------+---------------+--
                    362:        C |       |      mm2      |
                    363:        C +-------+---------------+--
                    364:        C
                    365:        C dest                  edi
                    366:        C +-------+---------------+---------------+--
                    367:        C |       |               |    written    |
                    368:        C +-------+---------------+---------------+--
                    369:        C
                    370:        C mm6 = shift
                    371:        C mm7 = ecx = 64-shift
                    372:
                    373:
                    374:        C Size odd, destination was unaligned.
                    375:        C
                    376:        C source
                    377:        C       edx
                    378:        C +-------+---------------+--
                    379:        C |       |      mm2      |
                    380:        C +-------+---------------+--
                    381:        C
                    382:        C dest          edi
                    383:        C +---------------+---------------+--
                    384:        C |               |    written    |
                    385:        C +---------------+---------------+--
                    386:        C
                    387:        C mm6 = shift+32
                    388:        C mm7 = ecx = 64-(shift+32)
                    389:
                    390:
                    391:        C In both cases there's one extra limb of src to fetch and combine
                    392:        C with mm2 to make a qword to store, and in the aligned case there's
                    393:        C a further extra limb of dst to be formed.
                    394:
                    395:
                    396:        movd    disp0(%edx), %mm0
                    397:        movq    %mm0, %mm1
                    398:
                    399:        psllq   %mm7, %mm0
                    400:        testb   $32, %cl
                    401:
                    402:        por     %mm2, %mm0
                    403:        psrlq   %mm6, %mm1
                    404:
                    405:        movq    %mm0, disp0(%edi)
                    406:        jz      L(finish_odd_unaligned)
                    407:
                    408:        movd    %mm1, disp1(%edi)
                    409: L(finish_odd_unaligned):
                    410:
                    411:        movl    SAVE_EDI, %edi
                    412:        addl    $SAVE_SIZE, %esp
                    413:        emms
                    414:
                    415:        ret
                    416:
                    417:
                    418: L(end_even):
                    419:
                    420:        C Size even, destination was aligned.
                    421:        C
                    422:        C source
                    423:        C +---------------+--
                    424:        C |      mm2      |
                    425:        C +---------------+--
                    426:        C
                    427:        C dest          edi
                    428:        C +---------------+---------------+--
                    429:        C |               |      mm3      |
                    430:        C +---------------+---------------+--
                    431:        C
                    432:        C mm6 = shift
                    433:        C mm7 = ecx = 64-shift
                    434:
                    435:
                    436:        C Size even, destination was unaligned.
                    437:        C
                    438:        C source
                    439:        C +---------------+--
                    440:        C |      mm2      |
                    441:        C +---------------+--
                    442:        C
                    443:        C dest  edi
                    444:        C +-------+---------------+--
                    445:        C |       |      mm3      |
                    446:        C +-------+---------------+--
                    447:        C
                    448:        C mm6 = shift+32
                    449:        C mm7 = 64-(shift+32)
                    450:
                    451:
                    452:        C The movd for the unaligned case is the same data as the movq for
                    453:        C the aligned case, it's just a choice between whether one or two
                    454:        C limbs should be written.
                    455:
                    456:
                    457:        testb   $32, %cl
                    458:        movd    %mm2, disp0(%edi)
                    459:
                    460:        jz      L(end_even_unaligned)
                    461:
                    462:        movq    %mm2, disp0(%edi)
                    463: L(end_even_unaligned):
                    464:
                    465:        movl    SAVE_EDI, %edi
                    466:        addl    $SAVE_SIZE, %esp
                    467:        emms
                    468:
                    469:        ret
                    470:
                    471: EPILOGUE()

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>