/* nrv2d_d.S -- AMD64 decompressor for NRV2D

   This file is part of the UPX executable compressor.

   Copyright (C) Markus Franz Xaver Johannes Oberhumer
   Copyright (C) Laszlo Molnar
   Copyright (C) John F. Reiser
   All Rights Reserved.

   UPX and the UCL library are free software; you can redistribute them
   and/or modify them 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.

   This program 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 this program; see the file COPYING.
   If not, write to the Free Software Foundation, Inc.,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

   Markus F.X.J. Oberhumer              Laszlo Molnar
   <markus@oberhumer.com>               <ezerotven+github@gmail.com>

   John F. Reiser
   <jreiser@users.sourceforge.net>
*/

#ifndef NO_METHOD_CHECK
        cmpb $ M_NRV2D_LE32,methb; jne not_n2d
#endif
        jmp top_n2d

#undef EOF
#ifdef WINDOWS_BACK
  #define EOF eofd
#else
  #define EOF eof_n2d
#endif

lit_n2d:
        incq %rsi; movb %dl,(%rdi)
        incq %rdi
top_n2d:
#ifdef WINDOWS_BACK
        movb (%rsi),%dl  // speculate: literal, or bottom 8 bits of offset
#else
        movzbl (%rsi),%edx  // speculate: literal, or bottom 8 bits of offset
#endif
        jnextb1yp lit_n2d
        lea 1(lenq),off  // [len= 0] off= 1
        jmp getoff_n2d

off_n2d:
        dec off
        getnextbp(off)
getoff_n2d:
        getnextbp(off)
        jnextb0np off_n2d

        subl $ 3,off; jc offprev_n2d
#ifdef WINDOWS_BACK
        shll $ 8,off; movzbl %dl,%edx
        orl %edx,off; incq %rsi
        xorl $~0,off; jz eof
#else
        shll $ 8,off; incq %rsi
        orl %edx,off
        xorl $~0,off; jz EOF
#endif
        sarl     off  // Carry= original low bit
        movslq   off,dispq  // XXX: 2GB
        jmp len_n2d-2  // CHEAT: assume tail of getnextb is "adcl len,len"
offprev_n2d:
        getnextb(len)
len_n2d:
        getnextb(len); jne gotlen_n2d
        inc len  // len= 1
lenmore_n2d:
        getnextb(len)
        jnextb0n lenmore_n2d
        addl $2,len
gotlen_n2d:
        cmpq $-0x500,dispq
        adcl $1,len  // len += 1+ (disp < -0x500);
        call copy
bot_n2d:  // In: 0==len
        jmp top_n2d

#ifndef NO_METHOD_CHECK
not_n2d:
        push %rdi; pop %rsi  # src = arg1
#endif
        // fall into daisy chain
/*
vi:ts=8:et:nowrap
*/

