| 2 |
theseven |
1 |
/* arm_nrv2e_d8.S -- ARM decompressor for NRV2E
|
|
|
2 |
|
|
|
3 |
This file is part of the UPX executable compressor.
|
|
|
4 |
|
|
|
5 |
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
|
|
6 |
Copyright (C) 1996-2008 Laszlo Molnar
|
|
|
7 |
Copyright (C) 2000-2008 John F. Reiser
|
|
|
8 |
All Rights Reserved.
|
|
|
9 |
|
|
|
10 |
UPX and the UCL library are free software; you can redistribute them
|
|
|
11 |
and/or modify them under the terms of the GNU General Public License as
|
|
|
12 |
published by the Free Software Foundation; either version 2 of
|
|
|
13 |
the License, or (at your option) any later version.
|
|
|
14 |
|
|
|
15 |
This program is distributed in the hope that it will be useful,
|
|
|
16 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
17 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
18 |
GNU General Public License for more details.
|
|
|
19 |
|
|
|
20 |
You should have received a copy of the GNU General Public License
|
|
|
21 |
along with this program; see the file COPYING.
|
|
|
22 |
If not, write to the Free Software Foundation, Inc.,
|
|
|
23 |
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
24 |
|
|
|
25 |
Markus F.X.J. Oberhumer Laszlo Molnar
|
|
|
26 |
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
|
|
27 |
|
|
|
28 |
John F. Reiser
|
|
|
29 |
<jreiser@users.sourceforge.net>
|
|
|
30 |
*/
|
|
|
31 |
|
|
|
32 |
#define src r0
|
|
|
33 |
#define len r1 /* overlaps 'cnt' */
|
|
|
34 |
#define dst r2
|
|
|
35 |
#define tmp r3
|
|
|
36 |
#define bits r4
|
|
|
37 |
#define off r5
|
|
|
38 |
#define wrnk r6 /* 0x500 M2_MAX_OFFSET before "wrinkle" */
|
|
|
39 |
#define srclim r7
|
|
|
40 |
|
|
|
41 |
#define cnt r1 /* overlaps 'len' while reading an offset */
|
|
|
42 |
|
|
|
43 |
/* "mov lr,pc; bxx ..." implements conditional subroutine call */
|
|
|
44 |
#define GETBIT add bits,bits; mov lr,pc; beq get1_n2e
|
|
|
45 |
|
|
|
46 |
#define getnextb(reg) GETBIT; adc reg,reg
|
|
|
47 |
#define jnextb0 GETBIT; bcc
|
|
|
48 |
#define jnextb1 GETBIT; bcs
|
|
|
49 |
|
|
|
50 |
.section .icode.ucl_decompress, "ax", %progbits
|
|
|
51 |
.align 2
|
|
|
52 |
ucl_decompress: .globl ucl_nrv2e_decompress_8 @ ARM mode
|
|
|
53 |
.type ucl_nrv2e_decompress_8, %function
|
|
|
54 |
/* error = (*)(char const *src, int len_src, char *dst, int *plen_dst)
|
|
|
55 |
Actual decompressed length is stored through plen_dst.
|
|
|
56 |
*/
|
|
|
57 |
adr r12,1+.thumb_nrv2e_d8; bx r12 @ enter THUMB mode
|
|
|
58 |
.code 16 @ THUMB mode
|
|
|
59 |
.thumb_func
|
|
|
60 |
|
|
|
61 |
.thumb_nrv2e_d8:
|
|
|
62 |
push {r2,r3,r4,r5,r6,r7,lr}
|
|
|
63 |
add srclim,len,src @ srclim= eof_src;
|
|
|
64 |
mov bits,#1; neg off,bits @ off= -1 initial condition
|
|
|
65 |
lsl bits,#31 @ 1<<31: refill next time
|
|
|
66 |
mov wrnk,#5
|
|
|
67 |
lsl wrnk,#8 @ 0x500 @ nrv2e M2_MAX_OFFSET
|
|
|
68 |
b top_n2e
|
|
|
69 |
|
|
|
70 |
eof_n2e:
|
|
|
71 |
pop {r3,r4} @ r3= orig_dst; r4= plen_dst
|
|
|
72 |
sub src,srclim @ 0 if actual src length equals expected length
|
|
|
73 |
sub dst,r3 @ actual dst length
|
|
|
74 |
str dst,[r4]
|
|
|
75 |
pop {r4,r5,r6,r7}
|
|
|
76 |
pop {r1}
|
|
|
77 |
bx r1
|
|
|
78 |
|
|
|
79 |
get1_n2e: @ In: Carry set [from adding 0x80000000 (1<<31) to itself]
|
|
|
80 |
ldrb bits,[src] @ zero-extend next byte
|
|
|
81 |
adc bits,bits @ double and insert CarryIn as low bit
|
|
|
82 |
add src,#1
|
|
|
83 |
lsl bits,#24 @ move to top byte, and set CarryOut from old bit 8
|
|
|
84 |
mov pc,lr @ return, stay in current (THUMB) mode
|
|
|
85 |
|
|
|
86 |
lit_n2e:
|
|
|
87 |
ldrb tmp,[src]; add src,#1
|
|
|
88 |
strb tmp,[dst]; add dst,#1
|
|
|
89 |
top_n2e:
|
|
|
90 |
jnextb1 lit_n2e
|
|
|
91 |
mov cnt,#1; b getoff_n2e
|
|
|
92 |
|
|
|
93 |
off_n2e:
|
|
|
94 |
sub cnt,#1
|
|
|
95 |
getnextb(cnt)
|
|
|
96 |
getoff_n2e:
|
|
|
97 |
getnextb(cnt)
|
|
|
98 |
jnextb0 off_n2e
|
|
|
99 |
|
|
|
100 |
sub tmp,cnt,#3 @ set Carry
|
|
|
101 |
mov len,#0 @ Carry unaffected
|
|
|
102 |
blo offprev_n2e @ cnt was 2; tests Carry only
|
|
|
103 |
lsl tmp,#8
|
|
|
104 |
ldrb off,[src]; add src,#1 @ low 7+1 bits
|
|
|
105 |
orr off,tmp
|
|
|
106 |
mvn off,off; beq eof_n2e @ off= ~off
|
|
|
107 |
asr off,#1; bcs lenlast_n2e
|
|
|
108 |
b lenmore_n2e
|
|
|
109 |
|
|
|
110 |
offprev_n2e:
|
|
|
111 |
jnextb1 lenlast_n2e
|
|
|
112 |
lenmore_n2e:
|
|
|
113 |
mov len,#1
|
|
|
114 |
jnextb1 lenlast_n2e
|
|
|
115 |
len_n2e:
|
|
|
116 |
getnextb(len)
|
|
|
117 |
jnextb0 len_n2e
|
|
|
118 |
add len,#6-2
|
|
|
119 |
b gotlen_n2e
|
|
|
120 |
|
|
|
121 |
lenlast_n2e:
|
|
|
122 |
getnextb(len) @ 0,1,2,3
|
|
|
123 |
add len,#2
|
|
|
124 |
gotlen_n2e: @ 'cmn': add the inputs, set condition codes, discard the sum
|
|
|
125 |
cmn wrnk,off; bcs near_n2e @ within M2_MAX_OFFSET
|
|
|
126 |
add len,#1 @ too far away, so minimum match length is 3
|
|
|
127 |
near_n2e:
|
|
|
128 |
ldrb tmp,[dst] @ force cacheline allocate
|
|
|
129 |
copy_n2e:
|
|
|
130 |
ldrb tmp,[dst,off]
|
|
|
131 |
strb tmp,[dst]; add dst,#1
|
|
|
132 |
sub len,#1; bne copy_n2e
|
|
|
133 |
b top_n2e
|
|
|
134 |
|
|
|
135 |
.size ucl_decompress, .-ucl_decompress
|