/* lzo1x_d.ash -- assembler implementation of the LZO1X decompression algorithm This file is part of the LZO real-time data compression library. Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ #if !defined(LZO1X) && !defined(LZO1Y) # define LZO1X #endif #if defined(LZO_FAST) # define NN 3 #else # define NN 0 #endif /*********************************************************************** // init ************************************************************************/ xorl %eax,%eax xorl %ebx,%ebx /* high bits 9-32 stay 0 */ lodsb cmpb $17,%al jbe .L01 subb $17-NN,%al #if defined(LZO_FAST) jmp .LFLR #else cmpb $4,%al jae .LFLR #if 1 TEST_OP((%edi,%eax),%edx) TEST_IP((%esi,%eax),%edx) movl %eax,%ecx jmp .LFLR2 #else jmp .LFLR3 #endif #endif /*********************************************************************** // literal run ************************************************************************/ 0: addl N_255,%eax TEST_IP(18(%esi,%eax),%edx) /* minimum */ 1: movb (%esi),%bl incl %esi orb %bl,%bl jz 0b leal 18+NN(%eax,%ebx),%eax jmp 3f ALIGN3 .L00: #ifdef LZO_DEBUG andl $0xffffff00,%eax ; jnz .L_assert_fail andl $0xffffff00,%ebx ; jnz .L_assert_fail xorl %eax,%eax ; xorl %ebx,%ebx xorl %ecx,%ecx ; xorl %edx,%edx #endif TEST_IP_R(%esi) LODSB .L01: cmpb $16,%al jae .LMATCH /* a literal run */ orb %al,%al jz 1b addl $3+NN,%eax 3: .LFLR: TEST_OP(-NN(%edi,%eax),%edx) TEST_IP(-NN(%esi,%eax),%edx) #if defined(LZO_FAST) movl %eax,%ecx NOTL_3(%eax) shrl $2,%ecx andl N_3,%eax COPYL(%esi,%edi,%edx) subl %eax,%esi subl %eax,%edi #else movl %eax,%ecx shrl $2,%eax andl N_3,%ecx COPYL_C(%esi,%edi,%edx,%eax) .LFLR2: rep movsb #endif #ifdef LZO_DEBUG andl $0xffffff00,%eax ; jnz .L_assert_fail andl $0xffffff00,%ebx ; jnz .L_assert_fail xorl %eax,%eax ; xorl %ebx,%ebx xorl %ecx,%ecx ; xorl %edx,%edx #endif LODSB cmpb $16,%al jae .LMATCH /*********************************************************************** // R1 ************************************************************************/ TEST_OP(3(%edi),%edx) shrl $2,%eax movb (%esi),%bl #if defined(LZO1X) leal -0x801(%edi),%edx #elif defined(LZO1Y) leal -0x401(%edi),%edx #endif leal (%eax,%ebx,4),%eax incl %esi subl %eax,%edx TEST_LOOKBEHIND(%edx) #if defined(LZO_FAST) movl (%edx),%ecx movl %ecx,(%edi) #else movb (%edx),%al movb %al,(%edi) movb 1(%edx),%al movb %al,1(%edi) movb 2(%edx),%al movb %al,2(%edi) #endif addl N_3,%edi jmp .LMDONE /*********************************************************************** // M2 ************************************************************************/ ALIGN3 .LMATCH: cmpb $64,%al jb .LM3MATCH /* a M2 match */ movl %eax,%ecx shrl $2,%eax leal -1(%edi),%edx #if defined(LZO1X) andl $7,%eax movb (%esi),%bl shrl $5,%ecx leal (%eax,%ebx,8),%eax #elif defined(LZO1Y) andl N_3,%eax movb (%esi),%bl shrl $4,%ecx leal (%eax,%ebx,4),%eax #endif incl %esi subl %eax,%edx #if defined(LZO_FAST) #if defined(LZO1X) addl $1+3,%ecx #elif defined(LZO1Y) addl $2,%ecx #endif #else #if defined(LZO1X) incl %ecx #elif defined(LZO1Y) decl %ecx #endif #endif cmpl N_3,%eax jae .LCOPYLONG jmp .LCOPYBYTE /*********************************************************************** // M3 ************************************************************************/ 0: addl N_255,%eax TEST_IP(3(%esi),%edx) /* minimum */ 1: movb (%esi),%bl incl %esi orb %bl,%bl jz 0b leal 33+NN(%eax,%ebx),%ecx xorl %eax,%eax jmp 3f ALIGN3 .LM3MATCH: cmpb $32,%al jb .LM4MATCH /* a M3 match */ andl $31,%eax jz 1b lea 2+NN(%eax),%ecx 3: #ifdef LZO_DEBUG andl $0xffff0000,%eax ; jnz .L_assert_fail #endif movw (%esi),%ax leal -1(%edi),%edx shrl $2,%eax addl $2,%esi subl %eax,%edx cmpl N_3,%eax jb .LCOPYBYTE /*********************************************************************** // copy match ************************************************************************/ ALIGN1 .LCOPYLONG: /* copy match using longwords */ TEST_LOOKBEHIND(%edx) #if defined(LZO_FAST) leal -3(%edi,%ecx),%eax shrl $2,%ecx TEST_OP_R(%eax) COPYL(%edx,%edi,%ebx) movl %eax,%edi xorl %ebx,%ebx #else TEST_OP((%edi,%ecx),%eax) movl %ecx,%ebx shrl $2,%ebx jz 2f COPYL_C(%edx,%edi,%eax,%ebx) andl N_3,%ecx jz 1f 2: COPYB_C(%edx,%edi,%al,%ecx) 1: #endif .LMDONE: movb -2(%esi),%al andl N_3,%eax jz .L00 .LFLR3: TEST_OP((%edi,%eax),%edx) TEST_IP((%esi,%eax),%edx) #if defined(LZO_FAST) movl (%esi),%edx addl %eax,%esi movl %edx,(%edi) addl %eax,%edi #else COPYB_C(%esi,%edi,%cl,%eax) #endif #ifdef LZO_DEBUG andl $0xffffff00,%eax ; jnz .L_assert_fail andl $0xffffff00,%ebx ; jnz .L_assert_fail xorl %eax,%eax ; xorl %ebx,%ebx xorl %ecx,%ecx ; xorl %edx,%edx #endif LODSB jmp .LMATCH ALIGN3 .LCOPYBYTE: /* copy match using bytes */ TEST_LOOKBEHIND(%edx) TEST_OP(-NN(%edi,%ecx),%eax) xchgl %edx,%esi #if defined(LZO_FAST) subl N_3,%ecx #endif rep movsb movl %edx,%esi jmp .LMDONE /*********************************************************************** // M4 ************************************************************************/ 0: addl N_255,%ecx TEST_IP(3(%esi),%edx) /* minimum */ 1: movb (%esi),%bl incl %esi orb %bl,%bl jz 0b leal 9+NN(%ebx,%ecx),%ecx jmp 3f ALIGN3 .LM4MATCH: cmpb $16,%al jb .LM1MATCH /* a M4 match */ movl %eax,%ecx andl $8,%eax shll $13,%eax /* save in bit 16 */ andl $7,%ecx jz 1b addl $2+NN,%ecx 3: #ifdef LZO_DEBUG movl %eax,%edx ; andl $0xfffe0000,%edx ; jnz .L_assert_fail #endif movw (%esi),%ax addl $2,%esi leal -0x4000(%edi),%edx shrl $2,%eax jz .LEOF subl %eax,%edx jmp .LCOPYLONG /*********************************************************************** // M1 ************************************************************************/ ALIGN3 .LM1MATCH: /* a M1 match */ TEST_OP(2(%edi),%edx) shrl $2,%eax movb (%esi),%bl leal -1(%edi),%edx leal (%eax,%ebx,4),%eax incl %esi subl %eax,%edx TEST_LOOKBEHIND(%edx) movb (%edx),%al /* we must use this because edx can be edi-1 */ movb %al,(%edi) movb 1(%edx),%bl movb %bl,1(%edi) addl $2,%edi jmp .LMDONE /*********************************************************************** // ************************************************************************/ .LEOF: /**** xorl %eax,%eax eax=0 from above */ cmpl $3+NN,%ecx /* ecx must be 3/6 */ setnz %al /* vi:ts=4 */