diff --git a/src/stub/arm_nrv2b_d8.S b/src/stub/arm_nrv2b_d8.S new file mode 100644 index 00000000..272dbaa1 --- /dev/null +++ b/src/stub/arm_nrv2b_d8.S @@ -0,0 +1,129 @@ +/* arm_nrv2b_d8.S -- ARM decompressor for NRV2B + + This file is part of the UPX executable compressor. + + Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2004 Laszlo Molnar + Copyright (C) 2000-2006 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 + + + John F. Reiser + +*/ + +#define src r0 +#define len r1 +#define dst r2 +#define tmp r3 +#define bits r4 +#define off r5 +#define g1b r6 +#define wrnk r7 /* 0xd00 M2_MAX_OFFSET before "wrinkle" */ + +/* r12 ("ip") is assumed to be a scratch register. */ + +#define GETBIT blx g1b + +#define getnextb(reg) GETBIT; adc reg,reg +#define jnextb0 GETBIT; bcc +#define jnextb1 GETBIT; bcs + +ucl_nrv2b_decompress_8: .globl ucl_nrv2b_decompress_8 @ ARM mode + .type ucl_nrv2b_decompress_8, %function +/* error = (*)(char const *src, int len_src, char *dst, int *plen_dst) */ + adr r12,1+go_thumb_n2b @ load pc-relative address + bx r12 @ enter THUMB mode + + .code 16 @ THUMB mode +go_thumb_n2b: + add r1,len,src @ r1= eof_src; + push {r1,r2,r3, r4,r5,r6,r7, lr} + mov bits,#1; neg off,bits @ off= -1 initial condition + lsl bits,#31 @ 1<<31: refill next time + mov wrnk,#0xd + lsl wrnk,#8 @ 0xd00 + adr g1b,get1_n2b @ load pc-relative address + add g1b,#1 @ force THUMB mode + b top_n2b + +eof_n2b: + pop {r1,r3,r4} @ r1= eof_src; r3= orig_dst; r4= plen_dst + sub src,r1 @ 0 if actual src length equals expected length + sub dst,r3 @ actual dst length + str dst,[r4] + pop {r4,r5,r6,r7, pc} @ return + + + .align 2 @ 1<<2 for benefit of loading address with 'adr' above +get1_n2b: + adc bits,bits; bne get1r_n2b @ CarryOut has data bit + ldrb bits,[src] @ zero-extend next byte + adc bits,bits @ double and insert CarryIn as low bit + add src,#1 + lsl bits,#24 @ move to top byte, and set CarryOut from old bit 8 +get1r_n2b: + bx lr + +lit_n2b: + ldrb tmp,[src]; add src,#1 + strb tmp,[dst]; add dst,#1 +top_n2b: + jnextb1 lit_n2b + + mov len,#1 @ the msb +getoff_n2b: @ ss11 len= [2..) + getnextb(len) + jnextb0 getoff_n2b + + sub tmp,len,#3 @ set Carry + mov len,#0 @ Carry unaffected + blo offprev_n2b @ ss11 returned 2 + lsl tmp,#8 + ldrb off,[src]; add src,#1 @ low 8 bits + orr off,tmp + mvn off,off; beq eof_n2b @ off= ~off +offprev_n2b: @ In: 0==len + getnextb(len); getnextb(len); bne plus1_n2b @ two bits; 1,2,3 ==> 2,3,4 + + mov len,#1 @ the msb +getlen_n2b: @ ss11 len= [2..) + getnextb(len) + jnextb0 getlen_n2b + + add len,#2 @ [2..) ==> [4..); +plus1_n2b: + add len,#1 @ 1,2,3 ==> 2,3,4; [4..) ==> [5..) +/* 'cmn': add the inputs, set condition codes, discard the sum */ + cmn off,wrnk; bcs near_n2b @ within M2_MAX_OFFSET + add len,#1 @ too far away, so minimum match length is 3 +near_n2b: + ldrb tmp,[dst] @ force cacheline allocate +copy_n2b: + ldrb tmp,[dst,off] + strb tmp,[dst]; add dst,#1 + sub len,#1; bne copy_n2b + b top_n2b + + .size ucl_nrv2b_decompress_8, .-ucl_nrv2b_decompress_8 +/* +vi:ts=8:et:nowrap + */ + diff --git a/src/stub/arm_nrv2e_d8.S b/src/stub/arm_nrv2e_d8.S new file mode 100644 index 00000000..b76a816b --- /dev/null +++ b/src/stub/arm_nrv2e_d8.S @@ -0,0 +1,135 @@ +/* arm_nrv2e_d8.S -- ARM decompressor for NRV2E + + This file is part of the UPX executable compressor. + + Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2004 Laszlo Molnar + Copyright (C) 2000-2006 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 + + + John F. Reiser + +*/ + +#define src r0 +#define len r1 /* overlaps 'cnt' */ +#define dst r2 +#define tmp r3 +#define bits r4 +#define off r5 +#define g1b r6 +#define wrnk r7 /* 0x500 M2_MAX_OFFSET before "wrinkle" */ + +#define cnt r1 /* overlaps 'len' while reading an offset */ + +#define GETBIT blx g1b + +#define getnextb(reg) GETBIT; adc reg,reg +#define jnextb0 GETBIT; bcc +#define jnextb1 GETBIT; bcs + +ucl_nrv2e_decompress_8: .globl ucl_nrv2e_decompress_8 @ ARM mode + .type ucl_nrv2e_decompress_8, %function +/* error = (*)(char const *src, int len_src, char *dst, int *plen_dst) */ + adr r12,1+thumb_nrv2e_d8; bx r12 @ enter THUMB mode + .code 16 @ THUMB mode +thumb_nrv2e_d8: + add r1,len,src @ r1= eof_src; + push {r1,r2,r3, r4,r5,r6,r7, lr} + mov bits,#1; neg off,bits @ off= -1 initial condition + lsl bits,#31 @ 1<<31; refill next time + mov wrnk,#5 + lsl wrnk,#8 @ 0x500 + adr g1b,get1_n2e @ load pc-relative address + add g1b,#1 @ force THUMB mode + b top_n2e +eof_n2e: + pop {r1,r3,r4} @ r1= eof_src; r3= orig_dst; r4= plen_dst + sub src,r1 @ 0 if actual src length equals expected length + sub dst,r3 @ actual dst length + str dst,[r4] + pop {r4,r5,r6,r7, pc} @ return + + .align 2 @ 1<<2 for benefit of loading address with 'adr' above +get1_n2e: + adc bits,bits; bne get1r_n2e @ CarryOut has data bit + ldrb bits,[src] @ zero-extend next byte + adc bits,bits @ double and insert CarryIn as low bit + add src,#1 + lsl bits,#24 @ move to top byte, and set CarryOut from old bit 8 +get1r_n2e: + bx lr + +lit_n2e: + ldrb tmp,[src]; add src,#1 + strb tmp,[dst]; add dst,#1 +top_n2e: + jnextb1 lit_n2e + mov cnt,#1; b getoff_n2e + +off_n2e: + sub cnt,#1 + getnextb(cnt) +getoff_n2e: + getnextb(cnt) + jnextb0 off_n2e + + sub tmp,cnt,#3 @ set Carry + mov len,#0 @ Carry unaffected + blo offprev_n2e @ cnt was 2; tests Carry only + lsl tmp,#8 + ldrb off,[src]; add src,#1 @ low 7+1 bits + orr off,tmp + mvn off,off; beq eof_n2e @ off= ~off + asr off,#1; bcs lenlast_n2e + b lenmore_n2e + +offprev_n2e: + jnextb1 lenlast_n2e +lenmore_n2e: + mov len,#1 + jnextb1 lenlast_n2e +len_n2e: + getnextb(len) + jnextb0 len_n2e + add len,#6-2 + b gotlen_n2e + +lenlast_n2e: + getnextb(len) @ 0,1,2,3 + add len,#2 +gotlen_n2e: @ 'cmn': add the inputs, set condition codes, discard the sum + cmn off,wrnk; bcs near_n2e @ within M2_MAX_OFFSET + add len,#1 @ too far away, so minimum match length is 3 +near_n2e: + ldrb tmp,[dst] @ force cacheline allocate +copy_n2e: + ldrb tmp,[dst,off] + strb tmp,[dst]; add dst,#1 + sub len,#1; bne copy_n2e + b top_n2e + + .size ucl_nrv2e_decompress_8, .-ucl_nrv2e_decompress_8 + +/* +vi:ts=8:et:nowrap + */ +