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