⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inffast.s

📁 gcc的组建
💻 S
📖 第 1 页 / 共 3 页
字号:
/* * inffast.S is a hand tuned assembler version of: * * inffast.c -- fast decoding * Copyright (C) 1995-2003 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Copyright (C) 2003 Chris Anderson <christop@charm.net> * Please use the copyright conditions above. * * This version (Jan-23-2003) of inflate_fast was coded and tested under * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution.  On that * machine, I found that gzip style archives decompressed about 20% faster than * the gcc-3.2 -O3 -fomit-frame-pointer compiled version.  Your results will * depend on how large of a buffer is used for z_stream.next_in & next_out * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in * stream processing I/O and crc32/addler32.  In my case, this routine used * 70% of the cpu time and crc32 used 20%. * * I am confident that this version will work in the general case, but I have * not tested a wide variety of datasets or a wide variety of platforms. * * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating. * It should be a runtime flag instead of compile time flag... * * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction. * With -DUSE_MMX, only MMX code is compiled.  With -DNO_MMX, only non-MMX code * is compiled.  Without either option, runtime detection is enabled.  Runtime * detection should work on all modern cpus and the recomended algorithm (flip * ID bit on eflags and then use the cpuid instruction) is used in many * multimedia applications.  Tested under win2k with gcc-2.95 and gas-2.12 * distributed with cygwin3.  Compiling with gcc-2.95 -c inffast.S -o * inffast.obj generates a COFF object which can then be linked with MSVC++ * compiled code.  Tested under FreeBSD 4.7 with gcc-2.95. * * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and * slower than compiler generated code).  Adjusted cpuid check to use the MMX * code only for Pentiums < P4 until I have more data on the P4.  Speed * improvment is only about 15% on the Athlon when compared with code generated * with MSVC++.  Not sure yet, but I think the P4 will also be slower using the * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and * have less latency than MMX ops.  Added code to buffer the last 11 bytes of * the input stream since the MMX code grabs bits in chunks of 32, which * differs from the inffast.c algorithm.  I don't think there would have been * read overruns where a page boundary was crossed (a segfault), but there * could have been overruns when next_in ends on unaligned memory (unintialized * memory read). * * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX.  I created a C * version of the non-MMX code so that it doesn't depend on zstrm and zstate * structure offsets which are hard coded in this file.  This was last tested * with zlib-1.2.0 which is currently in beta testing, newer versions of this * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and * http://www.charm.net/~christop/zlib/ *//* * if you have underscore linking problems (_inflate_fast undefined), try * using -DGAS_COFF */#if ! defined( GAS_COFF ) && ! defined( GAS_ELF )#if defined( WIN32 ) || defined( __CYGWIN__ )#define GAS_COFF /* windows object format */#else#define GAS_ELF#endif#endif /* ! GAS_COFF && ! GAS_ELF */#if defined( GAS_COFF )/* coff externals have underscores */#define inflate_fast _inflate_fast#define inflate_fast_use_mmx _inflate_fast_use_mmx#endif /* GAS_COFF */.file "inffast.S".globl inflate_fast.text.align 4,0.L_invalid_literal_length_code_msg:.string "invalid literal/length code".align 4,0.L_invalid_distance_code_msg:.string "invalid distance code".align 4,0.L_invalid_distance_too_far_msg:.string "invalid distance too far back"#if ! defined( NO_MMX ).align 4,0.L_mask: /* mask[N] = ( 1 << N ) - 1 */.long 0.long 1.long 3.long 7.long 15.long 31.long 63.long 127.long 255.long 511.long 1023.long 2047.long 4095.long 8191.long 16383.long 32767.long 65535.long 131071.long 262143.long 524287.long 1048575.long 2097151.long 4194303.long 8388607.long 16777215.long 33554431.long 67108863.long 134217727.long 268435455.long 536870911.long 1073741823.long 2147483647.long 4294967295#endif /* NO_MMX */.text/* * struct z_stream offsets, in zlib.h */#define next_in_strm   0   /* strm->next_in */#define avail_in_strm  4   /* strm->avail_in */#define next_out_strm  12  /* strm->next_out */#define avail_out_strm 16  /* strm->avail_out */#define msg_strm       24  /* strm->msg */#define state_strm     28  /* strm->state *//* * struct inflate_state offsets, in inflate.h */#define mode_state     0   /* state->mode */#define wsize_state    32  /* state->wsize */#define write_state    40  /* state->write */#define window_state   44  /* state->window */#define hold_state     48  /* state->hold */#define bits_state     52  /* state->bits */#define lencode_state  68  /* state->lencode */#define distcode_state 72  /* state->distcode */#define lenbits_state  76  /* state->lenbits */#define distbits_state 80  /* state->distbits *//* * inflate_fast's activation record */#define local_var_size 64 /* how much local space for vars */#define strm_sp        88 /* first arg: z_stream * (local_var_size + 24) */#define start_sp       92 /* second arg: unsigned int (local_var_size + 28) *//* * offsets for local vars on stack */#define out            60  /* unsigned char* */#define window         56  /* unsigned char* */#define wsize          52  /* unsigned int */#define write          48  /* unsigned int */#define in             44  /* unsigned char* */#define beg            40  /* unsigned char* */#define buf            28  /* char[ 12 ] */#define len            24  /* unsigned int */#define last           20  /* unsigned char* */#define end            16  /* unsigned char* */#define dcode          12  /* code* */#define lcode           8  /* code* */#define dmask           4  /* unsigned int */#define lmask           0  /* unsigned int *//* * typedef enum inflate_mode consts, in inflate.h */#define INFLATE_MODE_TYPE 11  /* state->mode flags enum-ed in inflate.h */#define INFLATE_MODE_BAD  26#if ! defined( USE_MMX ) && ! defined( NO_MMX )#define RUN_TIME_MMX#define CHECK_MMX    1#define DO_USE_MMX   2#define DONT_USE_MMX 3.globl inflate_fast_use_mmx.data.align 4,0inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */.long CHECK_MMX#if defined( GAS_ELF )/* elf info */.type   inflate_fast_use_mmx,@object.size   inflate_fast_use_mmx,4#endif#endif /* RUN_TIME_MMX */#if defined( GAS_COFF )/* coff info: scl 2 = extern, type 32 = function */.def inflate_fast; .scl 2; .type 32; .endef#endif.text.align 32,0x90inflate_fast:        pushl   %edi        pushl   %esi        pushl   %ebp        pushl   %ebx        pushf   /* save eflags (strm_sp, state_sp assumes this is 32 bits) */        subl    $local_var_size, %esp        cld#define strm_r  %esi#define state_r %edi        movl    strm_sp(%esp), strm_r        movl    state_strm(strm_r), state_r        /* in = strm->next_in;         * out = strm->next_out;         * last = in + strm->avail_in - 11;         * beg = out - (start - strm->avail_out);         * end = out + (strm->avail_out - 257);         */        movl    avail_in_strm(strm_r), %edx        movl    next_in_strm(strm_r), %eax        addl    %eax, %edx      /* avail_in += next_in */        subl    $11, %edx       /* avail_in -= 11 */        movl    %eax, in(%esp)        movl    %edx, last(%esp)        movl    start_sp(%esp), %ebp        movl    avail_out_strm(strm_r), %ecx        movl    next_out_strm(strm_r), %ebx        subl    %ecx, %ebp      /* start -= avail_out */        negl    %ebp            /* start = -start */        addl    %ebx, %ebp      /* start += next_out */        subl    $257, %ecx      /* avail_out -= 257 */        addl    %ebx, %ecx      /* avail_out += out */        movl    %ebx, out(%esp)        movl    %ebp, beg(%esp)        movl    %ecx, end(%esp)        /* wsize = state->wsize;         * write = state->write;         * window = state->window;         * hold = state->hold;         * bits = state->bits;         * lcode = state->lencode;         * dcode = state->distcode;         * lmask = ( 1 << state->lenbits ) - 1;         * dmask = ( 1 << state->distbits ) - 1;         */        movl    lencode_state(state_r), %eax        movl    distcode_state(state_r), %ecx        movl    %eax, lcode(%esp)        movl    %ecx, dcode(%esp)        movl    $1, %eax        movl    lenbits_state(state_r), %ecx        shll    %cl, %eax        decl    %eax        movl    %eax, lmask(%esp)        movl    $1, %eax        movl    distbits_state(state_r), %ecx        shll    %cl, %eax        decl    %eax        movl    %eax, dmask(%esp)        movl    wsize_state(state_r), %eax        movl    write_state(state_r), %ecx        movl    window_state(state_r), %edx        movl    %eax, wsize(%esp)        movl    %ecx, write(%esp)        movl    %edx, window(%esp)        movl    hold_state(state_r), %ebp        movl    bits_state(state_r), %ebx#undef strm_r#undef state_r#define in_r       %esi#define from_r     %esi#define out_r      %edi        movl    in(%esp), in_r        movl    last(%esp), %ecx        cmpl    in_r, %ecx        ja      .L_align_long           /* if in < last */        addl    $11, %ecx               /* ecx = &in[ avail_in ] */        subl    in_r, %ecx              /* ecx = avail_in */        movl    $12, %eax        subl    %ecx, %eax              /* eax = 12 - avail_in */        leal    buf(%esp), %edi        rep     movsb                   /* memcpy( buf, in, avail_in ) */        movl    %eax, %ecx        xorl    %eax, %eax        rep     stosb         /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */        leal    buf(%esp), in_r         /* in = buf */        movl    in_r, last(%esp)        /* last = in, do just one iteration */        jmp     .L_is_aligned        /* align in_r on long boundary */.L_align_long:        testl   $3, in_r        jz      .L_is_aligned        xorl    %eax, %eax        movb    (in_r), %al        incl    in_r        movl    %ebx, %ecx        addl    $8, %ebx        shll    %cl, %eax        orl     %eax, %ebp        jmp     .L_align_long.L_is_aligned:        movl    out(%esp), out_r#if defined( NO_MMX )        jmp     .L_do_loop#endif#if defined( USE_MMX )        jmp     .L_init_mmx#endif/*** Runtime MMX check ***/#if defined( RUN_TIME_MMX ).L_check_mmx:        cmpl    $DO_USE_MMX, inflate_fast_use_mmx        je      .L_init_mmx        ja      .L_do_loop /* > 2 */        pushl   %eax        pushl   %ebx        pushl   %ecx        pushl   %edx        pushf        movl    (%esp), %eax      /* copy eflags to eax */        xorl    $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21)                                   * to see if cpu supports cpuid...                                   * ID bit method not supported by NexGen but                                   * bios may load a cpuid instruction and                                   * cpuid may be disabled on Cyrix 5-6x86 */        popf        pushf        popl    %edx              /* copy new eflags to edx */        xorl    %eax, %edx        /* test if ID bit is flipped */        jz      .L_dont_use_mmx   /* not flipped if zero */        xorl    %eax, %eax        cpuid        cmpl    $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */        jne     .L_dont_use_mmx        cmpl    $0x6c65746e, %ecx        jne     .L_dont_use_mmx        cmpl    $0x49656e69, %edx        jne     .L_dont_use_mmx        movl    $1, %eax        cpuid                     /* get cpu features */        shrl    $8, %eax        andl    $15, %eax        cmpl    $6, %eax          /* check for Pentium family, is 0xf for P4 */        jne     .L_dont_use_mmx        testl   $0x800000, %edx   /* test if MMX feature is set (bit 23) */        jnz     .L_use_mmx        jmp     .L_dont_use_mmx.L_use_mmx:        movl    $DO_USE_MMX, inflate_fast_use_mmx        jmp     .L_check_mmx_pop.L_dont_use_mmx:        movl    $DONT_USE_MMX, inflate_fast_use_mmx.L_check_mmx_pop:        popl    %edx        popl    %ecx        popl    %ebx        popl    %eax        jmp     .L_check_mmx#endif/*** Non-MMX code ***/#if defined ( NO_MMX ) || defined( RUN_TIME_MMX )#define hold_r     %ebp#define bits_r     %bl#define bitslong_r %ebx.align 32,0x90.L_while_test:        /* while (in < last && out < end)         */        cmpl    out_r, end(%esp)        jbe     .L_break_loop           /* if (out >= end) */        cmpl    in_r, last(%esp)        jbe     .L_break_loop.L_do_loop:        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out         *         * do {         *   if (bits < 15) {         *     hold |= *((unsigned short *)in)++ << bits;         *     bits += 16         *   }         *   this = lcode[hold & lmask]         */        cmpb    $15, bits_r        ja      .L_get_length_code      /* if (15 < bits) */        xorl    %eax, %eax        lodsw                           /* al = *(ushort *)in++ */        movb    bits_r, %cl             /* cl = bits, needs it for shifting */        addb    $16, bits_r             /* bits += 16 */        shll    %cl, %eax        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */.L_get_length_code:        movl    lmask(%esp), %edx       /* edx = lmask */        movl    lcode(%esp), %ecx       /* ecx = lcode */        andl    hold_r, %edx            /* edx &= hold */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -