campo-sirio/zip/unzip/crc_i386.S
alex f0d81ffd1c This commit was generated by cvs2svn to compensate for changes in r5402,
which included commits to RCS files with non-trunk default branches.

git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-10-20 15:51:36 +00:00

164 lines
5.8 KiB
ArmAsm
Executable File

/*
* crc_i386.S, optimized CRC calculation function for Zip and UnZip, not
* copyrighted by Paul Kienitz and Christian Spieler. Last revised 10 Nov 96.
*
* GRR 961110: incorporated Scott Field optimizations from win32/crc_i386.asm
* => overall 6% speedup in "unzip -tq" on 9MB zipfile (486-66)
*
* FLAT memory model assumed. Calling interface:
* - args are pushed onto the stack from right to left,
* - return value is given in the EAX register,
* - all other registers (with exception of EFLAGS) are preserved. (With
* GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving
* them nevertheless does only cost 4 single byte instructions.)
*
* This source generates the function
* ulg crc32(ulg oldcrc, ZCONST uch *text, ulg textlen).
*
* The loop unroolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
* This results in shorter code at the expense of reduced performance.
*/
/* This file is NOT used in conjunction with zlib. */
#ifndef USE_ZLIB
/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
* external symbols with an underline character '_'.
*/
#if defined(NO_UNDERLINE) || defined(__ELF__)
# define _crc32 crc32
# define _get_crc_table get_crc_table
#endif
/* Use 16-byte alignment if your assembler supports it. Warning: gas
* uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4
* the parameter is a number of bytes.
*/
#ifndef ALIGNMENT
# define ALIGNMENT .align 4,0x90
#endif
#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)
/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).
* Warning: it uses the AT&T syntax: mov source,dest
* This file is only optional. If you want to use the C version,
* remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.
*/
.file "crc_i386.S"
#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)
# undef USE_STACKFRAME
#else
/* The default is to use standard stack frame entry, because it
* results in smaller code!
*/
# ifndef USE_STD_STACKFRAME
# define USE_STD_STACKFRAME
# endif
#endif
#ifdef USE_STD_STACKFRAME
# define _STD_ENTRY pushl %ebp ; movl %esp,%ebp
# define arg1 8(%ebp)
# define arg2 12(%ebp)
# define arg3 16(%ebp)
# define _STD_LEAVE popl %ebp
#else /* !USE_STD_STACKFRAME */
# define _STD_ENTRY
# define arg1 24(%esp)
# define arg2 28(%esp)
# define arg3 32(%esp)
# define _STD_LEAVE
#endif /* ?USE_STD_STACKFRAME */
/*
* This is the loop body of the CRC32 cruncher.
* registers modified:
* ebx : crc value "c"
* esi : pointer to next data byte "text++"
* registers read:
* edi : pointer to base of crc_table array
* scratch registers:
* eax : requires upper three bytes of eax = 0, uses al
*/
#define Do_CRC \
movb (%esi),%al ;/* al <-- *text */\
incl %esi ;/* text++ */\
xorb %bl,%al ;/* (c ^ *text++) & 0xFF */\
shrl $8,%ebx ;/* c = (c >> 8) */\
xorl (%edi,%eax,4),%ebx ;/* ^table[(c^(*text++))&0xFF] */
.text
.globl _crc32
_crc32: /* ulg crc32(ulg crc, uch *text, extent len) */
_STD_ENTRY
pushl %edi
pushl %esi
pushl %ebx
pushl %edx
pushl %ecx
movl arg2,%esi /* 2nd arg: uch *text */
subl %eax,%eax /* > if (!text) */
testl %esi,%esi /* > return 0; */
jz fine /* > else { */
call _get_crc_table
movl %eax,%edi
movl arg1,%ebx /* 1st arg: ulg crc */
subl %eax,%eax /* eax=0; al usable as dword */
movl arg3,%ecx /* 3rd arg: extent textlen */
notl %ebx /* > c = ~crc; */
#ifndef NO_UNROLLED_LOOPS
movl %ecx,%edx /* save textlen in edx */
andl $7,%edx /* edx = textlen % 8 */
shrl $3,%ecx /* ecx = textlen / 8 */
jz No_Eights
/* align loop head at start of 486 internal cache line !! */
ALIGNMENT
Next_Eight:
Do_CRC
Do_CRC
Do_CRC
Do_CRC
Do_CRC
Do_CRC
Do_CRC
Do_CRC
decl %ecx
jnz Next_Eight
No_Eights:
movl %edx,%ecx
#endif /* NO_UNROLLED_LOOPS */
jecxz bail /* > if (textlen) */
/* align loop head at start of 486 internal cache line !! */
ALIGNMENT
loupe: /* > do { */
Do_CRC /* c = CRC32(c, *text++); */
decl %ecx /* > } while (--textlen); */
jnz loupe
bail: /* > } */
movl %ebx,%eax
notl %eax /* > return ~c; */
fine:
popl %ecx
popl %edx
popl %ebx
popl %esi
popl %edi
_STD_LEAVE
ret
#else
error: this asm version is for 386 only
#endif /* i386 || _i386 || _I386 || __i386 */
#endif /* !USE_ZLIB */