1/* arm_nrv2b_d8.S -- ARM decompressor for NRV2B 2 3 This file is part of the UPX executable compressor. 4 5 Copyright (C) 1996-2020 Markus Franz Xaver Johannes Oberhumer 6 Copyright (C) 1996-2020 Laszlo Molnar 7 Copyright (C) 2000-2020 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> <ezerotven+github@gmail.com> 27 28 John F. Reiser 29 <jreiser@users.sourceforge.net> 30*/ 31 32#define src r0 33#define len r1 34#define dst r2 35#define tmp r3 36#define bits r4 37#define off r5 38/* r6 UNUSED */ 39#define wrnk r7 /* 0xd00 M2_MAX_OFFSET before "wrinkle" */ 40 41/* r12 ("ip") is assumed to be a scratch register. */ 42 43#define GETBIT add bits,bits; mov lr,pc; beq get1_n2b 44 45#define getnextb(reg) GETBIT; adc reg,reg 46#define jnextb0 GETBIT; bcc 47#define jnextb1 GETBIT; bcs 48 49#ifndef PURE_THUMB 50ucl_nrv2b_decompress_8: .globl ucl_nrv2b_decompress_8 @ ARM mode 51 .type ucl_nrv2b_decompress_8, %function 52/* error = (*)(char const *src, int len_src, char *dst, int *plen_dst) */ 53 adr r12,1+.thumb_nrv2b_d8 @ load pc-relative address 54 bx r12 @ enter THUMB mode 55 .code 16 @ THUMB mode 56 .thumb_func 57#endif 58 59.thumb_nrv2b_d8: 60 add r1,len,src @ r1= eof_src; 61 push {r1,r2,r3, r4,r5,r6,r7, lr} 62 mov bits,#1; neg off,bits @ off= -1 initial condition 63 lsl bits,#31 @ 1<<31: refill next time 64 mov wrnk,#0xd 65 lsl wrnk,#8 @ 0xd00 66 b top_n2b 67 68eof_n2b: 69 pop {r1,r3,r4} @ r1= eof_src; r3= orig_dst; r4= plen_dst 70 sub src,r1 @ 0 if actual src length equals expected length 71 sub dst,r3 @ actual dst length 72 str dst,[r4] 73 pop {r4,r5,r6,r7 /*,pc*/} 74 pop {r1}; bx r1 @ "pop {,pc}" fails return to ARM mode on ARMv4T 75 76get1_n2b: 77 ldrb bits,[src] @ zero-extend next byte 78 adc bits,bits @ double and insert CarryIn as low bit 79 add src,#1 80 lsl bits,#24 @ move to top byte, and set CarryOut from old bit 8 81 mov pc,lr 82 83lit_n2b: 84 ldrb tmp,[src]; add src,#1 85 strb tmp,[dst]; add dst,#1 86top_n2b: 87 jnextb1 lit_n2b 88 mov len,#1 @ the msb 89getoff_n2b: @ ss11 len= [2..) 90 getnextb(len) 91 jnextb0 getoff_n2b 92 93 sub tmp,len,#3 @ set Carry 94 mov len,#0 @ Carry unaffected 95 blo offprev_n2b @ ss11 returned 2 96 lsl tmp,#8 97 ldrb off,[src]; add src,#1 @ low 8 bits 98 orr off,tmp 99 mvn off,off; beq eof_n2b @ off= ~off 100offprev_n2b: @ In: 0==len 101 getnextb(len); getnextb(len); bne plus1_n2b @ two bits; 1,2,3 ==> 2,3,4 102 103 mov len,#1 @ the msb 104getlen_n2b: @ ss11 len= [2..) 105 getnextb(len) 106 jnextb0 getlen_n2b 107 108 add len,#2 @ [2..) ==> [4..); 109plus1_n2b: 110 add len,#1 @ 1,2,3 ==> 2,3,4; [4..) ==> [5..) 111/* 'cmn': add the inputs, set condition codes, discard the sum */ 112 cmn off,wrnk; bcs near_n2b @ within M2_MAX_OFFSET 113 add len,#1 @ too far away, so minimum match length is 3 114near_n2b: 115 ldrb tmp,[dst] @ force cacheline allocate 116copy_n2b: 117 ldrb tmp,[dst,off] 118 strb tmp,[dst]; add dst,#1 119 sub len,#1; bne copy_n2b 120 b top_n2b 121 122#ifndef PURE_THUMB 123 .size ucl_nrv2b_decompress_8, .-ucl_nrv2b_decompress_8 124#endif 125 126/* 127vi:ts=8:et:nowrap 128 */ 129 130