xref: /openbsd/libexec/ld.so/m88k/ldasm.S (revision 91f110e0)
1/*	$OpenBSD: ldasm.S,v 1.8 2013/12/25 13:06:02 miod Exp $	*/
2
3/*
4 * Copyright (c) 2013 Miodrag Vallat.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18/*
19 * Copyright (c) 2006 Dale Rahn
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 *    notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 *    notice, this list of conditions and the following disclaimer in the
28 *    documentation and/or other materials provided with the distribution.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
31 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 */
43
44#include <machine/asm.h>
45#include <sys/syscall.h>
46#include <SYS.h>
47
48/*
49 * ld.so entry point.
50 * On entry: r31 points to the kernel argument struct (argv, argv, environ).
51 * The environment pointers list is followed by an array of AuxInfo
52 * structs filled by the kernel.
53 */
54#define DL_DATA_SIZE	(4 * 16)	 /* 16 * sizeof(ELF_Addr) */
55ENTRY(_dl_start)
56	/*
57	 * Two nop because execution may skip up to two instructions.
58	 * See setregs() in the kernel for details.
59	 *
60	 * Note that I have been hacking m88k for years and still fall
61	 * into this trap, every time. -- miod
62	 */
63	or	%r0,  %r0,  %r0
64	or	%r0,  %r0,  %r0
65
66	/*
67	 * Get some room for the contiguous AUX pointers array.
68	  */
69	or	%r30, %r31, 0
70	subu	%r31, %r31, DL_DATA_SIZE
71
72	/*
73	 * Invoke _dl_boot_bind
74	 */
75	or	%r2,  %r30, 0		| kernel args
76	or	%r3,  %r31, 0		| array base
77#if 0 /* _dl_boot_bind() can compute this itself */
78	bsr	1f			| the following instruction is skipped
79	bcnd	eq0, %r0, _DYNAMIC	| but gives us the pc-relative offset
801:	ld.hu	%r5, %r1, 2		| fetch branch offset (low 16 bits)
81	lda	%r4, %r1[%r5]		|
82#endif
83	bsr	_dl_boot_bind
84
85	ld	%r2,  %r30, 0		| argc
86	addu	%r6,  %r30, 4 + 4
87	lda	%r3,  %r6[%r2]		| envp
88	ld	%r4,  %r31, 4 * 7	| ldoff
89	or	%r5,  %r31, 0		| array base
90	bsr.n	_dl_boot
91	 addu	%r2,  %r30, 4		| argv
92
93	addu	%r31, %r31, DL_DATA_SIZE
94	bsr	1f			| the following instruction is skipped
95	bcnd	eq0, %r0, _dl_dtors	| but gives us the pc-relative offset
961:	ld.hu	%r5, %r1, 2		| fetch branch offset (low 16 bits)
97	jmp.n	%r2
98	 lda	%r5, %r1[%r5]		| cleanup
99END(_dl_start)
100
101/*
102 * PLT resolver entry point.
103 * Invoked with the following stack frame:
104 *	r31(0x00)	zero
105 *	r31(0x04)	ELF object
106 *	r31(0x08)	saved r11
107 *	r31(0x0c)	saved r1
108 * All registers but r1 and r11 must be preserved. The resolver must return
109 * to the resolved address with r1 restored.
110 */
111#define	OBJECT_OFFSET	(4 * 1)
112#define	R11_OFFSET	(4 * 2)
113#define	R1_OFFSET	(4 * 3)
114#define	PLT_FRAME_SIZE	(4 * 4)
115#define REG_SIZE	(4 * 12)
116ENTRY(_dl_bind_start)
117	/*
118	 * Preserve caller-saved registers.
119	 */
120	subu	%r31, %r31, REG_SIZE
121	st.d	%r2,  %r31, 4 * 0
122	st.d	%r4,  %r31, 4 * 2
123	st.d	%r6,  %r31, 4 * 4
124	st.d	%r8,  %r31, 4 * 6
125	st	%r10, %r31, 4 * 8
126	st.d	%r12, %r31, 4 * 10
127
128	/*
129	 * Invoke resolver entry point.
130	 */
131	ld	%r2,  %r31, REG_SIZE + OBJECT_OFFSET
132	bsr.n	_dl_bind
133	 ld	%r3,  %r31, REG_SIZE + R11_OFFSET	| reloff
134
135	/*
136	 * Preserve return address.
137	 */
138	or	%r11, %r2,  %r0
139
140	/*
141	 * Restore caller-saved registers.
142	 */
143	ld.d	%r12, %r31, 4 * 10
144	ld	%r10, %r31, 4 * 8
145	ld.d	%r8,  %r31, 4 * 6
146	ld.d	%r6,  %r31, 4 * 4
147	ld.d	%r4,  %r31, 4 * 2
148	ld.d	%r2,  %r31, 4 * 0
149	ld	%r1,  %r31, REG_SIZE + R1_OFFSET
150
151	jmp.n	%r11
152	 addu	%r31, %r31, REG_SIZE + PLT_FRAME_SIZE
153
154/* ld.so SYSCALLS */
155
156#define DL_SYSCALL(n)	DL_SYSCALL2(n,n)
157#define DL_SYSCALL2(n,c)				\
158	__ENTRY(_dl_,n);				\
159	__DO_SYSCALL(c);				\
160	br	_dl_cerror
161
162#define DL_SYSCALL2_NOERR(n,c)				\
163	__ENTRY(_dl_,n);				\
164	__DO_SYSCALL(c)
165
166DL_SYSCALL(close)
167	jmp	%r1
168
169ENTRY(_dl_exit)
170	__DO_SYSCALL(exit)
1711:	br	1b
172
173DL_SYSCALL(issetugid)
174	jmp	%r1
175
176DL_SYSCALL2(_syscall,__syscall)
177	jmp	%r1
178
179DL_SYSCALL(munmap)
180	jmp	%r1
181
182DL_SYSCALL(mprotect)
183	jmp	%r1
184
185DL_SYSCALL(open)
186	jmp	%r1
187
188DL_SYSCALL(read)
189	jmp	%r1
190
191DL_SYSCALL(write)
192	jmp	%r1
193
194DL_SYSCALL(fstat)
195	jmp	%r1
196
197DL_SYSCALL(fcntl)
198	jmp	%r1
199
200DL_SYSCALL(gettimeofday)
201	jmp	%r1
202
203DL_SYSCALL(readlink)
204	jmp	%r1
205
206DL_SYSCALL(lstat)
207	jmp	%r1
208
209DL_SYSCALL(utrace)
210	jmp	%r1
211
212DL_SYSCALL2(getcwd,__getcwd)
213	jmp	%r1
214
215DL_SYSCALL2(sysctl,__sysctl)
216	jmp	%r1
217
218DL_SYSCALL(getdents)
219	jmp	%r1
220
221ENTRY(_dl_sigprocmask)
222	bcnd	ne0, %r3, 1f
223	or	%r2, %r0, 1		/* SIG_BLOCK */
224	br	2f
2251:
226	ld	%r3, %r3, 0
2272:
228	or	%r13, %r0, SYS_sigprocmask
229	tb0	0, %r0, 450
230	br	_dl_cerror
231	bcnd	eq0, %r4, 3f
232	st	%r2, %r4, 0
2333:
234	jmp.n	%r1
235	 or	%r2, %r0, 0
236END(_dl_sigprocmask)
237
238_dl_cerror:
239	jmp.n	%r1
240	 subu	%r2, %r0, 1
241
242ENTRY(_dl_cacheflush)
243	tb0	0, %r0, 451
244	br	_dl_cerror		| never hit
245	jmp	%r1
246END(_dl_cacheflush)
247