PowerPC unfilter, decompress, and register definitions
Added Files: ppc_bxx.S ppc_d_nrv2e.S ppc_regs.h committer: jreiser <jreiser> 1108855959 +0000
This commit is contained in:
@@ -0,0 +1,60 @@
|
|||||||
|
/* ppc_bxx.S -- PowerPC Branch Trick unfilter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 2005 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.
|
||||||
|
|
||||||
|
John F. Reiser
|
||||||
|
<jreiser@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ppc_regs.h"
|
||||||
|
|
||||||
|
ppcbxx: # (*f_unf)(xo->buf, out_len, h.b_cto8, h.b_ftid);
|
||||||
|
#define W_CTO 4 /* must match filteri/ppcbxx.h */
|
||||||
|
|
||||||
|
#define ptr a0
|
||||||
|
#define len a1
|
||||||
|
#define cto8 a2
|
||||||
|
#define ftid a3
|
||||||
|
|
||||||
|
#define ptr0 a4
|
||||||
|
|
||||||
|
cmpli cr0,ftid,0xd0; bnelr- cr0 # if (0xd0!=ftid) return;
|
||||||
|
rlwinm. len,len,32-2,2,31; beqlr- cr0 # if (0==(len>>=2)) return;
|
||||||
|
addi cto8,cto8,18<<W_CTO # cat(bxx_opcode, cto8)
|
||||||
|
movr ptr0,ptr # save base address
|
||||||
|
addi ptr,ptr,-4 # prepare for 'lwzu'
|
||||||
|
mtctr len # count of words
|
||||||
|
b L20
|
||||||
|
L10:
|
||||||
|
subf t1,ptr,t0 # raw distance
|
||||||
|
add t1,t1,ptr0 # relative to virtual address of base
|
||||||
|
rlwinm t1,t1,6+W_CTO,0,31-(6+W_CTO) # shift displacement up to sign bit
|
||||||
|
srawi t1,t1,6+W_CTO # sign extended displacement
|
||||||
|
rlwimi t0,t1,0,6,31-2 # t0= unfiltered instruction
|
||||||
|
stw t0,0(ptr) # replace in memory
|
||||||
|
bdzlr- # if (0==--ctr) return; // extremely unlikely
|
||||||
|
L20:
|
||||||
|
lwzu t0,4(ptr) # t0= *++ptr;
|
||||||
|
rlwinm t1,t0,6+W_CTO,32-(6+W_CTO),31 # t1= top (6+W_CTO) bits of t0
|
||||||
|
cmpl cr0,t1,cto8; beq- cr0,L10 # unconditional branch marked with cto8; unlikely
|
||||||
|
bdnz+ L20 # if (0!=--ctr) goto L20; // likely
|
||||||
|
ret
|
||||||
|
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
/* ppc_d_nrv2e.S -- PowerPC 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-2005 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
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
|
||||||
|
John F. Reiser
|
||||||
|
<jreiser@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ppc_regs.h"
|
||||||
|
|
||||||
|
/* Returns 0 on success; non-zero on failure. */
|
||||||
|
decompress: # (uchar const *src, size_t lsrc, uchar *dst, size_t &ldst)
|
||||||
|
|
||||||
|
/* PowerPC has no 'cmplis': compare logical [unsigned] immediate shifted [by 16] */
|
||||||
|
#define hibit r0 /* holds 0x80000000 during decompress */
|
||||||
|
|
||||||
|
#define src a0
|
||||||
|
#define lsrc a1
|
||||||
|
#define dst a2
|
||||||
|
#define ldst a3 /* Out: actually a reference: &len_dst */
|
||||||
|
|
||||||
|
#define off a4
|
||||||
|
#define len a5
|
||||||
|
#define bits a6
|
||||||
|
#define disp a7
|
||||||
|
|
||||||
|
stw dst,0(ldst) # original dst
|
||||||
|
add lsrc,lsrc,src # input eof
|
||||||
|
|
||||||
|
lis hibit,0x8000 # 0x80000000 for detecting next bit
|
||||||
|
lis bits,0x8000 # prepare for first load
|
||||||
|
addi src,src,-1 # prepare for 'lbzu'
|
||||||
|
addi dst,dst,-1 # prepare for 'stbu'
|
||||||
|
li disp,-1 # initial displacement
|
||||||
|
|
||||||
|
mflr t3 # return address
|
||||||
|
b top_n2e
|
||||||
|
|
||||||
|
/* jump on next bit, with branch prediction: y==>likely; n==>unlikely
|
||||||
|
cr0 is set by the cmpl ["compare logical"==>unsigned]:
|
||||||
|
lt next bit is 0
|
||||||
|
gt next bit is 1
|
||||||
|
eq must load next 32 bits from memory
|
||||||
|
|
||||||
|
beql-: branch and link [call subroutine] if cr0 is eq, unlikely
|
||||||
|
*/
|
||||||
|
#define jnextb0y cmpl 0,bits,hibit; add bits,bits,bits; beql- get32; blt+
|
||||||
|
#define jnextb0n cmpl 0,bits,hibit; add bits,bits,bits; beql- get32; blt-
|
||||||
|
#define jnextb1y cmpl 0,bits,hibit; add bits,bits,bits; beql- get32; bgt+
|
||||||
|
#define jnextb1n cmpl 0,bits,hibit; add bits,bits,bits; beql- get32; bgt-
|
||||||
|
|
||||||
|
/* rotate next bit into bottom bit of reg */
|
||||||
|
#define getnextb(reg) addc. bits,bits,bits; beql- get32; adde reg,reg,reg
|
||||||
|
|
||||||
|
get32:
|
||||||
|
# fetch 4 bytes unaligned and LITTLE ENDIAN
|
||||||
|
#if 0 /*{ clean; but 4 instr larger, and 3 cycles longer */
|
||||||
|
lbz bits,1(src) # lo8
|
||||||
|
lbz t0,2(src); rlwimi bits,t0, 8,16,23
|
||||||
|
lbz t0,3(src); rlwimi bits,t0,16, 8,15
|
||||||
|
lbzu t0,4(src); rlwimi bits,t0,24, 0, 7
|
||||||
|
#else /*}{ pray for no unalignment trap or slowdown */
|
||||||
|
li bits,1 # compensate for 'lbzu'
|
||||||
|
lwbrx bits,bits,src # bits= fetch_le32(bits+src)
|
||||||
|
addi src,src,4
|
||||||
|
#endif /*}*/
|
||||||
|
|
||||||
|
cmpl 0,bits,hibit # cr0 for jnextb
|
||||||
|
addc bits,bits,bits # CArry for getnextb
|
||||||
|
ori bits,bits,1 # the flag bit
|
||||||
|
ret
|
||||||
|
|
||||||
|
lit_n2e:
|
||||||
|
#define tmp len
|
||||||
|
lbzu tmp,1(src)
|
||||||
|
stbu tmp,1(dst)
|
||||||
|
#undef tmp
|
||||||
|
top_n2e:
|
||||||
|
jnextb1y lit_n2e
|
||||||
|
li off,1
|
||||||
|
b getoff_n2e
|
||||||
|
|
||||||
|
off_n2e:
|
||||||
|
addi off,off,-1
|
||||||
|
getnextb(off)
|
||||||
|
getoff_n2e:
|
||||||
|
getnextb(off)
|
||||||
|
jnextb0n off_n2e
|
||||||
|
|
||||||
|
li len,0
|
||||||
|
addic. off,off,-3 # CArry set [and ignored], but no 'addi.'
|
||||||
|
rlwinm off,off,8,0,31-8 # off<<=8;
|
||||||
|
blt- offprev_n2e
|
||||||
|
lbzu t0,1(src)
|
||||||
|
nor. disp,off,t0 # disp = -(1+ (off|t0));
|
||||||
|
srawi disp,disp,1 # shift off low bit (sets CArry; ignored)
|
||||||
|
beq- eof_n2e
|
||||||
|
andi. t0,t0,1 # complement of low bit of unshifted disp
|
||||||
|
beq+ lenlast_n2e # low bit was 1
|
||||||
|
b lenmore_n2e # low bit was 0
|
||||||
|
|
||||||
|
offprev_n2e:
|
||||||
|
jnextb1y lenlast_n2e
|
||||||
|
lenmore_n2e:
|
||||||
|
li len,1 # 1: "the msb"
|
||||||
|
jnextb1y lenlast_n2e
|
||||||
|
len_n2e:
|
||||||
|
getnextb(len)
|
||||||
|
jnextb0n len_n2e
|
||||||
|
addi len,len,6-2-2
|
||||||
|
b gotlen_n2e
|
||||||
|
|
||||||
|
lenlast_n2e:
|
||||||
|
getnextb(len) # 0,1,2,3
|
||||||
|
gotlen_n2e:
|
||||||
|
#define tmp off
|
||||||
|
subfic tmp,disp,(~0)+(-0x500) # want CArry only
|
||||||
|
#undef tmp
|
||||||
|
addi len,len,2
|
||||||
|
addze len,len # len += (disp < -0x500);
|
||||||
|
|
||||||
|
#define back off
|
||||||
|
add back,disp,dst # point back to match in dst
|
||||||
|
mtctr len
|
||||||
|
short_n2e:
|
||||||
|
#define tmp len
|
||||||
|
lbzu tmp,1(back)
|
||||||
|
stbu tmp,1(dst)
|
||||||
|
#undef tmp
|
||||||
|
bdnz+ short_n2e
|
||||||
|
b top_n2e
|
||||||
|
#undef back
|
||||||
|
|
||||||
|
eof_n2e:
|
||||||
|
#define tmp r0 /* hibit is dead */
|
||||||
|
lwz tmp,0(ldst) # original dst
|
||||||
|
mtlr t3 # return address
|
||||||
|
addi dst,dst,1 # uncorrect for 'stbu'
|
||||||
|
addi src,src,1 # uncorrect for 'lbzu'
|
||||||
|
subf dst,tmp,dst # dst -= tmp; // dst length
|
||||||
|
#undef tmp
|
||||||
|
subf a0,lsrc,src # src -= eof; // return 0: good; else: bad
|
||||||
|
stw dst,0(ldst)
|
||||||
|
ret
|
||||||
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __PPC_REGS__ /*{*/
|
||||||
|
#define __PPC_REGS__
|
||||||
|
|
||||||
|
#define r0 0
|
||||||
|
#define r1 1
|
||||||
|
#define r2 2
|
||||||
|
|
||||||
|
#define r29 29
|
||||||
|
#define r30 30
|
||||||
|
#define r31 31
|
||||||
|
|
||||||
|
/* Stack pointer */
|
||||||
|
#define sp 1
|
||||||
|
|
||||||
|
/* Subroutine arguments; not saved by callee */
|
||||||
|
#define a0 3
|
||||||
|
#define a1 4
|
||||||
|
#define a2 5
|
||||||
|
#define a3 6
|
||||||
|
#define a4 7
|
||||||
|
#define a5 8
|
||||||
|
#define a6 9
|
||||||
|
#define a7 10
|
||||||
|
|
||||||
|
/* Scratch (temporary) registers; not saved by callee */
|
||||||
|
#define t0 2
|
||||||
|
#define t1 11
|
||||||
|
#define t2 12
|
||||||
|
#define t3 13
|
||||||
|
|
||||||
|
/* branch and link */
|
||||||
|
#define call bl
|
||||||
|
|
||||||
|
/* branch to link register */
|
||||||
|
#define ret blr
|
||||||
|
|
||||||
|
/* move register */
|
||||||
|
#define movr mr
|
||||||
|
|
||||||
|
#endif /*} __PPC_REGS__ */
|
||||||
Reference in New Issue
Block a user