/* lzo1x_d.ash -- assembler implementation of the LZO1X decompression algorithm This file is part of the LZO real-time data compression library. Copyright (C) 1996-2014 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 <markus@oberhumer.com> 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 */