1/* powerpc-darwin.macho-fold.S -- linkage to C code to process Mach-o binary
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#include "arch/powerpc/64le/macros.S"
33#include "arch/powerpc/64le/ppc_regs.h"
34retaddr = 2*8
35
36sz_b_info= 12
37  sz_unc= 0
38  sz_cpr= 4
39
40sz_l_info= 12
41sz_p_info= 12
42
43/* Mach_ppc_thread_state */
44srr0 = 0*4
45srr1 = 1*4
46reg0 = 2*4
47
48reg_cr  = 34*4
49reg_xer = 35*4
50reg_lr  = 36*4
51reg_ctr = 37*4
52reg_mq  = 38*4
53reg_vrsave = 39*4
54
55
56_start: .globl _start  # ignored, but silence "cannot find entry symbol _start" from ld
57/* In:
58   r31= &decompress; also 8+ (char *)&(offset to {l_info; p_info; b_info})
59*/
60fold_begin:
61    teq r0,r0  // this code has not been converted to 64-bit!!
62        call L90
63#include "arch/powerpc/32/bxx.S"
64
65L90:
66        la sp,SZ_FRAME(sp)  // trim save area used by decompressor
67        li   a6,0
68        stwu a6,-4(sp)  # _push_ default value for dyld
69        movr a6,sp  # &mhdrp
70        mflr a5  # &ppcbxx: f_unfilter
71
72        lwz a1,-8(r31)  # offset to {l_info; p_info; b_info}
73        subf a0,a1,r31  # &l_info
74        lwz a3,sz_unc+sz_p_info+sz_l_info(a0)  # sz_mach_headers
75        cmplwi cr0,a3,2048; bgt L100; li a3,2048  # at least 2 KiB for /usr/lib/dyld
76L100:
77        movr r29,sp  # remember for restoring later
78        subf sp,a3,sp  # alloca
79        movr a2,sp  # &temp char[sz_mach_headers]
80        stdu sp,-SZ_FRAME(sp)  # ABI convention
81        movr a4,r31  # f_decompress
82        call upx_main  # Out: a0= &Mach_ppc_thread_state of dyld
83
84        movr sp,r29  # restore stack pointer
85        lwz r0,   srr0(a0); mtctr r0  # entry address
86                /* Next 3 lines probably are not needed, but ... */
87        lwz r0, reg_cr(a0); mtcr  r0  # condition code
88        lwz r0,reg_xer(a0); mtxer r0  # extended error reg (CArry, etc.)
89        lwz r0, reg_lr(a0); mtlr  r0  # link register
90
91        lmw 4,4*4+reg0(3)  # reg 4 thru 31
92        lwz 0,0*4+reg0(3)
93        lwz 2,2*4+reg0(3)
94        lwz 3,3*4+reg0(3)
95        bctr  # goto dyld
96
97SYS_exit  =1
98SYS_fork  =2
99SYS_read  =3
100SYS_write =4
101SYS_open  =5
102SYS_close =6
103
104SYS_pread =153
105SYS_mmap    =197
106SYS_mprotect= 74
107
108/* SYS_mmap takes a 64-bit off_t, but gcc-3.4.1-20040827 passes long long
109   in wrong registers.  So change C interface to use size_t (32-bits) instead
110   of off_t (64 bits), and convert here.
111*/
112pread: .globl pread
113        movr a4,a3; li a3,0  # zero extend 4th arg size_t to off_t
114        li 0,SYS_pread; b sysgo
115mmap: .globl mmap
116        movr a6,a5; li a5,0  # zero extend 6th arg size_t to off_t
117        li 0,SYS_mmap
118sysgo:
119        sc
120          li a0,-1  # failure return
121        ret
122
123exit: .globl exit
124        li 0,SYS_exit; b sysgo
125read: .globl read
126        li 0,SYS_read; b sysgo
127open: .globl open
128        li 0,SYS_open; b sysgo
129close: .globl close
130        li 0,SYS_close; b sysgo
131mprotect: .globl mprotect
132        li 0,SYS_mprotect; b sysgo
133
134#include "powerpc64-savegpr0.S"
135
136/* vim:set ts=8 sw=8 et: */
137