1/*
2 * fp_emu.S
3 *
4 * Copyright Roman Zippel, 1997.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, and the entire permission notice in its entirety,
11 *    including the disclaimer of warranties.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 *    products derived from this software without specific prior
17 *    written permission.
18 *
19 * ALTERNATIVELY, this product may be distributed under the terms of
20 * the GNU General Public License, in which case the provisions of the GPL are
21 * required INSTEAD OF the above restrictions.  (This clause is
22 * necessary due to a potential bad interaction between the GPL and
23 * the restrictions contained in a BSD-style copyright.)
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <linux/config.h>
39#include <linux/linkage.h>
40#include <asm/entry.h>
41
42#include "fp_emu.h"
43
44	.globl	SYMBOL_NAME(fpu_emu)
45	.globl	fp_debugprint
46	.globl	fp_err_ua1,fp_err_ua2
47
48	.text
49SYMBOL_NAME_LABEL(fpu_emu)
50	SAVE_ALL_INT
51	GET_CURRENT(%d0)
52
53#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
54        tst.l	SYMBOL_NAME(m68k_is040or060)
55        jeq	1f
56#endif
57#if defined(CPU_M68040_OR_M68060)
58	move.l	(FPS_PC2,%sp),(FPS_PC,%sp)
59#endif
601:
61	| emulate the instruction
62	jsr	fp_scan
63
64#if defined(CONFIG_M68060)
65#if !defined(CPU_M68060_ONLY)
66	btst	#3,SYMBOL_NAME(m68k_cputype)+3
67	jeq	1f
68#endif
69	btst	#7,(FPS_SR,%sp)
70	jne	fp_sendtrace060
71#endif
721:
73	| emulation successful?
74	tst.l	%d0
75	jeq	SYMBOL_NAME(ret_from_exception)
76
77	| send some signal to program here
78
79	jra	SYMBOL_NAME(ret_from_exception)
80
81	| we jump here after an access error while trying to access
82	| user space, we correct stackpointer and send a SIGSEGV to
83	| the user process
84fp_err_ua2:
85	addq.l	#4,%sp
86fp_err_ua1:
87	addq.l	#4,%sp
88	move.l	%a0,-(%sp)
89	pea	SEGV_MAPERR
90	pea	SIGSEGV
91	jsr	SYMBOL_NAME(fpemu_signal)
92	add.w	#12,%sp
93	jra	SYMBOL_NAME(ret_from_exception)
94
95#if defined(CONFIG_M68060)
96	| send a trace signal if we are debugged
97	| it does not really belong here, but...
98fp_sendtrace060:
99	move.l	(FPS_PC,%sp),-(%sp)
100	pea	TRAP_TRACE
101	pea	SIGTRAP
102	jsr	SYMBOL_NAME(fpemu_signal)
103	add.w	#12,%sp
104	jra	SYMBOL_NAME(ret_from_exception)
105#endif
106
107	.globl	fp_get_data_reg, fp_put_data_reg
108	.globl	fp_get_addr_reg, fp_put_addr_reg
109
110	| Entry points to get/put a register. Some of them can be get/put
111	| directly, others are on the stack, as we read/write the stack
112	| directly here, these function may only be called from within
113	| instruction decoding, otherwise the stack pointer is incorrect
114	| and the stack gets corrupted.
115fp_get_data_reg:
116	jmp	([0f:w,%pc,%d0.w*4])
117
118	.align	4
1190:
120	.long	fp_get_d0, fp_get_d1
121	.long	fp_get_d2, fp_get_d3
122	.long	fp_get_d4, fp_get_d5
123	.long	fp_get_d6, fp_get_d7
124
125fp_get_d0:
126	move.l	(PT_D0+8,%sp),%d0
127	printf	PREGISTER,"{d0->%08x}",1,%d0
128	rts
129
130fp_get_d1:
131	move.l	(PT_D1+8,%sp),%d0
132	printf	PREGISTER,"{d1->%08x}",1,%d0
133	rts
134
135fp_get_d2:
136	move.l	(PT_D2+8,%sp),%d0
137	printf	PREGISTER,"{d2->%08x}",1,%d0
138	rts
139
140fp_get_d3:
141	move.l	%d3,%d0
142	printf	PREGISTER,"{d3->%08x}",1,%d0
143	rts
144
145fp_get_d4:
146	move.l	%d4,%d0
147	printf	PREGISTER,"{d4->%08x}",1,%d0
148	rts
149
150fp_get_d5:
151	move.l	%d5,%d0
152	printf	PREGISTER,"{d5->%08x}",1,%d0
153	rts
154
155fp_get_d6:
156	move.l	%d6,%d0
157	printf	PREGISTER,"{d6->%08x}",1,%d0
158	rts
159
160fp_get_d7:
161	move.l	%d7,%d0
162	printf	PREGISTER,"{d7->%08x}",1,%d0
163	rts
164
165fp_put_data_reg:
166	jmp	([0f:w,%pc,%d1.w*4])
167
168	.align	4
1690:
170	.long	fp_put_d0, fp_put_d1
171	.long	fp_put_d2, fp_put_d3
172	.long	fp_put_d4, fp_put_d5
173	.long	fp_put_d6, fp_put_d7
174
175fp_put_d0:
176	printf	PREGISTER,"{d0<-%08x}",1,%d0
177	move.l	%d0,(PT_D0+8,%sp)
178	rts
179
180fp_put_d1:
181	printf	PREGISTER,"{d1<-%08x}",1,%d0
182	move.l	%d0,(PT_D1+8,%sp)
183	rts
184
185fp_put_d2:
186	printf	PREGISTER,"{d2<-%08x}",1,%d0
187	move.l	%d0,(PT_D2+8,%sp)
188	rts
189
190fp_put_d3:
191	printf	PREGISTER,"{d3<-%08x}",1,%d0
192|	move.l	%d0,%d3
193	move.l	%d0,(PT_D3+8,%sp)
194	rts
195
196fp_put_d4:
197	printf	PREGISTER,"{d4<-%08x}",1,%d0
198|	move.l	%d0,%d4
199	move.l	%d0,(PT_D4+8,%sp)
200	rts
201
202fp_put_d5:
203	printf	PREGISTER,"{d5<-%08x}",1,%d0
204|	move.l	%d0,%d5
205	move.l	%d0,(PT_D5+8,%sp)
206	rts
207
208fp_put_d6:
209	printf	PREGISTER,"{d6<-%08x}",1,%d0
210	move.l	%d0,%d6
211	rts
212
213fp_put_d7:
214	printf	PREGISTER,"{d7<-%08x}",1,%d0
215	move.l	%d0,%d7
216	rts
217
218fp_get_addr_reg:
219	jmp	([0f:w,%pc,%d0.w*4])
220
221	.align	4
2220:
223	.long	fp_get_a0, fp_get_a1
224	.long	fp_get_a2, fp_get_a3
225	.long	fp_get_a4, fp_get_a5
226	.long	fp_get_a6, fp_get_a7
227
228fp_get_a0:
229	move.l	(PT_A0+8,%sp),%a0
230	printf	PREGISTER,"{a0->%08x}",1,%a0
231	rts
232
233fp_get_a1:
234	move.l	(PT_A1+8,%sp),%a0
235	printf	PREGISTER,"{a1->%08x}",1,%a0
236	rts
237
238fp_get_a2:
239	move.l	(PT_A2+8,%sp),%a0
240	printf	PREGISTER,"{a2->%08x}",1,%a0
241	rts
242
243fp_get_a3:
244	move.l	%a3,%a0
245	printf	PREGISTER,"{a3->%08x}",1,%a0
246	rts
247
248fp_get_a4:
249	move.l	%a4,%a0
250	printf	PREGISTER,"{a4->%08x}",1,%a0
251	rts
252
253fp_get_a5:
254	move.l	%a5,%a0
255	printf	PREGISTER,"{a5->%08x}",1,%a0
256	rts
257
258fp_get_a6:
259	move.l	%a6,%a0
260	printf	PREGISTER,"{a6->%08x}",1,%a0
261	rts
262
263fp_get_a7:
264	move.l	%usp,%a0
265	printf	PREGISTER,"{a7->%08x}",1,%a0
266	rts
267
268fp_put_addr_reg:
269	jmp	([0f:w,%pc,%d0.w*4])
270
271	.align	4
2720:
273	.long	fp_put_a0, fp_put_a1
274	.long	fp_put_a2, fp_put_a3
275	.long	fp_put_a4, fp_put_a5
276	.long	fp_put_a6, fp_put_a7
277
278fp_put_a0:
279	printf	PREGISTER,"{a0<-%08x}",1,%a0
280	move.l	%a0,(PT_A0+8,%sp)
281	rts
282
283fp_put_a1:
284	printf	PREGISTER,"{a1<-%08x}",1,%a0
285	move.l	%a0,(PT_A1+8,%sp)
286	rts
287
288fp_put_a2:
289	printf	PREGISTER,"{a2<-%08x}",1,%a0
290	move.l	%a0,(PT_A2+8,%sp)
291	rts
292
293fp_put_a3:
294	printf	PREGISTER,"{a3<-%08x}",1,%a0
295	move.l	%a0,%a3
296	rts
297
298fp_put_a4:
299	printf	PREGISTER,"{a4<-%08x}",1,%a0
300	move.l	%a0,%a4
301	rts
302
303fp_put_a5:
304	printf	PREGISTER,"{a5<-%08x}",1,%a0
305	move.l	%a0,%a5
306	rts
307
308fp_put_a6:
309	printf	PREGISTER,"{a6<-%08x}",1,%a0
310	move.l	%a0,%a6
311	rts
312
313fp_put_a7:
314	printf	PREGISTER,"{a7<-%08x}",1,%a0
315	move.l	%a0,%usp
316	rts
317
318	.data
319	.align	4
320
321fp_debugprint:
322|	.long	PMDECODE
323	.long	PMINSTR+PMDECODE+PMCONV+PMNORM
324|	.long	PMCONV+PMNORM+PMINSTR
325|	.long	0
326