xref: /openbsd/libexec/ld.so/m88k/ldasm.S (revision d7a24b57)
1*d7a24b57Sguenther/*	$OpenBSD: ldasm.S,v 1.29 2019/02/03 02:20:36 guenther Exp $	*/
2d3d281f4Smiod
3d3d281f4Smiod/*
4d3d281f4Smiod * Copyright (c) 2013 Miodrag Vallat.
5d3d281f4Smiod *
6d3d281f4Smiod * Permission to use, copy, modify, and distribute this software for any
7d3d281f4Smiod * purpose with or without fee is hereby granted, provided that the above
8d3d281f4Smiod * copyright notice and this permission notice appear in all copies.
9d3d281f4Smiod *
10d3d281f4Smiod * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11d3d281f4Smiod * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12d3d281f4Smiod * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13d3d281f4Smiod * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14d3d281f4Smiod * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15d3d281f4Smiod * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16d3d281f4Smiod * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17d3d281f4Smiod */
18d3d281f4Smiod/*
19d3d281f4Smiod * Copyright (c) 2006 Dale Rahn
20d3d281f4Smiod *
21d3d281f4Smiod * Redistribution and use in source and binary forms, with or without
22d3d281f4Smiod * modification, are permitted provided that the following conditions
23d3d281f4Smiod * are met:
24d3d281f4Smiod * 1. Redistributions of source code must retain the above copyright
25d3d281f4Smiod *    notice, this list of conditions and the following disclaimer.
26d3d281f4Smiod * 2. Redistributions in binary form must reproduce the above copyright
27d3d281f4Smiod *    notice, this list of conditions and the following disclaimer in the
28d3d281f4Smiod *    documentation and/or other materials provided with the distribution.
29d3d281f4Smiod *
30d3d281f4Smiod * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
31d3d281f4Smiod * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32d3d281f4Smiod * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33d3d281f4Smiod * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
34d3d281f4Smiod * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35d3d281f4Smiod * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36d3d281f4Smiod * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37d3d281f4Smiod * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38d3d281f4Smiod * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39d3d281f4Smiod * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40d3d281f4Smiod * SUCH DAMAGE.
41d3d281f4Smiod *
42d3d281f4Smiod */
43d3d281f4Smiod
44d3d281f4Smiod#include <machine/asm.h>
45d3d281f4Smiod#include <sys/syscall.h>
46d3d281f4Smiod
47043a04f9Sguenther#define	AUX_base	7
48043a04f9Sguenther#define	AUX_entry	9
49043a04f9Sguenther
50d3d281f4Smiod/*
51d3d281f4Smiod * ld.so entry point.
52d3d281f4Smiod * On entry: r31 points to the kernel argument struct (argv, argv, environ).
53d3d281f4Smiod * The environment pointers list is followed by an array of AuxInfo
54d3d281f4Smiod * structs filled by the kernel.
55d3d281f4Smiod */
56d3d281f4SmiodENTRY(_dl_start)
57d3d281f4Smiod	/*
58d3d281f4Smiod	 * Two nop because execution may skip up to two instructions.
59d3d281f4Smiod	 * See setregs() in the kernel for details.
60d3d281f4Smiod	 *
61d3d281f4Smiod	 * Note that I have been hacking m88k for years and still fall
62d3d281f4Smiod	 * into this trap, every time. -- miod
63d3d281f4Smiod	 */
64d3d281f4Smiod	or	%r0,  %r0,  %r0
65d3d281f4Smiod	or	%r0,  %r0,  %r0
66d3d281f4Smiod
67d3d281f4Smiod	/*
68d3d281f4Smiod	 * Get some room for the contiguous AUX pointers array.
69d3d281f4Smiod	  */
70d3d281f4Smiod	or	%r30, %r31, 0
71043a04f9Sguenther	subu	%r31, %r31, (4 * (AUX_entry + 1))
72043a04f9Sguenther
73043a04f9Sguenther	/*
74043a04f9Sguenther	 * Align the stack to a 16 byte boundary.
75043a04f9Sguenther	 */
76043a04f9Sguenther	clr	%r31, %r31, 4<0>
77d3d281f4Smiod
78d3d281f4Smiod	/*
79d3d281f4Smiod	 * Invoke _dl_boot_bind
80d3d281f4Smiod	 */
81d3d281f4Smiod	or	%r2,  %r30, 0		| kernel args
82d3d281f4Smiod	or	%r3,  %r31, 0		| array base
83d3d281f4Smiod	bsr	1f			| the following instruction is skipped
841058c092Sguenther	bsr	_DYNAMIC		| but gives us the pc-relative offset
851058c092Sguenther1:	ld	%r6, %r1, 0		| fetch branch instruction
861058c092Sguenther	mak	%r5, %r6, 26<2>		| pick branch offset and shift left by 2
871058c092Sguenther	addu	%r4, %r5, %r1
88d3d281f4Smiod	bsr	_dl_boot_bind
89d3d281f4Smiod
90d3d281f4Smiod	ld	%r2,  %r30, 0		| argc
91d3d281f4Smiod	addu	%r6,  %r30, 4 + 4
92d3d281f4Smiod	lda	%r3,  %r6[%r2]		| envp
93043a04f9Sguenther	ld	%r4,  %r31, 4 * AUX_base| ldoff
94d3d281f4Smiod	or	%r5,  %r31, 0		| array base
95d3d281f4Smiod	bsr.n	_dl_boot
96d3d281f4Smiod	 addu	%r2,  %r30, 4		| argv
97d3d281f4Smiod
98043a04f9Sguenther	or	%r31, %r30, 0
999408922dSmiod	bsr	1f			| the following instruction is skipped
1009408922dSmiod	bcnd	eq0, %r0, _dl_dtors	| but gives us the pc-relative offset
101441804d4Saoyama1:	ld.h	%r5, %r1, 2		| fetch branch offset (low 16 bits)
102a4ce9818Smiod	jmp.n	%r2
1039408922dSmiod	 lda	%r5, %r1[%r5]		| cleanup
104d3d281f4SmiodEND(_dl_start)
105d3d281f4Smiod
106d3d281f4Smiod/*
107d3d281f4Smiod * PLT resolver entry point.
108d3d281f4Smiod * Invoked with the following stack frame:
109d3d281f4Smiod *	r31(0x00)	zero
110d3d281f4Smiod *	r31(0x04)	ELF object
111d3d281f4Smiod *	r31(0x08)	saved r11
112d3d281f4Smiod *	r31(0x0c)	saved r1
113d3d281f4Smiod * All registers but r1 and r11 must be preserved. The resolver must return
114d3d281f4Smiod * to the resolved address with r1 restored.
115d3d281f4Smiod */
116d3d281f4Smiod#define	OBJECT_OFFSET	(4 * 1)
117d3d281f4Smiod#define	R11_OFFSET	(4 * 2)
118d3d281f4Smiod#define	R1_OFFSET	(4 * 3)
119d3d281f4Smiod#define	PLT_FRAME_SIZE	(4 * 4)
120d3d281f4Smiod#define REG_SIZE	(4 * 12)
121d3d281f4SmiodENTRY(_dl_bind_start)
122d3d281f4Smiod	/*
123d3d281f4Smiod	 * Preserve caller-saved registers.
124d3d281f4Smiod	 */
125d3d281f4Smiod	subu	%r31, %r31, REG_SIZE
126a4ce9818Smiod	st.d	%r2,  %r31, 4 * 0
127a4ce9818Smiod	st.d	%r4,  %r31, 4 * 2
128a4ce9818Smiod	st.d	%r6,  %r31, 4 * 4
129a4ce9818Smiod	st.d	%r8,  %r31, 4 * 6
130d3d281f4Smiod	st	%r10, %r31, 4 * 8
131a4ce9818Smiod	st.d	%r12, %r31, 4 * 10
132d3d281f4Smiod
133d3d281f4Smiod	/*
134d3d281f4Smiod	 * Invoke resolver entry point.
135d3d281f4Smiod	 */
136d3d281f4Smiod	ld	%r2,  %r31, REG_SIZE + OBJECT_OFFSET
137d3d281f4Smiod	bsr.n	_dl_bind
138d3d281f4Smiod	 ld	%r3,  %r31, REG_SIZE + R11_OFFSET	| reloff
139d3d281f4Smiod
140d3d281f4Smiod	/*
141d3d281f4Smiod	 * Preserve return address.
142d3d281f4Smiod	 */
143d3d281f4Smiod	or	%r11, %r2,  %r0
144d3d281f4Smiod
145d3d281f4Smiod	/*
146d3d281f4Smiod	 * Restore caller-saved registers.
147d3d281f4Smiod	 */
148a4ce9818Smiod	ld.d	%r12, %r31, 4 * 10
149d3d281f4Smiod	ld	%r10, %r31, 4 * 8
150a4ce9818Smiod	ld.d	%r8,  %r31, 4 * 6
151a4ce9818Smiod	ld.d	%r6,  %r31, 4 * 4
152a4ce9818Smiod	ld.d	%r4,  %r31, 4 * 2
153a4ce9818Smiod	ld.d	%r2,  %r31, 4 * 0
154d3d281f4Smiod	ld	%r1,  %r31, REG_SIZE + R1_OFFSET
155d3d281f4Smiod
156a4ce9818Smiod	jmp.n	%r11
157d3d281f4Smiod	 addu	%r31, %r31, REG_SIZE + PLT_FRAME_SIZE
1584307ecf1SguentherEND(_dl_bind_start)
159d3d281f4Smiod
160c99d8a85SmiodENTRY(_dl_cacheflush)
161c99d8a85Smiod	tb0	0, %r0, 451
162*d7a24b57Sguenther	or	%r0, %r0, %r0				| never hit
163c99d8a85Smiod	jmp	%r1
164c99d8a85SmiodEND(_dl_cacheflush)
165