xref: /onnv-gate/usr/src/cmd/fps/fptest/fpu_test64.s (revision 7186:e728311aafb0)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * Usage of %ncc
31 *
32 * When the branch instructions were modified from Bicc to BPcc format,
33 * the pseudo-op %ncc was used. This will be converted by the assembler
34 * to %icc or %xcc depending on whether the compilation is being done
35 * for 32-bit or 64-bit platforms.
36 */
37
38
39#include<sys/asm_linkage.h>
40
41/*
42 * ------------------------------------------------------------------------
43 *  Name:        datap_add()
44 * Function:	This routine test the data path of the adder for single
45 * 		precision.
46 * Calling:	i0 = value
47 * Returns:
48 * Convention:
49 * --------------------------------------------------------------------------
50 *
51 *		f0 = value
52 *		f1 = 0
53 *	add =   f2 = value
54 */
55
56#ifdef __lint
57
58/*ARGSUSED*/
59unsigned long
60datap_add(unsigned long arg1)
61{
62	return (0);
63}
64
65#else
66
67.section        ".data"
68.align  4
69
70.Ldadd:
71        .skip   4
72.Ldadd1:
73        .skip   4
74
75ENTRY_NP(datap_add)
76	save    %sp, -SA(MINFRAME), %sp	! save the stack frame
77	setn	.Ldadd,%l6,%l0	! get a memory address
78	setn    .Ldadd1,%l6,%l1 ! .. one for the result
79	mov     %g0,%l3         ! .. get a zero
80	st      %l3, [%l1]      ! .... and store it in memory
81	st	%i0, [%l0]	! .... store the value passed
82	ld	[%l0], %f0	! .... put the passed value into f0
83	ld	[%l1], %f1	! .... put value 0 into reg f1
84	fadds   %f0, %f1, %f2   ! ...... add zero and value into f2
85	fcmps	%fcc0, %f0, %f2	! .... check the value passed and added value
86	fbe,a	%fcc0, datap_ok	! .. if they are equal
87	nop			! .... delay
88
89	st	%f2, [%l1]	! return the result on error
90
91datap_ok:
92	ld	[%l1], %i0	! then return a zero
93	ret			! .... delay
94	restore
95SET_SIZE(datap_add)
96
97#endif
98
99/*
100 * ------------------------------------------------------------------------
101 * Name:
102 * Function:
103 * Calling:
104 * Returns:
105 * Convention:
106 * --------------------------------------------------------------------------
107 *
108 * This routine test the data path of multiplier for single precision
109 *             f0 = value
110 *             f1 = 1
111 *     mult =  f2 = f0 * f1
112 */
113
114#ifdef __lint
115
116/*ARGSUSED*/
117unsigned long
118datap_mult(unsigned long arg1)
119{
120	return (0);
121}
122
123#else
124
125.section        ".data"
126.align  4
127
128.Ldtmlt:
129        .skip   4
130.Ldtmlt1:
131        .skip   4
132
133ENTRY_NP(datap_mult)
134	save    %sp, -SA(MINFRAME), %sp
135        setn    .Ldtmlt,%l6,%l0
136        setn    .Ldtmlt1,%l6,%l1
137        setn    0x3F800000,%l6,%l3      ! put value 1 into memory
138	st      %l3, [%l1]
139        st      %i0, [%l0]      ! store the value passed into memory location
140        ld      [%l0], %f0      ! put the passed value into f0
141        ld      [%l1], %f1      ! put value 1 into reg f1
142        fmuls   %f0, %f1, %f2	! multiply value with 1 , it has to be same
143	fcmps   %fcc0, %f0, %f2
144
145	fbne,a	%fcc0, datap_mult_done
146	st	%f2, [%l1]	! executed only when the conditional
147				! branch is taken as annul bit is set.
148				! This branch will be taken under
149				! an error condition (%f0 != %f2).
150				! Then we need to return the result.
151
152	mov	%g0,%l3
153	st	%l3, [%l1]
154
155datap_mult_done :
156	ld	[%l1], %i0
157	ret
158	restore
159SET_SIZE(datap_mult)
160
161#endif
162
163/*
164 * ------------------------------------------------------------------------
165 * Name:
166 * Function:
167 * Calling:
168 * Returns:
169 * Convention:
170 * --------------------------------------------------------------------------
171 *
172 *	This routine tests the data path of the weitek multiplier for
173 *	double precision. Single-precision load and store are being
174 *      used as the input double-precision value is taken as two SP
175 *      arguments
176 *
177 *              f0 = msw value
178 *		f1 = lsw value
179 *
180 *		f2 = 0
181 *		f3 = 0
182 *	add =   f4 = f0 + f2
183 */
184
185#ifdef __lint
186
187/*ARGSUSED*/
188unsigned long
189datap_add_dp(unsigned long arg1, unsigned long arg2)
190{
191	return (0);
192}
193
194#else
195
196.section        ".data"
197.align  8
198
199.Ldtadddp:
200        .skip   8
201.Ldtadddp1:
202        .skip   8
203.Ldtadddp2:
204        .skip   8
205.Lamsw:
206        .skip   8
207.Lalsw:
208        .skip   8
209
210ENTRY_NP(datap_add_dp)
211	save    %sp, -SA(MINFRAME), %sp
212        setn    .Ldtadddp,%l6,%l0
213        setn    .Ldtadddp1,%l6,%l1
214	setn	.Ldtadddp2,%l6,%l2
215	setn	.Lamsw,%l6,%l4
216	setn	.Lalsw,%l6,%l5
217	mov	%g0,%l3	! put value 0 into memory
218        st      %l3, [%l1]
219	st	%i0, [%l0]	! msw of value
220        st	%i1, [%l2]	! lsw of value
221	ld	[%l0], %f0	! put the msw into f0
222	ld	[%l2], %f1	! put the lsw into f1
223	ld	[%l1], %f2	! put 0 into f2
224	ld	[%l1], %f3	! put 0 into f3
225	faddd   %f0, %f2, %f4	! add value + 0 into f4
226	fcmpd   %fcc0, %f0, %f4	! now compare the result
227
228	fbe,a	%fcc0, datap_add_dp_ok	! good
229	nop
230
231	mov	0x1,%l3
232	st	%l3, [%l1]
233
234datap_add_dp_ok :
235	ld	[%l1], %i0
236	ret
237	restore
238
239SET_SIZE(datap_add_dp)
240
241#endif
242
243/*
244 * ------------------------------------------------------------------------
245 * Name:
246 * Function:
247 * Calling:
248 * Returns:
249 * Convention:
250 *
251 * This routine tests the data path of the weitek multiplier for
252 * double precision. Single-precision load and store are being
253 * used as the input double-precision value is taken as two SP
254 * arguments.
255 *
256 *             f0 = msw value
257 *             f1 = lsw value
258 *             f2 = 0
259 *             f3 = 0
260 *	mult = f4 = f0 * f2
261 * ------------------------------------------------------------------------
262 */
263
264#ifdef __lint
265
266/*ARGSUSED*/
267unsigned long
268datap_mult_dp(unsigned long arg1, unsigned long arg2)
269{
270	return (0);
271}
272
273#else
274
275.section        ".data"
276.align  8
277
278.Ldtmdp:
279        .skip   8
280.Ldtmdp1:
281        .skip   8
282.Ldtmdp2:
283        .skip   8
284.Lmmsw:
285        .skip   8
286.Lmlsw:
287        .skip   8
288
289ENTRY_NP(datap_mult_dp)
290	save    %sp, -SA(MINFRAME), %sp
291        setn    .Ldtmdp,%l6,%l0
292        setn    .Ldtmdp1,%l6,%l1
293        setn    .Ldtmdp2,%l6,%l2
294        setn    .Lmmsw,%l6,%l4
295	setn	.Lmlsw,%l6,%l5
296        setn    0x3FF00000,%l6,%l3 ! put msw value  of DP 1  into memory
297        st      %l3, [%l1]
298        st      %i0, [%l0]      ! msw of value
299        st      %i1, [%l2]      ! lsw of value
300        ld      [%l0], %f0      ! put the msw into f0
301        ld      [%l2], %f1      ! put the lsw into f1
302        ld      [%l1], %f2      ! put msw of DP 1 into f2
303	mov	%g0,%l3
304	st	%l3, [%l1]
305        ld      [%l1], %f3	! put 0 into f3, i.e f2|f3 = 0x3ff0000000000000 (dp 1)
306	fmuld	%f0, %f2, %f4   ! mult value * 1 into f4
307	fcmpd   %fcc0, %f0, %f4	! now compare the result
308
309        fbe,a     %fcc0, datap_mult_dp_ok        ! good
310	nop
311
312        mov     0x1,%l3
313        st      %l3, [%l1]
314
315datap_mult_dp_ok :
316	ld	[%l1], %i0
317	ret
318	restore
319
320SET_SIZE(datap_mult_dp)
321
322#endif
323
324/*
325 * -------------------------------------------------------------------------
326 * for add routine all the f registers from 0 - 19 will be filled with numbers
327 * and the result should be 10.
328 * -------------------------------------------------------------------------
329 */
330
331#ifdef __lint
332
333unsigned long
334timing_add_sp()
335{
336	return (0);
337}
338
339#else
340
341.section        ".data"
342.align  4
343
344.Ltmasp:
345        .skip   4
346.Ltmasp1:
347        .skip   4
348.Ltmasp2:
349        .skip   4
350
351ENTRY_NP(timing_add_sp)
352	save    %sp, -SA(MINFRAME), %sp		! save the registers, stacck
353        setn    .Ltmasp,%l6,%l0
354	setn	.Ltmasp1,%l6,%l1
355	setn	.Ltmasp2,%l6,%l2
356	mov	%g0,%l3
357	setn    0x3f800000,%l6,%l4 	! put value 1
358	setn	0x41200000,%l6,%l5		! put value 10 into local 5
359	st	%l5, [%l0]
360	st	%l4, [%l1]
361	st	%l3, [%l2]
362	ld	[%l0], %f31		! register 31 has 10
363	ld	[%l1], %f30		! register 30 has 1
364
365	ld	[%l2], %f0		! reg 0 has 0
366	fmovs   %f31, %f1		! reg1 has 10
367	fsubs   %f31, %f30, %f18	! reg 18 has 9
368	fmovs   %f18, %f3		! reg 3 has 9
369	fmovs   %f30, %f2		! reg 2 has 1
370	fmovs   %f30, %f19		! reg 19 has 1
371	fsubs   %f18, %f19, %f16	! reg 16 has 8
372	fmovs   %f16, %f5		! reg 5 has 8
373	fsubs   %f31, %f16, %f17	! reg 17 has 2
374	fmovs	%f17, %f4		! reg 4 has 2
375	fsubs   %f16, %f30, %f14	! reg 14 has 7
376	fmovs   %f14, %f7		! reg 7 has 7
377	fsubs   %f31, %f14, %f15	! reg 15 has 3
378	fmovs	%f15, %f6		! reg 6 has 3
379	fsubs   %f14, %f30, %f12	! reg 12 has 6
380	fmovs	%f12, %f9		! reg 9 has 6
381	fsubs   %f31, %f12, %f13	! reg 13 has 4
382	fmovs	%f13, %f8		! reg 8 has 4
383	fsubs   %f12, %f30, %f10	! reg 10 has 5
384	fmovs	%f10, %f11		! reg 11 has 5
385
386	fadds	%f0, %f1, %f20		! reg 0 + reg 1 = reg 20 = 10
387	fadds   %f2, %f3, %f21		! reg 2 + reg 3 = reg 21 = 10
388	fadds   %f4, %f5, %f22		! reg 4 + reg 5 = reg 22 = 10
389	fadds   %f6, %f7, %f23		! reg 6 + reg 7 = reg 23 = 10
390	fadds   %f8, %f9, %f24		! reg 8 + reg 9 = reg 24 = 10
391	fadds   %f10, %f11, %f25	! reg 10 + reg 11 = reg 25 = 10
392	fadds   %f12, %f13, %f26	! reg 12 + reg 13 = reg 26 = 10
393	fadds   %f14, %f15, %f27	! reg 14 + reg 15 = reg 27 = 10
394	fadds   %f16, %f17, %f28	! reg 16 + reg 17 = reg 28 = 10
395	fadds   %f18, %f19, %f29	! reg 18 + reg 19 = reg 29 = 10
396
397	!  Now additions are done check it out
398	fcmps	%fcc0, %f31, %f20
399	fbne,a,pn	%fcc0, done_t_add_sp	! If not equal, go to the end.
400	st	%f20, [%l2] 	! Executed only when the conditional
401				! branch is taken as annul bit is set.
402				! This branch will be taken under
403				! an error condition.
404
405	! No errors. Move on to the next register
406
407	fcmps	%fcc0, %f31, %f21
408	fbne,a,pn	%fcc0, done_t_add_sp
409	st	%f21, [%l2]
410
411
412	fcmps   %fcc0, %f31, %f22
413	fbne,a,pn	%fcc0, done_t_add_sp
414	st	%f22, [%l2]
415
416
417	fcmps	%fcc0, %f31, %f23
418	fbne,a,pn	%fcc0, done_t_add_sp
419        st      %f23, [%l2]
420
421
422        fcmps   %fcc0, %f31, %f24
423        fbne,a,pn	%fcc0, done_t_add_sp
424        st      %f24, [%l2]
425
426
427        fcmps   %fcc0, %f31, %f25
428        fbne,a,pn	%fcc0, done_t_add_sp
429        st      %f25, [%l2]
430
431
432        fcmps   %fcc0, %f31, %f26
433        fbne,a,pn	%fcc0, done_t_add_sp
434        st      %f26, [%l2]
435
436
437        fcmps   %fcc0, %f31, %f27
438        fbne,a,pn	%fcc0, done_t_add_sp
439        st      %f27, [%l2]
440
441
442        fcmps   %fcc0, %f31, %f28
443        fbne,a,pn	%fcc0, done_t_add_sp
444        st      %f28, [%l2]
445
446
447	! Though this is the last set of compare instructions
448	! we cannot fall through as the store needs to be done
449	! only when the registers are not equal. That is why
450	! we need the unconditional branch with the annul bit set.
451        fcmps   %fcc0, %f31, %f29
452        fbne,a,pn	%fcc0, done_t_add_sp
453	st	%f29, [%l2]
454
455done_t_add_sp:
456	ld	[%l2], %i0
457	ret
458        restore
459SET_SIZE(timing_add_sp)
460
461#endif
462
463/*
464 * ----------------------------------------------------------------------
465 *	for mult routine all the f registers from 0 - 19 will be filled
466 *	with numbers and the result should be the number.
467 * ----------------------------------------------------------------------
468 */
469
470
471#ifdef __lint
472
473unsigned long
474timing_mult_sp()
475{
476	return (0);
477}
478
479#else
480
481.section        ".data"
482.align  4
483
484.Ltmmsp:
485        .skip   4
486.Ltmmsp1:
487        .skip   4
488.Ltmmsp2:
489        .skip   4
490
491ENTRY_NP(timing_mult_sp)
492	save    %sp, -SA(MINFRAME), %sp           ! save the registers, stacck
493        setn    .Ltmmsp,%l6, %l0
494        setn    .Ltmmsp1,%l6, %l1
495        setn    .Ltmmsp2,%l6, %l2
496        mov     %g0, %l3
497	setn	0x3f800000,%l6, %l4         ! put value 1
498        setn    0x41200000,%l6, %l5         ! put value 10 into local 5
499        st      %l5, [%l0]
500        st      %l4, [%l1]
501        st      %l3, [%l2]
502        ld      [%l0], %f31             ! register 31 has 10
503        ld      [%l1], %f1              ! register 1 has 1
504	fmovs   %f1, %f3
505	fmovs   %f1, %f5
506	fmovs   %f1, %f7
507	fmovs   %f1, %f9
508	fmovs   %f1, %f11	! register 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
509	fmovs   %f1, %f13	! has a value of 1
510	fmovs   %f1, %f15
511	fmovs   %f1, %f17
512	fmovs   %f1, %f19	!
513	fmovs	%f1, %f0
514	fmovs   %f31, %f18	! reg 18 has 10
515	fsubs	%f31, %f0, %f16		! reg 16  has 9
516	fsubs   %f16, %f0, %f14		! reg 14 has 8
517	fsubs   %f14, %f0, %f12		! reg 12 has 7
518	fsubs   %f12, %f0, %f10		! reg 10 has 6
519	fsubs   %f10, %f0, %f8		! reg 8 has 5
520	fsubs   %f8, %f0, %f6		! reg 6 has 4
521	fsubs   %f6, %f0, %f4		! reg 4 has 3
522	fsubs   %f4, %f0, %f2		! reg 2 has 2
523
524	fmuls   %f0, %f1, %f20          ! reg 0 * reg 1 = reg 20 = 1
525        fmuls   %f2, %f3, %f21          ! reg 2 * reg 3 = reg 21 = 2
526        fmuls   %f4, %f5, %f22          ! reg 4 * reg 5 = reg 22 = 3
527        fmuls   %f6, %f7, %f23          ! reg 6 * reg 7 = reg 23 = 4
528        fmuls   %f8, %f9, %f24          ! reg 8 * reg 9 = reg 24 = 5
529        fmuls   %f10, %f11, %f25        ! reg 10 * reg 11 = reg 25 = 6
530        fmuls   %f12, %f13, %f26        ! reg 12 * reg 13 = reg 26 = 7
531        fmuls   %f14, %f15, %f27        ! reg 14 * reg 15 = reg 27 = 8
532        fmuls   %f16, %f17, %f28        ! reg 16 * reg 17 = reg 28 = 9
533        fmuls   %f18, %f19, %f29        ! reg 18 * reg 19 = reg 29 = 10
534
535	fcmps	%fcc0, %f0, %f20
536	fbne,a,pn	%fcc0, done_t_mult_sp
537	st	%f20, [%l2] 	! Executed only when the conditional
538				! branch is taken as annul bit is set.
539				! This branch will be taken under
540				! an error condition.
541
542	! No errors. Move on to the next register
543
544	fcmps	%fcc0, %f2, %f21
545	fbne,a,pn	%fcc0, done_t_mult_sp
546	st	%f21, [%l2]
547
548
549	fcmps   %fcc0, %f4, %f22
550	fbne,a,pn 	%fcc0, done_t_mult_sp
551	st	%f22, [%l2]
552
553
554	fcmps	%fcc0, %f6, %f23
555	fbne,a,pn	%fcc0, done_t_mult_sp
556        st      %f23, [%l2]
557
558
559	fcmps	%fcc0, %f8, %f24
560	fbne,a,pn	%fcc0, done_t_mult_sp
561        st      %f24, [%l2]
562
563
564	fcmps	%fcc0, %f10, %f25
565	fbne,a,pn	%fcc0, done_t_mult_sp
566        st      %f25, [%l2]
567
568
569	fcmps	%fcc0, %f12, %f26
570	fbne,a,pn	%fcc0, done_t_mult_sp
571        st      %f26, [%l2]
572
573
574	fcmps	%fcc0, %f14, %f27
575	fbne,a,pn	%fcc0, done_t_mult_sp
576        st      %f27, [%l2]
577
578
579	fcmps	%fcc0, %f16, %f28
580	fbne,a,pn	%fcc0, done_t_mult_sp
581        st      %f28, [%l2]
582
583
584	! Though this is the last set of compare instructions
585	! we cannot fall through as the store needs to be done
586	! only when the registers are not equal. That is why
587	! we need the unconditional branch with the annul bit set.
588	fcmps	%fcc0, %f18, %f29
589	fbne,a,pn	%fcc0, done_t_mult_sp
590	st	%f29, [%l2]
591
592
593done_t_mult_sp:
594	ld	[%l2], %i0
595	ret
596        restore
597SET_SIZE(timing_mult_sp)
598
599#endif
600
601/*
602 * ----------------------------------------------------------------
603 *	same thing for double precision
604 * ----------------------------------------------------------------
605 */
606
607#ifdef __lint
608
609uint64_t
610timing_add_dp()
611{
612	return (0);
613}
614
615#else
616
617.section        ".data"
618.align  8
619
620.Ltmadp:
621        .skip   8
622.Ltmadp1:
623        .skip   8
624.Ltmadp2:
625        .skip   8
626
627ENTRY_NP(timing_add_dp)
628	save    %sp, -SA(MINFRAME), %sp           ! save the registers, stacck
629        setn    .Ltmadp,%l6, %l0
630        setn    .Ltmadp1,%l6, %l1
631        setn    .Ltmadp2,%l6, %l2
632        mov     %g0, %l3
633	setn	0x3ff0000000000000,%l6, %l4         ! put value 1
634        setn    0x4024000000000000,%l6, %l5         ! put value 10 into local 5
635        stx     %l5, [%l0]
636        stx     %l4, [%l1]
637        stx     %l3, [%l2]
638	ldd	[%l0], %f30             ! register 30 has 10
639	fmovd   %f30, %f2		! reg 2 has 10
640	ldd	[%l2], %f0		! reg 0 has 0
641	ldd	[%l1], %f4		! reg 4 has 1
642	fsubd	%f30, %f4, %f6		! reg 6 has 9
643	fsubd	%f6, %f4, %f10		! reg 10 has 8
644	fsubd   %f30, %f10, %f8		! reg 8 has 2
645	fsubd	%f10, %f4, %f14		! reg 14 has 7
646	fsubd   %f30, %f14, %f12	! reg 12 has 3
647	fsubd	%f14, %f4, %f18		! reg 18 has 6
648	fsubd	%f30, %f18, %f16	! reg 16 has 4
649!
650	faddd	%f0, %f2, %f20		! reg 20 has 10
651	faddd   %f4, %f6, %f22		! reg 22 has 10
652	faddd   %f8, %f10, %f24		! reg 24 has 10
653	faddd   %f12, %f14, %f26	! reg 26 has 10
654	faddd   %f16, %f18, %f28	! reg 28 has 10
655!
656	fcmpd	%fcc0, %f30, %f20
657	fbne,a,pn	%fcc0, done_t_add_dp
658	std	%f20, [%l2]
659
660	fcmpd	%fcc0, %f30, %f22
661	fbne,a,pn	%fcc0, done_t_add_dp
662	std	%f22, [%l2]
663
664	fcmpd   %fcc0, %f30, %f24
665        fbne,a,pn     %fcc0, done_t_add_dp
666        std      %f24, [%l2]
667
668        fcmpd   %fcc0, %f30, %f26
669        fbne,a,pn     %fcc0, done_t_add_dp
670        std      %f26, [%l2]
671
672	! Though this is the last set of compare instructions
673	! we cannot fall through as the store needs to be done
674	! only when the registers are not equal. That is why
675	! we need the unconditional branch with the annul bit set.
676	fcmpd	%fcc0, %f30, %f28
677	fbne,a	%fcc0, done_t_add_dp
678	std	%f28, [%l2]
679
680done_t_add_dp:
681	ldx	[%l2], %i0
682
683	ret
684	restore
685SET_SIZE(timing_add_dp)
686
687#endif
688
689/*
690 * -------------------------------------------------------------------
691 *	Now for mult
692 * -------------------------------------------------------------------
693 */
694
695#ifdef __lint
696
697uint64_t
698timing_mult_dp()
699{
700	return (0);
701}
702
703#else
704
705.section        ".data"
706.align  8
707
708.Ltmmdp:
709        .skip   8
710.Ltmmdp1:
711        .skip   8
712.Ltmmdp2:
713        .skip   8
714
715ENTRY_NP(timing_mult_dp)
716	save    %sp, -SA(MINFRAME), %sp           ! save the registers, stacck
717        setn    .Ltmmdp,%l6, %l0
718        setn    .Ltmmdp1,%l6, %l1
719        setn    .Ltmmdp2,%l6, %l2
720        mov     %g0, %l3
721        setn    0x3ff0000000000000,%l6, %l4         ! put value 1
722        setn    0x4034000000000000,%l6, %l5         ! put value 20 into local 5
723        stx      %l5, [%l0]
724        stx      %l4, [%l1]
725        stx      %l3, [%l2]
726	ldd      [%l0], %f30             ! register 30 has 20
727	ldd	[%l1], %f2		! register  2 has 1
728	fmovd   %f30, %f0		! register  0 has 20
729	faddd	%f2, %f2, %f10		! register 10 has 2
730	fmovd   %f10, %f16		! register 16 has 2
731	faddd	%f10, %f16, %f4		! register 4 has 4
732	faddd   %f4, %f2, %f6		! register 6 has 5
733	fmovd	%f6, %f12		! reg. 12 has 5
734	fmovd	%f4, %f14		! reg 14 has 4
735	faddd	%f12, %f6, %f18		! reg 18 has 10
736	fmovd	%f18, %f8		! reg 8 has 10
737!
738! 	now everything is set
739!
740	fmuld   %f0, %f2, %f20          ! reg 20 has 20
741	fmuld	%f4, %f6, %f22          ! reg 22 has 20
742	fmuld	%f8, %f10, %f24         ! reg 24 has 20
743	fmuld	%f12, %f14, %f26        ! reg 26 has 20
744	fmuld	%f16, %f18, %f28        ! reg 28 has 20
745!
746	fcmpd   %fcc0, %f30, %f20
747	fbne,a,pn	%fcc0, done_t_mult_dp
748        std      %f20, [%l2]
749
750	fcmpd   %fcc0, %f30, %f22
751        fbne,a,pn     %fcc0, done_t_mult_dp
752        std      %f22, [%l2]
753
754	fcmpd   %fcc0, %f30, %f24
755        fbne,a,pn     %fcc0, done_t_mult_dp
756        std      %f24, [%l2]
757
758        fcmpd   %fcc0, %f30, %f26
759        fbne,a,pn     %fcc0, done_t_mult_dp
760        std      %f26, [%l2]
761
762	! Though this is the last set of compare instructions
763	! we cannot fall through as the store needs to be done
764	! only when the registers are not equal. That is why
765	! we need the unconditional branch with the annul bit set.
766        fcmpd   %fcc0, %f30, %f28
767        fbne,a     %fcc0, done_t_mult_dp
768        std      %f28, [%l2]
769
770done_t_mult_dp:
771	ldx	[%l2], %i0
772
773	ret
774	restore
775SET_SIZE(timing_mult_dp)
776
777#endif
778
779/*
780 * --------------------------------------------------------------------------
781 * The following routines are for testing the IEEE754 exception fields
782 * of the FSR (cexc, aexc)
783 *	The input is : i0 = amsw
784 *		       i1 = bmsw or alsw (for double precision)
785 *	  	       i2 = bmsw (for dp)
786 *		       i3 = blsw (for dp)
787 *
788 *	The output is  i0 = value of FSR register
789 * -------------------------------------------------------------------------
790 */
791
792#ifdef __lint
793
794/*ARGSUSED*/
795uint64_t
796wadd_sp(unsigned long arg1, unsigned long arg2)
797{
798	return (0);
799}
800
801#else
802
803.section        ".data"
804.align  8
805
806.Lwadds:
807        .word   0
808.Lwadds1:
809        .word   0
810.Lwadds2:
811        .xword  0    ! For the FSR contents
812
813ENTRY_NP(wadd_sp)
814	save    %sp, -SA(MINFRAME), %sp
815        setn    .Lwadds,%l6, %l0
816        setn    .Lwadds1,%l6, %l1
817	setn	.Lwadds2,%l6, %l2
818
819	st	%i0, [%l0]		! get the first value
820	st	%i1, [%l1]		! get the second value
821	ld	[%l0], %f0		! f0 has the first value
822	ld 	[%l1], %f2		! f2 has the second value
823
824	fadds   %f0, %f2, %f3		! now do the instruction
825	stx	%fsr, [%l2]		! get the fsr value
826
827	ldx     [%l2], %i0
828	ret
829	restore
830SET_SIZE(wadd_sp)
831
832#endif
833
834/*
835 * -------------------------------------------------------------
836 *	same thing for add double precision
837 * -------------------------------------------------------------
838 */
839
840#ifdef __lint
841
842/*ARGSUSED*/
843uint64_t
844wadd_dp(unsigned long arg1, unsigned long arg2,
845	    unsigned long arg3, unsigned long arg4)
846{
847	return (0);
848}
849
850#else
851
852.section        ".data"
853.align  8
854
855.Ladddp:
856        .word   0
857.Ladddp1:
858        .word   0
859.Ladddp2:
860        .xword  0    ! For the FSR contents
861
862ENTRY_NP(wadd_dp)
863	save    %sp, -SA(MINFRAME), %sp
864        setn    .Ladddp,%l6, %l0
865        setn    .Ladddp1,%l6, %l1
866        setn    .Ladddp2,%l6, %l2
867
868	st	%i0, [%l0]              ! get the first value
869        st      %i1, [%l1]              ! get the lsw of first value
870	ld	[%l0], %f0
871	ld	[%l1], %f1
872	st      %i2, [%l0]              ! get the second value
873	st      %i3, [%l1]              ! get the lsw of second value
874	ld	[%l0], %f2
875	ld	[%l1], %f3
876
877	faddd	%f0, %f2, %f4		! now do the instruction
878        stx      %fsr, [%l2]             ! get the fsr value
879
880	ldx     [%l2], %i0
881	ret
882	restore
883
884SET_SIZE(wadd_dp)
885
886#endif
887
888/*
889 * --------------------------------------------------------------
890 *	for divide single precision
891 * --------------------------------------------------------------
892 */
893
894#ifdef __lint
895
896/*ARGSUSED*/
897uint64_t wdiv_sp(unsigned long arg1, unsigned long arg2)
898{
899	return (0);
900}
901
902#else
903
904.section        ".data"
905.align  8
906
907.Ldvsp:
908        .word   0
909.Ldvsp1:
910        .word   0
911.Ldvsp2:
912        .xword  0    ! For the FSR contents
913
914ENTRY_NP(wdiv_sp)
915	save    %sp, -SA(MINFRAME), %sp
916        setn    .Ldvsp,%l6, %l0
917        setn    .Ldvsp1,%l6, %l1
918        setn    .Ldvsp2,%l6, %l2
919
920        st      %i0, [%l0]              ! get the first value
921        st      %i1, [%l1]              ! get the second value
922        ld      [%l0], %f0              ! f0 has the first value
923        ld      [%l1], %f2              ! f2 has the second value
924
925        fdivs	%f0, %f2, %f3           ! now do the instruction
926        stx      %fsr, [%l2]             ! get the fsr value
927
928	ldx     [%l2], %i0
929	ret
930	restore
931
932SET_SIZE(wdiv_sp)
933
934#endif
935
936/*
937 * ----------------------------------------------------------------
938 *	for divide double precision
939 * ----------------------------------------------------------------
940 */
941
942#ifdef __lint
943
944/*ARGSUSED*/
945uint64_t
946wdiv_dp(unsigned long arg1, unsigned long arg2,
947	    unsigned long arg3, unsigned long arg4)
948{
949	return (0);
950}
951
952#else
953
954 .section        ".data"
955 .align  8
956
957.Ldvdp:
958        .word   0
959.Ldvdp1:
960        .word   0
961.Ldvdp2:
962        .xword  0    ! For the FSR contents
963
964ENTRY_NP(wdiv_dp)
965	save    %sp, -SA(MINFRAME), %sp
966        setn    .Ldvdp,%l6, %l0
967        setn    .Ldvdp1,%l6, %l1
968        setn    .Ldvdp2,%l6, %l2
969
970        st      %i0, [%l0]              ! get the first value
971        st      %i1, [%l1]              ! get the lsw of first value
972        ld      [%l0], %f0
973        ld      [%l1], %f1
974        st      %i2, [%l0]              ! get the second value
975        st      %i3, [%l1]              ! get the lsw of second value
976        ld      [%l0], %f2
977        ld      [%l1], %f3
978
979        fdivd	%f0, %f2, %f4           ! now do the instruction
980        stx      %fsr, [%l2]             ! get the fsr value
981
982	ldx     [%l2], %i0
983	ret
984	restore
985
986SET_SIZE(wdiv_dp)
987
988#endif
989
990/*
991 * ------------------------------------------------------------------------
992 *      for multiply single precision
993 * ------------------------------------------------------------------------
994 */
995
996#ifdef __lint
997
998/*ARGSUSED*/
999uint64_t
1000wmult_sp(unsigned long arg1, unsigned long arg2)
1001{
1002	return (0);
1003}
1004
1005#else
1006
1007.section        ".data"
1008.align  8
1009
1010.Lmltsp:
1011        .word   0
1012.Lmltsp1:
1013        .word   0
1014.Lmltsp2:
1015        .xword  0    ! For the FSR contents
1016
1017ENTRY_NP(wmult_sp)
1018	save    %sp, -SA(MINFRAME), %sp
1019        setn    .Lmltsp,%l6, %l0
1020        setn    .Lmltsp1,%l6, %l1
1021        setn    .Lmltsp2,%l6, %l2
1022
1023        st      %i0, [%l0]              ! get the first value
1024        st      %i1, [%l1]              ! get the second value
1025        ld      [%l0], %f0              ! f0 has the first value
1026        ld      [%l1], %f2              ! f2 has the second value
1027
1028        fmuls   %f0, %f2, %f3           ! now do the instruction
1029        stx      %fsr, [%l2]             ! get the fsr value
1030
1031	ldx     [%l2], %i0
1032	ret
1033	restore
1034
1035SET_SIZE(wmult_sp)
1036
1037#endif
1038
1039/*
1040 * ---------------------------------------------------------------------
1041 *      for multiply double precision
1042 * ---------------------------------------------------------------------
1043 */
1044
1045#ifdef __lint
1046
1047/*ARGSUSED*/
1048uint64_t
1049wmult_dp(unsigned long arg1, unsigned long arg2,
1050	    unsigned long arg3, unsigned long arg4)
1051{
1052	return (0);
1053}
1054
1055#else
1056
1057.section        ".data"
1058.align  8
1059
1060.Lmltdp:
1061        .word   0
1062.Lmltdp1:
1063        .word   0
1064.Lmltdp2:
1065        .xword  0    ! For the FSR contents
1066
1067ENTRY_NP(wmult_dp)
1068        save    %sp, -SA(MINFRAME), %sp
1069        setn    .Lmltdp,%l6, %l0
1070        setn    .Lmltdp1,%l6, %l1
1071        setn    .Lmltdp2,%l6, %l2
1072
1073        st      %i0, [%l0]		! get the first value
1074        st      %i1, [%l1]		! get the lsw of first value
1075        ld      [%l0], %f0
1076        ld      [%l1], %f1
1077        st      %i2, [%l0]		! get the second value
1078        st      %i3, [%l1]		! get the lsw of second value
1079        ld      [%l0], %f2
1080        ld      [%l1], %f3
1081
1082        fmuld	 %f0, %f2, %f4		! now do the instruction
1083        stx      %fsr, [%l2]		! get the fsr value
1084
1085	ldx     [%l2], %i0
1086	ret
1087	restore
1088
1089SET_SIZE(wmult_dp)
1090
1091#endif
1092
1093/*
1094 * -----------------------------------------------------------------
1095 *      for square-root single precision
1096 * -----------------------------------------------------------------
1097 */
1098
1099#ifdef __lint
1100
1101/*ARGSUSED*/
1102uint64_t
1103wsqrt_sp(unsigned long arg1)
1104{
1105	return (0);
1106}
1107
1108#else
1109
1110.section        ".data"
1111.align  4
1112.Lsqsp_opr:
1113                .word   0
1114
1115        .align  8
1116.Lsqsp_fsr:
1117                .xword  0       ! For the FSR contents
1118
1119ENTRY_NP(wsqrt_sp)
1120	save	%sp, -SA(MINFRAME), %sp	! save the registers, stack
1121	setn	.Lsqsp_opr,%l6,%l0	! .. get the address of temp2
1122	setn	.Lsqsp_fsr,%l6,%l2	! .. and temp
1123
1124	st	%i0, [%l0]	! .. get the callers value
1125	ld	[%l0], %f0	! .. into the float register
1126
1127	fsqrts  %f0, %f2	! .... have the fpu perform the operation
1128        stx     %fsr, [%l2]		! get the fsr value
1129
1130	ldx     [%l2], %i0
1131	ret
1132	restore
1133
1134SET_SIZE(wsqrt_sp)
1135
1136#endif
1137
1138/*
1139 * ---------------------------------------------------------------------
1140 *       for square-root double precision
1141 * ---------------------------------------------------------------------
1142 */
1143
1144#ifdef __lint
1145
1146/*ARGSUSED*/
1147uint64_t
1148wsqrt_dp(uint64_t arg1)
1149{
1150	return (0);
1151}
1152
1153#else
1154
1155.section        ".data"
1156.align  8
1157.Lsqdp_opr:
1158                .xword  0
1159.Lsqdp_fsr:
1160                .xword  0       ! For the FSR contents
1161
1162ENTRY_NP(wsqrt_dp)
1163	save	%sp, -SA(MINFRAME), %sp	! save the registers, stack
1164	setn	.Lsqdp_opr,%l6,%l0 	! .. get the address of temp2
1165	setn	.Lsqdp_fsr,%l6,%l2 	! .. and temp
1166
1167	stx	%i0, [%l0] 	! .. get the callers value
1168	ldd	[%l0], %f0 	! .. into a float register
1169
1170	fsqrtd  %f0, %f2	! .... have the fpu perform the operation
1171        stx     %fsr, [%l2]	! get the fsr value
1172
1173	ldx     [%l2], %i0
1174	ret
1175	restore
1176
1177SET_SIZE(wsqrt_dp)
1178
1179#endif
1180
1181/*
1182 * ---------------------------------------------------------------------
1183 *	Chaining test.
1184 * ---------------------------------------------------------------------
1185 */
1186
1187#ifdef __lint
1188
1189/*ARGSUSED*/
1190unsigned long
1191chain_sp(int arg1)
1192{
1193	return (0);
1194}
1195
1196#else
1197
1198.section        ".data"
1199.align  8
1200
1201.Lchsp:
1202        .word   0
1203.Lchsp1:
1204        .word   0
1205
1206ENTRY_NP(chain_sp)
1207	save    %sp, -SA(MINFRAME), %sp
1208        setn    .Lchsp,%l6, %l0
1209        setn    .Lchsp1,%l6, %l1
1210	st	%i0, [%l0]	! store the value
1211	ld	[%l0], %f0
1212	fitos   %f0, %f2	! convert integer into single
1213	fmovs   %f2, %f0	! f0 has the same value  x
1214	fadds	%f0, %f2, %f4   ! f4 will have 2x
1215	fsubs   %f4, %f0, %f6   ! f6 will have x
1216	fmuls   %f6, %f4, %f8   ! f8 will have (2x * x)
1217	fdivs   %f8, %f4, %f10  ! f10 will have (2x * x) / 2x = x
1218	fstoi	%f10, %f12
1219
1220	st	%f12, [%l1]
1221	ld	[%l1], %i0
1222
1223	ret
1224        restore
1225SET_SIZE(chain_sp)
1226
1227#endif
1228
1229#ifdef __lint
1230
1231/*ARGSUSED*/
1232unsigned long
1233chain_dp(int arg1)
1234{
1235	return (0);
1236}
1237
1238#else
1239
1240.section        ".data"
1241.align  8
1242
1243.Lchdp:
1244        .word   0
1245.Lchdp1:
1246        .word   0
1247
1248ENTRY_NP(chain_dp)
1249	save    %sp, -SA(MINFRAME), %sp
1250        setn    .Lchdp,%l6, %l0
1251        setn    .Lchdp1,%l6, %l1
1252        st      %i0, [%l0]      ! store the value
1253        ld      [%l0], %f0
1254        fitod   %f0, %f2        ! convert integer into double
1255	fmovs   %f2, %f0        ! f0 has the same value  x
1256        faddd   %f0, %f2, %f4   ! f4 will have 2x
1257        fsubd   %f4, %f0, %f6   ! f6 will have x
1258        fmuld   %f6, %f4, %f8   ! f8 will have (2x * x)
1259        fdivd   %f8, %f4, %f10  ! f10 will have (2x * x) / 2x = x
1260        fdtoi   %f10, %f12
1261
1262	st	%f12, [%l1]
1263	ld	[%l1], %i0
1264
1265	ret
1266        restore
1267SET_SIZE(chain_dp)
1268
1269#endif
1270
1271/*
1272 * --------------------------------------------------------------------------
1273 * Name:	Initialize all SP Registers
1274 * Function:	Loads the callers value into all SP floating point registers.
1275 * Calling:	in0 = Value
1276 * Returns:	All float register = Value
1277 * Convention:	init_regs(val);
1278 * Method:	Copys the user value into each fp reg in sequence.
1279 * --------------------------------------------------------------------------
1280 */
1281
1282#ifdef __lint
1283
1284/*ARGSUSED*/
1285void
1286init_regs(uint32_t arg1)
1287{
1288}
1289
1290#else
1291
1292.section        ".data"
1293.align  8
1294
1295.Lclrg:
1296        .skip   8
1297
1298ENTRY_NP(init_regs)
1299	save    %sp, -SA(MINFRAME), %sp	! save the registers, stack
1300        setn    .Lclrg,%l6,%l0	! load the address of temp2 in local0
1301	st	%i0, [%l0]	! load the value in temp2 via local0
1302	ld	[%l0], %f0	! .. load the value
1303	ld	[%l0], %f1	! .. load the value
1304        ld      [%l0], %f2	! .. load the value
1305        ld      [%l0], %f3	! .. load the value
1306        ld      [%l0], %f4	! .. load the value
1307	ld	[%l0], %f5	! .. load the value
1308        ld      [%l0], %f6 	! .. load the value
1309        ld      [%l0], %f7 	! .. load the value
1310        ld      [%l0], %f8 	! .. load the value
1311        ld      [%l0], %f9 	! .. load the value
1312        ld      [%l0], %f10 	! .. load the value
1313        ld      [%l0], %f11 	! .. load the value
1314        ld      [%l0], %f12 	! .. load the value
1315        ld      [%l0], %f13 	! .. load the value
1316        ld      [%l0], %f14 	! .. load the value
1317        ld      [%l0], %f15 	! .. load the value
1318        ld      [%l0], %f16 	! .. load the value
1319        ld      [%l0], %f17 	! .. load the value
1320        ld      [%l0], %f18 	! .. load the value
1321        ld      [%l0], %f19 	! .. load the value
1322        ld      [%l0], %f20 	! .. load the value
1323        ld      [%l0], %f21 	! .. load the value
1324        ld      [%l0], %f22 	! .. load the value
1325        ld      [%l0], %f23 	! .. load the value
1326        ld      [%l0], %f24 	! .. load the value
1327        ld      [%l0], %f25 	! .. load the value
1328        ld      [%l0], %f26 	! .. load the value
1329        ld      [%l0], %f27 	! .. load the value
1330        ld      [%l0], %f28 	! .. load the value
1331        ld      [%l0], %f29 	! .. load the value
1332        ld      [%l0], %f30 	! .. load the value
1333        ld      [%l0], %f31	! .. load the value
1334	ret
1335        restore
1336SET_SIZE(init_regs)
1337
1338#endif
1339
1340/*
1341 * Name:	Initialize all double precision Registers
1342 * Function:	Loads the callers value into all floating point registers.
1343 * Calling:	in0 = Value
1344 * Returns:	All float register = Value
1345 * Convention:	init_regs_dp(val);
1346 * Method:	Copys the user value into each fp reg in sequence.
1347 * --------------------------------------------------------------------------
1348 */
1349
1350#ifdef __lint
1351
1352/*ARGSUSED*/
1353void
1354init_regs_dp(uint64_t arg1)
1355{
1356}
1357
1358#else
1359
1360.section        ".data"
1361.align  8
1362
1363.Lclrg_dp:
1364        .skip   16
1365
1366ENTRY_NP(init_regs_dp)
1367	save    %sp, -SA(MINFRAME), %sp
1368								! save the registers, stack
1369        setx    .Lclrg_dp,%l6,%l0	! load the address of temp2 in local0
1370	stx	%i0, [%l0]		! load the value in temp2 via local0
1371	ldd	[%l0], %f0		! .. load the value
1372	ldd	[%l0], %f2		! .. load the value
1373        ldd     [%l0], %f4		! .. load the value
1374        ldd     [%l0], %f6		! .. load the value
1375        ldd     [%l0], %f8		! .. load the value
1376	ldd	[%l0], %f10		! .. load the value
1377        ldd     [%l0], %f12		! .. load the value
1378        ldd     [%l0], %f14		! .. load the value
1379        ldd     [%l0], %f16		! .. load the value
1380        ldd     [%l0], %f18		! .. load the value
1381        ldd     [%l0], %f20 	! .. load the value
1382        ldd     [%l0], %f22 	! .. load the value
1383        ldd     [%l0], %f24 	! .. load the value
1384        ldd     [%l0], %f26 	! .. load the value
1385        ldd     [%l0], %f28 	! .. load the value
1386        ldd     [%l0], %f30 	! .. load the value
1387        ldd     [%l0], %f32 	! .. load the value
1388        ldd     [%l0], %f34 	! .. load the value
1389        ldd     [%l0], %f36 	! .. load the value
1390        ldd     [%l0], %f38 	! .. load the value
1391        ldd     [%l0], %f40 	! .. load the value
1392        ldd     [%l0], %f42 	! .. load the value
1393        ldd     [%l0], %f44 	! .. load the value
1394        ldd     [%l0], %f46 	! .. load the value
1395        ldd     [%l0], %f48 	! .. load the value
1396        ldd     [%l0], %f50 	! .. load the value
1397        ldd     [%l0], %f52 	! .. load the value
1398        ldd     [%l0], %f54 	! .. load the value
1399        ldd     [%l0], %f56 	! .. load the value
1400        ldd     [%l0], %f58 	! .. load the value
1401        ldd     [%l0], %f60 	! .. load the value
1402        ldd     [%l0], %f62		! .. load the value
1403	ret
1404        restore
1405SET_SIZE(init_regs_dp)
1406
1407#endif
1408
1409/*
1410 * Name:
1411 * Function:
1412 * Calling:
1413 * Returns:
1414 * Convention:
1415 * --------------------------------------------------------------------------
1416 */
1417
1418#ifdef __lint
1419
1420/*ARGSUSED*/
1421uint32_t
1422register_test(int arg1, uint32_t arg2)
1423{
1424	return (0);
1425}
1426
1427#else
1428
1429.section        ".data"
1430.align  4
1431
1432.Lrgtst1:
1433        .skip   4
1434.Lrgtst2:
1435        .skip   4
1436
1437ENTRY_NP(register_test)
1438	save    %sp, -SA(MINFRAME), %sp
1439
1440	setn	.Lrgtst1,%l6,%l1
1441	setn	.Lrgtst2,%l6,%l2
1442
1443
1444	setn	regTable, %l6, %o0
1445	mulx	%i0, 12, %o1		! Table entries are 12 bytes each.
1446
1447	! Jump to the appropriate set of instructions
1448	jmp	%o0+%o1
1449	st	%i1,  [%l1]		! save the pattern to be written
1450
1451
1452! If the number of instructions in this macro are changed,
1453! please ensure that the second operand for the mulx above
1454! is also updated. We can calculate this during run-time but
1455! that will mean extra instructions and time.
1456#define	TEST_REG(reg_num)		\
1457	ld	[%l1], %f/**/reg_num;	\
1458	ba	%ncc, reg_done;		\
1459	st	%f/**/reg_num, [%l2]
1460
1461regTable :
1462
1463	TEST_REG(0)
1464	TEST_REG(1)
1465	TEST_REG(2)
1466	TEST_REG(3)
1467	TEST_REG(4)
1468	TEST_REG(5)
1469	TEST_REG(6)
1470	TEST_REG(7)
1471	TEST_REG(8)
1472	TEST_REG(9)
1473	TEST_REG(10)
1474	TEST_REG(11)
1475	TEST_REG(12)
1476	TEST_REG(13)
1477	TEST_REG(14)
1478	TEST_REG(15)
1479	TEST_REG(16)
1480	TEST_REG(17)
1481	TEST_REG(18)
1482	TEST_REG(19)
1483	TEST_REG(20)
1484	TEST_REG(21)
1485	TEST_REG(22)
1486	TEST_REG(23)
1487	TEST_REG(24)
1488	TEST_REG(25)
1489	TEST_REG(26)
1490	TEST_REG(27)
1491	TEST_REG(28)
1492	TEST_REG(29)
1493	TEST_REG(30)
1494
1495	! No need for a branch here as this the last entry in
1496	! the table and the label is will be reached by falling
1497	! through.
1498	ld	[%l1], %f31
1499	st	%f31, [%l2]
1500
1501reg_done:
1502	ld	[%l2], %i0
1503
1504	ret
1505	restore
1506SET_SIZE(register_test)
1507
1508#endif
1509
1510/*
1511 * Name:
1512 * Function:
1513 * Calling:
1514 * Returns:
1515 * Convention:
1516 * --------------------------------------------------------------------------
1517 */
1518
1519#ifdef __lint
1520
1521/*ARGSUSED*/
1522uint64_t
1523register_test_dp(int arg1, uint64_t arg2)
1524{
1525	return (0);
1526}
1527
1528#else
1529
1530.section        ".data"
1531.align  8
1532
1533.Lrgtst1_dp:
1534        .skip   8
1535.Lrgtst2_dp:
1536        .skip   8
1537
1538ENTRY_NP(register_test_dp)
1539	save    %sp, -SA(MINFRAME), %sp
1540
1541	setx	.Lrgtst1_dp,%l6,%l1
1542	setx	.Lrgtst2_dp,%l6,%l2
1543
1544	setn	regTable_dp, %l6, %o0
1545	mulx	%i0, 6, %o1	! Registers are 64-bit and hence the
1546				! register numbers given will be even.
1547				! Each table entry is 12 bytes.
1548				! Multiplying the even register number
1549				! by 6 will give the correct offset.
1550
1551
1552	! Jump to the appropriate set of instructions
1553	jmp	%o0+%o1
1554	stx	%i1,  [%l1]		!save the pattern to be written
1555
1556! If the number of instructions in this macro are changed,
1557! please ensure that the second operand for the mulx above
1558! is also updated. We can calculate this during run-time but
1559! that will mean extra instructions and time.
1560#define TEST_REG_DP(reg_num)		\
1561	ldd	[%l1], %f/**/reg_num;	\
1562	ba	%ncc, reg_done_dp;	\
1563	std	%f/**/reg_num, [%l2]
1564
1565regTable_dp :
1566
1567	TEST_REG_DP(0)
1568	TEST_REG_DP(2)
1569	TEST_REG_DP(4)
1570	TEST_REG_DP(6)
1571	TEST_REG_DP(8)
1572	TEST_REG_DP(10)
1573	TEST_REG_DP(12)
1574	TEST_REG_DP(14)
1575	TEST_REG_DP(16)
1576	TEST_REG_DP(18)
1577	TEST_REG_DP(20)
1578	TEST_REG_DP(22)
1579	TEST_REG_DP(24)
1580	TEST_REG_DP(26)
1581	TEST_REG_DP(28)
1582	TEST_REG_DP(30)
1583	TEST_REG_DP(32)
1584	TEST_REG_DP(34)
1585	TEST_REG_DP(36)
1586	TEST_REG_DP(38)
1587	TEST_REG_DP(40)
1588	TEST_REG_DP(42)
1589	TEST_REG_DP(44)
1590	TEST_REG_DP(46)
1591	TEST_REG_DP(48)
1592	TEST_REG_DP(50)
1593	TEST_REG_DP(52)
1594	TEST_REG_DP(54)
1595	TEST_REG_DP(56)
1596	TEST_REG_DP(58)
1597	TEST_REG_DP(60)
1598
1599	! No need for a branch here as this the last entry in
1600	! the table and the label is will be reached by falling
1601	! through.
1602	ldd	[%l1], %f62
1603	std	%f62, [%l2]
1604
1605reg_done_dp:
1606	ldx	[%l2], %i0
1607
1608	ret
1609	restore
1610SET_SIZE(register_test_dp)
1611
1612#endif
1613
1614/*
1615 * ------------------------------------------------------------------------
1616 * Name:	Move Registers
1617 * Function:	Move a value thru the float registers
1618 * Calling:	in0 = value
1619 * Returns:	in0 = result
1620 * Convention:	if (result != move_regs(value))
1621 *                  error(result-value);
1622 * --------------------------------------------------------------------------
1623 */
1624
1625#ifdef __lint
1626
1627/*ARGSUSED*/
1628unsigned long
1629move_regs(unsigned long arg1)
1630{
1631	return (0);
1632}
1633
1634#else
1635
1636.section        ".data"
1637.align  4
1638
1639.Lmvrg:
1640        .skip   4
1641.Lmvrg1:
1642        .skip   4
1643
1644ENTRY_NP(move_regs)
1645	save    %sp, -SA(MINFRAME), %sp	! save the registers, stack
1646        setn    .Lmvrg1,%l6,%l0	! get the address to temp2
1647        setn    .Lmvrg,%l6,%l1	! .. and temp
1648        st      %i0, [%l0]	! get the callers value
1649        ld      [%l0], %f0	! .. into a float register
1650	fmovs   %f0, %f1	! copy from 1 register to the next
1651	fmovs   %f1, %f2	! .. to the next
1652	fmovs   %f2, %f3	! .. to the next
1653	fmovs   %f3, %f4	! .. to the next
1654	fmovs   %f4, %f5	! .. to the next
1655	fmovs   %f5, %f6	! .. to the next
1656	fmovs   %f6, %f7	! .. to the next
1657	fmovs   %f7, %f8	! .. to the next
1658	fmovs   %f8, %f9	! .. to the next
1659	fmovs   %f9, %f10	! .. to the next
1660	fmovs   %f10, %f11	! .. to the next
1661	fmovs   %f11, %f12	! .. to the next
1662	fmovs   %f12, %f13	! .. to the next
1663	fmovs   %f13, %f14	! .. to the next
1664	fmovs   %f14, %f15	! .. to the next
1665	fmovs   %f15, %f16	! .. to the next
1666	fmovs   %f16, %f17	! .. to the next
1667	fmovs   %f17, %f18	! .. to the next
1668	fmovs   %f18, %f19	! .. to the next
1669	fmovs   %f19, %f20	! .. to the next
1670	fmovs   %f20, %f21	! .. to the next
1671	fmovs   %f21, %f22	! .. to the next
1672	fmovs   %f22, %f23	! .. to the next
1673	fmovs   %f23, %f24	! .. to the next
1674	fmovs   %f24, %f25	! .. to the next
1675	fmovs   %f25, %f26	! .. to the next
1676	fmovs   %f26, %f27	! .. to the next
1677	fmovs   %f27, %f28	! .. to the next
1678	fmovs   %f28, %f29	! .. to the next
1679	fmovs   %f29, %f30	! .. to the next
1680	fmovs   %f30, %f31	! .. to the next
1681	st	%f31, [%l1]	! .... save the result
1682	ld	[%l1], %i0	! .. and return it to the caller
1683	ret
1684        restore
1685SET_SIZE(move_regs)
1686
1687#endif
1688
1689/*
1690 * ------------------------------------------------------------------------
1691 * Name:
1692 * Function:
1693 * Calling:
1694 * Returns:
1695 * Convention:
1696 * --------------------------------------------------------------------------
1697 *
1698 *	The following routine checks the branching is done accordingly
1699 *	to the ficc bits.
1700 * 	input	%i0 = 0 = branch unordered
1701 *		      1 = branch greater
1702 *		      2 = branch unordered or greater
1703 *		      3 = branch less
1704 *		      4 = branch unordered or less
1705 *		      5 = branch less or greater
1706 *		      6 = branch not equal
1707 *		      7 = branch equal
1708 *		      8 = branch unordered or equal
1709 *		    . 9 = branch greater or equal
1710 * 		     10 = branch branch unordered or greater or equal
1711 *		     11 = branch less or equal
1712 *		     12 = branch unordered or or less or equal
1713 *		     13 = branch ordered
1714 *		     14 = branch always
1715 *		     15 = branch never
1716 *
1717 *	ouput : %i0 = 0 = good
1718 *		    = 1 = error
1719 */
1720
1721#ifdef __lint
1722
1723/*ARGSUSED*/
1724unsigned long
1725branches(unsigned long arg1, unsigned long arg2, unsigned long arg3)
1726{
1727	return (0);
1728}
1729
1730#else
1731
1732.section        ".data"
1733.align  8
1734
1735.Lbr:
1736        .skip   8
1737.Lbr1:
1738        .skip   8
1739
1740ENTRY_NP(branches)
1741	save    %sp, -SA(MINFRAME), %sp           ! save the registers, stacck
1742        setn    .Lbr1,%l6,%l1
1743        setn    .Lbr,%l6,%l2
1744        st      %i1, [%l1]
1745	st	%i2, [%l2]
1746	ld      [%l1], %f0
1747        ld      [%l2], %f2
1748
1749	setn	brn_0, %l6, %o0
1750	mulx	%i0, 12, %o1
1751
1752
1753	jmp	%o0+%o1
1754	fcmps	%fcc0, %f0, %f2		! compare the values  to get ficc
1755!
1756!				branch unordered
1757brn_0:
1758	fbu,a	%fcc0, br_good
1759	nop
1760	ba,a	%ncc, br_error
1761
1762!				branch greater
1763brn_1:
1764	fbg,a	%fcc0, br_good
1765	nop
1766	ba,a	%ncc, br_error
1767
1768!				branch unordered or greater
1769brn_2:
1770	fbug,a	%fcc0, br_good
1771	nop
1772	ba,a	%ncc, br_error
1773
1774!				branch less
1775brn_3:
1776	fbl,a	%fcc0, br_good
1777	nop
1778	ba,a	%ncc, br_error
1779
1780!				branch unorderd or less
1781brn_4:
1782	fbul,a	%fcc0, br_good
1783	nop
1784	ba,a	%ncc, br_error
1785
1786!				branch less or greater
1787brn_5:
1788	fblg,a	%fcc0, br_good
1789	nop
1790	ba,a	%ncc, br_error
1791
1792!				branch not equal
1793brn_6:
1794	fbne,a	%fcc0, br_good
1795	nop
1796	ba,a	%ncc, br_error
1797
1798!                               branch equal
1799brn_7:
1800	fbe,a	%fcc0, br_good
1801        nop
1802	ba,a	%ncc, br_error
1803
1804!                               branch unordered or equal
1805brn_8:
1806	fbue,a	%fcc0, br_good
1807        nop
1808	ba,a	%ncc, br_error
1809
1810!                               branch greater or equal
1811brn_9:
1812	fbge,a	%fcc0, br_good
1813        nop
1814	ba,a	%ncc, br_error
1815
1816!                               branch unordered or greater or equal
1817brn_10:
1818	fbuge,a	%fcc0, br_good
1819        nop
1820	ba,a	%ncc, br_error
1821
1822!                               branch less or equal
1823brn_11:
1824	fble,a	%fcc0, br_good
1825        nop
1826	ba,a	%ncc, br_error
1827
1828!                               branch unordered or less or equal
1829brn_12:
1830	fbule,a	%fcc0, br_good
1831        nop
1832	ba,a	%ncc, br_error
1833
1834!                               branch ordered
1835brn_13:
1836	fbo,a	%fcc0, br_good
1837	nop
1838	ba,a	%ncc, br_error
1839
1840!				branch always
1841brn_14:
1842	fba,a	%fcc0, br_good
1843	nop
1844	ba,a	%ncc, br_error
1845
1846!				branch never
1847brn_15:
1848	fbn,a	%fcc0, br_error
1849	nop
1850
1851br_good:
1852	mov	%g0, %i0	! Branch worked as expected
1853
1854	ret
1855	restore
1856
1857br_error:
1858	mov	0xff, %i0	! set the flag that it is error
1859
1860        ret
1861        restore
1862SET_SIZE(branches)
1863
1864#endif
1865
1866/*
1867 * void read_fpreg(pf, n)
1868 *      FPU_REGS_TYPE   *pf;    Old freg value.
1869 *      unsigned        n;      Want to read register n.
1870 *
1871 * {
1872 *      *pf = %f[n];
1873 * }
1874 */
1875
1876
1877#ifdef __lint
1878
1879/*ARGSUSED*/
1880void
1881read_fpreg(unsigned int *arg1, int arg2)
1882{
1883}
1884
1885#else
1886
1887ENTRY_NP(read_fpreg)
1888	save    %sp, -SA(MINFRAME), %sp
1889        mulx    %i1, 12, %i1            ! Table entries are 12 bytes each.
1890        setn    stable, %l1, %g1        ! g1 gets base of table.
1891        jmp     %g1 + %i1               ! Jump into table
1892        nop                             ! Can't follow CTI by CTI.
1893
1894#define STOREFP(n) st %f/**/n, [%i0]; ret; restore
1895
1896stable:
1897	STOREFP(0)
1898	STOREFP(1)
1899	STOREFP(2)
1900	STOREFP(3)
1901	STOREFP(4)
1902	STOREFP(5)
1903	STOREFP(6)
1904	STOREFP(7)
1905	STOREFP(8)
1906	STOREFP(9)
1907	STOREFP(10)
1908	STOREFP(11)
1909	STOREFP(12)
1910	STOREFP(13)
1911	STOREFP(14)
1912	STOREFP(15)
1913	STOREFP(16)
1914	STOREFP(17)
1915	STOREFP(18)
1916	STOREFP(19)
1917	STOREFP(20)
1918	STOREFP(21)
1919	STOREFP(22)
1920	STOREFP(23)
1921	STOREFP(24)
1922	STOREFP(25)
1923	STOREFP(26)
1924	STOREFP(27)
1925	STOREFP(28)
1926	STOREFP(29)
1927	STOREFP(30)
1928	STOREFP(31)
1929SET_SIZE(read_fpreg)
1930
1931#endif
1932
1933#ifdef __lint
1934
1935/*ARGSUSED*/
1936void
1937read_fpreg_dp(unsigned long *arg1, int arg2)
1938{
1939	return;
1940}
1941
1942#else
1943
1944ENTRY_NP(read_fpreg_dp)
1945	save    %sp, -SA(MINFRAME), %sp
1946        mulx    %i1, 6, %i1             ! Table entries are 12 bytes each.
1947										! But o1 will have even numbered
1948										! index
1949        setn    stable_dp, %l0, %g1			! g1 gets base of table.
1950        jmp     %g1 + %i1               ! Jump into table
1951        nop                             ! Can't follow CTI by CTI.
1952
1953#define STOREFP_DP(n) std %f/**/n, [%i0]; ret; restore
1954
1955stable_dp:
1956	STOREFP_DP(0)
1957	STOREFP_DP(2)
1958	STOREFP_DP(4)
1959	STOREFP_DP(6)
1960	STOREFP_DP(8)
1961	STOREFP_DP(10)
1962	STOREFP_DP(12)
1963	STOREFP_DP(14)
1964	STOREFP_DP(16)
1965	STOREFP_DP(18)
1966	STOREFP_DP(20)
1967	STOREFP_DP(22)
1968	STOREFP_DP(24)
1969	STOREFP_DP(26)
1970	STOREFP_DP(28)
1971	STOREFP_DP(30)
1972	STOREFP_DP(32)
1973	STOREFP_DP(34)
1974	STOREFP_DP(36)
1975	STOREFP_DP(38)
1976	STOREFP_DP(40)
1977	STOREFP_DP(42)
1978	STOREFP_DP(44)
1979	STOREFP_DP(46)
1980	STOREFP_DP(48)
1981	STOREFP_DP(50)
1982	STOREFP_DP(52)
1983	STOREFP_DP(54)
1984	STOREFP_DP(56)
1985	STOREFP_DP(58)
1986	STOREFP_DP(60)
1987	STOREFP_DP(62)
1988
1989SET_SIZE(read_fpreg_dp)
1990
1991#endif
1992
1993/*
1994 * void
1995 * write_fpreg(pf, n)
1996 *      FPU_REGS_TYPE   *pf;    New freg value.
1997 *      unsigned        n;      Want to read register n.
1998 *
1999 * {
2000 *      %f[n] = *pf;
2001 * }
2002 */
2003
2004#ifdef __lint
2005
2006#else
2007
2008ENTRY_NP(write_fpreg)
2009        sll     %o1, 3, %o1             ! Table entries are 8 bytes each.
2010        setn     ltable, %l0,  %g1       ! g1 gets base of table.
2011        jmp     %g1 + %o1               ! Jump into table
2012        nop                             ! Can't follow CTI by CTI.
2013
2014
2015#define LOADFP(n) jmp %o7+8 ; ld [%o0],%f/**/n
2016
2017ltable:
2018	LOADFP(0)
2019	LOADFP(1)
2020	LOADFP(2)
2021	LOADFP(3)
2022	LOADFP(4)
2023	LOADFP(5)
2024	LOADFP(6)
2025	LOADFP(7)
2026	LOADFP(8)
2027	LOADFP(9)
2028	LOADFP(10)
2029	LOADFP(11)
2030	LOADFP(12)
2031	LOADFP(13)
2032	LOADFP(14)
2033	LOADFP(15)
2034	LOADFP(16)
2035	LOADFP(17)
2036	LOADFP(18)
2037	LOADFP(19)
2038	LOADFP(20)
2039	LOADFP(21)
2040	LOADFP(22)
2041	LOADFP(23)
2042	LOADFP(24)
2043	LOADFP(25)
2044	LOADFP(26)
2045	LOADFP(27)
2046	LOADFP(28)
2047	LOADFP(29)
2048	LOADFP(30)
2049	LOADFP(31)
2050SET_SIZE(write_fpreg)
2051
2052#endif
2053