xref: /netbsd/sys/arch/hppa/hppa/fpemu.S (revision c4a72b64)
1/*	$NetBSD: fpemu.S,v 1.1 2002/06/05 01:04:20 fredette Exp $	*/
2
3/*	$OpenBSD: fpemu.S,v 1.4 2001/03/29 02:18:45 mickey Exp $	*/
4
5/*
6 * Copyright (c) 2000 Michael Shalayeff
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by Michael Shalayeff.
20 * 4. The name of the author may not be used to endorse or promote products
21 *    derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <machine/asm.h>
36#include "assym.h"
37
38#define	FPEMU_VERSION	(1 << 11)
39
40#define	FP_TABLE2(name, ep0, ep1, ep2, ep3) \
41	ldil	L%$fpemu_tbl$name, t1			! \
42	ldo	R%$fpemu_tbl$name(t1), t1		! \
43	ldwx,s	r1(t1), t2				! \
44	bv	r0(t2)					! \
45	nop						! \
46	.label $fpemu_tbl$name				! \
47	.import	__CONCAT(__CONCAT(ep0,_),name), code	! \
48	.import	__CONCAT(__CONCAT(ep1,_),name), code	! \
49	.import	__CONCAT(__CONCAT(ep2,_),name), code	! \
50	.import	__CONCAT(__CONCAT(ep3,_),name), code	! \
51	.word	__CONCAT(__CONCAT(ep0,_),name),	__CONCAT(__CONCAT(ep1,_),name),	__CONCAT(__CONCAT(ep2,_),name),	__CONCAT(__CONCAT(ep3,_),name)
52
53#define	FP_TABLE3(name,ep0,ep1,ep2,ep3,ep4,ep5,ep6,ep7,ep8,ep9,epa,epb,epc,epd,epe,epf) \
54	ldil	L%$fpemu_tbl$name, t1			! \
55	ldo	R%$fpemu_tbl$name(t1), t1		! \
56	ldwx,s	r1(t1), t2				! \
57	bv	r0(t2)					! \
58	nop						! \
59	.label	$fpemu_tbl$name				! \
60	.import	__CONCAT(__CONCAT(ep0,_),name), code	! \
61	.import	__CONCAT(__CONCAT(ep1,_),name), code	! \
62	.import	__CONCAT(__CONCAT(ep2,_),name), code	! \
63	.import	__CONCAT(__CONCAT(ep3,_),name), code	! \
64	.import	__CONCAT(__CONCAT(ep4,_),name), code	! \
65	.import	__CONCAT(__CONCAT(ep5,_),name), code	! \
66	.import	__CONCAT(__CONCAT(ep6,_),name), code	! \
67	.import	__CONCAT(__CONCAT(ep7,_),name), code	! \
68	.import	__CONCAT(__CONCAT(ep8,_),name), code	! \
69	.import	__CONCAT(__CONCAT(ep9,_),name), code	! \
70	.import	__CONCAT(__CONCAT(epa,_),name), code	! \
71	.import	__CONCAT(__CONCAT(epb,_),name), code	! \
72	.import	__CONCAT(__CONCAT(epc,_),name), code	! \
73	.import	__CONCAT(__CONCAT(epd,_),name), code	! \
74	.import	__CONCAT(__CONCAT(epe,_),name), code	! \
75	.import	__CONCAT(__CONCAT(epf,_),name), code	! \
76	.word	__CONCAT(__CONCAT(ep0,_),name),	__CONCAT(__CONCAT(ep1,_),name),	__CONCAT(__CONCAT(ep2,_),name), __CONCAT(__CONCAT(ep3,_),name), __CONCAT(__CONCAT(ep4,_),name), __CONCAT(__CONCAT(ep5,_),name), __CONCAT(__CONCAT(ep6,_),name), __CONCAT(__CONCAT(ep7,_),name), __CONCAT(__CONCAT(ep8,_),name), __CONCAT(__CONCAT(ep9,_),name), __CONCAT(__CONCAT(epa,_),name), __CONCAT(__CONCAT(epb,_),name), __CONCAT(__CONCAT(epc,_),name), __CONCAT(__CONCAT(epd,_),name), __CONCAT(__CONCAT(epe,_),name), __CONCAT(__CONCAT(epf,_),name)
77
78	.section .bss
79
80	.export	$fpemu_stack, data
81$fpemu_stack
82	.comm	NBPG
83
84	.text
85/*
86 * fpu_emulate(iir)
87 */
88LEAF_ENTRY(fpu_emulate)
89
90	extru	arg0, 22, 2, arg3
91	extru	arg0, 18, 3, r31
92	comib,=	1, arg3, $fpu_cln1
93	nop
94	extru	arg0, 16, 2, r31
95
96$fpu_cln1
97	/*
98	 * theoreticaly we would need to determine the fpu instruction
99	 * exception type (there could be 4 of those, but stick w/
100	 * non-timex fpus for now.
101	 */
102	ldi	1, ret0
103	extru,<> arg0, 10, 5, r1
104	ldi	32, r1	/* fpemu zero reg */
105	extru,<> arg0, 31, 5, t1
106	b,n	$fpemu_nzt
107	comib,=,n 2, arg3, $fpemu_exit
108$fpemu_nzt
109	copy	arg0, t4
110	sh3add	r1, arg2, arg0
111	extru	arg1, 20, 2, r1
112	sh3add	t1, arg2, arg1
113
114	/*
115	 * arg0 -- source register (address)
116	 * arg1 -- target register (address)
117	 * arg2 -- fpregs context
118	 * arg3 -- class
119	 * r31 -- subop
120	 * r1 -- format specifier
121	 * (t4 -- copy or arg0, ie iir)
122	 */
123	comib,=,n 0, arg3, $fpemu0c_0
124	comib,=,n 1, arg3, $fpemu0c_1
125	comib,=,n 2, arg3, $fpemu0c_2
126	comib,=,n 3, arg3, $fpemu0c_3
127
128$fpemu0c_0
129	comib,=,n 0, r31, $fpemu0c_0_0
130	comib,=,n 1, r31, $fpemu_exit
131	comib,=,n 2, r31, $fpemu0c_0_2
132	comib,=,n 3, r31, $fpemu0c_0_3
133	comib,=,n 4, r31, $fpemu0c_0_4
134	comib,=,n 5, r31, $fpemu0c_0_5
135	comib,=,n 6, r31, $fpemu_exit
136	comib,=,n 7, r31, $fpemu_exit
137
138$fpemu0c_0_0
139	ldi	FPEMU_VERSION, t4
140	stw	t4, 0(arg2)
141	bv	0(rp)
142	copy	r0, ret0
143
144$fpemu0c_0_2	/* fcpy */
145	comib,=,n 2, r1, $fpemu_exit
146	subi	3, r1, r1
147	ldw	0*4(arg0), t1
148	ldw	1*4(arg0), t2
149	ldw	2*4(arg0), t3
150	ldw	3*4(arg0), t4
151	blr,n	r1, r0
152	nop
153	stw	t3, 2*4(arg1)
154	stw	t4, 3*4(arg1)
155	stw	t2, 1*4(arg1)
156	nop
157	nop
158	nop
159	stw	t1, 0*4(arg1)
160	bv	0(rp)
161	copy	r0, ret0
162
163$fpemu0c_0_3	/* fabs */
164	comib,=,n 2, r1, $fpemu_exit
165	subi	3, r1, r1
166	ldw	0*4(arg0), t1
167	ldw	1*4(arg0), t2
168	ldw	2*4(arg0), t3
169	ldw	3*4(arg0), t4
170	depi	0, 0, 1, t1
171	blr,n	r1, r0
172	nop
173	stw	t3, 2*4(arg1)
174	stw	t4, 3*4(arg1)
175	stw	t2, 1*4(arg1)
176	nop
177	nop
178	nop
179	stw	t1, 0*4(arg1)
180	bv	0(rp)
181	copy	r0, ret0
182
183$fpemu0c_0_4	/* fsqrt */
184	/* quad not implemented */
185	FP_TABLE2(fsqrt,sgl,dbl,invalid,invalid)
186
187$fpemu0c_0_5	/* frnd */
188	/* quad not implemented */
189	FP_TABLE2(frnd,sgl,dbl,invalid,quad)
190
191$fpemu0c_1
192	extru	t4, 18, 2, t2
193	sh2add	r1, t2, r1
194	comib,=,n 0, r31, $fpemu0c_1_0
195	comib,=,n 1, r31, $fpemu0c_1_1
196	comib,=,n 2, r31, $fpemu0c_1_2
197	comib,=,n 3, r31, $fpemu0c_1_3
198
199$fpemu0c_1_0	/* fcnvff */
200#define	sgl_to_quad_fcnvff	invalid_fcnvff
201#define	dbl_to_quad_fcnvff	invalid_fcnvff
202#define	quad_to_sgl_fcnvff	invalid_fcnvff
203#define	quad_to_dbl_fcnvff	invalid_fcnvff
204	FP_TABLE3(fcnvff, invalid, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, invalid, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, invalid)
205
206$fpemu0c_1_1	/* fcnvxf */
207#define	sgl_to_quad_fcnvxf	invalid_fcnvxf
208#define	dbl_to_quad_fcnvxf	invalid_fcnvxf
209#define	quad_to_sgl_fcnvxf	invalid_fcnvxf
210#define	quad_to_dbl_fcnvxf	invalid_fcnvxf
211#define	quad_to_quad_fcnvxf	invalid_fcnvxf
212	FP_TABLE3(fcnvxf, sgl_to_sgl, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, dbl_to_dbl, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, quad_to_quad)
213
214$fpemu0c_1_2	/* fcnvfx */
215#define	sgl_to_quad_fcnvfx	invalid_fcnvfx
216#define	dbl_to_quad_fcnvfx	invalid_fcnvfx
217#define	quad_to_sgl_fcnvfx	invalid_fcnvfx
218#define	quad_to_dbl_fcnvfx	invalid_fcnvfx
219#define	quad_to_quad_fcnvfx	invalid_fcnvfx
220	FP_TABLE3(fcnvfx, sgl_to_sgl, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, dbl_to_dbl, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, quad_to_quad)
221
222$fpemu0c_1_3	/* fcnvfxt */
223#define	sgl_to_quad_fcnvfxt	invalid_fcnvfxt
224#define	dbl_to_quad_fcnvfxt	invalid_fcnvfxt
225#define	quad_to_sgl_fcnvfxt	invalid_fcnvfxt
226#define	quad_to_dbl_fcnvfxt	invalid_fcnvfxt
227#define	quad_to_quad_fcnvfxt	invalid_fcnvfxt
228	FP_TABLE3(fcnvfxt, sgl_to_sgl, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, dbl_to_dbl, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, quad_to_quad)
229
230
231$fpemu0c_2
232	comib,=,n 0, r31, $fpemu0c_2_0
233	comib,=,n 1, r31, $fpemu0c_2_1
234	comib,=,n 2, r31, $fpemu_exit
235	comib,=,n 3, r31, $fpemu_exit
236	comib,=,n 4, r31, $fpemu_exit
237	comib,=,n 5, r31, $fpemu_exit
238	comib,=,n 6, r31, $fpemu_exit
239	comib,=,n 7, r31, $fpemu_exit
240
241$fpemu0c_2_0
242	copy	arg2, arg3
243	extru,<> t4, 15, 5, t1
244	ldi	32, t1
245	sh3add	t1, arg3, arg1
246	extru	t4, 31, 5, arg2
247	FP_TABLE2(fcmp,sgl,dbl,invalid,invalid)
248
249$fpemu0c_2_1
250	comib,<>,n 0, r1, $fpemu_exit
251
252	/* extru	t4, 31, 5, arg1 */
253	/* XXX timex is much more compilicated */
254	ldw	0(arg2), t1
255	ldi	0, ret0
256	extru,<> t1, 5, 1, r0
257	bv,n	r0(rp)
258
259	/* advance the pcqueue */
260	mtctl	r0, pcsq
261	mfctl	pcsq, t2
262	mtctl	t2, pcsq
263	mtctl	t2, pcsq
264	mtctl	r0, pcoq
265	mfctl	pcoq, t2
266	mtctl	t2, pcoq
267	ldo	4(t2), t2
268	bv	r0(rp)
269	mtctl	t2, pcoq
270
271$fpemu0c_3
272	copy	arg2, arg3
273	extru,<> t4, 31, 5, t1
274	ldi	32, t1
275	sh3add	t1, arg3, arg2
276
277	comib,=,n 0, r31, $fpemu0c_3_0
278	comib,=,n 1, r31, $fpemu0c_3_1
279	comib,=,n 2, r31, $fpemu0c_3_2
280	comib,=,n 3, r31, $fpemu0c_3_3
281	comib,=,n 4, r31, $fpemu0c_3_4
282	comib,=,n 5, r31, $fpemu_exit
283	comib,=,n 6, r31, $fpemu_exit
284	comib,=,n 7, r31, $fpemu_exit
285
286$fpemu0c_3_0	/* fadd */
287	FP_TABLE2(fadd,sgl,dbl,invalid,invalid)
288
289$fpemu0c_3_1	/* fsub */
290	FP_TABLE2(fsub,sgl,dbl,invalid,invalid)
291
292$fpemu0c_3_2	/* fmpy */
293	FP_TABLE2(fmpy,sgl,dbl,invalid,invalid)
294
295$fpemu0c_3_3	/* fdiv */
296	FP_TABLE2(fdiv,sgl,dbl,invalid,invalid)
297
298$fpemu0c_3_4	/* frem */
299	FP_TABLE2(frem,sgl,dbl,invalid,invalid)
300
301	.export	$fpemu_exit, code
302$fpemu_exit
303	/* these look very ugly, but we don't want to mess up w/ m4 just
304	 * for the sake of overall world prettieness value growth XXX */
305invalid_fsqrt
306invalid_frnd
307invalid_fcnvff
308invalid_fcnvxf
309invalid_fcnvfx
310invalid_fcnvfxt
311invalid_fcmp
312invalid_fadd
313invalid_fsub
314invalid_fmpy
315invalid_fdiv
316invalid_frem
317	bv,n	0(rp)
318EXIT(fpu_emulate)
319
320
321	.end
322
323