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