xref: /openbmc/linux/arch/m68k/ifpsp060/src/fplsp.S (revision 3cf3cdea)
1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3M68000 Hi-Performance Microprocessor Division
4M68060 Software Package
5Production Release P1.00 -- October 10, 1994
6
7M68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
8
9THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10To the maximum extent permitted by applicable law,
11MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13and any warranty against infringement with regard to the SOFTWARE
14(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16To the maximum extent permitted by applicable law,
17IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24so long as this entire notice is retained without alteration in any modified and/or
25redistributed versions, and that such modified versions are clearly identified as such.
26No licenses are granted by implication, estoppel or otherwise under any patents
27or trademarks of Motorola, Inc.
28~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29#
30# lfptop.s:
31#	This file is appended to the top of the 060ILSP package
32# and contains the entry points into the package. The user, in
33# effect, branches to one of the branch table entries located here.
34#
35
36	bra.l	_facoss_
37	short	0x0000
38	bra.l	_facosd_
39	short	0x0000
40	bra.l	_facosx_
41	short	0x0000
42
43	bra.l	_fasins_
44	short	0x0000
45	bra.l	_fasind_
46	short	0x0000
47	bra.l	_fasinx_
48	short	0x0000
49
50	bra.l	_fatans_
51	short	0x0000
52	bra.l	_fatand_
53	short	0x0000
54	bra.l	_fatanx_
55	short	0x0000
56
57	bra.l	_fatanhs_
58	short	0x0000
59	bra.l	_fatanhd_
60	short	0x0000
61	bra.l	_fatanhx_
62	short	0x0000
63
64	bra.l	_fcoss_
65	short	0x0000
66	bra.l	_fcosd_
67	short	0x0000
68	bra.l	_fcosx_
69	short	0x0000
70
71	bra.l	_fcoshs_
72	short	0x0000
73	bra.l	_fcoshd_
74	short	0x0000
75	bra.l	_fcoshx_
76	short	0x0000
77
78	bra.l	_fetoxs_
79	short	0x0000
80	bra.l	_fetoxd_
81	short	0x0000
82	bra.l	_fetoxx_
83	short	0x0000
84
85	bra.l	_fetoxm1s_
86	short	0x0000
87	bra.l	_fetoxm1d_
88	short	0x0000
89	bra.l	_fetoxm1x_
90	short	0x0000
91
92	bra.l	_fgetexps_
93	short	0x0000
94	bra.l	_fgetexpd_
95	short	0x0000
96	bra.l	_fgetexpx_
97	short	0x0000
98
99	bra.l	_fgetmans_
100	short	0x0000
101	bra.l	_fgetmand_
102	short	0x0000
103	bra.l	_fgetmanx_
104	short	0x0000
105
106	bra.l	_flog10s_
107	short	0x0000
108	bra.l	_flog10d_
109	short	0x0000
110	bra.l	_flog10x_
111	short	0x0000
112
113	bra.l	_flog2s_
114	short	0x0000
115	bra.l	_flog2d_
116	short	0x0000
117	bra.l	_flog2x_
118	short	0x0000
119
120	bra.l	_flogns_
121	short	0x0000
122	bra.l	_flognd_
123	short	0x0000
124	bra.l	_flognx_
125	short	0x0000
126
127	bra.l	_flognp1s_
128	short	0x0000
129	bra.l	_flognp1d_
130	short	0x0000
131	bra.l	_flognp1x_
132	short	0x0000
133
134	bra.l	_fmods_
135	short	0x0000
136	bra.l	_fmodd_
137	short	0x0000
138	bra.l	_fmodx_
139	short	0x0000
140
141	bra.l	_frems_
142	short	0x0000
143	bra.l	_fremd_
144	short	0x0000
145	bra.l	_fremx_
146	short	0x0000
147
148	bra.l	_fscales_
149	short	0x0000
150	bra.l	_fscaled_
151	short	0x0000
152	bra.l	_fscalex_
153	short	0x0000
154
155	bra.l	_fsins_
156	short	0x0000
157	bra.l	_fsind_
158	short	0x0000
159	bra.l	_fsinx_
160	short	0x0000
161
162	bra.l	_fsincoss_
163	short	0x0000
164	bra.l	_fsincosd_
165	short	0x0000
166	bra.l	_fsincosx_
167	short	0x0000
168
169	bra.l	_fsinhs_
170	short	0x0000
171	bra.l	_fsinhd_
172	short	0x0000
173	bra.l	_fsinhx_
174	short	0x0000
175
176	bra.l	_ftans_
177	short	0x0000
178	bra.l	_ftand_
179	short	0x0000
180	bra.l	_ftanx_
181	short	0x0000
182
183	bra.l	_ftanhs_
184	short	0x0000
185	bra.l	_ftanhd_
186	short	0x0000
187	bra.l	_ftanhx_
188	short	0x0000
189
190	bra.l	_ftentoxs_
191	short	0x0000
192	bra.l	_ftentoxd_
193	short	0x0000
194	bra.l	_ftentoxx_
195	short	0x0000
196
197	bra.l	_ftwotoxs_
198	short	0x0000
199	bra.l	_ftwotoxd_
200	short	0x0000
201	bra.l	_ftwotoxx_
202	short	0x0000
203
204	bra.l	_fabss_
205	short	0x0000
206	bra.l	_fabsd_
207	short	0x0000
208	bra.l	_fabsx_
209	short	0x0000
210
211	bra.l	_fadds_
212	short	0x0000
213	bra.l	_faddd_
214	short	0x0000
215	bra.l	_faddx_
216	short	0x0000
217
218	bra.l	_fdivs_
219	short	0x0000
220	bra.l	_fdivd_
221	short	0x0000
222	bra.l	_fdivx_
223	short	0x0000
224
225	bra.l	_fints_
226	short	0x0000
227	bra.l	_fintd_
228	short	0x0000
229	bra.l	_fintx_
230	short	0x0000
231
232	bra.l	_fintrzs_
233	short	0x0000
234	bra.l	_fintrzd_
235	short	0x0000
236	bra.l	_fintrzx_
237	short	0x0000
238
239	bra.l	_fmuls_
240	short	0x0000
241	bra.l	_fmuld_
242	short	0x0000
243	bra.l	_fmulx_
244	short	0x0000
245
246	bra.l	_fnegs_
247	short	0x0000
248	bra.l	_fnegd_
249	short	0x0000
250	bra.l	_fnegx_
251	short	0x0000
252
253	bra.l	_fsqrts_
254	short	0x0000
255	bra.l	_fsqrtd_
256	short	0x0000
257	bra.l	_fsqrtx_
258	short	0x0000
259
260	bra.l	_fsubs_
261	short	0x0000
262	bra.l	_fsubd_
263	short	0x0000
264	bra.l	_fsubx_
265	short	0x0000
266
267# leave room for future possible additions
268	align	0x400
269
270#
271# This file contains a set of define statements for constants
272# in order to promote readability within the corecode itself.
273#
274
275set LOCAL_SIZE,		192			# stack frame size(bytes)
276set LV,			-LOCAL_SIZE		# stack offset
277
278set EXC_SR,		0x4			# stack status register
279set EXC_PC,		0x6			# stack pc
280set EXC_VOFF,		0xa			# stacked vector offset
281set EXC_EA,		0xc			# stacked <ea>
282
283set EXC_FP,		0x0			# frame pointer
284
285set EXC_AREGS,		-68			# offset of all address regs
286set EXC_DREGS,		-100			# offset of all data regs
287set EXC_FPREGS,		-36			# offset of all fp regs
288
289set EXC_A7,		EXC_AREGS+(7*4)		# offset of saved a7
290set OLD_A7,		EXC_AREGS+(6*4)		# extra copy of saved a7
291set EXC_A6,		EXC_AREGS+(6*4)		# offset of saved a6
292set EXC_A5,		EXC_AREGS+(5*4)
293set EXC_A4,		EXC_AREGS+(4*4)
294set EXC_A3,		EXC_AREGS+(3*4)
295set EXC_A2,		EXC_AREGS+(2*4)
296set EXC_A1,		EXC_AREGS+(1*4)
297set EXC_A0,		EXC_AREGS+(0*4)
298set EXC_D7,		EXC_DREGS+(7*4)
299set EXC_D6,		EXC_DREGS+(6*4)
300set EXC_D5,		EXC_DREGS+(5*4)
301set EXC_D4,		EXC_DREGS+(4*4)
302set EXC_D3,		EXC_DREGS+(3*4)
303set EXC_D2,		EXC_DREGS+(2*4)
304set EXC_D1,		EXC_DREGS+(1*4)
305set EXC_D0,		EXC_DREGS+(0*4)
306
307set EXC_FP0,		EXC_FPREGS+(0*12)	# offset of saved fp0
308set EXC_FP1,		EXC_FPREGS+(1*12)	# offset of saved fp1
309set EXC_FP2,		EXC_FPREGS+(2*12)	# offset of saved fp2 (not used)
310
311set FP_SCR1,		LV+80			# fp scratch 1
312set FP_SCR1_EX,		FP_SCR1+0
313set FP_SCR1_SGN,	FP_SCR1+2
314set FP_SCR1_HI,		FP_SCR1+4
315set FP_SCR1_LO,		FP_SCR1+8
316
317set FP_SCR0,		LV+68			# fp scratch 0
318set FP_SCR0_EX,		FP_SCR0+0
319set FP_SCR0_SGN,	FP_SCR0+2
320set FP_SCR0_HI,		FP_SCR0+4
321set FP_SCR0_LO,		FP_SCR0+8
322
323set FP_DST,		LV+56			# fp destination operand
324set FP_DST_EX,		FP_DST+0
325set FP_DST_SGN,		FP_DST+2
326set FP_DST_HI,		FP_DST+4
327set FP_DST_LO,		FP_DST+8
328
329set FP_SRC,		LV+44			# fp source operand
330set FP_SRC_EX,		FP_SRC+0
331set FP_SRC_SGN,		FP_SRC+2
332set FP_SRC_HI,		FP_SRC+4
333set FP_SRC_LO,		FP_SRC+8
334
335set USER_FPIAR,		LV+40			# FP instr address register
336
337set USER_FPSR,		LV+36			# FP status register
338set FPSR_CC,		USER_FPSR+0		# FPSR condition codes
339set FPSR_QBYTE,		USER_FPSR+1		# FPSR qoutient byte
340set FPSR_EXCEPT,	USER_FPSR+2		# FPSR exception status byte
341set FPSR_AEXCEPT,	USER_FPSR+3		# FPSR accrued exception byte
342
343set USER_FPCR,		LV+32			# FP control register
344set FPCR_ENABLE,	USER_FPCR+2		# FPCR exception enable
345set FPCR_MODE,		USER_FPCR+3		# FPCR rounding mode control
346
347set L_SCR3,		LV+28			# integer scratch 3
348set L_SCR2,		LV+24			# integer scratch 2
349set L_SCR1,		LV+20			# integer scratch 1
350
351set STORE_FLG,		LV+19			# flag: operand store (ie. not fcmp/ftst)
352
353set EXC_TEMP2,		LV+24			# temporary space
354set EXC_TEMP,		LV+16			# temporary space
355
356set DTAG,		LV+15			# destination operand type
357set STAG,		LV+14			# source operand type
358
359set SPCOND_FLG,		LV+10			# flag: special case (see below)
360
361set EXC_CC,		LV+8			# saved condition codes
362set EXC_EXTWPTR,	LV+4			# saved current PC (active)
363set EXC_EXTWORD,	LV+2			# saved extension word
364set EXC_CMDREG,		LV+2			# saved extension word
365set EXC_OPWORD,		LV+0			# saved operation word
366
367################################
368
369# Helpful macros
370
371set FTEMP,		0			# offsets within an
372set FTEMP_EX,		0			# extended precision
373set FTEMP_SGN,		2			# value saved in memory.
374set FTEMP_HI,		4
375set FTEMP_LO,		8
376set FTEMP_GRS,		12
377
378set LOCAL,		0			# offsets within an
379set LOCAL_EX,		0			# extended precision
380set LOCAL_SGN,		2			# value saved in memory.
381set LOCAL_HI,		4
382set LOCAL_LO,		8
383set LOCAL_GRS,		12
384
385set DST,		0			# offsets within an
386set DST_EX,		0			# extended precision
387set DST_HI,		4			# value saved in memory.
388set DST_LO,		8
389
390set SRC,		0			# offsets within an
391set SRC_EX,		0			# extended precision
392set SRC_HI,		4			# value saved in memory.
393set SRC_LO,		8
394
395set SGL_LO,		0x3f81			# min sgl prec exponent
396set SGL_HI,		0x407e			# max sgl prec exponent
397set DBL_LO,		0x3c01			# min dbl prec exponent
398set DBL_HI,		0x43fe			# max dbl prec exponent
399set EXT_LO,		0x0			# min ext prec exponent
400set EXT_HI,		0x7ffe			# max ext prec exponent
401
402set EXT_BIAS,		0x3fff			# extended precision bias
403set SGL_BIAS,		0x007f			# single precision bias
404set DBL_BIAS,		0x03ff			# double precision bias
405
406set NORM,		0x00			# operand type for STAG/DTAG
407set ZERO,		0x01			# operand type for STAG/DTAG
408set INF,		0x02			# operand type for STAG/DTAG
409set QNAN,		0x03			# operand type for STAG/DTAG
410set DENORM,		0x04			# operand type for STAG/DTAG
411set SNAN,		0x05			# operand type for STAG/DTAG
412set UNNORM,		0x06			# operand type for STAG/DTAG
413
414##################
415# FPSR/FPCR bits #
416##################
417set neg_bit,		0x3			# negative result
418set z_bit,		0x2			# zero result
419set inf_bit,		0x1			# infinite result
420set nan_bit,		0x0			# NAN result
421
422set q_sn_bit,		0x7			# sign bit of quotient byte
423
424set bsun_bit,		7			# branch on unordered
425set snan_bit,		6			# signalling NAN
426set operr_bit,		5			# operand error
427set ovfl_bit,		4			# overflow
428set unfl_bit,		3			# underflow
429set dz_bit,		2			# divide by zero
430set inex2_bit,		1			# inexact result 2
431set inex1_bit,		0			# inexact result 1
432
433set aiop_bit,		7			# accrued inexact operation bit
434set aovfl_bit,		6			# accrued overflow bit
435set aunfl_bit,		5			# accrued underflow bit
436set adz_bit,		4			# accrued dz bit
437set ainex_bit,		3			# accrued inexact bit
438
439#############################
440# FPSR individual bit masks #
441#############################
442set neg_mask,		0x08000000		# negative bit mask (lw)
443set inf_mask,		0x02000000		# infinity bit mask (lw)
444set z_mask,		0x04000000		# zero bit mask (lw)
445set nan_mask,		0x01000000		# nan bit mask (lw)
446
447set neg_bmask,		0x08			# negative bit mask (byte)
448set inf_bmask,		0x02			# infinity bit mask (byte)
449set z_bmask,		0x04			# zero bit mask (byte)
450set nan_bmask,		0x01			# nan bit mask (byte)
451
452set bsun_mask,		0x00008000		# bsun exception mask
453set snan_mask,		0x00004000		# snan exception mask
454set operr_mask,		0x00002000		# operr exception mask
455set ovfl_mask,		0x00001000		# overflow exception mask
456set unfl_mask,		0x00000800		# underflow exception mask
457set dz_mask,		0x00000400		# dz exception mask
458set inex2_mask,		0x00000200		# inex2 exception mask
459set inex1_mask,		0x00000100		# inex1 exception mask
460
461set aiop_mask,		0x00000080		# accrued illegal operation
462set aovfl_mask,		0x00000040		# accrued overflow
463set aunfl_mask,		0x00000020		# accrued underflow
464set adz_mask,		0x00000010		# accrued divide by zero
465set ainex_mask,		0x00000008		# accrued inexact
466
467######################################
468# FPSR combinations used in the FPSP #
469######################################
470set dzinf_mask,		inf_mask+dz_mask+adz_mask
471set opnan_mask,		nan_mask+operr_mask+aiop_mask
472set nzi_mask,		0x01ffffff		#clears N, Z, and I
473set unfinx_mask,	unfl_mask+inex2_mask+aunfl_mask+ainex_mask
474set unf2inx_mask,	unfl_mask+inex2_mask+ainex_mask
475set ovfinx_mask,	ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
476set inx1a_mask,		inex1_mask+ainex_mask
477set inx2a_mask,		inex2_mask+ainex_mask
478set snaniop_mask,	nan_mask+snan_mask+aiop_mask
479set snaniop2_mask,	snan_mask+aiop_mask
480set naniop_mask,	nan_mask+aiop_mask
481set neginf_mask,	neg_mask+inf_mask
482set infaiop_mask,	inf_mask+aiop_mask
483set negz_mask,		neg_mask+z_mask
484set opaop_mask,		operr_mask+aiop_mask
485set unfl_inx_mask,	unfl_mask+aunfl_mask+ainex_mask
486set ovfl_inx_mask,	ovfl_mask+aovfl_mask+ainex_mask
487
488#########
489# misc. #
490#########
491set rnd_stky_bit,	29			# stky bit pos in longword
492
493set sign_bit,		0x7			# sign bit
494set signan_bit,		0x6			# signalling nan bit
495
496set sgl_thresh,		0x3f81			# minimum sgl exponent
497set dbl_thresh,		0x3c01			# minimum dbl exponent
498
499set x_mode,		0x0			# extended precision
500set s_mode,		0x4			# single precision
501set d_mode,		0x8			# double precision
502
503set rn_mode,		0x0			# round-to-nearest
504set rz_mode,		0x1			# round-to-zero
505set rm_mode,		0x2			# round-tp-minus-infinity
506set rp_mode,		0x3			# round-to-plus-infinity
507
508set mantissalen,	64			# length of mantissa in bits
509
510set BYTE,		1			# len(byte) == 1 byte
511set WORD,		2			# len(word) == 2 bytes
512set LONG,		4			# len(longword) == 2 bytes
513
514set BSUN_VEC,		0xc0			# bsun    vector offset
515set INEX_VEC,		0xc4			# inexact vector offset
516set DZ_VEC,		0xc8			# dz      vector offset
517set UNFL_VEC,		0xcc			# unfl    vector offset
518set OPERR_VEC,		0xd0			# operr   vector offset
519set OVFL_VEC,		0xd4			# ovfl    vector offset
520set SNAN_VEC,		0xd8			# snan    vector offset
521
522###########################
523# SPecial CONDition FLaGs #
524###########################
525set ftrapcc_flg,	0x01			# flag bit: ftrapcc exception
526set fbsun_flg,		0x02			# flag bit: bsun exception
527set mia7_flg,		0x04			# flag bit: (a7)+ <ea>
528set mda7_flg,		0x08			# flag bit: -(a7) <ea>
529set fmovm_flg,		0x40			# flag bit: fmovm instruction
530set immed_flg,		0x80			# flag bit: &<data> <ea>
531
532set ftrapcc_bit,	0x0
533set fbsun_bit,		0x1
534set mia7_bit,		0x2
535set mda7_bit,		0x3
536set immed_bit,		0x7
537
538##################################
539# TRANSCENDENTAL "LAST-OP" FLAGS #
540##################################
541set FMUL_OP,		0x0			# fmul instr performed last
542set FDIV_OP,		0x1			# fdiv performed last
543set FADD_OP,		0x2			# fadd performed last
544set FMOV_OP,		0x3			# fmov performed last
545
546#############
547# CONSTANTS #
548#############
549T1:	long		0x40C62D38,0xD3D64634	# 16381 LOG2 LEAD
550T2:	long		0x3D6F90AE,0xB1E75CC7	# 16381 LOG2 TRAIL
551
552PI:	long		0x40000000,0xC90FDAA2,0x2168C235,0x00000000
553PIBY2:	long		0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
554
555TWOBYPI:
556	long		0x3FE45F30,0x6DC9C883
557
558#########################################################################
559# MONADIC TEMPLATE							#
560#########################################################################
561	global		_fsins_
562_fsins_:
563	link		%a6,&-LOCAL_SIZE
564
565	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
566	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
567	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
568
569	fmov.l		&0x0,%fpcr		# zero FPCR
570
571#
572#	copy, convert, and tag input argument
573#
574	fmov.s		0x8(%a6),%fp0		# load sgl input
575	fmov.x		%fp0,FP_SRC(%a6)
576	lea		FP_SRC(%a6),%a0
577	bsr.l		tag			# fetch operand type
578	mov.b		%d0,STAG(%a6)
579	mov.b		%d0,%d1
580
581	andi.l		&0x00ff00ff,USER_FPSR(%a6)
582
583	clr.l		%d0
584	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
585
586	tst.b		%d1
587	bne.b		_L0_2s
588	bsr.l		ssin			# operand is a NORM
589	bra.b		_L0_6s
590_L0_2s:
591	cmpi.b		%d1,&ZERO		# is operand a ZERO?
592	bne.b		_L0_3s			# no
593	bsr.l		src_zero			# yes
594	bra.b		_L0_6s
595_L0_3s:
596	cmpi.b		%d1,&INF		# is operand an INF?
597	bne.b		_L0_4s			# no
598	bsr.l		t_operr			# yes
599	bra.b		_L0_6s
600_L0_4s:
601	cmpi.b		%d1,&QNAN		# is operand a QNAN?
602	bne.b		_L0_5s			# no
603	bsr.l		src_qnan			# yes
604	bra.b		_L0_6s
605_L0_5s:
606	bsr.l		ssind			# operand is a DENORM
607_L0_6s:
608
609#
610#	Result is now in FP0
611#
612	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
613	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
614	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
615	unlk		%a6
616	rts
617
618	global		_fsind_
619_fsind_:
620	link		%a6,&-LOCAL_SIZE
621
622	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
623	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
624	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
625
626	fmov.l		&0x0,%fpcr		# zero FPCR
627
628#
629#	copy, convert, and tag input argument
630#
631	fmov.d		0x8(%a6),%fp0		# load dbl input
632	fmov.x		%fp0,FP_SRC(%a6)
633	lea		FP_SRC(%a6),%a0
634	bsr.l		tag			# fetch operand type
635	mov.b		%d0,STAG(%a6)
636	mov.b		%d0,%d1
637
638	andi.l		&0x00ff00ff,USER_FPSR(%a6)
639
640	clr.l		%d0
641	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
642
643	mov.b		%d1,STAG(%a6)
644	tst.b		%d1
645	bne.b		_L0_2d
646	bsr.l		ssin			# operand is a NORM
647	bra.b		_L0_6d
648_L0_2d:
649	cmpi.b		%d1,&ZERO		# is operand a ZERO?
650	bne.b		_L0_3d			# no
651	bsr.l		src_zero			# yes
652	bra.b		_L0_6d
653_L0_3d:
654	cmpi.b		%d1,&INF		# is operand an INF?
655	bne.b		_L0_4d			# no
656	bsr.l		t_operr			# yes
657	bra.b		_L0_6d
658_L0_4d:
659	cmpi.b		%d1,&QNAN		# is operand a QNAN?
660	bne.b		_L0_5d			# no
661	bsr.l		src_qnan			# yes
662	bra.b		_L0_6d
663_L0_5d:
664	bsr.l		ssind			# operand is a DENORM
665_L0_6d:
666
667#
668#	Result is now in FP0
669#
670	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
671	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
672	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
673	unlk		%a6
674	rts
675
676	global		_fsinx_
677_fsinx_:
678	link		%a6,&-LOCAL_SIZE
679
680	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
681	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
682	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
683
684	fmov.l		&0x0,%fpcr		# zero FPCR
685
686#
687#	copy, convert, and tag input argument
688#
689	lea		FP_SRC(%a6),%a0
690	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
691	mov.l		0x8+0x4(%a6),0x4(%a0)
692	mov.l		0x8+0x8(%a6),0x8(%a0)
693	bsr.l		tag			# fetch operand type
694	mov.b		%d0,STAG(%a6)
695	mov.b		%d0,%d1
696
697	andi.l		&0x00ff00ff,USER_FPSR(%a6)
698
699	clr.l		%d0
700	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
701
702	tst.b		%d1
703	bne.b		_L0_2x
704	bsr.l		ssin			# operand is a NORM
705	bra.b		_L0_6x
706_L0_2x:
707	cmpi.b		%d1,&ZERO		# is operand a ZERO?
708	bne.b		_L0_3x			# no
709	bsr.l		src_zero			# yes
710	bra.b		_L0_6x
711_L0_3x:
712	cmpi.b		%d1,&INF		# is operand an INF?
713	bne.b		_L0_4x			# no
714	bsr.l		t_operr			# yes
715	bra.b		_L0_6x
716_L0_4x:
717	cmpi.b		%d1,&QNAN		# is operand a QNAN?
718	bne.b		_L0_5x			# no
719	bsr.l		src_qnan			# yes
720	bra.b		_L0_6x
721_L0_5x:
722	bsr.l		ssind			# operand is a DENORM
723_L0_6x:
724
725#
726#	Result is now in FP0
727#
728	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
729	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
730	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
731	unlk		%a6
732	rts
733
734
735#########################################################################
736# MONADIC TEMPLATE							#
737#########################################################################
738	global		_fcoss_
739_fcoss_:
740	link		%a6,&-LOCAL_SIZE
741
742	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
743	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
744	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
745
746	fmov.l		&0x0,%fpcr		# zero FPCR
747
748#
749#	copy, convert, and tag input argument
750#
751	fmov.s		0x8(%a6),%fp0		# load sgl input
752	fmov.x		%fp0,FP_SRC(%a6)
753	lea		FP_SRC(%a6),%a0
754	bsr.l		tag			# fetch operand type
755	mov.b		%d0,STAG(%a6)
756	mov.b		%d0,%d1
757
758	andi.l		&0x00ff00ff,USER_FPSR(%a6)
759
760	clr.l		%d0
761	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
762
763	tst.b		%d1
764	bne.b		_L1_2s
765	bsr.l		scos			# operand is a NORM
766	bra.b		_L1_6s
767_L1_2s:
768	cmpi.b		%d1,&ZERO		# is operand a ZERO?
769	bne.b		_L1_3s			# no
770	bsr.l		ld_pone			# yes
771	bra.b		_L1_6s
772_L1_3s:
773	cmpi.b		%d1,&INF		# is operand an INF?
774	bne.b		_L1_4s			# no
775	bsr.l		t_operr			# yes
776	bra.b		_L1_6s
777_L1_4s:
778	cmpi.b		%d1,&QNAN		# is operand a QNAN?
779	bne.b		_L1_5s			# no
780	bsr.l		src_qnan			# yes
781	bra.b		_L1_6s
782_L1_5s:
783	bsr.l		scosd			# operand is a DENORM
784_L1_6s:
785
786#
787#	Result is now in FP0
788#
789	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
790	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
791	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
792	unlk		%a6
793	rts
794
795	global		_fcosd_
796_fcosd_:
797	link		%a6,&-LOCAL_SIZE
798
799	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
800	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
801	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
802
803	fmov.l		&0x0,%fpcr		# zero FPCR
804
805#
806#	copy, convert, and tag input argument
807#
808	fmov.d		0x8(%a6),%fp0		# load dbl input
809	fmov.x		%fp0,FP_SRC(%a6)
810	lea		FP_SRC(%a6),%a0
811	bsr.l		tag			# fetch operand type
812	mov.b		%d0,STAG(%a6)
813	mov.b		%d0,%d1
814
815	andi.l		&0x00ff00ff,USER_FPSR(%a6)
816
817	clr.l		%d0
818	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
819
820	mov.b		%d1,STAG(%a6)
821	tst.b		%d1
822	bne.b		_L1_2d
823	bsr.l		scos			# operand is a NORM
824	bra.b		_L1_6d
825_L1_2d:
826	cmpi.b		%d1,&ZERO		# is operand a ZERO?
827	bne.b		_L1_3d			# no
828	bsr.l		ld_pone			# yes
829	bra.b		_L1_6d
830_L1_3d:
831	cmpi.b		%d1,&INF		# is operand an INF?
832	bne.b		_L1_4d			# no
833	bsr.l		t_operr			# yes
834	bra.b		_L1_6d
835_L1_4d:
836	cmpi.b		%d1,&QNAN		# is operand a QNAN?
837	bne.b		_L1_5d			# no
838	bsr.l		src_qnan			# yes
839	bra.b		_L1_6d
840_L1_5d:
841	bsr.l		scosd			# operand is a DENORM
842_L1_6d:
843
844#
845#	Result is now in FP0
846#
847	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
848	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
849	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
850	unlk		%a6
851	rts
852
853	global		_fcosx_
854_fcosx_:
855	link		%a6,&-LOCAL_SIZE
856
857	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
858	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
859	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
860
861	fmov.l		&0x0,%fpcr		# zero FPCR
862
863#
864#	copy, convert, and tag input argument
865#
866	lea		FP_SRC(%a6),%a0
867	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
868	mov.l		0x8+0x4(%a6),0x4(%a0)
869	mov.l		0x8+0x8(%a6),0x8(%a0)
870	bsr.l		tag			# fetch operand type
871	mov.b		%d0,STAG(%a6)
872	mov.b		%d0,%d1
873
874	andi.l		&0x00ff00ff,USER_FPSR(%a6)
875
876	clr.l		%d0
877	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
878
879	tst.b		%d1
880	bne.b		_L1_2x
881	bsr.l		scos			# operand is a NORM
882	bra.b		_L1_6x
883_L1_2x:
884	cmpi.b		%d1,&ZERO		# is operand a ZERO?
885	bne.b		_L1_3x			# no
886	bsr.l		ld_pone			# yes
887	bra.b		_L1_6x
888_L1_3x:
889	cmpi.b		%d1,&INF		# is operand an INF?
890	bne.b		_L1_4x			# no
891	bsr.l		t_operr			# yes
892	bra.b		_L1_6x
893_L1_4x:
894	cmpi.b		%d1,&QNAN		# is operand a QNAN?
895	bne.b		_L1_5x			# no
896	bsr.l		src_qnan			# yes
897	bra.b		_L1_6x
898_L1_5x:
899	bsr.l		scosd			# operand is a DENORM
900_L1_6x:
901
902#
903#	Result is now in FP0
904#
905	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
906	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
907	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
908	unlk		%a6
909	rts
910
911
912#########################################################################
913# MONADIC TEMPLATE							#
914#########################################################################
915	global		_fsinhs_
916_fsinhs_:
917	link		%a6,&-LOCAL_SIZE
918
919	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
920	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
921	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
922
923	fmov.l		&0x0,%fpcr		# zero FPCR
924
925#
926#	copy, convert, and tag input argument
927#
928	fmov.s		0x8(%a6),%fp0		# load sgl input
929	fmov.x		%fp0,FP_SRC(%a6)
930	lea		FP_SRC(%a6),%a0
931	bsr.l		tag			# fetch operand type
932	mov.b		%d0,STAG(%a6)
933	mov.b		%d0,%d1
934
935	andi.l		&0x00ff00ff,USER_FPSR(%a6)
936
937	clr.l		%d0
938	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
939
940	tst.b		%d1
941	bne.b		_L2_2s
942	bsr.l		ssinh			# operand is a NORM
943	bra.b		_L2_6s
944_L2_2s:
945	cmpi.b		%d1,&ZERO		# is operand a ZERO?
946	bne.b		_L2_3s			# no
947	bsr.l		src_zero			# yes
948	bra.b		_L2_6s
949_L2_3s:
950	cmpi.b		%d1,&INF		# is operand an INF?
951	bne.b		_L2_4s			# no
952	bsr.l		src_inf			# yes
953	bra.b		_L2_6s
954_L2_4s:
955	cmpi.b		%d1,&QNAN		# is operand a QNAN?
956	bne.b		_L2_5s			# no
957	bsr.l		src_qnan			# yes
958	bra.b		_L2_6s
959_L2_5s:
960	bsr.l		ssinhd			# operand is a DENORM
961_L2_6s:
962
963#
964#	Result is now in FP0
965#
966	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
967	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
968	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
969	unlk		%a6
970	rts
971
972	global		_fsinhd_
973_fsinhd_:
974	link		%a6,&-LOCAL_SIZE
975
976	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
977	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
978	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
979
980	fmov.l		&0x0,%fpcr		# zero FPCR
981
982#
983#	copy, convert, and tag input argument
984#
985	fmov.d		0x8(%a6),%fp0		# load dbl input
986	fmov.x		%fp0,FP_SRC(%a6)
987	lea		FP_SRC(%a6),%a0
988	bsr.l		tag			# fetch operand type
989	mov.b		%d0,STAG(%a6)
990	mov.b		%d0,%d1
991
992	andi.l		&0x00ff00ff,USER_FPSR(%a6)
993
994	clr.l		%d0
995	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
996
997	mov.b		%d1,STAG(%a6)
998	tst.b		%d1
999	bne.b		_L2_2d
1000	bsr.l		ssinh			# operand is a NORM
1001	bra.b		_L2_6d
1002_L2_2d:
1003	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1004	bne.b		_L2_3d			# no
1005	bsr.l		src_zero			# yes
1006	bra.b		_L2_6d
1007_L2_3d:
1008	cmpi.b		%d1,&INF		# is operand an INF?
1009	bne.b		_L2_4d			# no
1010	bsr.l		src_inf			# yes
1011	bra.b		_L2_6d
1012_L2_4d:
1013	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1014	bne.b		_L2_5d			# no
1015	bsr.l		src_qnan			# yes
1016	bra.b		_L2_6d
1017_L2_5d:
1018	bsr.l		ssinhd			# operand is a DENORM
1019_L2_6d:
1020
1021#
1022#	Result is now in FP0
1023#
1024	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1025	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1026	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1027	unlk		%a6
1028	rts
1029
1030	global		_fsinhx_
1031_fsinhx_:
1032	link		%a6,&-LOCAL_SIZE
1033
1034	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1035	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1036	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1037
1038	fmov.l		&0x0,%fpcr		# zero FPCR
1039
1040#
1041#	copy, convert, and tag input argument
1042#
1043	lea		FP_SRC(%a6),%a0
1044	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
1045	mov.l		0x8+0x4(%a6),0x4(%a0)
1046	mov.l		0x8+0x8(%a6),0x8(%a0)
1047	bsr.l		tag			# fetch operand type
1048	mov.b		%d0,STAG(%a6)
1049	mov.b		%d0,%d1
1050
1051	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1052
1053	clr.l		%d0
1054	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1055
1056	tst.b		%d1
1057	bne.b		_L2_2x
1058	bsr.l		ssinh			# operand is a NORM
1059	bra.b		_L2_6x
1060_L2_2x:
1061	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1062	bne.b		_L2_3x			# no
1063	bsr.l		src_zero			# yes
1064	bra.b		_L2_6x
1065_L2_3x:
1066	cmpi.b		%d1,&INF		# is operand an INF?
1067	bne.b		_L2_4x			# no
1068	bsr.l		src_inf			# yes
1069	bra.b		_L2_6x
1070_L2_4x:
1071	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1072	bne.b		_L2_5x			# no
1073	bsr.l		src_qnan			# yes
1074	bra.b		_L2_6x
1075_L2_5x:
1076	bsr.l		ssinhd			# operand is a DENORM
1077_L2_6x:
1078
1079#
1080#	Result is now in FP0
1081#
1082	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1083	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1084	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1085	unlk		%a6
1086	rts
1087
1088
1089#########################################################################
1090# MONADIC TEMPLATE							#
1091#########################################################################
1092	global		_flognp1s_
1093_flognp1s_:
1094	link		%a6,&-LOCAL_SIZE
1095
1096	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1097	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1098	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1099
1100	fmov.l		&0x0,%fpcr		# zero FPCR
1101
1102#
1103#	copy, convert, and tag input argument
1104#
1105	fmov.s		0x8(%a6),%fp0		# load sgl input
1106	fmov.x		%fp0,FP_SRC(%a6)
1107	lea		FP_SRC(%a6),%a0
1108	bsr.l		tag			# fetch operand type
1109	mov.b		%d0,STAG(%a6)
1110	mov.b		%d0,%d1
1111
1112	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1113
1114	clr.l		%d0
1115	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1116
1117	tst.b		%d1
1118	bne.b		_L3_2s
1119	bsr.l		slognp1			# operand is a NORM
1120	bra.b		_L3_6s
1121_L3_2s:
1122	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1123	bne.b		_L3_3s			# no
1124	bsr.l		src_zero			# yes
1125	bra.b		_L3_6s
1126_L3_3s:
1127	cmpi.b		%d1,&INF		# is operand an INF?
1128	bne.b		_L3_4s			# no
1129	bsr.l		sopr_inf			# yes
1130	bra.b		_L3_6s
1131_L3_4s:
1132	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1133	bne.b		_L3_5s			# no
1134	bsr.l		src_qnan			# yes
1135	bra.b		_L3_6s
1136_L3_5s:
1137	bsr.l		slognp1d			# operand is a DENORM
1138_L3_6s:
1139
1140#
1141#	Result is now in FP0
1142#
1143	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1144	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1145	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1146	unlk		%a6
1147	rts
1148
1149	global		_flognp1d_
1150_flognp1d_:
1151	link		%a6,&-LOCAL_SIZE
1152
1153	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1154	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1155	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1156
1157	fmov.l		&0x0,%fpcr		# zero FPCR
1158
1159#
1160#	copy, convert, and tag input argument
1161#
1162	fmov.d		0x8(%a6),%fp0		# load dbl input
1163	fmov.x		%fp0,FP_SRC(%a6)
1164	lea		FP_SRC(%a6),%a0
1165	bsr.l		tag			# fetch operand type
1166	mov.b		%d0,STAG(%a6)
1167	mov.b		%d0,%d1
1168
1169	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1170
1171	clr.l		%d0
1172	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1173
1174	mov.b		%d1,STAG(%a6)
1175	tst.b		%d1
1176	bne.b		_L3_2d
1177	bsr.l		slognp1			# operand is a NORM
1178	bra.b		_L3_6d
1179_L3_2d:
1180	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1181	bne.b		_L3_3d			# no
1182	bsr.l		src_zero			# yes
1183	bra.b		_L3_6d
1184_L3_3d:
1185	cmpi.b		%d1,&INF		# is operand an INF?
1186	bne.b		_L3_4d			# no
1187	bsr.l		sopr_inf			# yes
1188	bra.b		_L3_6d
1189_L3_4d:
1190	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1191	bne.b		_L3_5d			# no
1192	bsr.l		src_qnan			# yes
1193	bra.b		_L3_6d
1194_L3_5d:
1195	bsr.l		slognp1d			# operand is a DENORM
1196_L3_6d:
1197
1198#
1199#	Result is now in FP0
1200#
1201	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1202	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1203	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1204	unlk		%a6
1205	rts
1206
1207	global		_flognp1x_
1208_flognp1x_:
1209	link		%a6,&-LOCAL_SIZE
1210
1211	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1212	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1213	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1214
1215	fmov.l		&0x0,%fpcr		# zero FPCR
1216
1217#
1218#	copy, convert, and tag input argument
1219#
1220	lea		FP_SRC(%a6),%a0
1221	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
1222	mov.l		0x8+0x4(%a6),0x4(%a0)
1223	mov.l		0x8+0x8(%a6),0x8(%a0)
1224	bsr.l		tag			# fetch operand type
1225	mov.b		%d0,STAG(%a6)
1226	mov.b		%d0,%d1
1227
1228	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1229
1230	clr.l		%d0
1231	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1232
1233	tst.b		%d1
1234	bne.b		_L3_2x
1235	bsr.l		slognp1			# operand is a NORM
1236	bra.b		_L3_6x
1237_L3_2x:
1238	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1239	bne.b		_L3_3x			# no
1240	bsr.l		src_zero			# yes
1241	bra.b		_L3_6x
1242_L3_3x:
1243	cmpi.b		%d1,&INF		# is operand an INF?
1244	bne.b		_L3_4x			# no
1245	bsr.l		sopr_inf			# yes
1246	bra.b		_L3_6x
1247_L3_4x:
1248	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1249	bne.b		_L3_5x			# no
1250	bsr.l		src_qnan			# yes
1251	bra.b		_L3_6x
1252_L3_5x:
1253	bsr.l		slognp1d			# operand is a DENORM
1254_L3_6x:
1255
1256#
1257#	Result is now in FP0
1258#
1259	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1260	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1261	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1262	unlk		%a6
1263	rts
1264
1265
1266#########################################################################
1267# MONADIC TEMPLATE							#
1268#########################################################################
1269	global		_fetoxm1s_
1270_fetoxm1s_:
1271	link		%a6,&-LOCAL_SIZE
1272
1273	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1274	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1275	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1276
1277	fmov.l		&0x0,%fpcr		# zero FPCR
1278
1279#
1280#	copy, convert, and tag input argument
1281#
1282	fmov.s		0x8(%a6),%fp0		# load sgl input
1283	fmov.x		%fp0,FP_SRC(%a6)
1284	lea		FP_SRC(%a6),%a0
1285	bsr.l		tag			# fetch operand type
1286	mov.b		%d0,STAG(%a6)
1287	mov.b		%d0,%d1
1288
1289	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1290
1291	clr.l		%d0
1292	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1293
1294	tst.b		%d1
1295	bne.b		_L4_2s
1296	bsr.l		setoxm1			# operand is a NORM
1297	bra.b		_L4_6s
1298_L4_2s:
1299	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1300	bne.b		_L4_3s			# no
1301	bsr.l		src_zero			# yes
1302	bra.b		_L4_6s
1303_L4_3s:
1304	cmpi.b		%d1,&INF		# is operand an INF?
1305	bne.b		_L4_4s			# no
1306	bsr.l		setoxm1i			# yes
1307	bra.b		_L4_6s
1308_L4_4s:
1309	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1310	bne.b		_L4_5s			# no
1311	bsr.l		src_qnan			# yes
1312	bra.b		_L4_6s
1313_L4_5s:
1314	bsr.l		setoxm1d			# operand is a DENORM
1315_L4_6s:
1316
1317#
1318#	Result is now in FP0
1319#
1320	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1321	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1322	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1323	unlk		%a6
1324	rts
1325
1326	global		_fetoxm1d_
1327_fetoxm1d_:
1328	link		%a6,&-LOCAL_SIZE
1329
1330	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1331	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1332	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1333
1334	fmov.l		&0x0,%fpcr		# zero FPCR
1335
1336#
1337#	copy, convert, and tag input argument
1338#
1339	fmov.d		0x8(%a6),%fp0		# load dbl input
1340	fmov.x		%fp0,FP_SRC(%a6)
1341	lea		FP_SRC(%a6),%a0
1342	bsr.l		tag			# fetch operand type
1343	mov.b		%d0,STAG(%a6)
1344	mov.b		%d0,%d1
1345
1346	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1347
1348	clr.l		%d0
1349	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1350
1351	mov.b		%d1,STAG(%a6)
1352	tst.b		%d1
1353	bne.b		_L4_2d
1354	bsr.l		setoxm1			# operand is a NORM
1355	bra.b		_L4_6d
1356_L4_2d:
1357	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1358	bne.b		_L4_3d			# no
1359	bsr.l		src_zero			# yes
1360	bra.b		_L4_6d
1361_L4_3d:
1362	cmpi.b		%d1,&INF		# is operand an INF?
1363	bne.b		_L4_4d			# no
1364	bsr.l		setoxm1i			# yes
1365	bra.b		_L4_6d
1366_L4_4d:
1367	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1368	bne.b		_L4_5d			# no
1369	bsr.l		src_qnan			# yes
1370	bra.b		_L4_6d
1371_L4_5d:
1372	bsr.l		setoxm1d			# operand is a DENORM
1373_L4_6d:
1374
1375#
1376#	Result is now in FP0
1377#
1378	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1379	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1380	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1381	unlk		%a6
1382	rts
1383
1384	global		_fetoxm1x_
1385_fetoxm1x_:
1386	link		%a6,&-LOCAL_SIZE
1387
1388	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1389	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1390	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1391
1392	fmov.l		&0x0,%fpcr		# zero FPCR
1393
1394#
1395#	copy, convert, and tag input argument
1396#
1397	lea		FP_SRC(%a6),%a0
1398	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
1399	mov.l		0x8+0x4(%a6),0x4(%a0)
1400	mov.l		0x8+0x8(%a6),0x8(%a0)
1401	bsr.l		tag			# fetch operand type
1402	mov.b		%d0,STAG(%a6)
1403	mov.b		%d0,%d1
1404
1405	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1406
1407	clr.l		%d0
1408	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1409
1410	tst.b		%d1
1411	bne.b		_L4_2x
1412	bsr.l		setoxm1			# operand is a NORM
1413	bra.b		_L4_6x
1414_L4_2x:
1415	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1416	bne.b		_L4_3x			# no
1417	bsr.l		src_zero			# yes
1418	bra.b		_L4_6x
1419_L4_3x:
1420	cmpi.b		%d1,&INF		# is operand an INF?
1421	bne.b		_L4_4x			# no
1422	bsr.l		setoxm1i			# yes
1423	bra.b		_L4_6x
1424_L4_4x:
1425	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1426	bne.b		_L4_5x			# no
1427	bsr.l		src_qnan			# yes
1428	bra.b		_L4_6x
1429_L4_5x:
1430	bsr.l		setoxm1d			# operand is a DENORM
1431_L4_6x:
1432
1433#
1434#	Result is now in FP0
1435#
1436	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1437	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1438	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1439	unlk		%a6
1440	rts
1441
1442
1443#########################################################################
1444# MONADIC TEMPLATE							#
1445#########################################################################
1446	global		_ftanhs_
1447_ftanhs_:
1448	link		%a6,&-LOCAL_SIZE
1449
1450	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1451	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1452	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1453
1454	fmov.l		&0x0,%fpcr		# zero FPCR
1455
1456#
1457#	copy, convert, and tag input argument
1458#
1459	fmov.s		0x8(%a6),%fp0		# load sgl input
1460	fmov.x		%fp0,FP_SRC(%a6)
1461	lea		FP_SRC(%a6),%a0
1462	bsr.l		tag			# fetch operand type
1463	mov.b		%d0,STAG(%a6)
1464	mov.b		%d0,%d1
1465
1466	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1467
1468	clr.l		%d0
1469	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1470
1471	tst.b		%d1
1472	bne.b		_L5_2s
1473	bsr.l		stanh			# operand is a NORM
1474	bra.b		_L5_6s
1475_L5_2s:
1476	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1477	bne.b		_L5_3s			# no
1478	bsr.l		src_zero			# yes
1479	bra.b		_L5_6s
1480_L5_3s:
1481	cmpi.b		%d1,&INF		# is operand an INF?
1482	bne.b		_L5_4s			# no
1483	bsr.l		src_one			# yes
1484	bra.b		_L5_6s
1485_L5_4s:
1486	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1487	bne.b		_L5_5s			# no
1488	bsr.l		src_qnan			# yes
1489	bra.b		_L5_6s
1490_L5_5s:
1491	bsr.l		stanhd			# operand is a DENORM
1492_L5_6s:
1493
1494#
1495#	Result is now in FP0
1496#
1497	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1498	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1499	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1500	unlk		%a6
1501	rts
1502
1503	global		_ftanhd_
1504_ftanhd_:
1505	link		%a6,&-LOCAL_SIZE
1506
1507	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1508	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1509	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1510
1511	fmov.l		&0x0,%fpcr		# zero FPCR
1512
1513#
1514#	copy, convert, and tag input argument
1515#
1516	fmov.d		0x8(%a6),%fp0		# load dbl input
1517	fmov.x		%fp0,FP_SRC(%a6)
1518	lea		FP_SRC(%a6),%a0
1519	bsr.l		tag			# fetch operand type
1520	mov.b		%d0,STAG(%a6)
1521	mov.b		%d0,%d1
1522
1523	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1524
1525	clr.l		%d0
1526	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1527
1528	mov.b		%d1,STAG(%a6)
1529	tst.b		%d1
1530	bne.b		_L5_2d
1531	bsr.l		stanh			# operand is a NORM
1532	bra.b		_L5_6d
1533_L5_2d:
1534	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1535	bne.b		_L5_3d			# no
1536	bsr.l		src_zero			# yes
1537	bra.b		_L5_6d
1538_L5_3d:
1539	cmpi.b		%d1,&INF		# is operand an INF?
1540	bne.b		_L5_4d			# no
1541	bsr.l		src_one			# yes
1542	bra.b		_L5_6d
1543_L5_4d:
1544	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1545	bne.b		_L5_5d			# no
1546	bsr.l		src_qnan			# yes
1547	bra.b		_L5_6d
1548_L5_5d:
1549	bsr.l		stanhd			# operand is a DENORM
1550_L5_6d:
1551
1552#
1553#	Result is now in FP0
1554#
1555	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1556	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1557	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1558	unlk		%a6
1559	rts
1560
1561	global		_ftanhx_
1562_ftanhx_:
1563	link		%a6,&-LOCAL_SIZE
1564
1565	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1566	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1567	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1568
1569	fmov.l		&0x0,%fpcr		# zero FPCR
1570
1571#
1572#	copy, convert, and tag input argument
1573#
1574	lea		FP_SRC(%a6),%a0
1575	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
1576	mov.l		0x8+0x4(%a6),0x4(%a0)
1577	mov.l		0x8+0x8(%a6),0x8(%a0)
1578	bsr.l		tag			# fetch operand type
1579	mov.b		%d0,STAG(%a6)
1580	mov.b		%d0,%d1
1581
1582	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1583
1584	clr.l		%d0
1585	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1586
1587	tst.b		%d1
1588	bne.b		_L5_2x
1589	bsr.l		stanh			# operand is a NORM
1590	bra.b		_L5_6x
1591_L5_2x:
1592	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1593	bne.b		_L5_3x			# no
1594	bsr.l		src_zero			# yes
1595	bra.b		_L5_6x
1596_L5_3x:
1597	cmpi.b		%d1,&INF		# is operand an INF?
1598	bne.b		_L5_4x			# no
1599	bsr.l		src_one			# yes
1600	bra.b		_L5_6x
1601_L5_4x:
1602	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1603	bne.b		_L5_5x			# no
1604	bsr.l		src_qnan			# yes
1605	bra.b		_L5_6x
1606_L5_5x:
1607	bsr.l		stanhd			# operand is a DENORM
1608_L5_6x:
1609
1610#
1611#	Result is now in FP0
1612#
1613	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1614	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1615	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1616	unlk		%a6
1617	rts
1618
1619
1620#########################################################################
1621# MONADIC TEMPLATE							#
1622#########################################################################
1623	global		_fatans_
1624_fatans_:
1625	link		%a6,&-LOCAL_SIZE
1626
1627	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1628	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1629	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1630
1631	fmov.l		&0x0,%fpcr		# zero FPCR
1632
1633#
1634#	copy, convert, and tag input argument
1635#
1636	fmov.s		0x8(%a6),%fp0		# load sgl input
1637	fmov.x		%fp0,FP_SRC(%a6)
1638	lea		FP_SRC(%a6),%a0
1639	bsr.l		tag			# fetch operand type
1640	mov.b		%d0,STAG(%a6)
1641	mov.b		%d0,%d1
1642
1643	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1644
1645	clr.l		%d0
1646	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1647
1648	tst.b		%d1
1649	bne.b		_L6_2s
1650	bsr.l		satan			# operand is a NORM
1651	bra.b		_L6_6s
1652_L6_2s:
1653	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1654	bne.b		_L6_3s			# no
1655	bsr.l		src_zero			# yes
1656	bra.b		_L6_6s
1657_L6_3s:
1658	cmpi.b		%d1,&INF		# is operand an INF?
1659	bne.b		_L6_4s			# no
1660	bsr.l		spi_2			# yes
1661	bra.b		_L6_6s
1662_L6_4s:
1663	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1664	bne.b		_L6_5s			# no
1665	bsr.l		src_qnan			# yes
1666	bra.b		_L6_6s
1667_L6_5s:
1668	bsr.l		satand			# operand is a DENORM
1669_L6_6s:
1670
1671#
1672#	Result is now in FP0
1673#
1674	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1675	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1676	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1677	unlk		%a6
1678	rts
1679
1680	global		_fatand_
1681_fatand_:
1682	link		%a6,&-LOCAL_SIZE
1683
1684	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1685	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1686	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1687
1688	fmov.l		&0x0,%fpcr		# zero FPCR
1689
1690#
1691#	copy, convert, and tag input argument
1692#
1693	fmov.d		0x8(%a6),%fp0		# load dbl input
1694	fmov.x		%fp0,FP_SRC(%a6)
1695	lea		FP_SRC(%a6),%a0
1696	bsr.l		tag			# fetch operand type
1697	mov.b		%d0,STAG(%a6)
1698	mov.b		%d0,%d1
1699
1700	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1701
1702	clr.l		%d0
1703	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1704
1705	mov.b		%d1,STAG(%a6)
1706	tst.b		%d1
1707	bne.b		_L6_2d
1708	bsr.l		satan			# operand is a NORM
1709	bra.b		_L6_6d
1710_L6_2d:
1711	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1712	bne.b		_L6_3d			# no
1713	bsr.l		src_zero			# yes
1714	bra.b		_L6_6d
1715_L6_3d:
1716	cmpi.b		%d1,&INF		# is operand an INF?
1717	bne.b		_L6_4d			# no
1718	bsr.l		spi_2			# yes
1719	bra.b		_L6_6d
1720_L6_4d:
1721	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1722	bne.b		_L6_5d			# no
1723	bsr.l		src_qnan			# yes
1724	bra.b		_L6_6d
1725_L6_5d:
1726	bsr.l		satand			# operand is a DENORM
1727_L6_6d:
1728
1729#
1730#	Result is now in FP0
1731#
1732	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1733	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1734	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1735	unlk		%a6
1736	rts
1737
1738	global		_fatanx_
1739_fatanx_:
1740	link		%a6,&-LOCAL_SIZE
1741
1742	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1743	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1744	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1745
1746	fmov.l		&0x0,%fpcr		# zero FPCR
1747
1748#
1749#	copy, convert, and tag input argument
1750#
1751	lea		FP_SRC(%a6),%a0
1752	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
1753	mov.l		0x8+0x4(%a6),0x4(%a0)
1754	mov.l		0x8+0x8(%a6),0x8(%a0)
1755	bsr.l		tag			# fetch operand type
1756	mov.b		%d0,STAG(%a6)
1757	mov.b		%d0,%d1
1758
1759	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1760
1761	clr.l		%d0
1762	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1763
1764	tst.b		%d1
1765	bne.b		_L6_2x
1766	bsr.l		satan			# operand is a NORM
1767	bra.b		_L6_6x
1768_L6_2x:
1769	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1770	bne.b		_L6_3x			# no
1771	bsr.l		src_zero			# yes
1772	bra.b		_L6_6x
1773_L6_3x:
1774	cmpi.b		%d1,&INF		# is operand an INF?
1775	bne.b		_L6_4x			# no
1776	bsr.l		spi_2			# yes
1777	bra.b		_L6_6x
1778_L6_4x:
1779	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1780	bne.b		_L6_5x			# no
1781	bsr.l		src_qnan			# yes
1782	bra.b		_L6_6x
1783_L6_5x:
1784	bsr.l		satand			# operand is a DENORM
1785_L6_6x:
1786
1787#
1788#	Result is now in FP0
1789#
1790	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1791	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1792	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1793	unlk		%a6
1794	rts
1795
1796
1797#########################################################################
1798# MONADIC TEMPLATE							#
1799#########################################################################
1800	global		_fasins_
1801_fasins_:
1802	link		%a6,&-LOCAL_SIZE
1803
1804	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1805	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1806	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1807
1808	fmov.l		&0x0,%fpcr		# zero FPCR
1809
1810#
1811#	copy, convert, and tag input argument
1812#
1813	fmov.s		0x8(%a6),%fp0		# load sgl input
1814	fmov.x		%fp0,FP_SRC(%a6)
1815	lea		FP_SRC(%a6),%a0
1816	bsr.l		tag			# fetch operand type
1817	mov.b		%d0,STAG(%a6)
1818	mov.b		%d0,%d1
1819
1820	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1821
1822	clr.l		%d0
1823	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1824
1825	tst.b		%d1
1826	bne.b		_L7_2s
1827	bsr.l		sasin			# operand is a NORM
1828	bra.b		_L7_6s
1829_L7_2s:
1830	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1831	bne.b		_L7_3s			# no
1832	bsr.l		src_zero			# yes
1833	bra.b		_L7_6s
1834_L7_3s:
1835	cmpi.b		%d1,&INF		# is operand an INF?
1836	bne.b		_L7_4s			# no
1837	bsr.l		t_operr			# yes
1838	bra.b		_L7_6s
1839_L7_4s:
1840	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1841	bne.b		_L7_5s			# no
1842	bsr.l		src_qnan			# yes
1843	bra.b		_L7_6s
1844_L7_5s:
1845	bsr.l		sasind			# operand is a DENORM
1846_L7_6s:
1847
1848#
1849#	Result is now in FP0
1850#
1851	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1852	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1853	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1854	unlk		%a6
1855	rts
1856
1857	global		_fasind_
1858_fasind_:
1859	link		%a6,&-LOCAL_SIZE
1860
1861	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1862	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1863	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1864
1865	fmov.l		&0x0,%fpcr		# zero FPCR
1866
1867#
1868#	copy, convert, and tag input argument
1869#
1870	fmov.d		0x8(%a6),%fp0		# load dbl input
1871	fmov.x		%fp0,FP_SRC(%a6)
1872	lea		FP_SRC(%a6),%a0
1873	bsr.l		tag			# fetch operand type
1874	mov.b		%d0,STAG(%a6)
1875	mov.b		%d0,%d1
1876
1877	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1878
1879	clr.l		%d0
1880	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1881
1882	mov.b		%d1,STAG(%a6)
1883	tst.b		%d1
1884	bne.b		_L7_2d
1885	bsr.l		sasin			# operand is a NORM
1886	bra.b		_L7_6d
1887_L7_2d:
1888	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1889	bne.b		_L7_3d			# no
1890	bsr.l		src_zero			# yes
1891	bra.b		_L7_6d
1892_L7_3d:
1893	cmpi.b		%d1,&INF		# is operand an INF?
1894	bne.b		_L7_4d			# no
1895	bsr.l		t_operr			# yes
1896	bra.b		_L7_6d
1897_L7_4d:
1898	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1899	bne.b		_L7_5d			# no
1900	bsr.l		src_qnan			# yes
1901	bra.b		_L7_6d
1902_L7_5d:
1903	bsr.l		sasind			# operand is a DENORM
1904_L7_6d:
1905
1906#
1907#	Result is now in FP0
1908#
1909	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1910	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1911	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1912	unlk		%a6
1913	rts
1914
1915	global		_fasinx_
1916_fasinx_:
1917	link		%a6,&-LOCAL_SIZE
1918
1919	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1920	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1921	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1922
1923	fmov.l		&0x0,%fpcr		# zero FPCR
1924
1925#
1926#	copy, convert, and tag input argument
1927#
1928	lea		FP_SRC(%a6),%a0
1929	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
1930	mov.l		0x8+0x4(%a6),0x4(%a0)
1931	mov.l		0x8+0x8(%a6),0x8(%a0)
1932	bsr.l		tag			# fetch operand type
1933	mov.b		%d0,STAG(%a6)
1934	mov.b		%d0,%d1
1935
1936	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1937
1938	clr.l		%d0
1939	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
1940
1941	tst.b		%d1
1942	bne.b		_L7_2x
1943	bsr.l		sasin			# operand is a NORM
1944	bra.b		_L7_6x
1945_L7_2x:
1946	cmpi.b		%d1,&ZERO		# is operand a ZERO?
1947	bne.b		_L7_3x			# no
1948	bsr.l		src_zero			# yes
1949	bra.b		_L7_6x
1950_L7_3x:
1951	cmpi.b		%d1,&INF		# is operand an INF?
1952	bne.b		_L7_4x			# no
1953	bsr.l		t_operr			# yes
1954	bra.b		_L7_6x
1955_L7_4x:
1956	cmpi.b		%d1,&QNAN		# is operand a QNAN?
1957	bne.b		_L7_5x			# no
1958	bsr.l		src_qnan			# yes
1959	bra.b		_L7_6x
1960_L7_5x:
1961	bsr.l		sasind			# operand is a DENORM
1962_L7_6x:
1963
1964#
1965#	Result is now in FP0
1966#
1967	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
1968	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1969	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
1970	unlk		%a6
1971	rts
1972
1973
1974#########################################################################
1975# MONADIC TEMPLATE							#
1976#########################################################################
1977	global		_fatanhs_
1978_fatanhs_:
1979	link		%a6,&-LOCAL_SIZE
1980
1981	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
1982	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1983	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
1984
1985	fmov.l		&0x0,%fpcr		# zero FPCR
1986
1987#
1988#	copy, convert, and tag input argument
1989#
1990	fmov.s		0x8(%a6),%fp0		# load sgl input
1991	fmov.x		%fp0,FP_SRC(%a6)
1992	lea		FP_SRC(%a6),%a0
1993	bsr.l		tag			# fetch operand type
1994	mov.b		%d0,STAG(%a6)
1995	mov.b		%d0,%d1
1996
1997	andi.l		&0x00ff00ff,USER_FPSR(%a6)
1998
1999	clr.l		%d0
2000	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2001
2002	tst.b		%d1
2003	bne.b		_L8_2s
2004	bsr.l		satanh			# operand is a NORM
2005	bra.b		_L8_6s
2006_L8_2s:
2007	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2008	bne.b		_L8_3s			# no
2009	bsr.l		src_zero			# yes
2010	bra.b		_L8_6s
2011_L8_3s:
2012	cmpi.b		%d1,&INF		# is operand an INF?
2013	bne.b		_L8_4s			# no
2014	bsr.l		t_operr			# yes
2015	bra.b		_L8_6s
2016_L8_4s:
2017	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2018	bne.b		_L8_5s			# no
2019	bsr.l		src_qnan			# yes
2020	bra.b		_L8_6s
2021_L8_5s:
2022	bsr.l		satanhd			# operand is a DENORM
2023_L8_6s:
2024
2025#
2026#	Result is now in FP0
2027#
2028	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2029	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2030	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2031	unlk		%a6
2032	rts
2033
2034	global		_fatanhd_
2035_fatanhd_:
2036	link		%a6,&-LOCAL_SIZE
2037
2038	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2039	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2040	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2041
2042	fmov.l		&0x0,%fpcr		# zero FPCR
2043
2044#
2045#	copy, convert, and tag input argument
2046#
2047	fmov.d		0x8(%a6),%fp0		# load dbl input
2048	fmov.x		%fp0,FP_SRC(%a6)
2049	lea		FP_SRC(%a6),%a0
2050	bsr.l		tag			# fetch operand type
2051	mov.b		%d0,STAG(%a6)
2052	mov.b		%d0,%d1
2053
2054	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2055
2056	clr.l		%d0
2057	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2058
2059	mov.b		%d1,STAG(%a6)
2060	tst.b		%d1
2061	bne.b		_L8_2d
2062	bsr.l		satanh			# operand is a NORM
2063	bra.b		_L8_6d
2064_L8_2d:
2065	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2066	bne.b		_L8_3d			# no
2067	bsr.l		src_zero			# yes
2068	bra.b		_L8_6d
2069_L8_3d:
2070	cmpi.b		%d1,&INF		# is operand an INF?
2071	bne.b		_L8_4d			# no
2072	bsr.l		t_operr			# yes
2073	bra.b		_L8_6d
2074_L8_4d:
2075	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2076	bne.b		_L8_5d			# no
2077	bsr.l		src_qnan			# yes
2078	bra.b		_L8_6d
2079_L8_5d:
2080	bsr.l		satanhd			# operand is a DENORM
2081_L8_6d:
2082
2083#
2084#	Result is now in FP0
2085#
2086	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2087	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2088	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2089	unlk		%a6
2090	rts
2091
2092	global		_fatanhx_
2093_fatanhx_:
2094	link		%a6,&-LOCAL_SIZE
2095
2096	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2097	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2098	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2099
2100	fmov.l		&0x0,%fpcr		# zero FPCR
2101
2102#
2103#	copy, convert, and tag input argument
2104#
2105	lea		FP_SRC(%a6),%a0
2106	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
2107	mov.l		0x8+0x4(%a6),0x4(%a0)
2108	mov.l		0x8+0x8(%a6),0x8(%a0)
2109	bsr.l		tag			# fetch operand type
2110	mov.b		%d0,STAG(%a6)
2111	mov.b		%d0,%d1
2112
2113	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2114
2115	clr.l		%d0
2116	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2117
2118	tst.b		%d1
2119	bne.b		_L8_2x
2120	bsr.l		satanh			# operand is a NORM
2121	bra.b		_L8_6x
2122_L8_2x:
2123	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2124	bne.b		_L8_3x			# no
2125	bsr.l		src_zero			# yes
2126	bra.b		_L8_6x
2127_L8_3x:
2128	cmpi.b		%d1,&INF		# is operand an INF?
2129	bne.b		_L8_4x			# no
2130	bsr.l		t_operr			# yes
2131	bra.b		_L8_6x
2132_L8_4x:
2133	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2134	bne.b		_L8_5x			# no
2135	bsr.l		src_qnan			# yes
2136	bra.b		_L8_6x
2137_L8_5x:
2138	bsr.l		satanhd			# operand is a DENORM
2139_L8_6x:
2140
2141#
2142#	Result is now in FP0
2143#
2144	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2145	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2146	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2147	unlk		%a6
2148	rts
2149
2150
2151#########################################################################
2152# MONADIC TEMPLATE							#
2153#########################################################################
2154	global		_ftans_
2155_ftans_:
2156	link		%a6,&-LOCAL_SIZE
2157
2158	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2159	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2160	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2161
2162	fmov.l		&0x0,%fpcr		# zero FPCR
2163
2164#
2165#	copy, convert, and tag input argument
2166#
2167	fmov.s		0x8(%a6),%fp0		# load sgl input
2168	fmov.x		%fp0,FP_SRC(%a6)
2169	lea		FP_SRC(%a6),%a0
2170	bsr.l		tag			# fetch operand type
2171	mov.b		%d0,STAG(%a6)
2172	mov.b		%d0,%d1
2173
2174	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2175
2176	clr.l		%d0
2177	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2178
2179	tst.b		%d1
2180	bne.b		_L9_2s
2181	bsr.l		stan			# operand is a NORM
2182	bra.b		_L9_6s
2183_L9_2s:
2184	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2185	bne.b		_L9_3s			# no
2186	bsr.l		src_zero			# yes
2187	bra.b		_L9_6s
2188_L9_3s:
2189	cmpi.b		%d1,&INF		# is operand an INF?
2190	bne.b		_L9_4s			# no
2191	bsr.l		t_operr			# yes
2192	bra.b		_L9_6s
2193_L9_4s:
2194	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2195	bne.b		_L9_5s			# no
2196	bsr.l		src_qnan			# yes
2197	bra.b		_L9_6s
2198_L9_5s:
2199	bsr.l		stand			# operand is a DENORM
2200_L9_6s:
2201
2202#
2203#	Result is now in FP0
2204#
2205	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2206	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2207	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2208	unlk		%a6
2209	rts
2210
2211	global		_ftand_
2212_ftand_:
2213	link		%a6,&-LOCAL_SIZE
2214
2215	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2216	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2217	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2218
2219	fmov.l		&0x0,%fpcr		# zero FPCR
2220
2221#
2222#	copy, convert, and tag input argument
2223#
2224	fmov.d		0x8(%a6),%fp0		# load dbl input
2225	fmov.x		%fp0,FP_SRC(%a6)
2226	lea		FP_SRC(%a6),%a0
2227	bsr.l		tag			# fetch operand type
2228	mov.b		%d0,STAG(%a6)
2229	mov.b		%d0,%d1
2230
2231	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2232
2233	clr.l		%d0
2234	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2235
2236	mov.b		%d1,STAG(%a6)
2237	tst.b		%d1
2238	bne.b		_L9_2d
2239	bsr.l		stan			# operand is a NORM
2240	bra.b		_L9_6d
2241_L9_2d:
2242	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2243	bne.b		_L9_3d			# no
2244	bsr.l		src_zero			# yes
2245	bra.b		_L9_6d
2246_L9_3d:
2247	cmpi.b		%d1,&INF		# is operand an INF?
2248	bne.b		_L9_4d			# no
2249	bsr.l		t_operr			# yes
2250	bra.b		_L9_6d
2251_L9_4d:
2252	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2253	bne.b		_L9_5d			# no
2254	bsr.l		src_qnan			# yes
2255	bra.b		_L9_6d
2256_L9_5d:
2257	bsr.l		stand			# operand is a DENORM
2258_L9_6d:
2259
2260#
2261#	Result is now in FP0
2262#
2263	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2264	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2265	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2266	unlk		%a6
2267	rts
2268
2269	global		_ftanx_
2270_ftanx_:
2271	link		%a6,&-LOCAL_SIZE
2272
2273	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2274	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2275	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2276
2277	fmov.l		&0x0,%fpcr		# zero FPCR
2278
2279#
2280#	copy, convert, and tag input argument
2281#
2282	lea		FP_SRC(%a6),%a0
2283	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
2284	mov.l		0x8+0x4(%a6),0x4(%a0)
2285	mov.l		0x8+0x8(%a6),0x8(%a0)
2286	bsr.l		tag			# fetch operand type
2287	mov.b		%d0,STAG(%a6)
2288	mov.b		%d0,%d1
2289
2290	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2291
2292	clr.l		%d0
2293	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2294
2295	tst.b		%d1
2296	bne.b		_L9_2x
2297	bsr.l		stan			# operand is a NORM
2298	bra.b		_L9_6x
2299_L9_2x:
2300	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2301	bne.b		_L9_3x			# no
2302	bsr.l		src_zero			# yes
2303	bra.b		_L9_6x
2304_L9_3x:
2305	cmpi.b		%d1,&INF		# is operand an INF?
2306	bne.b		_L9_4x			# no
2307	bsr.l		t_operr			# yes
2308	bra.b		_L9_6x
2309_L9_4x:
2310	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2311	bne.b		_L9_5x			# no
2312	bsr.l		src_qnan			# yes
2313	bra.b		_L9_6x
2314_L9_5x:
2315	bsr.l		stand			# operand is a DENORM
2316_L9_6x:
2317
2318#
2319#	Result is now in FP0
2320#
2321	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2322	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2323	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2324	unlk		%a6
2325	rts
2326
2327
2328#########################################################################
2329# MONADIC TEMPLATE							#
2330#########################################################################
2331	global		_fetoxs_
2332_fetoxs_:
2333	link		%a6,&-LOCAL_SIZE
2334
2335	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2336	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2337	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2338
2339	fmov.l		&0x0,%fpcr		# zero FPCR
2340
2341#
2342#	copy, convert, and tag input argument
2343#
2344	fmov.s		0x8(%a6),%fp0		# load sgl input
2345	fmov.x		%fp0,FP_SRC(%a6)
2346	lea		FP_SRC(%a6),%a0
2347	bsr.l		tag			# fetch operand type
2348	mov.b		%d0,STAG(%a6)
2349	mov.b		%d0,%d1
2350
2351	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2352
2353	clr.l		%d0
2354	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2355
2356	tst.b		%d1
2357	bne.b		_L10_2s
2358	bsr.l		setox			# operand is a NORM
2359	bra.b		_L10_6s
2360_L10_2s:
2361	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2362	bne.b		_L10_3s			# no
2363	bsr.l		ld_pone			# yes
2364	bra.b		_L10_6s
2365_L10_3s:
2366	cmpi.b		%d1,&INF		# is operand an INF?
2367	bne.b		_L10_4s			# no
2368	bsr.l		szr_inf			# yes
2369	bra.b		_L10_6s
2370_L10_4s:
2371	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2372	bne.b		_L10_5s			# no
2373	bsr.l		src_qnan			# yes
2374	bra.b		_L10_6s
2375_L10_5s:
2376	bsr.l		setoxd			# operand is a DENORM
2377_L10_6s:
2378
2379#
2380#	Result is now in FP0
2381#
2382	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2383	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2384	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2385	unlk		%a6
2386	rts
2387
2388	global		_fetoxd_
2389_fetoxd_:
2390	link		%a6,&-LOCAL_SIZE
2391
2392	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2393	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2394	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2395
2396	fmov.l		&0x0,%fpcr		# zero FPCR
2397
2398#
2399#	copy, convert, and tag input argument
2400#
2401	fmov.d		0x8(%a6),%fp0		# load dbl input
2402	fmov.x		%fp0,FP_SRC(%a6)
2403	lea		FP_SRC(%a6),%a0
2404	bsr.l		tag			# fetch operand type
2405	mov.b		%d0,STAG(%a6)
2406	mov.b		%d0,%d1
2407
2408	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2409
2410	clr.l		%d0
2411	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2412
2413	mov.b		%d1,STAG(%a6)
2414	tst.b		%d1
2415	bne.b		_L10_2d
2416	bsr.l		setox			# operand is a NORM
2417	bra.b		_L10_6d
2418_L10_2d:
2419	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2420	bne.b		_L10_3d			# no
2421	bsr.l		ld_pone			# yes
2422	bra.b		_L10_6d
2423_L10_3d:
2424	cmpi.b		%d1,&INF		# is operand an INF?
2425	bne.b		_L10_4d			# no
2426	bsr.l		szr_inf			# yes
2427	bra.b		_L10_6d
2428_L10_4d:
2429	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2430	bne.b		_L10_5d			# no
2431	bsr.l		src_qnan			# yes
2432	bra.b		_L10_6d
2433_L10_5d:
2434	bsr.l		setoxd			# operand is a DENORM
2435_L10_6d:
2436
2437#
2438#	Result is now in FP0
2439#
2440	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2441	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2442	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2443	unlk		%a6
2444	rts
2445
2446	global		_fetoxx_
2447_fetoxx_:
2448	link		%a6,&-LOCAL_SIZE
2449
2450	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2451	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2452	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2453
2454	fmov.l		&0x0,%fpcr		# zero FPCR
2455
2456#
2457#	copy, convert, and tag input argument
2458#
2459	lea		FP_SRC(%a6),%a0
2460	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
2461	mov.l		0x8+0x4(%a6),0x4(%a0)
2462	mov.l		0x8+0x8(%a6),0x8(%a0)
2463	bsr.l		tag			# fetch operand type
2464	mov.b		%d0,STAG(%a6)
2465	mov.b		%d0,%d1
2466
2467	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2468
2469	clr.l		%d0
2470	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2471
2472	tst.b		%d1
2473	bne.b		_L10_2x
2474	bsr.l		setox			# operand is a NORM
2475	bra.b		_L10_6x
2476_L10_2x:
2477	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2478	bne.b		_L10_3x			# no
2479	bsr.l		ld_pone			# yes
2480	bra.b		_L10_6x
2481_L10_3x:
2482	cmpi.b		%d1,&INF		# is operand an INF?
2483	bne.b		_L10_4x			# no
2484	bsr.l		szr_inf			# yes
2485	bra.b		_L10_6x
2486_L10_4x:
2487	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2488	bne.b		_L10_5x			# no
2489	bsr.l		src_qnan			# yes
2490	bra.b		_L10_6x
2491_L10_5x:
2492	bsr.l		setoxd			# operand is a DENORM
2493_L10_6x:
2494
2495#
2496#	Result is now in FP0
2497#
2498	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2499	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2500	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2501	unlk		%a6
2502	rts
2503
2504
2505#########################################################################
2506# MONADIC TEMPLATE							#
2507#########################################################################
2508	global		_ftwotoxs_
2509_ftwotoxs_:
2510	link		%a6,&-LOCAL_SIZE
2511
2512	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2513	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2514	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2515
2516	fmov.l		&0x0,%fpcr		# zero FPCR
2517
2518#
2519#	copy, convert, and tag input argument
2520#
2521	fmov.s		0x8(%a6),%fp0		# load sgl input
2522	fmov.x		%fp0,FP_SRC(%a6)
2523	lea		FP_SRC(%a6),%a0
2524	bsr.l		tag			# fetch operand type
2525	mov.b		%d0,STAG(%a6)
2526	mov.b		%d0,%d1
2527
2528	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2529
2530	clr.l		%d0
2531	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2532
2533	tst.b		%d1
2534	bne.b		_L11_2s
2535	bsr.l		stwotox			# operand is a NORM
2536	bra.b		_L11_6s
2537_L11_2s:
2538	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2539	bne.b		_L11_3s			# no
2540	bsr.l		ld_pone			# yes
2541	bra.b		_L11_6s
2542_L11_3s:
2543	cmpi.b		%d1,&INF		# is operand an INF?
2544	bne.b		_L11_4s			# no
2545	bsr.l		szr_inf			# yes
2546	bra.b		_L11_6s
2547_L11_4s:
2548	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2549	bne.b		_L11_5s			# no
2550	bsr.l		src_qnan			# yes
2551	bra.b		_L11_6s
2552_L11_5s:
2553	bsr.l		stwotoxd			# operand is a DENORM
2554_L11_6s:
2555
2556#
2557#	Result is now in FP0
2558#
2559	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2560	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2561	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2562	unlk		%a6
2563	rts
2564
2565	global		_ftwotoxd_
2566_ftwotoxd_:
2567	link		%a6,&-LOCAL_SIZE
2568
2569	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2570	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2571	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2572
2573	fmov.l		&0x0,%fpcr		# zero FPCR
2574
2575#
2576#	copy, convert, and tag input argument
2577#
2578	fmov.d		0x8(%a6),%fp0		# load dbl input
2579	fmov.x		%fp0,FP_SRC(%a6)
2580	lea		FP_SRC(%a6),%a0
2581	bsr.l		tag			# fetch operand type
2582	mov.b		%d0,STAG(%a6)
2583	mov.b		%d0,%d1
2584
2585	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2586
2587	clr.l		%d0
2588	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2589
2590	mov.b		%d1,STAG(%a6)
2591	tst.b		%d1
2592	bne.b		_L11_2d
2593	bsr.l		stwotox			# operand is a NORM
2594	bra.b		_L11_6d
2595_L11_2d:
2596	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2597	bne.b		_L11_3d			# no
2598	bsr.l		ld_pone			# yes
2599	bra.b		_L11_6d
2600_L11_3d:
2601	cmpi.b		%d1,&INF		# is operand an INF?
2602	bne.b		_L11_4d			# no
2603	bsr.l		szr_inf			# yes
2604	bra.b		_L11_6d
2605_L11_4d:
2606	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2607	bne.b		_L11_5d			# no
2608	bsr.l		src_qnan			# yes
2609	bra.b		_L11_6d
2610_L11_5d:
2611	bsr.l		stwotoxd			# operand is a DENORM
2612_L11_6d:
2613
2614#
2615#	Result is now in FP0
2616#
2617	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2618	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2619	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2620	unlk		%a6
2621	rts
2622
2623	global		_ftwotoxx_
2624_ftwotoxx_:
2625	link		%a6,&-LOCAL_SIZE
2626
2627	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2628	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2629	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2630
2631	fmov.l		&0x0,%fpcr		# zero FPCR
2632
2633#
2634#	copy, convert, and tag input argument
2635#
2636	lea		FP_SRC(%a6),%a0
2637	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
2638	mov.l		0x8+0x4(%a6),0x4(%a0)
2639	mov.l		0x8+0x8(%a6),0x8(%a0)
2640	bsr.l		tag			# fetch operand type
2641	mov.b		%d0,STAG(%a6)
2642	mov.b		%d0,%d1
2643
2644	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2645
2646	clr.l		%d0
2647	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2648
2649	tst.b		%d1
2650	bne.b		_L11_2x
2651	bsr.l		stwotox			# operand is a NORM
2652	bra.b		_L11_6x
2653_L11_2x:
2654	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2655	bne.b		_L11_3x			# no
2656	bsr.l		ld_pone			# yes
2657	bra.b		_L11_6x
2658_L11_3x:
2659	cmpi.b		%d1,&INF		# is operand an INF?
2660	bne.b		_L11_4x			# no
2661	bsr.l		szr_inf			# yes
2662	bra.b		_L11_6x
2663_L11_4x:
2664	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2665	bne.b		_L11_5x			# no
2666	bsr.l		src_qnan			# yes
2667	bra.b		_L11_6x
2668_L11_5x:
2669	bsr.l		stwotoxd			# operand is a DENORM
2670_L11_6x:
2671
2672#
2673#	Result is now in FP0
2674#
2675	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2676	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2677	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2678	unlk		%a6
2679	rts
2680
2681
2682#########################################################################
2683# MONADIC TEMPLATE							#
2684#########################################################################
2685	global		_ftentoxs_
2686_ftentoxs_:
2687	link		%a6,&-LOCAL_SIZE
2688
2689	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2690	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2691	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2692
2693	fmov.l		&0x0,%fpcr		# zero FPCR
2694
2695#
2696#	copy, convert, and tag input argument
2697#
2698	fmov.s		0x8(%a6),%fp0		# load sgl input
2699	fmov.x		%fp0,FP_SRC(%a6)
2700	lea		FP_SRC(%a6),%a0
2701	bsr.l		tag			# fetch operand type
2702	mov.b		%d0,STAG(%a6)
2703	mov.b		%d0,%d1
2704
2705	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2706
2707	clr.l		%d0
2708	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2709
2710	tst.b		%d1
2711	bne.b		_L12_2s
2712	bsr.l		stentox			# operand is a NORM
2713	bra.b		_L12_6s
2714_L12_2s:
2715	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2716	bne.b		_L12_3s			# no
2717	bsr.l		ld_pone			# yes
2718	bra.b		_L12_6s
2719_L12_3s:
2720	cmpi.b		%d1,&INF		# is operand an INF?
2721	bne.b		_L12_4s			# no
2722	bsr.l		szr_inf			# yes
2723	bra.b		_L12_6s
2724_L12_4s:
2725	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2726	bne.b		_L12_5s			# no
2727	bsr.l		src_qnan			# yes
2728	bra.b		_L12_6s
2729_L12_5s:
2730	bsr.l		stentoxd			# operand is a DENORM
2731_L12_6s:
2732
2733#
2734#	Result is now in FP0
2735#
2736	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2737	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2738	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2739	unlk		%a6
2740	rts
2741
2742	global		_ftentoxd_
2743_ftentoxd_:
2744	link		%a6,&-LOCAL_SIZE
2745
2746	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2747	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2748	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2749
2750	fmov.l		&0x0,%fpcr		# zero FPCR
2751
2752#
2753#	copy, convert, and tag input argument
2754#
2755	fmov.d		0x8(%a6),%fp0		# load dbl input
2756	fmov.x		%fp0,FP_SRC(%a6)
2757	lea		FP_SRC(%a6),%a0
2758	bsr.l		tag			# fetch operand type
2759	mov.b		%d0,STAG(%a6)
2760	mov.b		%d0,%d1
2761
2762	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2763
2764	clr.l		%d0
2765	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2766
2767	mov.b		%d1,STAG(%a6)
2768	tst.b		%d1
2769	bne.b		_L12_2d
2770	bsr.l		stentox			# operand is a NORM
2771	bra.b		_L12_6d
2772_L12_2d:
2773	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2774	bne.b		_L12_3d			# no
2775	bsr.l		ld_pone			# yes
2776	bra.b		_L12_6d
2777_L12_3d:
2778	cmpi.b		%d1,&INF		# is operand an INF?
2779	bne.b		_L12_4d			# no
2780	bsr.l		szr_inf			# yes
2781	bra.b		_L12_6d
2782_L12_4d:
2783	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2784	bne.b		_L12_5d			# no
2785	bsr.l		src_qnan			# yes
2786	bra.b		_L12_6d
2787_L12_5d:
2788	bsr.l		stentoxd			# operand is a DENORM
2789_L12_6d:
2790
2791#
2792#	Result is now in FP0
2793#
2794	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2795	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2796	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2797	unlk		%a6
2798	rts
2799
2800	global		_ftentoxx_
2801_ftentoxx_:
2802	link		%a6,&-LOCAL_SIZE
2803
2804	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2805	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2806	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2807
2808	fmov.l		&0x0,%fpcr		# zero FPCR
2809
2810#
2811#	copy, convert, and tag input argument
2812#
2813	lea		FP_SRC(%a6),%a0
2814	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
2815	mov.l		0x8+0x4(%a6),0x4(%a0)
2816	mov.l		0x8+0x8(%a6),0x8(%a0)
2817	bsr.l		tag			# fetch operand type
2818	mov.b		%d0,STAG(%a6)
2819	mov.b		%d0,%d1
2820
2821	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2822
2823	clr.l		%d0
2824	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2825
2826	tst.b		%d1
2827	bne.b		_L12_2x
2828	bsr.l		stentox			# operand is a NORM
2829	bra.b		_L12_6x
2830_L12_2x:
2831	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2832	bne.b		_L12_3x			# no
2833	bsr.l		ld_pone			# yes
2834	bra.b		_L12_6x
2835_L12_3x:
2836	cmpi.b		%d1,&INF		# is operand an INF?
2837	bne.b		_L12_4x			# no
2838	bsr.l		szr_inf			# yes
2839	bra.b		_L12_6x
2840_L12_4x:
2841	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2842	bne.b		_L12_5x			# no
2843	bsr.l		src_qnan			# yes
2844	bra.b		_L12_6x
2845_L12_5x:
2846	bsr.l		stentoxd			# operand is a DENORM
2847_L12_6x:
2848
2849#
2850#	Result is now in FP0
2851#
2852	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2853	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2854	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2855	unlk		%a6
2856	rts
2857
2858
2859#########################################################################
2860# MONADIC TEMPLATE							#
2861#########################################################################
2862	global		_flogns_
2863_flogns_:
2864	link		%a6,&-LOCAL_SIZE
2865
2866	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2867	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2868	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2869
2870	fmov.l		&0x0,%fpcr		# zero FPCR
2871
2872#
2873#	copy, convert, and tag input argument
2874#
2875	fmov.s		0x8(%a6),%fp0		# load sgl input
2876	fmov.x		%fp0,FP_SRC(%a6)
2877	lea		FP_SRC(%a6),%a0
2878	bsr.l		tag			# fetch operand type
2879	mov.b		%d0,STAG(%a6)
2880	mov.b		%d0,%d1
2881
2882	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2883
2884	clr.l		%d0
2885	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2886
2887	tst.b		%d1
2888	bne.b		_L13_2s
2889	bsr.l		slogn			# operand is a NORM
2890	bra.b		_L13_6s
2891_L13_2s:
2892	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2893	bne.b		_L13_3s			# no
2894	bsr.l		t_dz2			# yes
2895	bra.b		_L13_6s
2896_L13_3s:
2897	cmpi.b		%d1,&INF		# is operand an INF?
2898	bne.b		_L13_4s			# no
2899	bsr.l		sopr_inf			# yes
2900	bra.b		_L13_6s
2901_L13_4s:
2902	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2903	bne.b		_L13_5s			# no
2904	bsr.l		src_qnan			# yes
2905	bra.b		_L13_6s
2906_L13_5s:
2907	bsr.l		slognd			# operand is a DENORM
2908_L13_6s:
2909
2910#
2911#	Result is now in FP0
2912#
2913	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2914	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2915	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2916	unlk		%a6
2917	rts
2918
2919	global		_flognd_
2920_flognd_:
2921	link		%a6,&-LOCAL_SIZE
2922
2923	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2924	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2925	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2926
2927	fmov.l		&0x0,%fpcr		# zero FPCR
2928
2929#
2930#	copy, convert, and tag input argument
2931#
2932	fmov.d		0x8(%a6),%fp0		# load dbl input
2933	fmov.x		%fp0,FP_SRC(%a6)
2934	lea		FP_SRC(%a6),%a0
2935	bsr.l		tag			# fetch operand type
2936	mov.b		%d0,STAG(%a6)
2937	mov.b		%d0,%d1
2938
2939	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2940
2941	clr.l		%d0
2942	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
2943
2944	mov.b		%d1,STAG(%a6)
2945	tst.b		%d1
2946	bne.b		_L13_2d
2947	bsr.l		slogn			# operand is a NORM
2948	bra.b		_L13_6d
2949_L13_2d:
2950	cmpi.b		%d1,&ZERO		# is operand a ZERO?
2951	bne.b		_L13_3d			# no
2952	bsr.l		t_dz2			# yes
2953	bra.b		_L13_6d
2954_L13_3d:
2955	cmpi.b		%d1,&INF		# is operand an INF?
2956	bne.b		_L13_4d			# no
2957	bsr.l		sopr_inf			# yes
2958	bra.b		_L13_6d
2959_L13_4d:
2960	cmpi.b		%d1,&QNAN		# is operand a QNAN?
2961	bne.b		_L13_5d			# no
2962	bsr.l		src_qnan			# yes
2963	bra.b		_L13_6d
2964_L13_5d:
2965	bsr.l		slognd			# operand is a DENORM
2966_L13_6d:
2967
2968#
2969#	Result is now in FP0
2970#
2971	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
2972	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2973	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
2974	unlk		%a6
2975	rts
2976
2977	global		_flognx_
2978_flognx_:
2979	link		%a6,&-LOCAL_SIZE
2980
2981	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
2982	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2983	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
2984
2985	fmov.l		&0x0,%fpcr		# zero FPCR
2986
2987#
2988#	copy, convert, and tag input argument
2989#
2990	lea		FP_SRC(%a6),%a0
2991	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
2992	mov.l		0x8+0x4(%a6),0x4(%a0)
2993	mov.l		0x8+0x8(%a6),0x8(%a0)
2994	bsr.l		tag			# fetch operand type
2995	mov.b		%d0,STAG(%a6)
2996	mov.b		%d0,%d1
2997
2998	andi.l		&0x00ff00ff,USER_FPSR(%a6)
2999
3000	clr.l		%d0
3001	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3002
3003	tst.b		%d1
3004	bne.b		_L13_2x
3005	bsr.l		slogn			# operand is a NORM
3006	bra.b		_L13_6x
3007_L13_2x:
3008	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3009	bne.b		_L13_3x			# no
3010	bsr.l		t_dz2			# yes
3011	bra.b		_L13_6x
3012_L13_3x:
3013	cmpi.b		%d1,&INF		# is operand an INF?
3014	bne.b		_L13_4x			# no
3015	bsr.l		sopr_inf			# yes
3016	bra.b		_L13_6x
3017_L13_4x:
3018	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3019	bne.b		_L13_5x			# no
3020	bsr.l		src_qnan			# yes
3021	bra.b		_L13_6x
3022_L13_5x:
3023	bsr.l		slognd			# operand is a DENORM
3024_L13_6x:
3025
3026#
3027#	Result is now in FP0
3028#
3029	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3030	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3031	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3032	unlk		%a6
3033	rts
3034
3035
3036#########################################################################
3037# MONADIC TEMPLATE							#
3038#########################################################################
3039	global		_flog10s_
3040_flog10s_:
3041	link		%a6,&-LOCAL_SIZE
3042
3043	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3044	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3045	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3046
3047	fmov.l		&0x0,%fpcr		# zero FPCR
3048
3049#
3050#	copy, convert, and tag input argument
3051#
3052	fmov.s		0x8(%a6),%fp0		# load sgl input
3053	fmov.x		%fp0,FP_SRC(%a6)
3054	lea		FP_SRC(%a6),%a0
3055	bsr.l		tag			# fetch operand type
3056	mov.b		%d0,STAG(%a6)
3057	mov.b		%d0,%d1
3058
3059	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3060
3061	clr.l		%d0
3062	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3063
3064	tst.b		%d1
3065	bne.b		_L14_2s
3066	bsr.l		slog10			# operand is a NORM
3067	bra.b		_L14_6s
3068_L14_2s:
3069	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3070	bne.b		_L14_3s			# no
3071	bsr.l		t_dz2			# yes
3072	bra.b		_L14_6s
3073_L14_3s:
3074	cmpi.b		%d1,&INF		# is operand an INF?
3075	bne.b		_L14_4s			# no
3076	bsr.l		sopr_inf			# yes
3077	bra.b		_L14_6s
3078_L14_4s:
3079	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3080	bne.b		_L14_5s			# no
3081	bsr.l		src_qnan			# yes
3082	bra.b		_L14_6s
3083_L14_5s:
3084	bsr.l		slog10d			# operand is a DENORM
3085_L14_6s:
3086
3087#
3088#	Result is now in FP0
3089#
3090	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3091	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3092	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3093	unlk		%a6
3094	rts
3095
3096	global		_flog10d_
3097_flog10d_:
3098	link		%a6,&-LOCAL_SIZE
3099
3100	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3101	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3102	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3103
3104	fmov.l		&0x0,%fpcr		# zero FPCR
3105
3106#
3107#	copy, convert, and tag input argument
3108#
3109	fmov.d		0x8(%a6),%fp0		# load dbl input
3110	fmov.x		%fp0,FP_SRC(%a6)
3111	lea		FP_SRC(%a6),%a0
3112	bsr.l		tag			# fetch operand type
3113	mov.b		%d0,STAG(%a6)
3114	mov.b		%d0,%d1
3115
3116	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3117
3118	clr.l		%d0
3119	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3120
3121	mov.b		%d1,STAG(%a6)
3122	tst.b		%d1
3123	bne.b		_L14_2d
3124	bsr.l		slog10			# operand is a NORM
3125	bra.b		_L14_6d
3126_L14_2d:
3127	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3128	bne.b		_L14_3d			# no
3129	bsr.l		t_dz2			# yes
3130	bra.b		_L14_6d
3131_L14_3d:
3132	cmpi.b		%d1,&INF		# is operand an INF?
3133	bne.b		_L14_4d			# no
3134	bsr.l		sopr_inf			# yes
3135	bra.b		_L14_6d
3136_L14_4d:
3137	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3138	bne.b		_L14_5d			# no
3139	bsr.l		src_qnan			# yes
3140	bra.b		_L14_6d
3141_L14_5d:
3142	bsr.l		slog10d			# operand is a DENORM
3143_L14_6d:
3144
3145#
3146#	Result is now in FP0
3147#
3148	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3149	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3150	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3151	unlk		%a6
3152	rts
3153
3154	global		_flog10x_
3155_flog10x_:
3156	link		%a6,&-LOCAL_SIZE
3157
3158	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3159	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3160	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3161
3162	fmov.l		&0x0,%fpcr		# zero FPCR
3163
3164#
3165#	copy, convert, and tag input argument
3166#
3167	lea		FP_SRC(%a6),%a0
3168	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
3169	mov.l		0x8+0x4(%a6),0x4(%a0)
3170	mov.l		0x8+0x8(%a6),0x8(%a0)
3171	bsr.l		tag			# fetch operand type
3172	mov.b		%d0,STAG(%a6)
3173	mov.b		%d0,%d1
3174
3175	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3176
3177	clr.l		%d0
3178	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3179
3180	tst.b		%d1
3181	bne.b		_L14_2x
3182	bsr.l		slog10			# operand is a NORM
3183	bra.b		_L14_6x
3184_L14_2x:
3185	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3186	bne.b		_L14_3x			# no
3187	bsr.l		t_dz2			# yes
3188	bra.b		_L14_6x
3189_L14_3x:
3190	cmpi.b		%d1,&INF		# is operand an INF?
3191	bne.b		_L14_4x			# no
3192	bsr.l		sopr_inf			# yes
3193	bra.b		_L14_6x
3194_L14_4x:
3195	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3196	bne.b		_L14_5x			# no
3197	bsr.l		src_qnan			# yes
3198	bra.b		_L14_6x
3199_L14_5x:
3200	bsr.l		slog10d			# operand is a DENORM
3201_L14_6x:
3202
3203#
3204#	Result is now in FP0
3205#
3206	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3207	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3208	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3209	unlk		%a6
3210	rts
3211
3212
3213#########################################################################
3214# MONADIC TEMPLATE							#
3215#########################################################################
3216	global		_flog2s_
3217_flog2s_:
3218	link		%a6,&-LOCAL_SIZE
3219
3220	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3221	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3222	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3223
3224	fmov.l		&0x0,%fpcr		# zero FPCR
3225
3226#
3227#	copy, convert, and tag input argument
3228#
3229	fmov.s		0x8(%a6),%fp0		# load sgl input
3230	fmov.x		%fp0,FP_SRC(%a6)
3231	lea		FP_SRC(%a6),%a0
3232	bsr.l		tag			# fetch operand type
3233	mov.b		%d0,STAG(%a6)
3234	mov.b		%d0,%d1
3235
3236	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3237
3238	clr.l		%d0
3239	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3240
3241	tst.b		%d1
3242	bne.b		_L15_2s
3243	bsr.l		slog2			# operand is a NORM
3244	bra.b		_L15_6s
3245_L15_2s:
3246	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3247	bne.b		_L15_3s			# no
3248	bsr.l		t_dz2			# yes
3249	bra.b		_L15_6s
3250_L15_3s:
3251	cmpi.b		%d1,&INF		# is operand an INF?
3252	bne.b		_L15_4s			# no
3253	bsr.l		sopr_inf			# yes
3254	bra.b		_L15_6s
3255_L15_4s:
3256	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3257	bne.b		_L15_5s			# no
3258	bsr.l		src_qnan			# yes
3259	bra.b		_L15_6s
3260_L15_5s:
3261	bsr.l		slog2d			# operand is a DENORM
3262_L15_6s:
3263
3264#
3265#	Result is now in FP0
3266#
3267	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3268	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3269	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3270	unlk		%a6
3271	rts
3272
3273	global		_flog2d_
3274_flog2d_:
3275	link		%a6,&-LOCAL_SIZE
3276
3277	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3278	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3279	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3280
3281	fmov.l		&0x0,%fpcr		# zero FPCR
3282
3283#
3284#	copy, convert, and tag input argument
3285#
3286	fmov.d		0x8(%a6),%fp0		# load dbl input
3287	fmov.x		%fp0,FP_SRC(%a6)
3288	lea		FP_SRC(%a6),%a0
3289	bsr.l		tag			# fetch operand type
3290	mov.b		%d0,STAG(%a6)
3291	mov.b		%d0,%d1
3292
3293	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3294
3295	clr.l		%d0
3296	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3297
3298	mov.b		%d1,STAG(%a6)
3299	tst.b		%d1
3300	bne.b		_L15_2d
3301	bsr.l		slog2			# operand is a NORM
3302	bra.b		_L15_6d
3303_L15_2d:
3304	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3305	bne.b		_L15_3d			# no
3306	bsr.l		t_dz2			# yes
3307	bra.b		_L15_6d
3308_L15_3d:
3309	cmpi.b		%d1,&INF		# is operand an INF?
3310	bne.b		_L15_4d			# no
3311	bsr.l		sopr_inf			# yes
3312	bra.b		_L15_6d
3313_L15_4d:
3314	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3315	bne.b		_L15_5d			# no
3316	bsr.l		src_qnan			# yes
3317	bra.b		_L15_6d
3318_L15_5d:
3319	bsr.l		slog2d			# operand is a DENORM
3320_L15_6d:
3321
3322#
3323#	Result is now in FP0
3324#
3325	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3326	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3327	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3328	unlk		%a6
3329	rts
3330
3331	global		_flog2x_
3332_flog2x_:
3333	link		%a6,&-LOCAL_SIZE
3334
3335	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3336	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3337	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3338
3339	fmov.l		&0x0,%fpcr		# zero FPCR
3340
3341#
3342#	copy, convert, and tag input argument
3343#
3344	lea		FP_SRC(%a6),%a0
3345	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
3346	mov.l		0x8+0x4(%a6),0x4(%a0)
3347	mov.l		0x8+0x8(%a6),0x8(%a0)
3348	bsr.l		tag			# fetch operand type
3349	mov.b		%d0,STAG(%a6)
3350	mov.b		%d0,%d1
3351
3352	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3353
3354	clr.l		%d0
3355	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3356
3357	tst.b		%d1
3358	bne.b		_L15_2x
3359	bsr.l		slog2			# operand is a NORM
3360	bra.b		_L15_6x
3361_L15_2x:
3362	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3363	bne.b		_L15_3x			# no
3364	bsr.l		t_dz2			# yes
3365	bra.b		_L15_6x
3366_L15_3x:
3367	cmpi.b		%d1,&INF		# is operand an INF?
3368	bne.b		_L15_4x			# no
3369	bsr.l		sopr_inf			# yes
3370	bra.b		_L15_6x
3371_L15_4x:
3372	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3373	bne.b		_L15_5x			# no
3374	bsr.l		src_qnan			# yes
3375	bra.b		_L15_6x
3376_L15_5x:
3377	bsr.l		slog2d			# operand is a DENORM
3378_L15_6x:
3379
3380#
3381#	Result is now in FP0
3382#
3383	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3384	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3385	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3386	unlk		%a6
3387	rts
3388
3389
3390#########################################################################
3391# MONADIC TEMPLATE							#
3392#########################################################################
3393	global		_fcoshs_
3394_fcoshs_:
3395	link		%a6,&-LOCAL_SIZE
3396
3397	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3398	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3399	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3400
3401	fmov.l		&0x0,%fpcr		# zero FPCR
3402
3403#
3404#	copy, convert, and tag input argument
3405#
3406	fmov.s		0x8(%a6),%fp0		# load sgl input
3407	fmov.x		%fp0,FP_SRC(%a6)
3408	lea		FP_SRC(%a6),%a0
3409	bsr.l		tag			# fetch operand type
3410	mov.b		%d0,STAG(%a6)
3411	mov.b		%d0,%d1
3412
3413	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3414
3415	clr.l		%d0
3416	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3417
3418	tst.b		%d1
3419	bne.b		_L16_2s
3420	bsr.l		scosh			# operand is a NORM
3421	bra.b		_L16_6s
3422_L16_2s:
3423	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3424	bne.b		_L16_3s			# no
3425	bsr.l		ld_pone			# yes
3426	bra.b		_L16_6s
3427_L16_3s:
3428	cmpi.b		%d1,&INF		# is operand an INF?
3429	bne.b		_L16_4s			# no
3430	bsr.l		ld_pinf			# yes
3431	bra.b		_L16_6s
3432_L16_4s:
3433	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3434	bne.b		_L16_5s			# no
3435	bsr.l		src_qnan			# yes
3436	bra.b		_L16_6s
3437_L16_5s:
3438	bsr.l		scoshd			# operand is a DENORM
3439_L16_6s:
3440
3441#
3442#	Result is now in FP0
3443#
3444	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3445	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3446	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3447	unlk		%a6
3448	rts
3449
3450	global		_fcoshd_
3451_fcoshd_:
3452	link		%a6,&-LOCAL_SIZE
3453
3454	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3455	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3456	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3457
3458	fmov.l		&0x0,%fpcr		# zero FPCR
3459
3460#
3461#	copy, convert, and tag input argument
3462#
3463	fmov.d		0x8(%a6),%fp0		# load dbl input
3464	fmov.x		%fp0,FP_SRC(%a6)
3465	lea		FP_SRC(%a6),%a0
3466	bsr.l		tag			# fetch operand type
3467	mov.b		%d0,STAG(%a6)
3468	mov.b		%d0,%d1
3469
3470	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3471
3472	clr.l		%d0
3473	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3474
3475	mov.b		%d1,STAG(%a6)
3476	tst.b		%d1
3477	bne.b		_L16_2d
3478	bsr.l		scosh			# operand is a NORM
3479	bra.b		_L16_6d
3480_L16_2d:
3481	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3482	bne.b		_L16_3d			# no
3483	bsr.l		ld_pone			# yes
3484	bra.b		_L16_6d
3485_L16_3d:
3486	cmpi.b		%d1,&INF		# is operand an INF?
3487	bne.b		_L16_4d			# no
3488	bsr.l		ld_pinf			# yes
3489	bra.b		_L16_6d
3490_L16_4d:
3491	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3492	bne.b		_L16_5d			# no
3493	bsr.l		src_qnan			# yes
3494	bra.b		_L16_6d
3495_L16_5d:
3496	bsr.l		scoshd			# operand is a DENORM
3497_L16_6d:
3498
3499#
3500#	Result is now in FP0
3501#
3502	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3503	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3504	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3505	unlk		%a6
3506	rts
3507
3508	global		_fcoshx_
3509_fcoshx_:
3510	link		%a6,&-LOCAL_SIZE
3511
3512	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3513	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3514	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3515
3516	fmov.l		&0x0,%fpcr		# zero FPCR
3517
3518#
3519#	copy, convert, and tag input argument
3520#
3521	lea		FP_SRC(%a6),%a0
3522	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
3523	mov.l		0x8+0x4(%a6),0x4(%a0)
3524	mov.l		0x8+0x8(%a6),0x8(%a0)
3525	bsr.l		tag			# fetch operand type
3526	mov.b		%d0,STAG(%a6)
3527	mov.b		%d0,%d1
3528
3529	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3530
3531	clr.l		%d0
3532	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3533
3534	tst.b		%d1
3535	bne.b		_L16_2x
3536	bsr.l		scosh			# operand is a NORM
3537	bra.b		_L16_6x
3538_L16_2x:
3539	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3540	bne.b		_L16_3x			# no
3541	bsr.l		ld_pone			# yes
3542	bra.b		_L16_6x
3543_L16_3x:
3544	cmpi.b		%d1,&INF		# is operand an INF?
3545	bne.b		_L16_4x			# no
3546	bsr.l		ld_pinf			# yes
3547	bra.b		_L16_6x
3548_L16_4x:
3549	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3550	bne.b		_L16_5x			# no
3551	bsr.l		src_qnan			# yes
3552	bra.b		_L16_6x
3553_L16_5x:
3554	bsr.l		scoshd			# operand is a DENORM
3555_L16_6x:
3556
3557#
3558#	Result is now in FP0
3559#
3560	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3561	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3562	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3563	unlk		%a6
3564	rts
3565
3566
3567#########################################################################
3568# MONADIC TEMPLATE							#
3569#########################################################################
3570	global		_facoss_
3571_facoss_:
3572	link		%a6,&-LOCAL_SIZE
3573
3574	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3575	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3576	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3577
3578	fmov.l		&0x0,%fpcr		# zero FPCR
3579
3580#
3581#	copy, convert, and tag input argument
3582#
3583	fmov.s		0x8(%a6),%fp0		# load sgl input
3584	fmov.x		%fp0,FP_SRC(%a6)
3585	lea		FP_SRC(%a6),%a0
3586	bsr.l		tag			# fetch operand type
3587	mov.b		%d0,STAG(%a6)
3588	mov.b		%d0,%d1
3589
3590	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3591
3592	clr.l		%d0
3593	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3594
3595	tst.b		%d1
3596	bne.b		_L17_2s
3597	bsr.l		sacos			# operand is a NORM
3598	bra.b		_L17_6s
3599_L17_2s:
3600	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3601	bne.b		_L17_3s			# no
3602	bsr.l		ld_ppi2			# yes
3603	bra.b		_L17_6s
3604_L17_3s:
3605	cmpi.b		%d1,&INF		# is operand an INF?
3606	bne.b		_L17_4s			# no
3607	bsr.l		t_operr			# yes
3608	bra.b		_L17_6s
3609_L17_4s:
3610	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3611	bne.b		_L17_5s			# no
3612	bsr.l		src_qnan			# yes
3613	bra.b		_L17_6s
3614_L17_5s:
3615	bsr.l		sacosd			# operand is a DENORM
3616_L17_6s:
3617
3618#
3619#	Result is now in FP0
3620#
3621	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3622	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3623	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3624	unlk		%a6
3625	rts
3626
3627	global		_facosd_
3628_facosd_:
3629	link		%a6,&-LOCAL_SIZE
3630
3631	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3632	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3633	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3634
3635	fmov.l		&0x0,%fpcr		# zero FPCR
3636
3637#
3638#	copy, convert, and tag input argument
3639#
3640	fmov.d		0x8(%a6),%fp0		# load dbl input
3641	fmov.x		%fp0,FP_SRC(%a6)
3642	lea		FP_SRC(%a6),%a0
3643	bsr.l		tag			# fetch operand type
3644	mov.b		%d0,STAG(%a6)
3645	mov.b		%d0,%d1
3646
3647	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3648
3649	clr.l		%d0
3650	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3651
3652	mov.b		%d1,STAG(%a6)
3653	tst.b		%d1
3654	bne.b		_L17_2d
3655	bsr.l		sacos			# operand is a NORM
3656	bra.b		_L17_6d
3657_L17_2d:
3658	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3659	bne.b		_L17_3d			# no
3660	bsr.l		ld_ppi2			# yes
3661	bra.b		_L17_6d
3662_L17_3d:
3663	cmpi.b		%d1,&INF		# is operand an INF?
3664	bne.b		_L17_4d			# no
3665	bsr.l		t_operr			# yes
3666	bra.b		_L17_6d
3667_L17_4d:
3668	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3669	bne.b		_L17_5d			# no
3670	bsr.l		src_qnan			# yes
3671	bra.b		_L17_6d
3672_L17_5d:
3673	bsr.l		sacosd			# operand is a DENORM
3674_L17_6d:
3675
3676#
3677#	Result is now in FP0
3678#
3679	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3680	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3681	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3682	unlk		%a6
3683	rts
3684
3685	global		_facosx_
3686_facosx_:
3687	link		%a6,&-LOCAL_SIZE
3688
3689	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3690	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3691	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3692
3693	fmov.l		&0x0,%fpcr		# zero FPCR
3694
3695#
3696#	copy, convert, and tag input argument
3697#
3698	lea		FP_SRC(%a6),%a0
3699	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
3700	mov.l		0x8+0x4(%a6),0x4(%a0)
3701	mov.l		0x8+0x8(%a6),0x8(%a0)
3702	bsr.l		tag			# fetch operand type
3703	mov.b		%d0,STAG(%a6)
3704	mov.b		%d0,%d1
3705
3706	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3707
3708	clr.l		%d0
3709	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3710
3711	tst.b		%d1
3712	bne.b		_L17_2x
3713	bsr.l		sacos			# operand is a NORM
3714	bra.b		_L17_6x
3715_L17_2x:
3716	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3717	bne.b		_L17_3x			# no
3718	bsr.l		ld_ppi2			# yes
3719	bra.b		_L17_6x
3720_L17_3x:
3721	cmpi.b		%d1,&INF		# is operand an INF?
3722	bne.b		_L17_4x			# no
3723	bsr.l		t_operr			# yes
3724	bra.b		_L17_6x
3725_L17_4x:
3726	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3727	bne.b		_L17_5x			# no
3728	bsr.l		src_qnan			# yes
3729	bra.b		_L17_6x
3730_L17_5x:
3731	bsr.l		sacosd			# operand is a DENORM
3732_L17_6x:
3733
3734#
3735#	Result is now in FP0
3736#
3737	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3738	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3739	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3740	unlk		%a6
3741	rts
3742
3743
3744#########################################################################
3745# MONADIC TEMPLATE							#
3746#########################################################################
3747	global		_fgetexps_
3748_fgetexps_:
3749	link		%a6,&-LOCAL_SIZE
3750
3751	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3752	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3753	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3754
3755	fmov.l		&0x0,%fpcr		# zero FPCR
3756
3757#
3758#	copy, convert, and tag input argument
3759#
3760	fmov.s		0x8(%a6),%fp0		# load sgl input
3761	fmov.x		%fp0,FP_SRC(%a6)
3762	lea		FP_SRC(%a6),%a0
3763	bsr.l		tag			# fetch operand type
3764	mov.b		%d0,STAG(%a6)
3765	mov.b		%d0,%d1
3766
3767	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3768
3769	clr.l		%d0
3770	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3771
3772	tst.b		%d1
3773	bne.b		_L18_2s
3774	bsr.l		sgetexp			# operand is a NORM
3775	bra.b		_L18_6s
3776_L18_2s:
3777	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3778	bne.b		_L18_3s			# no
3779	bsr.l		src_zero			# yes
3780	bra.b		_L18_6s
3781_L18_3s:
3782	cmpi.b		%d1,&INF		# is operand an INF?
3783	bne.b		_L18_4s			# no
3784	bsr.l		t_operr			# yes
3785	bra.b		_L18_6s
3786_L18_4s:
3787	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3788	bne.b		_L18_5s			# no
3789	bsr.l		src_qnan			# yes
3790	bra.b		_L18_6s
3791_L18_5s:
3792	bsr.l		sgetexpd			# operand is a DENORM
3793_L18_6s:
3794
3795#
3796#	Result is now in FP0
3797#
3798	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3799	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3800	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3801	unlk		%a6
3802	rts
3803
3804	global		_fgetexpd_
3805_fgetexpd_:
3806	link		%a6,&-LOCAL_SIZE
3807
3808	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3809	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3810	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3811
3812	fmov.l		&0x0,%fpcr		# zero FPCR
3813
3814#
3815#	copy, convert, and tag input argument
3816#
3817	fmov.d		0x8(%a6),%fp0		# load dbl input
3818	fmov.x		%fp0,FP_SRC(%a6)
3819	lea		FP_SRC(%a6),%a0
3820	bsr.l		tag			# fetch operand type
3821	mov.b		%d0,STAG(%a6)
3822	mov.b		%d0,%d1
3823
3824	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3825
3826	clr.l		%d0
3827	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3828
3829	mov.b		%d1,STAG(%a6)
3830	tst.b		%d1
3831	bne.b		_L18_2d
3832	bsr.l		sgetexp			# operand is a NORM
3833	bra.b		_L18_6d
3834_L18_2d:
3835	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3836	bne.b		_L18_3d			# no
3837	bsr.l		src_zero			# yes
3838	bra.b		_L18_6d
3839_L18_3d:
3840	cmpi.b		%d1,&INF		# is operand an INF?
3841	bne.b		_L18_4d			# no
3842	bsr.l		t_operr			# yes
3843	bra.b		_L18_6d
3844_L18_4d:
3845	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3846	bne.b		_L18_5d			# no
3847	bsr.l		src_qnan			# yes
3848	bra.b		_L18_6d
3849_L18_5d:
3850	bsr.l		sgetexpd			# operand is a DENORM
3851_L18_6d:
3852
3853#
3854#	Result is now in FP0
3855#
3856	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3857	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3858	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3859	unlk		%a6
3860	rts
3861
3862	global		_fgetexpx_
3863_fgetexpx_:
3864	link		%a6,&-LOCAL_SIZE
3865
3866	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3867	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3868	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3869
3870	fmov.l		&0x0,%fpcr		# zero FPCR
3871
3872#
3873#	copy, convert, and tag input argument
3874#
3875	lea		FP_SRC(%a6),%a0
3876	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
3877	mov.l		0x8+0x4(%a6),0x4(%a0)
3878	mov.l		0x8+0x8(%a6),0x8(%a0)
3879	bsr.l		tag			# fetch operand type
3880	mov.b		%d0,STAG(%a6)
3881	mov.b		%d0,%d1
3882
3883	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3884
3885	clr.l		%d0
3886	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3887
3888	tst.b		%d1
3889	bne.b		_L18_2x
3890	bsr.l		sgetexp			# operand is a NORM
3891	bra.b		_L18_6x
3892_L18_2x:
3893	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3894	bne.b		_L18_3x			# no
3895	bsr.l		src_zero			# yes
3896	bra.b		_L18_6x
3897_L18_3x:
3898	cmpi.b		%d1,&INF		# is operand an INF?
3899	bne.b		_L18_4x			# no
3900	bsr.l		t_operr			# yes
3901	bra.b		_L18_6x
3902_L18_4x:
3903	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3904	bne.b		_L18_5x			# no
3905	bsr.l		src_qnan			# yes
3906	bra.b		_L18_6x
3907_L18_5x:
3908	bsr.l		sgetexpd			# operand is a DENORM
3909_L18_6x:
3910
3911#
3912#	Result is now in FP0
3913#
3914	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3915	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3916	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3917	unlk		%a6
3918	rts
3919
3920
3921#########################################################################
3922# MONADIC TEMPLATE							#
3923#########################################################################
3924	global		_fgetmans_
3925_fgetmans_:
3926	link		%a6,&-LOCAL_SIZE
3927
3928	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3929	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3930	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3931
3932	fmov.l		&0x0,%fpcr		# zero FPCR
3933
3934#
3935#	copy, convert, and tag input argument
3936#
3937	fmov.s		0x8(%a6),%fp0		# load sgl input
3938	fmov.x		%fp0,FP_SRC(%a6)
3939	lea		FP_SRC(%a6),%a0
3940	bsr.l		tag			# fetch operand type
3941	mov.b		%d0,STAG(%a6)
3942	mov.b		%d0,%d1
3943
3944	andi.l		&0x00ff00ff,USER_FPSR(%a6)
3945
3946	clr.l		%d0
3947	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
3948
3949	tst.b		%d1
3950	bne.b		_L19_2s
3951	bsr.l		sgetman			# operand is a NORM
3952	bra.b		_L19_6s
3953_L19_2s:
3954	cmpi.b		%d1,&ZERO		# is operand a ZERO?
3955	bne.b		_L19_3s			# no
3956	bsr.l		src_zero			# yes
3957	bra.b		_L19_6s
3958_L19_3s:
3959	cmpi.b		%d1,&INF		# is operand an INF?
3960	bne.b		_L19_4s			# no
3961	bsr.l		t_operr			# yes
3962	bra.b		_L19_6s
3963_L19_4s:
3964	cmpi.b		%d1,&QNAN		# is operand a QNAN?
3965	bne.b		_L19_5s			# no
3966	bsr.l		src_qnan			# yes
3967	bra.b		_L19_6s
3968_L19_5s:
3969	bsr.l		sgetmand			# operand is a DENORM
3970_L19_6s:
3971
3972#
3973#	Result is now in FP0
3974#
3975	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
3976	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3977	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
3978	unlk		%a6
3979	rts
3980
3981	global		_fgetmand_
3982_fgetmand_:
3983	link		%a6,&-LOCAL_SIZE
3984
3985	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
3986	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3987	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
3988
3989	fmov.l		&0x0,%fpcr		# zero FPCR
3990
3991#
3992#	copy, convert, and tag input argument
3993#
3994	fmov.d		0x8(%a6),%fp0		# load dbl input
3995	fmov.x		%fp0,FP_SRC(%a6)
3996	lea		FP_SRC(%a6),%a0
3997	bsr.l		tag			# fetch operand type
3998	mov.b		%d0,STAG(%a6)
3999	mov.b		%d0,%d1
4000
4001	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4002
4003	clr.l		%d0
4004	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4005
4006	mov.b		%d1,STAG(%a6)
4007	tst.b		%d1
4008	bne.b		_L19_2d
4009	bsr.l		sgetman			# operand is a NORM
4010	bra.b		_L19_6d
4011_L19_2d:
4012	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4013	bne.b		_L19_3d			# no
4014	bsr.l		src_zero			# yes
4015	bra.b		_L19_6d
4016_L19_3d:
4017	cmpi.b		%d1,&INF		# is operand an INF?
4018	bne.b		_L19_4d			# no
4019	bsr.l		t_operr			# yes
4020	bra.b		_L19_6d
4021_L19_4d:
4022	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4023	bne.b		_L19_5d			# no
4024	bsr.l		src_qnan			# yes
4025	bra.b		_L19_6d
4026_L19_5d:
4027	bsr.l		sgetmand			# operand is a DENORM
4028_L19_6d:
4029
4030#
4031#	Result is now in FP0
4032#
4033	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4034	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4035	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4036	unlk		%a6
4037	rts
4038
4039	global		_fgetmanx_
4040_fgetmanx_:
4041	link		%a6,&-LOCAL_SIZE
4042
4043	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4044	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4045	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4046
4047	fmov.l		&0x0,%fpcr		# zero FPCR
4048
4049#
4050#	copy, convert, and tag input argument
4051#
4052	lea		FP_SRC(%a6),%a0
4053	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
4054	mov.l		0x8+0x4(%a6),0x4(%a0)
4055	mov.l		0x8+0x8(%a6),0x8(%a0)
4056	bsr.l		tag			# fetch operand type
4057	mov.b		%d0,STAG(%a6)
4058	mov.b		%d0,%d1
4059
4060	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4061
4062	clr.l		%d0
4063	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4064
4065	tst.b		%d1
4066	bne.b		_L19_2x
4067	bsr.l		sgetman			# operand is a NORM
4068	bra.b		_L19_6x
4069_L19_2x:
4070	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4071	bne.b		_L19_3x			# no
4072	bsr.l		src_zero			# yes
4073	bra.b		_L19_6x
4074_L19_3x:
4075	cmpi.b		%d1,&INF		# is operand an INF?
4076	bne.b		_L19_4x			# no
4077	bsr.l		t_operr			# yes
4078	bra.b		_L19_6x
4079_L19_4x:
4080	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4081	bne.b		_L19_5x			# no
4082	bsr.l		src_qnan			# yes
4083	bra.b		_L19_6x
4084_L19_5x:
4085	bsr.l		sgetmand			# operand is a DENORM
4086_L19_6x:
4087
4088#
4089#	Result is now in FP0
4090#
4091	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4092	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4093	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4094	unlk		%a6
4095	rts
4096
4097
4098#########################################################################
4099# MONADIC TEMPLATE							#
4100#########################################################################
4101	global		_fsincoss_
4102_fsincoss_:
4103	link		%a6,&-LOCAL_SIZE
4104
4105	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4106	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4107	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4108
4109	fmov.l		&0x0,%fpcr		# zero FPCR
4110
4111#
4112#	copy, convert, and tag input argument
4113#
4114	fmov.s		0x8(%a6),%fp0		# load sgl input
4115	fmov.x		%fp0,FP_SRC(%a6)
4116	lea		FP_SRC(%a6),%a0
4117	bsr.l		tag			# fetch operand type
4118	mov.b		%d0,STAG(%a6)
4119	mov.b		%d0,%d1
4120
4121	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4122
4123	clr.l		%d0
4124	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4125
4126	tst.b		%d1
4127	bne.b		_L20_2s
4128	bsr.l		ssincos			# operand is a NORM
4129	bra.b		_L20_6s
4130_L20_2s:
4131	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4132	bne.b		_L20_3s			# no
4133	bsr.l		ssincosz			# yes
4134	bra.b		_L20_6s
4135_L20_3s:
4136	cmpi.b		%d1,&INF		# is operand an INF?
4137	bne.b		_L20_4s			# no
4138	bsr.l		ssincosi			# yes
4139	bra.b		_L20_6s
4140_L20_4s:
4141	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4142	bne.b		_L20_5s			# no
4143	bsr.l		ssincosqnan			# yes
4144	bra.b		_L20_6s
4145_L20_5s:
4146	bsr.l		ssincosd			# operand is a DENORM
4147_L20_6s:
4148
4149#
4150#	Result is now in FP0
4151#
4152	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4153	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4154	fmovm.x		&0x03,-(%sp)		# store off fp0/fp1
4155	fmovm.x		(%sp)+,&0x40		# fp0 now in fp1
4156	fmovm.x		(%sp)+,&0x80		# fp1 now in fp0
4157	unlk		%a6
4158	rts
4159
4160	global		_fsincosd_
4161_fsincosd_:
4162	link		%a6,&-LOCAL_SIZE
4163
4164	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4165	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4166	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4167
4168	fmov.l		&0x0,%fpcr		# zero FPCR
4169
4170#
4171#	copy, convert, and tag input argument
4172#
4173	fmov.d		0x8(%a6),%fp0		# load dbl input
4174	fmov.x		%fp0,FP_SRC(%a6)
4175	lea		FP_SRC(%a6),%a0
4176	bsr.l		tag			# fetch operand type
4177	mov.b		%d0,STAG(%a6)
4178	mov.b		%d0,%d1
4179
4180	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4181
4182	clr.l		%d0
4183	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4184
4185	mov.b		%d1,STAG(%a6)
4186	tst.b		%d1
4187	bne.b		_L20_2d
4188	bsr.l		ssincos			# operand is a NORM
4189	bra.b		_L20_6d
4190_L20_2d:
4191	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4192	bne.b		_L20_3d			# no
4193	bsr.l		ssincosz			# yes
4194	bra.b		_L20_6d
4195_L20_3d:
4196	cmpi.b		%d1,&INF		# is operand an INF?
4197	bne.b		_L20_4d			# no
4198	bsr.l		ssincosi			# yes
4199	bra.b		_L20_6d
4200_L20_4d:
4201	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4202	bne.b		_L20_5d			# no
4203	bsr.l		ssincosqnan			# yes
4204	bra.b		_L20_6d
4205_L20_5d:
4206	bsr.l		ssincosd			# operand is a DENORM
4207_L20_6d:
4208
4209#
4210#	Result is now in FP0
4211#
4212	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4213	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4214	fmovm.x		&0x03,-(%sp)		# store off fp0/fp1
4215	fmovm.x		(%sp)+,&0x40		# fp0 now in fp1
4216	fmovm.x		(%sp)+,&0x80		# fp1 now in fp0
4217	unlk		%a6
4218	rts
4219
4220	global		_fsincosx_
4221_fsincosx_:
4222	link		%a6,&-LOCAL_SIZE
4223
4224	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4225	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4226	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4227
4228	fmov.l		&0x0,%fpcr		# zero FPCR
4229
4230#
4231#	copy, convert, and tag input argument
4232#
4233	lea		FP_SRC(%a6),%a0
4234	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext input
4235	mov.l		0x8+0x4(%a6),0x4(%a0)
4236	mov.l		0x8+0x8(%a6),0x8(%a0)
4237	bsr.l		tag			# fetch operand type
4238	mov.b		%d0,STAG(%a6)
4239	mov.b		%d0,%d1
4240
4241	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4242
4243	clr.l		%d0
4244	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4245
4246	tst.b		%d1
4247	bne.b		_L20_2x
4248	bsr.l		ssincos			# operand is a NORM
4249	bra.b		_L20_6x
4250_L20_2x:
4251	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4252	bne.b		_L20_3x			# no
4253	bsr.l		ssincosz			# yes
4254	bra.b		_L20_6x
4255_L20_3x:
4256	cmpi.b		%d1,&INF		# is operand an INF?
4257	bne.b		_L20_4x			# no
4258	bsr.l		ssincosi			# yes
4259	bra.b		_L20_6x
4260_L20_4x:
4261	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4262	bne.b		_L20_5x			# no
4263	bsr.l		ssincosqnan			# yes
4264	bra.b		_L20_6x
4265_L20_5x:
4266	bsr.l		ssincosd			# operand is a DENORM
4267_L20_6x:
4268
4269#
4270#	Result is now in FP0
4271#
4272	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4273	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4274	fmovm.x		&0x03,-(%sp)		# store off fp0/fp1
4275	fmovm.x		(%sp)+,&0x40		# fp0 now in fp1
4276	fmovm.x		(%sp)+,&0x80		# fp1 now in fp0
4277	unlk		%a6
4278	rts
4279
4280
4281#########################################################################
4282# DYADIC TEMPLATE							#
4283#########################################################################
4284	global		_frems_
4285_frems_:
4286	link		%a6,&-LOCAL_SIZE
4287
4288	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4289	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4290	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4291
4292	fmov.l		&0x0,%fpcr		# zero FPCR
4293
4294#
4295#	copy, convert, and tag input argument
4296#
4297	fmov.s		0x8(%a6),%fp0		# load sgl dst
4298	fmov.x		%fp0,FP_DST(%a6)
4299	lea		FP_DST(%a6),%a0
4300	bsr.l		tag			# fetch operand type
4301	mov.b		%d0,DTAG(%a6)
4302
4303	fmov.s		0xc(%a6),%fp0		# load sgl src
4304	fmov.x		%fp0,FP_SRC(%a6)
4305	lea		FP_SRC(%a6),%a0
4306	bsr.l		tag			# fetch operand type
4307	mov.b		%d0,STAG(%a6)
4308	mov.l		%d0,%d1
4309
4310	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4311
4312	clr.l		%d0
4313	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4314
4315	lea		FP_SRC(%a6),%a0		# pass ptr to src
4316	lea		FP_DST(%a6),%a1		# pass ptr to dst
4317
4318	tst.b		%d1
4319	bne.b		_L21_2s
4320	bsr.l		srem_snorm			# operand is a NORM
4321	bra.b		_L21_6s
4322_L21_2s:
4323	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4324	bne.b		_L21_3s			# no
4325	bsr.l		srem_szero			# yes
4326	bra.b		_L21_6s
4327_L21_3s:
4328	cmpi.b		%d1,&INF		# is operand an INF?
4329	bne.b		_L21_4s			# no
4330	bsr.l		srem_sinf			# yes
4331	bra.b		_L21_6s
4332_L21_4s:
4333	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4334	bne.b		_L21_5s			# no
4335	bsr.l		sop_sqnan			# yes
4336	bra.b		_L21_6s
4337_L21_5s:
4338	bsr.l		srem_sdnrm			# operand is a DENORM
4339_L21_6s:
4340
4341#
4342#	Result is now in FP0
4343#
4344	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4345	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4346	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4347	unlk		%a6
4348	rts
4349
4350	global		_fremd_
4351_fremd_:
4352	link		%a6,&-LOCAL_SIZE
4353
4354	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4355	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4356	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4357
4358	fmov.l		&0x0,%fpcr		# zero FPCR
4359
4360#
4361#	copy, convert, and tag input argument
4362#
4363	fmov.d		0x8(%a6),%fp0		# load dbl dst
4364	fmov.x		%fp0,FP_DST(%a6)
4365	lea		FP_DST(%a6),%a0
4366	bsr.l		tag			# fetch operand type
4367	mov.b		%d0,DTAG(%a6)
4368
4369	fmov.d		0x10(%a6),%fp0		# load dbl src
4370	fmov.x		%fp0,FP_SRC(%a6)
4371	lea		FP_SRC(%a6),%a0
4372	bsr.l		tag			# fetch operand type
4373	mov.b		%d0,STAG(%a6)
4374	mov.l		%d0,%d1
4375
4376	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4377
4378	clr.l		%d0
4379	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4380
4381	lea		FP_SRC(%a6),%a0		# pass ptr to src
4382	lea		FP_DST(%a6),%a1		# pass ptr to dst
4383
4384	tst.b		%d1
4385	bne.b		_L21_2d
4386	bsr.l		srem_snorm			# operand is a NORM
4387	bra.b		_L21_6d
4388_L21_2d:
4389	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4390	bne.b		_L21_3d			# no
4391	bsr.l		srem_szero			# yes
4392	bra.b		_L21_6d
4393_L21_3d:
4394	cmpi.b		%d1,&INF		# is operand an INF?
4395	bne.b		_L21_4d			# no
4396	bsr.l		srem_sinf			# yes
4397	bra.b		_L21_6d
4398_L21_4d:
4399	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4400	bne.b		_L21_5d			# no
4401	bsr.l		sop_sqnan			# yes
4402	bra.b		_L21_6d
4403_L21_5d:
4404	bsr.l		srem_sdnrm			# operand is a DENORM
4405_L21_6d:
4406
4407#
4408#	Result is now in FP0
4409#
4410	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4411	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4412	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4413	unlk		%a6
4414	rts
4415
4416	global		_fremx_
4417_fremx_:
4418	link		%a6,&-LOCAL_SIZE
4419
4420	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4421	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4422	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4423
4424	fmov.l		&0x0,%fpcr		# zero FPCR
4425
4426#
4427#	copy, convert, and tag input argument
4428#
4429	lea		FP_DST(%a6),%a0
4430	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext dst
4431	mov.l		0x8+0x4(%a6),0x4(%a0)
4432	mov.l		0x8+0x8(%a6),0x8(%a0)
4433	bsr.l		tag			# fetch operand type
4434	mov.b		%d0,DTAG(%a6)
4435
4436	lea		FP_SRC(%a6),%a0
4437	mov.l		0x14+0x0(%a6),0x0(%a0)	# load ext src
4438	mov.l		0x14+0x4(%a6),0x4(%a0)
4439	mov.l		0x14+0x8(%a6),0x8(%a0)
4440	bsr.l		tag			# fetch operand type
4441	mov.b		%d0,STAG(%a6)
4442	mov.l		%d0,%d1
4443
4444	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4445
4446	clr.l		%d0
4447	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4448
4449	lea		FP_SRC(%a6),%a0		# pass ptr to src
4450	lea		FP_DST(%a6),%a1		# pass ptr to dst
4451
4452	tst.b		%d1
4453	bne.b		_L21_2x
4454	bsr.l		srem_snorm			# operand is a NORM
4455	bra.b		_L21_6x
4456_L21_2x:
4457	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4458	bne.b		_L21_3x			# no
4459	bsr.l		srem_szero			# yes
4460	bra.b		_L21_6x
4461_L21_3x:
4462	cmpi.b		%d1,&INF		# is operand an INF?
4463	bne.b		_L21_4x			# no
4464	bsr.l		srem_sinf			# yes
4465	bra.b		_L21_6x
4466_L21_4x:
4467	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4468	bne.b		_L21_5x			# no
4469	bsr.l		sop_sqnan			# yes
4470	bra.b		_L21_6x
4471_L21_5x:
4472	bsr.l		srem_sdnrm			# operand is a DENORM
4473_L21_6x:
4474
4475#
4476#	Result is now in FP0
4477#
4478	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4479	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4480	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4481	unlk		%a6
4482	rts
4483
4484
4485#########################################################################
4486# DYADIC TEMPLATE							#
4487#########################################################################
4488	global		_fmods_
4489_fmods_:
4490	link		%a6,&-LOCAL_SIZE
4491
4492	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4493	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4494	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4495
4496	fmov.l		&0x0,%fpcr		# zero FPCR
4497
4498#
4499#	copy, convert, and tag input argument
4500#
4501	fmov.s		0x8(%a6),%fp0		# load sgl dst
4502	fmov.x		%fp0,FP_DST(%a6)
4503	lea		FP_DST(%a6),%a0
4504	bsr.l		tag			# fetch operand type
4505	mov.b		%d0,DTAG(%a6)
4506
4507	fmov.s		0xc(%a6),%fp0		# load sgl src
4508	fmov.x		%fp0,FP_SRC(%a6)
4509	lea		FP_SRC(%a6),%a0
4510	bsr.l		tag			# fetch operand type
4511	mov.b		%d0,STAG(%a6)
4512	mov.l		%d0,%d1
4513
4514	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4515
4516	clr.l		%d0
4517	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4518
4519	lea		FP_SRC(%a6),%a0		# pass ptr to src
4520	lea		FP_DST(%a6),%a1		# pass ptr to dst
4521
4522	tst.b		%d1
4523	bne.b		_L22_2s
4524	bsr.l		smod_snorm			# operand is a NORM
4525	bra.b		_L22_6s
4526_L22_2s:
4527	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4528	bne.b		_L22_3s			# no
4529	bsr.l		smod_szero			# yes
4530	bra.b		_L22_6s
4531_L22_3s:
4532	cmpi.b		%d1,&INF		# is operand an INF?
4533	bne.b		_L22_4s			# no
4534	bsr.l		smod_sinf			# yes
4535	bra.b		_L22_6s
4536_L22_4s:
4537	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4538	bne.b		_L22_5s			# no
4539	bsr.l		sop_sqnan			# yes
4540	bra.b		_L22_6s
4541_L22_5s:
4542	bsr.l		smod_sdnrm			# operand is a DENORM
4543_L22_6s:
4544
4545#
4546#	Result is now in FP0
4547#
4548	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4549	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4550	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4551	unlk		%a6
4552	rts
4553
4554	global		_fmodd_
4555_fmodd_:
4556	link		%a6,&-LOCAL_SIZE
4557
4558	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4559	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4560	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4561
4562	fmov.l		&0x0,%fpcr		# zero FPCR
4563
4564#
4565#	copy, convert, and tag input argument
4566#
4567	fmov.d		0x8(%a6),%fp0		# load dbl dst
4568	fmov.x		%fp0,FP_DST(%a6)
4569	lea		FP_DST(%a6),%a0
4570	bsr.l		tag			# fetch operand type
4571	mov.b		%d0,DTAG(%a6)
4572
4573	fmov.d		0x10(%a6),%fp0		# load dbl src
4574	fmov.x		%fp0,FP_SRC(%a6)
4575	lea		FP_SRC(%a6),%a0
4576	bsr.l		tag			# fetch operand type
4577	mov.b		%d0,STAG(%a6)
4578	mov.l		%d0,%d1
4579
4580	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4581
4582	clr.l		%d0
4583	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4584
4585	lea		FP_SRC(%a6),%a0		# pass ptr to src
4586	lea		FP_DST(%a6),%a1		# pass ptr to dst
4587
4588	tst.b		%d1
4589	bne.b		_L22_2d
4590	bsr.l		smod_snorm			# operand is a NORM
4591	bra.b		_L22_6d
4592_L22_2d:
4593	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4594	bne.b		_L22_3d			# no
4595	bsr.l		smod_szero			# yes
4596	bra.b		_L22_6d
4597_L22_3d:
4598	cmpi.b		%d1,&INF		# is operand an INF?
4599	bne.b		_L22_4d			# no
4600	bsr.l		smod_sinf			# yes
4601	bra.b		_L22_6d
4602_L22_4d:
4603	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4604	bne.b		_L22_5d			# no
4605	bsr.l		sop_sqnan			# yes
4606	bra.b		_L22_6d
4607_L22_5d:
4608	bsr.l		smod_sdnrm			# operand is a DENORM
4609_L22_6d:
4610
4611#
4612#	Result is now in FP0
4613#
4614	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4615	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4616	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4617	unlk		%a6
4618	rts
4619
4620	global		_fmodx_
4621_fmodx_:
4622	link		%a6,&-LOCAL_SIZE
4623
4624	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4625	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4626	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4627
4628	fmov.l		&0x0,%fpcr		# zero FPCR
4629
4630#
4631#	copy, convert, and tag input argument
4632#
4633	lea		FP_DST(%a6),%a0
4634	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext dst
4635	mov.l		0x8+0x4(%a6),0x4(%a0)
4636	mov.l		0x8+0x8(%a6),0x8(%a0)
4637	bsr.l		tag			# fetch operand type
4638	mov.b		%d0,DTAG(%a6)
4639
4640	lea		FP_SRC(%a6),%a0
4641	mov.l		0x14+0x0(%a6),0x0(%a0)	# load ext src
4642	mov.l		0x14+0x4(%a6),0x4(%a0)
4643	mov.l		0x14+0x8(%a6),0x8(%a0)
4644	bsr.l		tag			# fetch operand type
4645	mov.b		%d0,STAG(%a6)
4646	mov.l		%d0,%d1
4647
4648	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4649
4650	clr.l		%d0
4651	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4652
4653	lea		FP_SRC(%a6),%a0		# pass ptr to src
4654	lea		FP_DST(%a6),%a1		# pass ptr to dst
4655
4656	tst.b		%d1
4657	bne.b		_L22_2x
4658	bsr.l		smod_snorm			# operand is a NORM
4659	bra.b		_L22_6x
4660_L22_2x:
4661	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4662	bne.b		_L22_3x			# no
4663	bsr.l		smod_szero			# yes
4664	bra.b		_L22_6x
4665_L22_3x:
4666	cmpi.b		%d1,&INF		# is operand an INF?
4667	bne.b		_L22_4x			# no
4668	bsr.l		smod_sinf			# yes
4669	bra.b		_L22_6x
4670_L22_4x:
4671	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4672	bne.b		_L22_5x			# no
4673	bsr.l		sop_sqnan			# yes
4674	bra.b		_L22_6x
4675_L22_5x:
4676	bsr.l		smod_sdnrm			# operand is a DENORM
4677_L22_6x:
4678
4679#
4680#	Result is now in FP0
4681#
4682	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4683	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4684	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4685	unlk		%a6
4686	rts
4687
4688
4689#########################################################################
4690# DYADIC TEMPLATE							#
4691#########################################################################
4692	global		_fscales_
4693_fscales_:
4694	link		%a6,&-LOCAL_SIZE
4695
4696	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4697	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4698	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4699
4700	fmov.l		&0x0,%fpcr		# zero FPCR
4701
4702#
4703#	copy, convert, and tag input argument
4704#
4705	fmov.s		0x8(%a6),%fp0		# load sgl dst
4706	fmov.x		%fp0,FP_DST(%a6)
4707	lea		FP_DST(%a6),%a0
4708	bsr.l		tag			# fetch operand type
4709	mov.b		%d0,DTAG(%a6)
4710
4711	fmov.s		0xc(%a6),%fp0		# load sgl src
4712	fmov.x		%fp0,FP_SRC(%a6)
4713	lea		FP_SRC(%a6),%a0
4714	bsr.l		tag			# fetch operand type
4715	mov.b		%d0,STAG(%a6)
4716	mov.l		%d0,%d1
4717
4718	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4719
4720	clr.l		%d0
4721	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4722
4723	lea		FP_SRC(%a6),%a0		# pass ptr to src
4724	lea		FP_DST(%a6),%a1		# pass ptr to dst
4725
4726	tst.b		%d1
4727	bne.b		_L23_2s
4728	bsr.l		sscale_snorm			# operand is a NORM
4729	bra.b		_L23_6s
4730_L23_2s:
4731	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4732	bne.b		_L23_3s			# no
4733	bsr.l		sscale_szero			# yes
4734	bra.b		_L23_6s
4735_L23_3s:
4736	cmpi.b		%d1,&INF		# is operand an INF?
4737	bne.b		_L23_4s			# no
4738	bsr.l		sscale_sinf			# yes
4739	bra.b		_L23_6s
4740_L23_4s:
4741	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4742	bne.b		_L23_5s			# no
4743	bsr.l		sop_sqnan			# yes
4744	bra.b		_L23_6s
4745_L23_5s:
4746	bsr.l		sscale_sdnrm			# operand is a DENORM
4747_L23_6s:
4748
4749#
4750#	Result is now in FP0
4751#
4752	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4753	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4754	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4755	unlk		%a6
4756	rts
4757
4758	global		_fscaled_
4759_fscaled_:
4760	link		%a6,&-LOCAL_SIZE
4761
4762	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4763	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4764	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4765
4766	fmov.l		&0x0,%fpcr		# zero FPCR
4767
4768#
4769#	copy, convert, and tag input argument
4770#
4771	fmov.d		0x8(%a6),%fp0		# load dbl dst
4772	fmov.x		%fp0,FP_DST(%a6)
4773	lea		FP_DST(%a6),%a0
4774	bsr.l		tag			# fetch operand type
4775	mov.b		%d0,DTAG(%a6)
4776
4777	fmov.d		0x10(%a6),%fp0		# load dbl src
4778	fmov.x		%fp0,FP_SRC(%a6)
4779	lea		FP_SRC(%a6),%a0
4780	bsr.l		tag			# fetch operand type
4781	mov.b		%d0,STAG(%a6)
4782	mov.l		%d0,%d1
4783
4784	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4785
4786	clr.l		%d0
4787	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4788
4789	lea		FP_SRC(%a6),%a0		# pass ptr to src
4790	lea		FP_DST(%a6),%a1		# pass ptr to dst
4791
4792	tst.b		%d1
4793	bne.b		_L23_2d
4794	bsr.l		sscale_snorm			# operand is a NORM
4795	bra.b		_L23_6d
4796_L23_2d:
4797	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4798	bne.b		_L23_3d			# no
4799	bsr.l		sscale_szero			# yes
4800	bra.b		_L23_6d
4801_L23_3d:
4802	cmpi.b		%d1,&INF		# is operand an INF?
4803	bne.b		_L23_4d			# no
4804	bsr.l		sscale_sinf			# yes
4805	bra.b		_L23_6d
4806_L23_4d:
4807	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4808	bne.b		_L23_5d			# no
4809	bsr.l		sop_sqnan			# yes
4810	bra.b		_L23_6d
4811_L23_5d:
4812	bsr.l		sscale_sdnrm			# operand is a DENORM
4813_L23_6d:
4814
4815#
4816#	Result is now in FP0
4817#
4818	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4819	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4820	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4821	unlk		%a6
4822	rts
4823
4824	global		_fscalex_
4825_fscalex_:
4826	link		%a6,&-LOCAL_SIZE
4827
4828	movm.l		&0x0303,EXC_DREGS(%a6)	# save d0-d1/a0-a1
4829	fmovm.l		%fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4830	fmovm.x		&0xc0,EXC_FP0(%a6)	# save fp0/fp1
4831
4832	fmov.l		&0x0,%fpcr		# zero FPCR
4833
4834#
4835#	copy, convert, and tag input argument
4836#
4837	lea		FP_DST(%a6),%a0
4838	mov.l		0x8+0x0(%a6),0x0(%a0)	# load ext dst
4839	mov.l		0x8+0x4(%a6),0x4(%a0)
4840	mov.l		0x8+0x8(%a6),0x8(%a0)
4841	bsr.l		tag			# fetch operand type
4842	mov.b		%d0,DTAG(%a6)
4843
4844	lea		FP_SRC(%a6),%a0
4845	mov.l		0x14+0x0(%a6),0x0(%a0)	# load ext src
4846	mov.l		0x14+0x4(%a6),0x4(%a0)
4847	mov.l		0x14+0x8(%a6),0x8(%a0)
4848	bsr.l		tag			# fetch operand type
4849	mov.b		%d0,STAG(%a6)
4850	mov.l		%d0,%d1
4851
4852	andi.l		&0x00ff00ff,USER_FPSR(%a6)
4853
4854	clr.l		%d0
4855	mov.b		FPCR_MODE(%a6),%d0	# pass rnd mode,prec
4856
4857	lea		FP_SRC(%a6),%a0		# pass ptr to src
4858	lea		FP_DST(%a6),%a1		# pass ptr to dst
4859
4860	tst.b		%d1
4861	bne.b		_L23_2x
4862	bsr.l		sscale_snorm			# operand is a NORM
4863	bra.b		_L23_6x
4864_L23_2x:
4865	cmpi.b		%d1,&ZERO		# is operand a ZERO?
4866	bne.b		_L23_3x			# no
4867	bsr.l		sscale_szero			# yes
4868	bra.b		_L23_6x
4869_L23_3x:
4870	cmpi.b		%d1,&INF		# is operand an INF?
4871	bne.b		_L23_4x			# no
4872	bsr.l		sscale_sinf			# yes
4873	bra.b		_L23_6x
4874_L23_4x:
4875	cmpi.b		%d1,&QNAN		# is operand a QNAN?
4876	bne.b		_L23_5x			# no
4877	bsr.l		sop_sqnan			# yes
4878	bra.b		_L23_6x
4879_L23_5x:
4880	bsr.l		sscale_sdnrm			# operand is a DENORM
4881_L23_6x:
4882
4883#
4884#	Result is now in FP0
4885#
4886	movm.l		EXC_DREGS(%a6),&0x0303	# restore d0-d1/a0-a1
4887	fmovm.l		USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4888	fmovm.x		EXC_FP1(%a6),&0x40	# restore fp1
4889	unlk		%a6
4890	rts
4891
4892
4893#########################################################################
4894# ssin():     computes the sine of a normalized input			#
4895# ssind():    computes the sine of a denormalized input			#
4896# scos():     computes the cosine of a normalized input			#
4897# scosd():    computes the cosine of a denormalized input		#
4898# ssincos():  computes the sine and cosine of a normalized input	#
4899# ssincosd(): computes the sine and cosine of a denormalized input	#
4900#									#
4901# INPUT *************************************************************** #
4902#	a0 = pointer to extended precision input			#
4903#	d0 = round precision,mode					#
4904#									#
4905# OUTPUT ************************************************************** #
4906#	fp0 = sin(X) or cos(X)						#
4907#									#
4908#    For ssincos(X):							#
4909#	fp0 = sin(X)							#
4910#	fp1 = cos(X)							#
4911#									#
4912# ACCURACY and MONOTONICITY ******************************************* #
4913#	The returned result is within 1 ulp in 64 significant bit, i.e.	#
4914#	within 0.5001 ulp to 53 bits if the result is subsequently	#
4915#	rounded to double precision. The result is provably monotonic	#
4916#	in double precision.						#
4917#									#
4918# ALGORITHM ***********************************************************	#
4919#									#
4920#	SIN and COS:							#
4921#	1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1.	#
4922#									#
4923#	2. If |X| >= 15Pi or |X| < 2**(-40), go to 7.			#
4924#									#
4925#	3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let	#
4926#		k = N mod 4, so in particular, k = 0,1,2,or 3.		#
4927#		Overwrite k by k := k + AdjN.				#
4928#									#
4929#	4. If k is even, go to 6.					#
4930#									#
4931#	5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j.			#
4932#		Return sgn*cos(r) where cos(r) is approximated by an	#
4933#		even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)),	#
4934#		s = r*r.						#
4935#		Exit.							#
4936#									#
4937#	6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r)	#
4938#		where sin(r) is approximated by an odd polynomial in r	#
4939#		r + r*s*(A1+s*(A2+ ... + s*A7)),	s = r*r.	#
4940#		Exit.							#
4941#									#
4942#	7. If |X| > 1, go to 9.						#
4943#									#
4944#	8. (|X|<2**(-40)) If SIN is invoked, return X;			#
4945#		otherwise return 1.					#
4946#									#
4947#	9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,		#
4948#		go back to 3.						#
4949#									#
4950#	SINCOS:								#
4951#	1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.			#
4952#									#
4953#	2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let	#
4954#		k = N mod 4, so in particular, k = 0,1,2,or 3.		#
4955#									#
4956#	3. If k is even, go to 5.					#
4957#									#
4958#	4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie.	#
4959#		j1 exclusive or with the l.s.b. of k.			#
4960#		sgn1 := (-1)**j1, sgn2 := (-1)**j2.			#
4961#		SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where	#
4962#		sin(r) and cos(r) are computed as odd and even		#
4963#		polynomials in r, respectively. Exit			#
4964#									#
4965#	5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1.			#
4966#		SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where	#
4967#		sin(r) and cos(r) are computed as odd and even		#
4968#		polynomials in r, respectively. Exit			#
4969#									#
4970#	6. If |X| > 1, go to 8.						#
4971#									#
4972#	7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit.		#
4973#									#
4974#	8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,		#
4975#		go back to 2.						#
4976#									#
4977#########################################################################
4978
4979SINA7:	long		0xBD6AAA77,0xCCC994F5
4980SINA6:	long		0x3DE61209,0x7AAE8DA1
4981SINA5:	long		0xBE5AE645,0x2A118AE4
4982SINA4:	long		0x3EC71DE3,0xA5341531
4983SINA3:	long		0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
4984SINA2:	long		0x3FF80000,0x88888888,0x888859AF,0x00000000
4985SINA1:	long		0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
4986
4987COSB8:	long		0x3D2AC4D0,0xD6011EE3
4988COSB7:	long		0xBDA9396F,0x9F45AC19
4989COSB6:	long		0x3E21EED9,0x0612C972
4990COSB5:	long		0xBE927E4F,0xB79D9FCF
4991COSB4:	long		0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
4992COSB3:	long		0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
4993COSB2:	long		0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
4994COSB1:	long		0xBF000000
4995
4996	set		INARG,FP_SCR0
4997
4998	set		X,FP_SCR0
4999#	set		XDCARE,X+2
5000	set		XFRAC,X+4
5001
5002	set		RPRIME,FP_SCR0
5003	set		SPRIME,FP_SCR1
5004
5005	set		POSNEG1,L_SCR1
5006	set		TWOTO63,L_SCR1
5007
5008	set		ENDFLAG,L_SCR2
5009	set		INT,L_SCR2
5010
5011	set		ADJN,L_SCR3
5012
5013############################################
5014	global		ssin
5015ssin:
5016	mov.l		&0,ADJN(%a6)		# yes; SET ADJN TO 0
5017	bra.b		SINBGN
5018
5019############################################
5020	global		scos
5021scos:
5022	mov.l		&1,ADJN(%a6)		# yes; SET ADJN TO 1
5023
5024############################################
5025SINBGN:
5026#--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
5027
5028	fmov.x		(%a0),%fp0		# LOAD INPUT
5029	fmov.x		%fp0,X(%a6)		# save input at X
5030
5031# "COMPACTIFY" X
5032	mov.l		(%a0),%d1		# put exp in hi word
5033	mov.w		4(%a0),%d1		# fetch hi(man)
5034	and.l		&0x7FFFFFFF,%d1		# strip sign
5035
5036	cmpi.l		%d1,&0x3FD78000		# is |X| >= 2**(-40)?
5037	bge.b		SOK1			# no
5038	bra.w		SINSM			# yes; input is very small
5039
5040SOK1:
5041	cmp.l		%d1,&0x4004BC7E		# is |X| < 15 PI?
5042	blt.b		SINMAIN			# no
5043	bra.w		SREDUCEX		# yes; input is very large
5044
5045#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5046#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5047SINMAIN:
5048	fmov.x		%fp0,%fp1
5049	fmul.d		TWOBYPI(%pc),%fp1	# X*2/PI
5050
5051	lea		PITBL+0x200(%pc),%a1	# TABLE OF N*PI/2, N = -32,...,32
5052
5053	fmov.l		%fp1,INT(%a6)		# CONVERT TO INTEGER
5054
5055	mov.l		INT(%a6),%d1		# make a copy of N
5056	asl.l		&4,%d1			# N *= 16
5057	add.l		%d1,%a1			# tbl_addr = a1 + (N*16)
5058
5059# A1 IS THE ADDRESS OF N*PIBY2
5060# ...WHICH IS IN TWO PIECES Y1 & Y2
5061	fsub.x		(%a1)+,%fp0		# X-Y1
5062	fsub.s		(%a1),%fp0		# fp0 = R = (X-Y1)-Y2
5063
5064SINCONT:
5065#--continuation from REDUCEX
5066
5067#--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
5068	mov.l		INT(%a6),%d1
5069	add.l		ADJN(%a6),%d1		# SEE IF D0 IS ODD OR EVEN
5070	ror.l		&1,%d1			# D0 WAS ODD IFF D0 IS NEGATIVE
5071	cmp.l		%d1,&0
5072	blt.w		COSPOLY
5073
5074#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5075#--THEN WE RETURN	SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
5076#--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
5077#--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
5078#--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
5079#--WHERE T=S*S.
5080#--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
5081#--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
5082SINPOLY:
5083	fmovm.x		&0x0c,-(%sp)		# save fp2/fp3
5084
5085	fmov.x		%fp0,X(%a6)		# X IS R
5086	fmul.x		%fp0,%fp0		# FP0 IS S
5087
5088	fmov.d		SINA7(%pc),%fp3
5089	fmov.d		SINA6(%pc),%fp2
5090
5091	fmov.x		%fp0,%fp1
5092	fmul.x		%fp1,%fp1		# FP1 IS T
5093
5094	ror.l		&1,%d1
5095	and.l		&0x80000000,%d1
5096# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5097	eor.l		%d1,X(%a6)		# X IS NOW R'= SGN*R
5098
5099	fmul.x		%fp1,%fp3		# TA7
5100	fmul.x		%fp1,%fp2		# TA6
5101
5102	fadd.d		SINA5(%pc),%fp3		# A5+TA7
5103	fadd.d		SINA4(%pc),%fp2		# A4+TA6
5104
5105	fmul.x		%fp1,%fp3		# T(A5+TA7)
5106	fmul.x		%fp1,%fp2		# T(A4+TA6)
5107
5108	fadd.d		SINA3(%pc),%fp3		# A3+T(A5+TA7)
5109	fadd.x		SINA2(%pc),%fp2		# A2+T(A4+TA6)
5110
5111	fmul.x		%fp3,%fp1		# T(A3+T(A5+TA7))
5112
5113	fmul.x		%fp0,%fp2		# S(A2+T(A4+TA6))
5114	fadd.x		SINA1(%pc),%fp1		# A1+T(A3+T(A5+TA7))
5115	fmul.x		X(%a6),%fp0		# R'*S
5116
5117	fadd.x		%fp2,%fp1		# [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
5118
5119	fmul.x		%fp1,%fp0		# SIN(R')-R'
5120
5121	fmovm.x		(%sp)+,&0x30		# restore fp2/fp3
5122
5123	fmov.l		%d0,%fpcr		# restore users round mode,prec
5124	fadd.x		X(%a6),%fp0		# last inst - possible exception set
5125	bra		t_inx2
5126
5127#--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5128#--THEN WE RETURN	SGN*COS(R). SGN*COS(R) IS COMPUTED BY
5129#--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
5130#--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
5131#--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
5132#--WHERE T=S*S.
5133#--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
5134#--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
5135#--AND IS THEREFORE STORED AS SINGLE PRECISION.
5136COSPOLY:
5137	fmovm.x		&0x0c,-(%sp)		# save fp2/fp3
5138
5139	fmul.x		%fp0,%fp0		# FP0 IS S
5140
5141	fmov.d		COSB8(%pc),%fp2
5142	fmov.d		COSB7(%pc),%fp3
5143
5144	fmov.x		%fp0,%fp1
5145	fmul.x		%fp1,%fp1		# FP1 IS T
5146
5147	fmov.x		%fp0,X(%a6)		# X IS S
5148	ror.l		&1,%d1
5149	and.l		&0x80000000,%d1
5150# ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5151
5152	fmul.x		%fp1,%fp2		# TB8
5153
5154	eor.l		%d1,X(%a6)		# X IS NOW S'= SGN*S
5155	and.l		&0x80000000,%d1
5156
5157	fmul.x		%fp1,%fp3		# TB7
5158
5159	or.l		&0x3F800000,%d1		# D0 IS SGN IN SINGLE
5160	mov.l		%d1,POSNEG1(%a6)
5161
5162	fadd.d		COSB6(%pc),%fp2		# B6+TB8
5163	fadd.d		COSB5(%pc),%fp3		# B5+TB7
5164
5165	fmul.x		%fp1,%fp2		# T(B6+TB8)
5166	fmul.x		%fp1,%fp3		# T(B5+TB7)
5167
5168	fadd.d		COSB4(%pc),%fp2		# B4+T(B6+TB8)
5169	fadd.x		COSB3(%pc),%fp3		# B3+T(B5+TB7)
5170
5171	fmul.x		%fp1,%fp2		# T(B4+T(B6+TB8))
5172	fmul.x		%fp3,%fp1		# T(B3+T(B5+TB7))
5173
5174	fadd.x		COSB2(%pc),%fp2		# B2+T(B4+T(B6+TB8))
5175	fadd.s		COSB1(%pc),%fp1		# B1+T(B3+T(B5+TB7))
5176
5177	fmul.x		%fp2,%fp0		# S(B2+T(B4+T(B6+TB8)))
5178
5179	fadd.x		%fp1,%fp0
5180
5181	fmul.x		X(%a6),%fp0
5182
5183	fmovm.x		(%sp)+,&0x30		# restore fp2/fp3
5184
5185	fmov.l		%d0,%fpcr		# restore users round mode,prec
5186	fadd.s		POSNEG1(%a6),%fp0	# last inst - possible exception set
5187	bra		t_inx2
5188
5189##############################################
5190
5191# SINe: Big OR Small?
5192#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5193#--IF |X| < 2**(-40), RETURN X OR 1.
5194SINBORS:
5195	cmp.l		%d1,&0x3FFF8000
5196	bgt.l		SREDUCEX
5197
5198SINSM:
5199	mov.l		ADJN(%a6),%d1
5200	cmp.l		%d1,&0
5201	bgt.b		COSTINY
5202
5203# here, the operation may underflow iff the precision is sgl or dbl.
5204# extended denorms are handled through another entry point.
5205SINTINY:
5206#	mov.w		&0x0000,XDCARE(%a6)	# JUST IN CASE
5207
5208	fmov.l		%d0,%fpcr		# restore users round mode,prec
5209	mov.b		&FMOV_OP,%d1		# last inst is MOVE
5210	fmov.x		X(%a6),%fp0		# last inst - possible exception set
5211	bra		t_catch
5212
5213COSTINY:
5214	fmov.s		&0x3F800000,%fp0	# fp0 = 1.0
5215	fmov.l		%d0,%fpcr		# restore users round mode,prec
5216	fadd.s		&0x80800000,%fp0	# last inst - possible exception set
5217	bra		t_pinx2
5218
5219################################################
5220	global		ssind
5221#--SIN(X) = X FOR DENORMALIZED X
5222ssind:
5223	bra		t_extdnrm
5224
5225############################################
5226	global		scosd
5227#--COS(X) = 1 FOR DENORMALIZED X
5228scosd:
5229	fmov.s		&0x3F800000,%fp0	# fp0 = 1.0
5230	bra		t_pinx2
5231
5232##################################################
5233
5234	global		ssincos
5235ssincos:
5236#--SET ADJN TO 4
5237	mov.l		&4,ADJN(%a6)
5238
5239	fmov.x		(%a0),%fp0		# LOAD INPUT
5240	fmov.x		%fp0,X(%a6)
5241
5242	mov.l		(%a0),%d1
5243	mov.w		4(%a0),%d1
5244	and.l		&0x7FFFFFFF,%d1		# COMPACTIFY X
5245
5246	cmp.l		%d1,&0x3FD78000		# |X| >= 2**(-40)?
5247	bge.b		SCOK1
5248	bra.w		SCSM
5249
5250SCOK1:
5251	cmp.l		%d1,&0x4004BC7E		# |X| < 15 PI?
5252	blt.b		SCMAIN
5253	bra.w		SREDUCEX
5254
5255
5256#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5257#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5258SCMAIN:
5259	fmov.x		%fp0,%fp1
5260
5261	fmul.d		TWOBYPI(%pc),%fp1	# X*2/PI
5262
5263	lea		PITBL+0x200(%pc),%a1	# TABLE OF N*PI/2, N = -32,...,32
5264
5265	fmov.l		%fp1,INT(%a6)		# CONVERT TO INTEGER
5266
5267	mov.l		INT(%a6),%d1
5268	asl.l		&4,%d1
5269	add.l		%d1,%a1			# ADDRESS OF N*PIBY2, IN Y1, Y2
5270
5271	fsub.x		(%a1)+,%fp0		# X-Y1
5272	fsub.s		(%a1),%fp0		# FP0 IS R = (X-Y1)-Y2
5273
5274SCCONT:
5275#--continuation point from REDUCEX
5276
5277	mov.l		INT(%a6),%d1
5278	ror.l		&1,%d1
5279	cmp.l		%d1,&0			# D0 < 0 IFF N IS ODD
5280	bge.w		NEVEN
5281
5282SNODD:
5283#--REGISTERS SAVED SO FAR: D0, A0, FP2.
5284	fmovm.x		&0x04,-(%sp)		# save fp2
5285
5286	fmov.x		%fp0,RPRIME(%a6)
5287	fmul.x		%fp0,%fp0		# FP0 IS S = R*R
5288	fmov.d		SINA7(%pc),%fp1		# A7
5289	fmov.d		COSB8(%pc),%fp2		# B8
5290	fmul.x		%fp0,%fp1		# SA7
5291	fmul.x		%fp0,%fp2		# SB8
5292
5293	mov.l		%d2,-(%sp)
5294	mov.l		%d1,%d2
5295	ror.l		&1,%d2
5296	and.l		&0x80000000,%d2
5297	eor.l		%d1,%d2
5298	and.l		&0x80000000,%d2
5299
5300	fadd.d		SINA6(%pc),%fp1		# A6+SA7
5301	fadd.d		COSB7(%pc),%fp2		# B7+SB8
5302
5303	fmul.x		%fp0,%fp1		# S(A6+SA7)
5304	eor.l		%d2,RPRIME(%a6)
5305	mov.l		(%sp)+,%d2
5306	fmul.x		%fp0,%fp2		# S(B7+SB8)
5307	ror.l		&1,%d1
5308	and.l		&0x80000000,%d1
5309	mov.l		&0x3F800000,POSNEG1(%a6)
5310	eor.l		%d1,POSNEG1(%a6)
5311
5312	fadd.d		SINA5(%pc),%fp1		# A5+S(A6+SA7)
5313	fadd.d		COSB6(%pc),%fp2		# B6+S(B7+SB8)
5314
5315	fmul.x		%fp0,%fp1		# S(A5+S(A6+SA7))
5316	fmul.x		%fp0,%fp2		# S(B6+S(B7+SB8))
5317	fmov.x		%fp0,SPRIME(%a6)
5318
5319	fadd.d		SINA4(%pc),%fp1		# A4+S(A5+S(A6+SA7))
5320	eor.l		%d1,SPRIME(%a6)
5321	fadd.d		COSB5(%pc),%fp2		# B5+S(B6+S(B7+SB8))
5322
5323	fmul.x		%fp0,%fp1		# S(A4+...)
5324	fmul.x		%fp0,%fp2		# S(B5+...)
5325
5326	fadd.d		SINA3(%pc),%fp1		# A3+S(A4+...)
5327	fadd.d		COSB4(%pc),%fp2		# B4+S(B5+...)
5328
5329	fmul.x		%fp0,%fp1		# S(A3+...)
5330	fmul.x		%fp0,%fp2		# S(B4+...)
5331
5332	fadd.x		SINA2(%pc),%fp1		# A2+S(A3+...)
5333	fadd.x		COSB3(%pc),%fp2		# B3+S(B4+...)
5334
5335	fmul.x		%fp0,%fp1		# S(A2+...)
5336	fmul.x		%fp0,%fp2		# S(B3+...)
5337
5338	fadd.x		SINA1(%pc),%fp1		# A1+S(A2+...)
5339	fadd.x		COSB2(%pc),%fp2		# B2+S(B3+...)
5340
5341	fmul.x		%fp0,%fp1		# S(A1+...)
5342	fmul.x		%fp2,%fp0		# S(B2+...)
5343
5344	fmul.x		RPRIME(%a6),%fp1	# R'S(A1+...)
5345	fadd.s		COSB1(%pc),%fp0		# B1+S(B2...)
5346	fmul.x		SPRIME(%a6),%fp0	# S'(B1+S(B2+...))
5347
5348	fmovm.x		(%sp)+,&0x20		# restore fp2
5349
5350	fmov.l		%d0,%fpcr
5351	fadd.x		RPRIME(%a6),%fp1	# COS(X)
5352	bsr		sto_cos			# store cosine result
5353	fadd.s		POSNEG1(%a6),%fp0	# SIN(X)
5354	bra		t_inx2
5355
5356NEVEN:
5357#--REGISTERS SAVED SO FAR: FP2.
5358	fmovm.x		&0x04,-(%sp)		# save fp2
5359
5360	fmov.x		%fp0,RPRIME(%a6)
5361	fmul.x		%fp0,%fp0		# FP0 IS S = R*R
5362
5363	fmov.d		COSB8(%pc),%fp1		# B8
5364	fmov.d		SINA7(%pc),%fp2		# A7
5365
5366	fmul.x		%fp0,%fp1		# SB8
5367	fmov.x		%fp0,SPRIME(%a6)
5368	fmul.x		%fp0,%fp2		# SA7
5369
5370	ror.l		&1,%d1
5371	and.l		&0x80000000,%d1
5372
5373	fadd.d		COSB7(%pc),%fp1		# B7+SB8
5374	fadd.d		SINA6(%pc),%fp2		# A6+SA7
5375
5376	eor.l		%d1,RPRIME(%a6)
5377	eor.l		%d1,SPRIME(%a6)
5378
5379	fmul.x		%fp0,%fp1		# S(B7+SB8)
5380
5381	or.l		&0x3F800000,%d1
5382	mov.l		%d1,POSNEG1(%a6)
5383
5384	fmul.x		%fp0,%fp2		# S(A6+SA7)
5385
5386	fadd.d		COSB6(%pc),%fp1		# B6+S(B7+SB8)
5387	fadd.d		SINA5(%pc),%fp2		# A5+S(A6+SA7)
5388
5389	fmul.x		%fp0,%fp1		# S(B6+S(B7+SB8))
5390	fmul.x		%fp0,%fp2		# S(A5+S(A6+SA7))
5391
5392	fadd.d		COSB5(%pc),%fp1		# B5+S(B6+S(B7+SB8))
5393	fadd.d		SINA4(%pc),%fp2		# A4+S(A5+S(A6+SA7))
5394
5395	fmul.x		%fp0,%fp1		# S(B5+...)
5396	fmul.x		%fp0,%fp2		# S(A4+...)
5397
5398	fadd.d		COSB4(%pc),%fp1		# B4+S(B5+...)
5399	fadd.d		SINA3(%pc),%fp2		# A3+S(A4+...)
5400
5401	fmul.x		%fp0,%fp1		# S(B4+...)
5402	fmul.x		%fp0,%fp2		# S(A3+...)
5403
5404	fadd.x		COSB3(%pc),%fp1		# B3+S(B4+...)
5405	fadd.x		SINA2(%pc),%fp2		# A2+S(A3+...)
5406
5407	fmul.x		%fp0,%fp1		# S(B3+...)
5408	fmul.x		%fp0,%fp2		# S(A2+...)
5409
5410	fadd.x		COSB2(%pc),%fp1		# B2+S(B3+...)
5411	fadd.x		SINA1(%pc),%fp2		# A1+S(A2+...)
5412
5413	fmul.x		%fp0,%fp1		# S(B2+...)
5414	fmul.x		%fp2,%fp0		# s(a1+...)
5415
5416
5417	fadd.s		COSB1(%pc),%fp1		# B1+S(B2...)
5418	fmul.x		RPRIME(%a6),%fp0	# R'S(A1+...)
5419	fmul.x		SPRIME(%a6),%fp1	# S'(B1+S(B2+...))
5420
5421	fmovm.x		(%sp)+,&0x20		# restore fp2
5422
5423	fmov.l		%d0,%fpcr
5424	fadd.s		POSNEG1(%a6),%fp1	# COS(X)
5425	bsr		sto_cos			# store cosine result
5426	fadd.x		RPRIME(%a6),%fp0	# SIN(X)
5427	bra		t_inx2
5428
5429################################################
5430
5431SCBORS:
5432	cmp.l		%d1,&0x3FFF8000
5433	bgt.w		SREDUCEX
5434
5435################################################
5436
5437SCSM:
5438#	mov.w		&0x0000,XDCARE(%a6)
5439	fmov.s		&0x3F800000,%fp1
5440
5441	fmov.l		%d0,%fpcr
5442	fsub.s		&0x00800000,%fp1
5443	bsr		sto_cos			# store cosine result
5444	fmov.l		%fpcr,%d0		# d0 must have fpcr,too
5445	mov.b		&FMOV_OP,%d1		# last inst is MOVE
5446	fmov.x		X(%a6),%fp0
5447	bra		t_catch
5448
5449##############################################
5450
5451	global		ssincosd
5452#--SIN AND COS OF X FOR DENORMALIZED X
5453ssincosd:
5454	mov.l		%d0,-(%sp)		# save d0
5455	fmov.s		&0x3F800000,%fp1
5456	bsr		sto_cos			# store cosine result
5457	mov.l		(%sp)+,%d0		# restore d0
5458	bra		t_extdnrm
5459
5460############################################
5461
5462#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5463#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5464#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5465SREDUCEX:
5466	fmovm.x		&0x3c,-(%sp)		# save {fp2-fp5}
5467	mov.l		%d2,-(%sp)		# save d2
5468	fmov.s		&0x00000000,%fp1	# fp1 = 0
5469
5470#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5471#--there is a danger of unwanted overflow in first LOOP iteration.  In this
5472#--case, reduce argument by one remainder step to make subsequent reduction
5473#--safe.
5474	cmp.l		%d1,&0x7ffeffff		# is arg dangerously large?
5475	bne.b		SLOOP			# no
5476
5477# yes; create 2**16383*PI/2
5478	mov.w		&0x7ffe,FP_SCR0_EX(%a6)
5479	mov.l		&0xc90fdaa2,FP_SCR0_HI(%a6)
5480	clr.l		FP_SCR0_LO(%a6)
5481
5482# create low half of 2**16383*PI/2 at FP_SCR1
5483	mov.w		&0x7fdc,FP_SCR1_EX(%a6)
5484	mov.l		&0x85a308d3,FP_SCR1_HI(%a6)
5485	clr.l		FP_SCR1_LO(%a6)
5486
5487	ftest.x		%fp0			# test sign of argument
5488	fblt.w		sred_neg
5489
5490	or.b		&0x80,FP_SCR0_EX(%a6)	# positive arg
5491	or.b		&0x80,FP_SCR1_EX(%a6)
5492sred_neg:
5493	fadd.x		FP_SCR0(%a6),%fp0	# high part of reduction is exact
5494	fmov.x		%fp0,%fp1		# save high result in fp1
5495	fadd.x		FP_SCR1(%a6),%fp0	# low part of reduction
5496	fsub.x		%fp0,%fp1		# determine low component of result
5497	fadd.x		FP_SCR1(%a6),%fp1	# fp0/fp1 are reduced argument.
5498
5499#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5500#--integer quotient will be stored in N
5501#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5502SLOOP:
5503	fmov.x		%fp0,INARG(%a6)		# +-2**K * F, 1 <= F < 2
5504	mov.w		INARG(%a6),%d1
5505	mov.l		%d1,%a1			# save a copy of D0
5506	and.l		&0x00007FFF,%d1
5507	sub.l		&0x00003FFF,%d1		# d0 = K
5508	cmp.l		%d1,&28
5509	ble.b		SLASTLOOP
5510SCONTLOOP:
5511	sub.l		&27,%d1			# d0 = L := K-27
5512	mov.b		&0,ENDFLAG(%a6)
5513	bra.b		SWORK
5514SLASTLOOP:
5515	clr.l		%d1			# d0 = L := 0
5516	mov.b		&1,ENDFLAG(%a6)
5517
5518SWORK:
5519#--FIND THE REMAINDER OF (R,r) W.R.T.	2**L * (PI/2). L IS SO CHOSEN
5520#--THAT	INT( X * (2/PI) / 2**(L) ) < 2**29.
5521
5522#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5523#--2**L * (PIby2_1), 2**L * (PIby2_2)
5524
5525	mov.l		&0x00003FFE,%d2		# BIASED EXP OF 2/PI
5526	sub.l		%d1,%d2			# BIASED EXP OF 2**(-L)*(2/PI)
5527
5528	mov.l		&0xA2F9836E,FP_SCR0_HI(%a6)
5529	mov.l		&0x4E44152A,FP_SCR0_LO(%a6)
5530	mov.w		%d2,FP_SCR0_EX(%a6)	# FP_SCR0 = 2**(-L)*(2/PI)
5531
5532	fmov.x		%fp0,%fp2
5533	fmul.x		FP_SCR0(%a6),%fp2	# fp2 = X * 2**(-L)*(2/PI)
5534
5535#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5536#--FLOATING POINT FORMAT, THE TWO FMOVE'S	FMOVE.L FP <--> N
5537#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5538#--(SIGN(INARG)*2**63	+	FP2) - SIGN(INARG)*2**63 WILL GIVE
5539#--US THE DESIRED VALUE IN FLOATING POINT.
5540	mov.l		%a1,%d2
5541	swap		%d2
5542	and.l		&0x80000000,%d2
5543	or.l		&0x5F000000,%d2		# d2 = SIGN(INARG)*2**63 IN SGL
5544	mov.l		%d2,TWOTO63(%a6)
5545	fadd.s		TWOTO63(%a6),%fp2	# THE FRACTIONAL PART OF FP1 IS ROUNDED
5546	fsub.s		TWOTO63(%a6),%fp2	# fp2 = N
5547#	fint.x		%fp2
5548
5549#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5550	mov.l		%d1,%d2			# d2 = L
5551
5552	add.l		&0x00003FFF,%d2		# BIASED EXP OF 2**L * (PI/2)
5553	mov.w		%d2,FP_SCR0_EX(%a6)
5554	mov.l		&0xC90FDAA2,FP_SCR0_HI(%a6)
5555	clr.l		FP_SCR0_LO(%a6)		# FP_SCR0 = 2**(L) * Piby2_1
5556
5557	add.l		&0x00003FDD,%d1
5558	mov.w		%d1,FP_SCR1_EX(%a6)
5559	mov.l		&0x85A308D3,FP_SCR1_HI(%a6)
5560	clr.l		FP_SCR1_LO(%a6)		# FP_SCR1 = 2**(L) * Piby2_2
5561
5562	mov.b		ENDFLAG(%a6),%d1
5563
5564#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5565#--P2 = 2**(L) * Piby2_2
5566	fmov.x		%fp2,%fp4		# fp4 = N
5567	fmul.x		FP_SCR0(%a6),%fp4	# fp4 = W = N*P1
5568	fmov.x		%fp2,%fp5		# fp5 = N
5569	fmul.x		FP_SCR1(%a6),%fp5	# fp5 = w = N*P2
5570	fmov.x		%fp4,%fp3		# fp3 = W = N*P1
5571
5572#--we want P+p = W+w  but  |p| <= half ulp of P
5573#--Then, we need to compute  A := R-P   and  a := r-p
5574	fadd.x		%fp5,%fp3		# fp3 = P
5575	fsub.x		%fp3,%fp4		# fp4 = W-P
5576
5577	fsub.x		%fp3,%fp0		# fp0 = A := R - P
5578	fadd.x		%fp5,%fp4		# fp4 = p = (W-P)+w
5579
5580	fmov.x		%fp0,%fp3		# fp3 = A
5581	fsub.x		%fp4,%fp1		# fp1 = a := r - p
5582
5583#--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
5584#--|r| <= half ulp of R.
5585	fadd.x		%fp1,%fp0		# fp0 = R := A+a
5586#--No need to calculate r if this is the last loop
5587	cmp.b		%d1,&0
5588	bgt.w		SRESTORE
5589
5590#--Need to calculate r
5591	fsub.x		%fp0,%fp3		# fp3 = A-R
5592	fadd.x		%fp3,%fp1		# fp1 = r := (A-R)+a
5593	bra.w		SLOOP
5594
5595SRESTORE:
5596	fmov.l		%fp2,INT(%a6)
5597	mov.l		(%sp)+,%d2		# restore d2
5598	fmovm.x		(%sp)+,&0x3c		# restore {fp2-fp5}
5599
5600	mov.l		ADJN(%a6),%d1
5601	cmp.l		%d1,&4
5602
5603	blt.w		SINCONT
5604	bra.w		SCCONT
5605
5606#########################################################################
5607# stan():  computes the tangent of a normalized input			#
5608# stand(): computes the tangent of a denormalized input			#
5609#									#
5610# INPUT *************************************************************** #
5611#	a0 = pointer to extended precision input			#
5612#	d0 = round precision,mode					#
5613#									#
5614# OUTPUT ************************************************************** #
5615#	fp0 = tan(X)							#
5616#									#
5617# ACCURACY and MONOTONICITY ******************************************* #
5618#	The returned result is within 3 ulp in 64 significant bit, i.e. #
5619#	within 0.5001 ulp to 53 bits if the result is subsequently	#
5620#	rounded to double precision. The result is provably monotonic	#
5621#	in double precision.						#
5622#									#
5623# ALGORITHM *********************************************************** #
5624#									#
5625#	1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.			#
5626#									#
5627#	2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let	#
5628#		k = N mod 2, so in particular, k = 0 or 1.		#
5629#									#
5630#	3. If k is odd, go to 5.					#
5631#									#
5632#	4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a	#
5633#		rational function U/V where				#
5634#		U = r + r*s*(P1 + s*(P2 + s*P3)), and			#
5635#		V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))),  s = r*r.	#
5636#		Exit.							#
5637#									#
5638#	4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
5639#		a rational function U/V where				#
5640#		U = r + r*s*(P1 + s*(P2 + s*P3)), and			#
5641#		V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r,	#
5642#		-Cot(r) = -V/U. Exit.					#
5643#									#
5644#	6. If |X| > 1, go to 8.						#
5645#									#
5646#	7. (|X|<2**(-40)) Tan(X) = X. Exit.				#
5647#									#
5648#	8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back	#
5649#		to 2.							#
5650#									#
5651#########################################################################
5652
5653TANQ4:
5654	long		0x3EA0B759,0xF50F8688
5655TANP3:
5656	long		0xBEF2BAA5,0xA8924F04
5657
5658TANQ3:
5659	long		0xBF346F59,0xB39BA65F,0x00000000,0x00000000
5660
5661TANP2:
5662	long		0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
5663
5664TANQ2:
5665	long		0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
5666
5667TANP1:
5668	long		0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
5669
5670TANQ1:
5671	long		0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
5672
5673INVTWOPI:
5674	long		0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
5675
5676TWOPI1:
5677	long		0x40010000,0xC90FDAA2,0x00000000,0x00000000
5678TWOPI2:
5679	long		0x3FDF0000,0x85A308D4,0x00000000,0x00000000
5680
5681#--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
5682#--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
5683#--MOST 69 BITS LONG.
5684#	global		PITBL
5685PITBL:
5686	long		0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
5687	long		0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
5688	long		0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
5689	long		0xC0040000,0xB6365E22,0xEE46F000,0x21480000
5690	long		0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
5691	long		0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
5692	long		0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
5693	long		0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
5694	long		0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
5695	long		0xC0040000,0x90836524,0x88034B96,0x20B00000
5696	long		0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
5697	long		0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
5698	long		0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
5699	long		0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
5700	long		0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
5701	long		0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
5702	long		0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
5703	long		0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
5704	long		0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
5705	long		0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
5706	long		0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
5707	long		0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
5708	long		0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
5709	long		0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
5710	long		0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
5711	long		0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
5712	long		0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
5713	long		0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
5714	long		0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
5715	long		0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
5716	long		0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
5717	long		0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
5718	long		0x00000000,0x00000000,0x00000000,0x00000000
5719	long		0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
5720	long		0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
5721	long		0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
5722	long		0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
5723	long		0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
5724	long		0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
5725	long		0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
5726	long		0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
5727	long		0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
5728	long		0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
5729	long		0x40030000,0x8A3AE64F,0x76F80584,0x21080000
5730	long		0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
5731	long		0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
5732	long		0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
5733	long		0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
5734	long		0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
5735	long		0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
5736	long		0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
5737	long		0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
5738	long		0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
5739	long		0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
5740	long		0x40040000,0x8A3AE64F,0x76F80584,0x21880000
5741	long		0x40040000,0x90836524,0x88034B96,0xA0B00000
5742	long		0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
5743	long		0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
5744	long		0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
5745	long		0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
5746	long		0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
5747	long		0x40040000,0xB6365E22,0xEE46F000,0xA1480000
5748	long		0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
5749	long		0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
5750	long		0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
5751
5752	set		INARG,FP_SCR0
5753
5754	set		TWOTO63,L_SCR1
5755	set		INT,L_SCR1
5756	set		ENDFLAG,L_SCR2
5757
5758	global		stan
5759stan:
5760	fmov.x		(%a0),%fp0		# LOAD INPUT
5761
5762	mov.l		(%a0),%d1
5763	mov.w		4(%a0),%d1
5764	and.l		&0x7FFFFFFF,%d1
5765
5766	cmp.l		%d1,&0x3FD78000		# |X| >= 2**(-40)?
5767	bge.b		TANOK1
5768	bra.w		TANSM
5769TANOK1:
5770	cmp.l		%d1,&0x4004BC7E		# |X| < 15 PI?
5771	blt.b		TANMAIN
5772	bra.w		REDUCEX
5773
5774TANMAIN:
5775#--THIS IS THE USUAL CASE, |X| <= 15 PI.
5776#--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5777	fmov.x		%fp0,%fp1
5778	fmul.d		TWOBYPI(%pc),%fp1	# X*2/PI
5779
5780	lea.l		PITBL+0x200(%pc),%a1	# TABLE OF N*PI/2, N = -32,...,32
5781
5782	fmov.l		%fp1,%d1		# CONVERT TO INTEGER
5783
5784	asl.l		&4,%d1
5785	add.l		%d1,%a1			# ADDRESS N*PIBY2 IN Y1, Y2
5786
5787	fsub.x		(%a1)+,%fp0		# X-Y1
5788
5789	fsub.s		(%a1),%fp0		# FP0 IS R = (X-Y1)-Y2
5790
5791	ror.l		&5,%d1
5792	and.l		&0x80000000,%d1		# D0 WAS ODD IFF D0 < 0
5793
5794TANCONT:
5795	fmovm.x		&0x0c,-(%sp)		# save fp2,fp3
5796
5797	cmp.l		%d1,&0
5798	blt.w		NODD
5799
5800	fmov.x		%fp0,%fp1
5801	fmul.x		%fp1,%fp1		# S = R*R
5802
5803	fmov.d		TANQ4(%pc),%fp3
5804	fmov.d		TANP3(%pc),%fp2
5805
5806	fmul.x		%fp1,%fp3		# SQ4
5807	fmul.x		%fp1,%fp2		# SP3
5808
5809	fadd.d		TANQ3(%pc),%fp3		# Q3+SQ4
5810	fadd.x		TANP2(%pc),%fp2		# P2+SP3
5811
5812	fmul.x		%fp1,%fp3		# S(Q3+SQ4)
5813	fmul.x		%fp1,%fp2		# S(P2+SP3)
5814
5815	fadd.x		TANQ2(%pc),%fp3		# Q2+S(Q3+SQ4)
5816	fadd.x		TANP1(%pc),%fp2		# P1+S(P2+SP3)
5817
5818	fmul.x		%fp1,%fp3		# S(Q2+S(Q3+SQ4))
5819	fmul.x		%fp1,%fp2		# S(P1+S(P2+SP3))
5820
5821	fadd.x		TANQ1(%pc),%fp3		# Q1+S(Q2+S(Q3+SQ4))
5822	fmul.x		%fp0,%fp2		# RS(P1+S(P2+SP3))
5823
5824	fmul.x		%fp3,%fp1		# S(Q1+S(Q2+S(Q3+SQ4)))
5825
5826	fadd.x		%fp2,%fp0		# R+RS(P1+S(P2+SP3))
5827
5828	fadd.s		&0x3F800000,%fp1	# 1+S(Q1+...)
5829
5830	fmovm.x		(%sp)+,&0x30		# restore fp2,fp3
5831
5832	fmov.l		%d0,%fpcr		# restore users round mode,prec
5833	fdiv.x		%fp1,%fp0		# last inst - possible exception set
5834	bra		t_inx2
5835
5836NODD:
5837	fmov.x		%fp0,%fp1
5838	fmul.x		%fp0,%fp0		# S = R*R
5839
5840	fmov.d		TANQ4(%pc),%fp3
5841	fmov.d		TANP3(%pc),%fp2
5842
5843	fmul.x		%fp0,%fp3		# SQ4
5844	fmul.x		%fp0,%fp2		# SP3
5845
5846	fadd.d		TANQ3(%pc),%fp3		# Q3+SQ4
5847	fadd.x		TANP2(%pc),%fp2		# P2+SP3
5848
5849	fmul.x		%fp0,%fp3		# S(Q3+SQ4)
5850	fmul.x		%fp0,%fp2		# S(P2+SP3)
5851
5852	fadd.x		TANQ2(%pc),%fp3		# Q2+S(Q3+SQ4)
5853	fadd.x		TANP1(%pc),%fp2		# P1+S(P2+SP3)
5854
5855	fmul.x		%fp0,%fp3		# S(Q2+S(Q3+SQ4))
5856	fmul.x		%fp0,%fp2		# S(P1+S(P2+SP3))
5857
5858	fadd.x		TANQ1(%pc),%fp3		# Q1+S(Q2+S(Q3+SQ4))
5859	fmul.x		%fp1,%fp2		# RS(P1+S(P2+SP3))
5860
5861	fmul.x		%fp3,%fp0		# S(Q1+S(Q2+S(Q3+SQ4)))
5862
5863	fadd.x		%fp2,%fp1		# R+RS(P1+S(P2+SP3))
5864	fadd.s		&0x3F800000,%fp0	# 1+S(Q1+...)
5865
5866	fmovm.x		(%sp)+,&0x30		# restore fp2,fp3
5867
5868	fmov.x		%fp1,-(%sp)
5869	eor.l		&0x80000000,(%sp)
5870
5871	fmov.l		%d0,%fpcr		# restore users round mode,prec
5872	fdiv.x		(%sp)+,%fp0		# last inst - possible exception set
5873	bra		t_inx2
5874
5875TANBORS:
5876#--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5877#--IF |X| < 2**(-40), RETURN X OR 1.
5878	cmp.l		%d1,&0x3FFF8000
5879	bgt.b		REDUCEX
5880
5881TANSM:
5882	fmov.x		%fp0,-(%sp)
5883	fmov.l		%d0,%fpcr		# restore users round mode,prec
5884	mov.b		&FMOV_OP,%d1		# last inst is MOVE
5885	fmov.x		(%sp)+,%fp0		# last inst - posibble exception set
5886	bra		t_catch
5887
5888	global		stand
5889#--TAN(X) = X FOR DENORMALIZED X
5890stand:
5891	bra		t_extdnrm
5892
5893#--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5894#--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5895#--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5896REDUCEX:
5897	fmovm.x		&0x3c,-(%sp)		# save {fp2-fp5}
5898	mov.l		%d2,-(%sp)		# save d2
5899	fmov.s		&0x00000000,%fp1	# fp1 = 0
5900
5901#--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5902#--there is a danger of unwanted overflow in first LOOP iteration.  In this
5903#--case, reduce argument by one remainder step to make subsequent reduction
5904#--safe.
5905	cmp.l		%d1,&0x7ffeffff		# is arg dangerously large?
5906	bne.b		LOOP			# no
5907
5908# yes; create 2**16383*PI/2
5909	mov.w		&0x7ffe,FP_SCR0_EX(%a6)
5910	mov.l		&0xc90fdaa2,FP_SCR0_HI(%a6)
5911	clr.l		FP_SCR0_LO(%a6)
5912
5913# create low half of 2**16383*PI/2 at FP_SCR1
5914	mov.w		&0x7fdc,FP_SCR1_EX(%a6)
5915	mov.l		&0x85a308d3,FP_SCR1_HI(%a6)
5916	clr.l		FP_SCR1_LO(%a6)
5917
5918	ftest.x		%fp0			# test sign of argument
5919	fblt.w		red_neg
5920
5921	or.b		&0x80,FP_SCR0_EX(%a6)	# positive arg
5922	or.b		&0x80,FP_SCR1_EX(%a6)
5923red_neg:
5924	fadd.x		FP_SCR0(%a6),%fp0	# high part of reduction is exact
5925	fmov.x		%fp0,%fp1		# save high result in fp1
5926	fadd.x		FP_SCR1(%a6),%fp0	# low part of reduction
5927	fsub.x		%fp0,%fp1		# determine low component of result
5928	fadd.x		FP_SCR1(%a6),%fp1	# fp0/fp1 are reduced argument.
5929
5930#--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5931#--integer quotient will be stored in N
5932#--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5933LOOP:
5934	fmov.x		%fp0,INARG(%a6)		# +-2**K * F, 1 <= F < 2
5935	mov.w		INARG(%a6),%d1
5936	mov.l		%d1,%a1			# save a copy of D0
5937	and.l		&0x00007FFF,%d1
5938	sub.l		&0x00003FFF,%d1		# d0 = K
5939	cmp.l		%d1,&28
5940	ble.b		LASTLOOP
5941CONTLOOP:
5942	sub.l		&27,%d1			# d0 = L := K-27
5943	mov.b		&0,ENDFLAG(%a6)
5944	bra.b		WORK
5945LASTLOOP:
5946	clr.l		%d1			# d0 = L := 0
5947	mov.b		&1,ENDFLAG(%a6)
5948
5949WORK:
5950#--FIND THE REMAINDER OF (R,r) W.R.T.	2**L * (PI/2). L IS SO CHOSEN
5951#--THAT	INT( X * (2/PI) / 2**(L) ) < 2**29.
5952
5953#--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5954#--2**L * (PIby2_1), 2**L * (PIby2_2)
5955
5956	mov.l		&0x00003FFE,%d2		# BIASED EXP OF 2/PI
5957	sub.l		%d1,%d2			# BIASED EXP OF 2**(-L)*(2/PI)
5958
5959	mov.l		&0xA2F9836E,FP_SCR0_HI(%a6)
5960	mov.l		&0x4E44152A,FP_SCR0_LO(%a6)
5961	mov.w		%d2,FP_SCR0_EX(%a6)	# FP_SCR0 = 2**(-L)*(2/PI)
5962
5963	fmov.x		%fp0,%fp2
5964	fmul.x		FP_SCR0(%a6),%fp2	# fp2 = X * 2**(-L)*(2/PI)
5965
5966#--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5967#--FLOATING POINT FORMAT, THE TWO FMOVE'S	FMOVE.L FP <--> N
5968#--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5969#--(SIGN(INARG)*2**63	+	FP2) - SIGN(INARG)*2**63 WILL GIVE
5970#--US THE DESIRED VALUE IN FLOATING POINT.
5971	mov.l		%a1,%d2
5972	swap		%d2
5973	and.l		&0x80000000,%d2
5974	or.l		&0x5F000000,%d2		# d2 = SIGN(INARG)*2**63 IN SGL
5975	mov.l		%d2,TWOTO63(%a6)
5976	fadd.s		TWOTO63(%a6),%fp2	# THE FRACTIONAL PART OF FP1 IS ROUNDED
5977	fsub.s		TWOTO63(%a6),%fp2	# fp2 = N
5978#	fintrz.x	%fp2,%fp2
5979
5980#--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5981	mov.l		%d1,%d2			# d2 = L
5982
5983	add.l		&0x00003FFF,%d2		# BIASED EXP OF 2**L * (PI/2)
5984	mov.w		%d2,FP_SCR0_EX(%a6)
5985	mov.l		&0xC90FDAA2,FP_SCR0_HI(%a6)
5986	clr.l		FP_SCR0_LO(%a6)		# FP_SCR0 = 2**(L) * Piby2_1
5987
5988	add.l		&0x00003FDD,%d1
5989	mov.w		%d1,FP_SCR1_EX(%a6)
5990	mov.l		&0x85A308D3,FP_SCR1_HI(%a6)
5991	clr.l		FP_SCR1_LO(%a6)		# FP_SCR1 = 2**(L) * Piby2_2
5992
5993	mov.b		ENDFLAG(%a6),%d1
5994
5995#--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5996#--P2 = 2**(L) * Piby2_2
5997	fmov.x		%fp2,%fp4		# fp4 = N
5998	fmul.x		FP_SCR0(%a6),%fp4	# fp4 = W = N*P1
5999	fmov.x		%fp2,%fp5		# fp5 = N
6000	fmul.x		FP_SCR1(%a6),%fp5	# fp5 = w = N*P2
6001	fmov.x		%fp4,%fp3		# fp3 = W = N*P1
6002
6003#--we want P+p = W+w  but  |p| <= half ulp of P
6004#--Then, we need to compute  A := R-P   and  a := r-p
6005	fadd.x		%fp5,%fp3		# fp3 = P
6006	fsub.x		%fp3,%fp4		# fp4 = W-P
6007
6008	fsub.x		%fp3,%fp0		# fp0 = A := R - P
6009	fadd.x		%fp5,%fp4		# fp4 = p = (W-P)+w
6010
6011	fmov.x		%fp0,%fp3		# fp3 = A
6012	fsub.x		%fp4,%fp1		# fp1 = a := r - p
6013
6014#--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
6015#--|r| <= half ulp of R.
6016	fadd.x		%fp1,%fp0		# fp0 = R := A+a
6017#--No need to calculate r if this is the last loop
6018	cmp.b		%d1,&0
6019	bgt.w		RESTORE
6020
6021#--Need to calculate r
6022	fsub.x		%fp0,%fp3		# fp3 = A-R
6023	fadd.x		%fp3,%fp1		# fp1 = r := (A-R)+a
6024	bra.w		LOOP
6025
6026RESTORE:
6027	fmov.l		%fp2,INT(%a6)
6028	mov.l		(%sp)+,%d2		# restore d2
6029	fmovm.x		(%sp)+,&0x3c		# restore {fp2-fp5}
6030
6031	mov.l		INT(%a6),%d1
6032	ror.l		&1,%d1
6033
6034	bra.w		TANCONT
6035
6036#########################################################################
6037# satan():  computes the arctangent of a normalized number		#
6038# satand(): computes the arctangent of a denormalized number		#
6039#									#
6040# INPUT	*************************************************************** #
6041#	a0 = pointer to extended precision input			#
6042#	d0 = round precision,mode					#
6043#									#
6044# OUTPUT ************************************************************** #
6045#	fp0 = arctan(X)							#
6046#									#
6047# ACCURACY and MONOTONICITY ******************************************* #
6048#	The returned result is within 2 ulps in	64 significant bit,	#
6049#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently	#
6050#	rounded to double precision. The result is provably monotonic	#
6051#	in double precision.						#
6052#									#
6053# ALGORITHM *********************************************************** #
6054#	Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5.		#
6055#									#
6056#	Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x.			#
6057#		Note that k = -4, -3,..., or 3.				#
6058#		Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5	#
6059#		significant bits of X with a bit-1 attached at the 6-th	#
6060#		bit position. Define u to be u = (X-F) / (1 + X*F).	#
6061#									#
6062#	Step 3. Approximate arctan(u) by a polynomial poly.		#
6063#									#
6064#	Step 4. Return arctan(F) + poly, arctan(F) is fetched from a	#
6065#		table of values calculated beforehand. Exit.		#
6066#									#
6067#	Step 5. If |X| >= 16, go to Step 7.				#
6068#									#
6069#	Step 6. Approximate arctan(X) by an odd polynomial in X. Exit.	#
6070#									#
6071#	Step 7. Define X' = -1/X. Approximate arctan(X') by an odd	#
6072#		polynomial in X'.					#
6073#		Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit.		#
6074#									#
6075#########################################################################
6076
6077ATANA3:	long		0xBFF6687E,0x314987D8
6078ATANA2:	long		0x4002AC69,0x34A26DB3
6079ATANA1:	long		0xBFC2476F,0x4E1DA28E
6080
6081ATANB6:	long		0x3FB34444,0x7F876989
6082ATANB5:	long		0xBFB744EE,0x7FAF45DB
6083ATANB4:	long		0x3FBC71C6,0x46940220
6084ATANB3:	long		0xBFC24924,0x921872F9
6085ATANB2:	long		0x3FC99999,0x99998FA9
6086ATANB1:	long		0xBFD55555,0x55555555
6087
6088ATANC5:	long		0xBFB70BF3,0x98539E6A
6089ATANC4:	long		0x3FBC7187,0x962D1D7D
6090ATANC3:	long		0xBFC24924,0x827107B8
6091ATANC2:	long		0x3FC99999,0x9996263E
6092ATANC1:	long		0xBFD55555,0x55555536
6093
6094PPIBY2:	long		0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
6095NPIBY2:	long		0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
6096
6097PTINY:	long		0x00010000,0x80000000,0x00000000,0x00000000
6098NTINY:	long		0x80010000,0x80000000,0x00000000,0x00000000
6099
6100ATANTBL:
6101	long		0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
6102	long		0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
6103	long		0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
6104	long		0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
6105	long		0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
6106	long		0x3FFB0000,0xAB98E943,0x62765619,0x00000000
6107	long		0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
6108	long		0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
6109	long		0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
6110	long		0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
6111	long		0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
6112	long		0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
6113	long		0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
6114	long		0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
6115	long		0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
6116	long		0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
6117	long		0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
6118	long		0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
6119	long		0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
6120	long		0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
6121	long		0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
6122	long		0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
6123	long		0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
6124	long		0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
6125	long		0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
6126	long		0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
6127	long		0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
6128	long		0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
6129	long		0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
6130	long		0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
6131	long		0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
6132	long		0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
6133	long		0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
6134	long		0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
6135	long		0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
6136	long		0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
6137	long		0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
6138	long		0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
6139	long		0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
6140	long		0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
6141	long		0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
6142	long		0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
6143	long		0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
6144	long		0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
6145	long		0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
6146	long		0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
6147	long		0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
6148	long		0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
6149	long		0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
6150	long		0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
6151	long		0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
6152	long		0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
6153	long		0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
6154	long		0x3FFE0000,0x97731420,0x365E538C,0x00000000
6155	long		0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
6156	long		0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
6157	long		0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
6158	long		0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
6159	long		0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
6160	long		0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
6161	long		0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
6162	long		0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
6163	long		0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
6164	long		0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
6165	long		0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
6166	long		0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
6167	long		0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
6168	long		0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
6169	long		0x3FFE0000,0xE8771129,0xC4353259,0x00000000
6170	long		0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
6171	long		0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
6172	long		0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
6173	long		0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
6174	long		0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
6175	long		0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
6176	long		0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
6177	long		0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
6178	long		0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
6179	long		0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
6180	long		0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
6181	long		0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
6182	long		0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
6183	long		0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
6184	long		0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
6185	long		0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
6186	long		0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
6187	long		0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
6188	long		0x3FFF0000,0x9F100575,0x006CC571,0x00000000
6189	long		0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
6190	long		0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
6191	long		0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
6192	long		0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
6193	long		0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
6194	long		0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
6195	long		0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
6196	long		0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
6197	long		0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
6198	long		0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
6199	long		0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
6200	long		0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
6201	long		0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
6202	long		0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
6203	long		0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
6204	long		0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
6205	long		0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
6206	long		0x3FFF0000,0xB525529D,0x562246BD,0x00000000
6207	long		0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
6208	long		0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
6209	long		0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
6210	long		0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
6211	long		0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
6212	long		0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
6213	long		0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
6214	long		0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
6215	long		0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
6216	long		0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
6217	long		0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
6218	long		0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
6219	long		0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
6220	long		0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
6221	long		0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
6222	long		0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
6223	long		0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
6224	long		0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
6225	long		0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
6226	long		0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
6227	long		0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
6228	long		0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
6229
6230	set		X,FP_SCR0
6231	set		XDCARE,X+2
6232	set		XFRAC,X+4
6233	set		XFRACLO,X+8
6234
6235	set		ATANF,FP_SCR1
6236	set		ATANFHI,ATANF+4
6237	set		ATANFLO,ATANF+8
6238
6239	global		satan
6240#--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
6241satan:
6242	fmov.x		(%a0),%fp0		# LOAD INPUT
6243
6244	mov.l		(%a0),%d1
6245	mov.w		4(%a0),%d1
6246	fmov.x		%fp0,X(%a6)
6247	and.l		&0x7FFFFFFF,%d1
6248
6249	cmp.l		%d1,&0x3FFB8000		# |X| >= 1/16?
6250	bge.b		ATANOK1
6251	bra.w		ATANSM
6252
6253ATANOK1:
6254	cmp.l		%d1,&0x4002FFFF		# |X| < 16 ?
6255	ble.b		ATANMAIN
6256	bra.w		ATANBIG
6257
6258#--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
6259#--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
6260#--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
6261#--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
6262#--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
6263#--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
6264#--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
6265#--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
6266#--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
6267#--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
6268#--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
6269#--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
6270#--WILL INVOLVE A VERY LONG POLYNOMIAL.
6271
6272#--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
6273#--WE CHOSE F TO BE +-2^K * 1.BBBB1
6274#--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
6275#--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
6276#--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
6277#-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
6278
6279ATANMAIN:
6280
6281	and.l		&0xF8000000,XFRAC(%a6)	# FIRST 5 BITS
6282	or.l		&0x04000000,XFRAC(%a6)	# SET 6-TH BIT TO 1
6283	mov.l		&0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
6284
6285	fmov.x		%fp0,%fp1		# FP1 IS X
6286	fmul.x		X(%a6),%fp1		# FP1 IS X*F, NOTE THAT X*F > 0
6287	fsub.x		X(%a6),%fp0		# FP0 IS X-F
6288	fadd.s		&0x3F800000,%fp1	# FP1 IS 1 + X*F
6289	fdiv.x		%fp1,%fp0		# FP0 IS U = (X-F)/(1+X*F)
6290
6291#--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
6292#--CREATE ATAN(F) AND STORE IT IN ATANF, AND
6293#--SAVE REGISTERS FP2.
6294
6295	mov.l		%d2,-(%sp)		# SAVE d2 TEMPORARILY
6296	mov.l		%d1,%d2			# THE EXP AND 16 BITS OF X
6297	and.l		&0x00007800,%d1		# 4 VARYING BITS OF F'S FRACTION
6298	and.l		&0x7FFF0000,%d2		# EXPONENT OF F
6299	sub.l		&0x3FFB0000,%d2		# K+4
6300	asr.l		&1,%d2
6301	add.l		%d2,%d1			# THE 7 BITS IDENTIFYING F
6302	asr.l		&7,%d1			# INDEX INTO TBL OF ATAN(|F|)
6303	lea		ATANTBL(%pc),%a1
6304	add.l		%d1,%a1			# ADDRESS OF ATAN(|F|)
6305	mov.l		(%a1)+,ATANF(%a6)
6306	mov.l		(%a1)+,ATANFHI(%a6)
6307	mov.l		(%a1)+,ATANFLO(%a6)	# ATANF IS NOW ATAN(|F|)
6308	mov.l		X(%a6),%d1		# LOAD SIGN AND EXPO. AGAIN
6309	and.l		&0x80000000,%d1		# SIGN(F)
6310	or.l		%d1,ATANF(%a6)		# ATANF IS NOW SIGN(F)*ATAN(|F|)
6311	mov.l		(%sp)+,%d2		# RESTORE d2
6312
6313#--THAT'S ALL I HAVE TO DO FOR NOW,
6314#--BUT ALAS, THE DIVIDE IS STILL CRANKING!
6315
6316#--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
6317#--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
6318#--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
6319#--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
6320#--WHAT WE HAVE HERE IS MERELY	A1 = A3, A2 = A1/A3, A3 = A2/A3.
6321#--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
6322#--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
6323
6324	fmovm.x		&0x04,-(%sp)		# save fp2
6325
6326	fmov.x		%fp0,%fp1
6327	fmul.x		%fp1,%fp1
6328	fmov.d		ATANA3(%pc),%fp2
6329	fadd.x		%fp1,%fp2		# A3+V
6330	fmul.x		%fp1,%fp2		# V*(A3+V)
6331	fmul.x		%fp0,%fp1		# U*V
6332	fadd.d		ATANA2(%pc),%fp2	# A2+V*(A3+V)
6333	fmul.d		ATANA1(%pc),%fp1	# A1*U*V
6334	fmul.x		%fp2,%fp1		# A1*U*V*(A2+V*(A3+V))
6335	fadd.x		%fp1,%fp0		# ATAN(U), FP1 RELEASED
6336
6337	fmovm.x		(%sp)+,&0x20		# restore fp2
6338
6339	fmov.l		%d0,%fpcr		# restore users rnd mode,prec
6340	fadd.x		ATANF(%a6),%fp0		# ATAN(X)
6341	bra		t_inx2
6342
6343ATANBORS:
6344#--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
6345#--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
6346	cmp.l		%d1,&0x3FFF8000
6347	bgt.w		ATANBIG			# I.E. |X| >= 16
6348
6349ATANSM:
6350#--|X| <= 1/16
6351#--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
6352#--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
6353#--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
6354#--WHERE Y = X*X, AND Z = Y*Y.
6355
6356	cmp.l		%d1,&0x3FD78000
6357	blt.w		ATANTINY
6358
6359#--COMPUTE POLYNOMIAL
6360	fmovm.x		&0x0c,-(%sp)		# save fp2/fp3
6361
6362	fmul.x		%fp0,%fp0		# FPO IS Y = X*X
6363
6364	fmov.x		%fp0,%fp1
6365	fmul.x		%fp1,%fp1		# FP1 IS Z = Y*Y
6366
6367	fmov.d		ATANB6(%pc),%fp2
6368	fmov.d		ATANB5(%pc),%fp3
6369
6370	fmul.x		%fp1,%fp2		# Z*B6
6371	fmul.x		%fp1,%fp3		# Z*B5
6372
6373	fadd.d		ATANB4(%pc),%fp2	# B4+Z*B6
6374	fadd.d		ATANB3(%pc),%fp3	# B3+Z*B5
6375
6376	fmul.x		%fp1,%fp2		# Z*(B4+Z*B6)
6377	fmul.x		%fp3,%fp1		# Z*(B3+Z*B5)
6378
6379	fadd.d		ATANB2(%pc),%fp2	# B2+Z*(B4+Z*B6)
6380	fadd.d		ATANB1(%pc),%fp1	# B1+Z*(B3+Z*B5)
6381
6382	fmul.x		%fp0,%fp2		# Y*(B2+Z*(B4+Z*B6))
6383	fmul.x		X(%a6),%fp0		# X*Y
6384
6385	fadd.x		%fp2,%fp1		# [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
6386
6387	fmul.x		%fp1,%fp0		# X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
6388
6389	fmovm.x		(%sp)+,&0x30		# restore fp2/fp3
6390
6391	fmov.l		%d0,%fpcr		# restore users rnd mode,prec
6392	fadd.x		X(%a6),%fp0
6393	bra		t_inx2
6394
6395ATANTINY:
6396#--|X| < 2^(-40), ATAN(X) = X
6397
6398	fmov.l		%d0,%fpcr		# restore users rnd mode,prec
6399	mov.b		&FMOV_OP,%d1		# last inst is MOVE
6400	fmov.x		X(%a6),%fp0		# last inst - possible exception set
6401
6402	bra		t_catch
6403
6404ATANBIG:
6405#--IF |X| > 2^(100), RETURN	SIGN(X)*(PI/2 - TINY). OTHERWISE,
6406#--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
6407	cmp.l		%d1,&0x40638000
6408	bgt.w		ATANHUGE
6409
6410#--APPROXIMATE ATAN(-1/X) BY
6411#--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
6412#--THIS CAN BE RE-WRITTEN AS
6413#--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
6414
6415	fmovm.x		&0x0c,-(%sp)		# save fp2/fp3
6416
6417	fmov.s		&0xBF800000,%fp1	# LOAD -1
6418	fdiv.x		%fp0,%fp1		# FP1 IS -1/X
6419
6420#--DIVIDE IS STILL CRANKING
6421
6422	fmov.x		%fp1,%fp0		# FP0 IS X'
6423	fmul.x		%fp0,%fp0		# FP0 IS Y = X'*X'
6424	fmov.x		%fp1,X(%a6)		# X IS REALLY X'
6425
6426	fmov.x		%fp0,%fp1
6427	fmul.x		%fp1,%fp1		# FP1 IS Z = Y*Y
6428
6429	fmov.d		ATANC5(%pc),%fp3
6430	fmov.d		ATANC4(%pc),%fp2
6431
6432	fmul.x		%fp1,%fp3		# Z*C5
6433	fmul.x		%fp1,%fp2		# Z*B4
6434
6435	fadd.d		ATANC3(%pc),%fp3	# C3+Z*C5
6436	fadd.d		ATANC2(%pc),%fp2	# C2+Z*C4
6437
6438	fmul.x		%fp3,%fp1		# Z*(C3+Z*C5), FP3 RELEASED
6439	fmul.x		%fp0,%fp2		# Y*(C2+Z*C4)
6440
6441	fadd.d		ATANC1(%pc),%fp1	# C1+Z*(C3+Z*C5)
6442	fmul.x		X(%a6),%fp0		# X'*Y
6443
6444	fadd.x		%fp2,%fp1		# [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
6445
6446	fmul.x		%fp1,%fp0		# X'*Y*([B1+Z*(B3+Z*B5)]
6447#					...	+[Y*(B2+Z*(B4+Z*B6))])
6448	fadd.x		X(%a6),%fp0
6449
6450	fmovm.x		(%sp)+,&0x30		# restore fp2/fp3
6451
6452	fmov.l		%d0,%fpcr		# restore users rnd mode,prec
6453	tst.b		(%a0)
6454	bpl.b		pos_big
6455
6456neg_big:
6457	fadd.x		NPIBY2(%pc),%fp0
6458	bra		t_minx2
6459
6460pos_big:
6461	fadd.x		PPIBY2(%pc),%fp0
6462	bra		t_pinx2
6463
6464ATANHUGE:
6465#--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
6466	tst.b		(%a0)
6467	bpl.b		pos_huge
6468
6469neg_huge:
6470	fmov.x		NPIBY2(%pc),%fp0
6471	fmov.l		%d0,%fpcr
6472	fadd.x		PTINY(%pc),%fp0
6473	bra		t_minx2
6474
6475pos_huge:
6476	fmov.x		PPIBY2(%pc),%fp0
6477	fmov.l		%d0,%fpcr
6478	fadd.x		NTINY(%pc),%fp0
6479	bra		t_pinx2
6480
6481	global		satand
6482#--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
6483satand:
6484	bra		t_extdnrm
6485
6486#########################################################################
6487# sasin():  computes the inverse sine of a normalized input		#
6488# sasind(): computes the inverse sine of a denormalized input		#
6489#									#
6490# INPUT ***************************************************************	#
6491#	a0 = pointer to extended precision input			#
6492#	d0 = round precision,mode					#
6493#									#
6494# OUTPUT **************************************************************	#
6495#	fp0 = arcsin(X)							#
6496#									#
6497# ACCURACY and MONOTONICITY *******************************************	#
6498#	The returned result is within 3 ulps in	64 significant bit,	#
6499#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently	#
6500#	rounded to double precision. The result is provably monotonic	#
6501#	in double precision.						#
6502#									#
6503# ALGORITHM ***********************************************************	#
6504#									#
6505#	ASIN								#
6506#	1. If |X| >= 1, go to 3.					#
6507#									#
6508#	2. (|X| < 1) Calculate asin(X) by				#
6509#		z := sqrt( [1-X][1+X] )					#
6510#		asin(X) = atan( x / z ).				#
6511#		Exit.							#
6512#									#
6513#	3. If |X| > 1, go to 5.						#
6514#									#
6515#	4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
6516#									#
6517#	5. (|X| > 1) Generate an invalid operation by 0 * infinity.	#
6518#		Exit.							#
6519#									#
6520#########################################################################
6521
6522	global		sasin
6523sasin:
6524	fmov.x		(%a0),%fp0		# LOAD INPUT
6525
6526	mov.l		(%a0),%d1
6527	mov.w		4(%a0),%d1
6528	and.l		&0x7FFFFFFF,%d1
6529	cmp.l		%d1,&0x3FFF8000
6530	bge.b		ASINBIG
6531
6532# This catch is added here for the '060 QSP. Originally, the call to
6533# satan() would handle this case by causing the exception which would
6534# not be caught until gen_except(). Now, with the exceptions being
6535# detected inside of satan(), the exception would have been handled there
6536# instead of inside sasin() as expected.
6537	cmp.l		%d1,&0x3FD78000
6538	blt.w		ASINTINY
6539
6540#--THIS IS THE USUAL CASE, |X| < 1
6541#--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
6542
6543ASINMAIN:
6544	fmov.s		&0x3F800000,%fp1
6545	fsub.x		%fp0,%fp1		# 1-X
6546	fmovm.x		&0x4,-(%sp)		#  {fp2}
6547	fmov.s		&0x3F800000,%fp2
6548	fadd.x		%fp0,%fp2		# 1+X
6549	fmul.x		%fp2,%fp1		# (1+X)(1-X)
6550	fmovm.x		(%sp)+,&0x20		#  {fp2}
6551	fsqrt.x		%fp1			# SQRT([1-X][1+X])
6552	fdiv.x		%fp1,%fp0		# X/SQRT([1-X][1+X])
6553	fmovm.x		&0x01,-(%sp)		# save X/SQRT(...)
6554	lea		(%sp),%a0		# pass ptr to X/SQRT(...)
6555	bsr		satan
6556	add.l		&0xc,%sp		# clear X/SQRT(...) from stack
6557	bra		t_inx2
6558
6559ASINBIG:
6560	fabs.x		%fp0			# |X|
6561	fcmp.s		%fp0,&0x3F800000
6562	fbgt		t_operr			# cause an operr exception
6563
6564#--|X| = 1, ASIN(X) = +- PI/2.
6565ASINONE:
6566	fmov.x		PIBY2(%pc),%fp0
6567	mov.l		(%a0),%d1
6568	and.l		&0x80000000,%d1		# SIGN BIT OF X
6569	or.l		&0x3F800000,%d1		# +-1 IN SGL FORMAT
6570	mov.l		%d1,-(%sp)		# push SIGN(X) IN SGL-FMT
6571	fmov.l		%d0,%fpcr
6572	fmul.s		(%sp)+,%fp0
6573	bra		t_inx2
6574
6575#--|X| < 2^(-40), ATAN(X) = X
6576ASINTINY:
6577	fmov.l		%d0,%fpcr		# restore users rnd mode,prec
6578	mov.b		&FMOV_OP,%d1		# last inst is MOVE
6579	fmov.x		(%a0),%fp0		# last inst - possible exception
6580	bra		t_catch
6581
6582	global		sasind
6583#--ASIN(X) = X FOR DENORMALIZED X
6584sasind:
6585	bra		t_extdnrm
6586
6587#########################################################################
6588# sacos():  computes the inverse cosine of a normalized input		#
6589# sacosd(): computes the inverse cosine of a denormalized input		#
6590#									#
6591# INPUT ***************************************************************	#
6592#	a0 = pointer to extended precision input			#
6593#	d0 = round precision,mode					#
6594#									#
6595# OUTPUT ************************************************************** #
6596#	fp0 = arccos(X)							#
6597#									#
6598# ACCURACY and MONOTONICITY *******************************************	#
6599#	The returned result is within 3 ulps in	64 significant bit,	#
6600#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently	#
6601#	rounded to double precision. The result is provably monotonic	#
6602#	in double precision.						#
6603#									#
6604# ALGORITHM *********************************************************** #
6605#									#
6606#	ACOS								#
6607#	1. If |X| >= 1, go to 3.					#
6608#									#
6609#	2. (|X| < 1) Calculate acos(X) by				#
6610#		z := (1-X) / (1+X)					#
6611#		acos(X) = 2 * atan( sqrt(z) ).				#
6612#		Exit.							#
6613#									#
6614#	3. If |X| > 1, go to 5.						#
6615#									#
6616#	4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit.	#
6617#									#
6618#	5. (|X| > 1) Generate an invalid operation by 0 * infinity.	#
6619#		Exit.							#
6620#									#
6621#########################################################################
6622
6623	global		sacos
6624sacos:
6625	fmov.x		(%a0),%fp0		# LOAD INPUT
6626
6627	mov.l		(%a0),%d1		# pack exp w/ upper 16 fraction
6628	mov.w		4(%a0),%d1
6629	and.l		&0x7FFFFFFF,%d1
6630	cmp.l		%d1,&0x3FFF8000
6631	bge.b		ACOSBIG
6632
6633#--THIS IS THE USUAL CASE, |X| < 1
6634#--ACOS(X) = 2 * ATAN(	SQRT( (1-X)/(1+X) ) )
6635
6636ACOSMAIN:
6637	fmov.s		&0x3F800000,%fp1
6638	fadd.x		%fp0,%fp1		# 1+X
6639	fneg.x		%fp0			# -X
6640	fadd.s		&0x3F800000,%fp0	# 1-X
6641	fdiv.x		%fp1,%fp0		# (1-X)/(1+X)
6642	fsqrt.x		%fp0			# SQRT((1-X)/(1+X))
6643	mov.l		%d0,-(%sp)		# save original users fpcr
6644	clr.l		%d0
6645	fmovm.x		&0x01,-(%sp)		# save SQRT(...) to stack
6646	lea		(%sp),%a0		# pass ptr to sqrt
6647	bsr		satan			# ATAN(SQRT([1-X]/[1+X]))
6648	add.l		&0xc,%sp		# clear SQRT(...) from stack
6649
6650	fmov.l		(%sp)+,%fpcr		# restore users round prec,mode
6651	fadd.x		%fp0,%fp0		# 2 * ATAN( STUFF )
6652	bra		t_pinx2
6653
6654ACOSBIG:
6655	fabs.x		%fp0
6656	fcmp.s		%fp0,&0x3F800000
6657	fbgt		t_operr			# cause an operr exception
6658
6659#--|X| = 1, ACOS(X) = 0 OR PI
6660	tst.b		(%a0)			# is X positive or negative?
6661	bpl.b		ACOSP1
6662
6663#--X = -1
6664#Returns PI and inexact exception
6665ACOSM1:
6666	fmov.x		PI(%pc),%fp0		# load PI
6667	fmov.l		%d0,%fpcr		# load round mode,prec
6668	fadd.s		&0x00800000,%fp0	# add a small value
6669	bra		t_pinx2
6670
6671ACOSP1:
6672	bra		ld_pzero		# answer is positive zero
6673
6674	global		sacosd
6675#--ACOS(X) = PI/2 FOR DENORMALIZED X
6676sacosd:
6677	fmov.l		%d0,%fpcr		# load user's rnd mode/prec
6678	fmov.x		PIBY2(%pc),%fp0
6679	bra		t_pinx2
6680
6681#########################################################################
6682# setox():    computes the exponential for a normalized input		#
6683# setoxd():   computes the exponential for a denormalized input		#
6684# setoxm1():  computes the exponential minus 1 for a normalized input	#
6685# setoxm1d(): computes the exponential minus 1 for a denormalized input	#
6686#									#
6687# INPUT	*************************************************************** #
6688#	a0 = pointer to extended precision input			#
6689#	d0 = round precision,mode					#
6690#									#
6691# OUTPUT ************************************************************** #
6692#	fp0 = exp(X) or exp(X)-1					#
6693#									#
6694# ACCURACY and MONOTONICITY ******************************************* #
6695#	The returned result is within 0.85 ulps in 64 significant bit,	#
6696#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6697#	rounded to double precision. The result is provably monotonic	#
6698#	in double precision.						#
6699#									#
6700# ALGORITHM and IMPLEMENTATION **************************************** #
6701#									#
6702#	setoxd								#
6703#	------								#
6704#	Step 1.	Set ans := 1.0						#
6705#									#
6706#	Step 2.	Return	ans := ans + sign(X)*2^(-126). Exit.		#
6707#	Notes:	This will always generate one exception -- inexact.	#
6708#									#
6709#									#
6710#	setox								#
6711#	-----								#
6712#									#
6713#	Step 1.	Filter out extreme cases of input argument.		#
6714#		1.1	If |X| >= 2^(-65), go to Step 1.3.		#
6715#		1.2	Go to Step 7.					#
6716#		1.3	If |X| < 16380 log(2), go to Step 2.		#
6717#		1.4	Go to Step 8.					#
6718#	Notes:	The usual case should take the branches 1.1 -> 1.3 -> 2.#
6719#		To avoid the use of floating-point comparisons, a	#
6720#		compact representation of |X| is used. This format is a	#
6721#		32-bit integer, the upper (more significant) 16 bits	#
6722#		are the sign and biased exponent field of |X|; the	#
6723#		lower 16 bits are the 16 most significant fraction	#
6724#		(including the explicit bit) bits of |X|. Consequently,	#
6725#		the comparisons in Steps 1.1 and 1.3 can be performed	#
6726#		by integer comparison. Note also that the constant	#
6727#		16380 log(2) used in Step 1.3 is also in the compact	#
6728#		form. Thus taking the branch to Step 2 guarantees	#
6729#		|X| < 16380 log(2). There is no harm to have a small	#
6730#		number of cases where |X| is less than,	but close to,	#
6731#		16380 log(2) and the branch to Step 9 is taken.		#
6732#									#
6733#	Step 2.	Calculate N = round-to-nearest-int( X * 64/log2 ).	#
6734#		2.1	Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
6735#			was taken)					#
6736#		2.2	N := round-to-nearest-integer( X * 64/log2 ).	#
6737#		2.3	Calculate	J = N mod 64; so J = 0,1,2,..., #
6738#			or 63.						#
6739#		2.4	Calculate	M = (N - J)/64; so N = 64M + J.	#
6740#		2.5	Calculate the address of the stored value of	#
6741#			2^(J/64).					#
6742#		2.6	Create the value Scale = 2^M.			#
6743#	Notes:	The calculation in 2.2 is really performed by		#
6744#			Z := X * constant				#
6745#			N := round-to-nearest-integer(Z)		#
6746#		where							#
6747#			constant := single-precision( 64/log 2 ).	#
6748#									#
6749#		Using a single-precision constant avoids memory		#
6750#		access. Another effect of using a single-precision	#
6751#		"constant" is that the calculated value Z is		#
6752#									#
6753#			Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24).	#
6754#									#
6755#		This error has to be considered later in Steps 3 and 4.	#
6756#									#
6757#	Step 3.	Calculate X - N*log2/64.				#
6758#		3.1	R := X + N*L1,					#
6759#				where L1 := single-precision(-log2/64).	#
6760#		3.2	R := R + N*L2,					#
6761#				L2 := extended-precision(-log2/64 - L1).#
6762#	Notes:	a) The way L1 and L2 are chosen ensures L1+L2		#
6763#		approximate the value -log2/64 to 88 bits of accuracy.	#
6764#		b) N*L1 is exact because N is no longer than 22 bits	#
6765#		and L1 is no longer than 24 bits.			#
6766#		c) The calculation X+N*L1 is also exact due to		#
6767#		cancellation. Thus, R is practically X+N(L1+L2) to full	#
6768#		64 bits.						#
6769#		d) It is important to estimate how large can |R| be	#
6770#		after Step 3.2.						#
6771#									#
6772#		N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24)	#
6773#		X*64/log2 (1+eps)	=	N + f,	|f| <= 0.5	#
6774#		X*64/log2 - N	=	f - eps*X 64/log2		#
6775#		X - N*log2/64	=	f*log2/64 - eps*X		#
6776#									#
6777#									#
6778#		Now |X| <= 16446 log2, thus				#
6779#									#
6780#			|X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64	#
6781#					<= 0.57 log2/64.		#
6782#		 This bound will be used in Step 4.			#
6783#									#
6784#	Step 4.	Approximate exp(R)-1 by a polynomial			#
6785#		p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))	#
6786#	Notes:	a) In order to reduce memory access, the coefficients	#
6787#		are made as "short" as possible: A1 (which is 1/2), A4	#
6788#		and A5 are single precision; A2 and A3 are double	#
6789#		precision.						#
6790#		b) Even with the restrictions above,			#
6791#		   |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062.	#
6792#		Note that 0.0062 is slightly bigger than 0.57 log2/64.	#
6793#		c) To fully utilize the pipeline, p is separated into	#
6794#		two independent pieces of roughly equal complexities	#
6795#			p = [ R + R*S*(A2 + S*A4) ]	+		#
6796#				[ S*(A1 + S*(A3 + S*A5)) ]		#
6797#		where S = R*R.						#
6798#									#
6799#	Step 5.	Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by		#
6800#				ans := T + ( T*p + t)			#
6801#		where T and t are the stored values for 2^(J/64).	#
6802#	Notes:	2^(J/64) is stored as T and t where T+t approximates	#
6803#		2^(J/64) to roughly 85 bits; T is in extended precision	#
6804#		and t is in single precision. Note also that T is	#
6805#		rounded to 62 bits so that the last two bits of T are	#
6806#		zero. The reason for such a special form is that T-1,	#
6807#		T-2, and T-8 will all be exact --- a property that will	#
6808#		give much more accurate computation of the function	#
6809#		EXPM1.							#
6810#									#
6811#	Step 6.	Reconstruction of exp(X)				#
6812#			exp(X) = 2^M * 2^(J/64) * exp(R).		#
6813#		6.1	If AdjFlag = 0, go to 6.3			#
6814#		6.2	ans := ans * AdjScale				#
6815#		6.3	Restore the user FPCR				#
6816#		6.4	Return ans := ans * Scale. Exit.		#
6817#	Notes:	If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R,	#
6818#		|M| <= 16380, and Scale = 2^M. Moreover, exp(X) will	#
6819#		neither overflow nor underflow. If AdjFlag = 1, that	#
6820#		means that						#
6821#			X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380.	#
6822#		Hence, exp(X) may overflow or underflow or neither.	#
6823#		When that is the case, AdjScale = 2^(M1) where M1 is	#
6824#		approximately M. Thus 6.2 will never cause		#
6825#		over/underflow. Possible exception in 6.4 is overflow	#
6826#		or underflow. The inexact exception is not generated in	#
6827#		6.4. Although one can argue that the inexact flag	#
6828#		should always be raised, to simulate that exception	#
6829#		cost to much than the flag is worth in practical uses.	#
6830#									#
6831#	Step 7.	Return 1 + X.						#
6832#		7.1	ans := X					#
6833#		7.2	Restore user FPCR.				#
6834#		7.3	Return ans := 1 + ans. Exit			#
6835#	Notes:	For non-zero X, the inexact exception will always be	#
6836#		raised by 7.3. That is the only exception raised by 7.3.#
6837#		Note also that we use the FMOVEM instruction to move X	#
6838#		in Step 7.1 to avoid unnecessary trapping. (Although	#
6839#		the FMOVEM may not seem relevant since X is normalized,	#
6840#		the precaution will be useful in the library version of	#
6841#		this code where the separate entry for denormalized	#
6842#		inputs will be done away with.)				#
6843#									#
6844#	Step 8.	Handle exp(X) where |X| >= 16380log2.			#
6845#		8.1	If |X| > 16480 log2, go to Step 9.		#
6846#		(mimic 2.2 - 2.6)					#
6847#		8.2	N := round-to-integer( X * 64/log2 )		#
6848#		8.3	Calculate J = N mod 64, J = 0,1,...,63		#
6849#		8.4	K := (N-J)/64, M1 := truncate(K/2), M = K-M1,	#
6850#			AdjFlag := 1.					#
6851#		8.5	Calculate the address of the stored value	#
6852#			2^(J/64).					#
6853#		8.6	Create the values Scale = 2^M, AdjScale = 2^M1.	#
6854#		8.7	Go to Step 3.					#
6855#	Notes:	Refer to notes for 2.2 - 2.6.				#
6856#									#
6857#	Step 9.	Handle exp(X), |X| > 16480 log2.			#
6858#		9.1	If X < 0, go to 9.3				#
6859#		9.2	ans := Huge, go to 9.4				#
6860#		9.3	ans := Tiny.					#
6861#		9.4	Restore user FPCR.				#
6862#		9.5	Return ans := ans * ans. Exit.			#
6863#	Notes:	Exp(X) will surely overflow or underflow, depending on	#
6864#		X's sign. "Huge" and "Tiny" are respectively large/tiny	#
6865#		extended-precision numbers whose square over/underflow	#
6866#		with an inexact result. Thus, 9.5 always raises the	#
6867#		inexact together with either overflow or underflow.	#
6868#									#
6869#	setoxm1d							#
6870#	--------							#
6871#									#
6872#	Step 1.	Set ans := 0						#
6873#									#
6874#	Step 2.	Return	ans := X + ans. Exit.				#
6875#	Notes:	This will return X with the appropriate rounding	#
6876#		 precision prescribed by the user FPCR.			#
6877#									#
6878#	setoxm1								#
6879#	-------								#
6880#									#
6881#	Step 1.	Check |X|						#
6882#		1.1	If |X| >= 1/4, go to Step 1.3.			#
6883#		1.2	Go to Step 7.					#
6884#		1.3	If |X| < 70 log(2), go to Step 2.		#
6885#		1.4	Go to Step 10.					#
6886#	Notes:	The usual case should take the branches 1.1 -> 1.3 -> 2.#
6887#		However, it is conceivable |X| can be small very often	#
6888#		because EXPM1 is intended to evaluate exp(X)-1		#
6889#		accurately when |X| is small. For further details on	#
6890#		the comparisons, see the notes on Step 1 of setox.	#
6891#									#
6892#	Step 2.	Calculate N = round-to-nearest-int( X * 64/log2 ).	#
6893#		2.1	N := round-to-nearest-integer( X * 64/log2 ).	#
6894#		2.2	Calculate	J = N mod 64; so J = 0,1,2,..., #
6895#			or 63.						#
6896#		2.3	Calculate	M = (N - J)/64; so N = 64M + J.	#
6897#		2.4	Calculate the address of the stored value of	#
6898#			2^(J/64).					#
6899#		2.5	Create the values Sc = 2^M and			#
6900#			OnebySc := -2^(-M).				#
6901#	Notes:	See the notes on Step 2 of setox.			#
6902#									#
6903#	Step 3.	Calculate X - N*log2/64.				#
6904#		3.1	R := X + N*L1,					#
6905#				where L1 := single-precision(-log2/64).	#
6906#		3.2	R := R + N*L2,					#
6907#				L2 := extended-precision(-log2/64 - L1).#
6908#	Notes:	Applying the analysis of Step 3 of setox in this case	#
6909#		shows that |R| <= 0.0055 (note that |X| <= 70 log2 in	#
6910#		this case).						#
6911#									#
6912#	Step 4.	Approximate exp(R)-1 by a polynomial			#
6913#			p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6)))))	#
6914#	Notes:	a) In order to reduce memory access, the coefficients	#
6915#		are made as "short" as possible: A1 (which is 1/2), A5	#
6916#		and A6 are single precision; A2, A3 and A4 are double	#
6917#		precision.						#
6918#		b) Even with the restriction above,			#
6919#			|p - (exp(R)-1)| <	|R| * 2^(-72.7)		#
6920#		for all |R| <= 0.0055.					#
6921#		c) To fully utilize the pipeline, p is separated into	#
6922#		two independent pieces of roughly equal complexity	#
6923#			p = [ R*S*(A2 + S*(A4 + S*A6)) ]	+	#
6924#				[ R + S*(A1 + S*(A3 + S*A5)) ]		#
6925#		where S = R*R.						#
6926#									#
6927#	Step 5.	Compute 2^(J/64)*p by					#
6928#				p := T*p				#
6929#		where T and t are the stored values for 2^(J/64).	#
6930#	Notes:	2^(J/64) is stored as T and t where T+t approximates	#
6931#		2^(J/64) to roughly 85 bits; T is in extended precision	#
6932#		and t is in single precision. Note also that T is	#
6933#		rounded to 62 bits so that the last two bits of T are	#
6934#		zero. The reason for such a special form is that T-1,	#
6935#		T-2, and T-8 will all be exact --- a property that will	#
6936#		be exploited in Step 6 below. The total relative error	#
6937#		in p is no bigger than 2^(-67.7) compared to the final	#
6938#		result.							#
6939#									#
6940#	Step 6.	Reconstruction of exp(X)-1				#
6941#			exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ).	#
6942#		6.1	If M <= 63, go to Step 6.3.			#
6943#		6.2	ans := T + (p + (t + OnebySc)). Go to 6.6	#
6944#		6.3	If M >= -3, go to 6.5.				#
6945#		6.4	ans := (T + (p + t)) + OnebySc. Go to 6.6	#
6946#		6.5	ans := (T + OnebySc) + (p + t).			#
6947#		6.6	Restore user FPCR.				#
6948#		6.7	Return ans := Sc * ans. Exit.			#
6949#	Notes:	The various arrangements of the expressions give	#
6950#		accurate evaluations.					#
6951#									#
6952#	Step 7.	exp(X)-1 for |X| < 1/4.					#
6953#		7.1	If |X| >= 2^(-65), go to Step 9.		#
6954#		7.2	Go to Step 8.					#
6955#									#
6956#	Step 8.	Calculate exp(X)-1, |X| < 2^(-65).			#
6957#		8.1	If |X| < 2^(-16312), goto 8.3			#
6958#		8.2	Restore FPCR; return ans := X - 2^(-16382).	#
6959#			Exit.						#
6960#		8.3	X := X * 2^(140).				#
6961#		8.4	Restore FPCR; ans := ans - 2^(-16382).		#
6962#		 Return ans := ans*2^(140). Exit			#
6963#	Notes:	The idea is to return "X - tiny" under the user		#
6964#		precision and rounding modes. To avoid unnecessary	#
6965#		inefficiency, we stay away from denormalized numbers	#
6966#		the best we can. For |X| >= 2^(-16312), the		#
6967#		straightforward 8.2 generates the inexact exception as	#
6968#		the case warrants.					#
6969#									#
6970#	Step 9.	Calculate exp(X)-1, |X| < 1/4, by a polynomial		#
6971#			p = X + X*X*(B1 + X*(B2 + ... + X*B12))		#
6972#	Notes:	a) In order to reduce memory access, the coefficients	#
6973#		are made as "short" as possible: B1 (which is 1/2), B9	#
6974#		to B12 are single precision; B3 to B8 are double	#
6975#		precision; and B2 is double extended.			#
6976#		b) Even with the restriction above,			#
6977#			|p - (exp(X)-1)| < |X| 2^(-70.6)		#
6978#		for all |X| <= 0.251.					#
6979#		Note that 0.251 is slightly bigger than 1/4.		#
6980#		c) To fully preserve accuracy, the polynomial is	#
6981#		computed as						#
6982#			X + ( S*B1 +	Q ) where S = X*X and		#
6983#			Q	=	X*S*(B2 + X*(B3 + ... + X*B12))	#
6984#		d) To fully utilize the pipeline, Q is separated into	#
6985#		two independent pieces of roughly equal complexity	#
6986#			Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] +	#
6987#				[ S*S*(B3 + S*(B5 + ... + S*B11)) ]	#
6988#									#
6989#	Step 10. Calculate exp(X)-1 for |X| >= 70 log 2.		#
6990#		10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all	#
6991#		practical purposes. Therefore, go to Step 1 of setox.	#
6992#		10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical	#
6993#		purposes.						#
6994#		ans := -1						#
6995#		Restore user FPCR					#
6996#		Return ans := ans + 2^(-126). Exit.			#
6997#	Notes:	10.2 will always create an inexact and return -1 + tiny	#
6998#		in the user rounding precision and mode.		#
6999#									#
7000#########################################################################
7001
7002L2:	long		0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
7003
7004EEXPA3:	long		0x3FA55555,0x55554CC1
7005EEXPA2:	long		0x3FC55555,0x55554A54
7006
7007EM1A4:	long		0x3F811111,0x11174385
7008EM1A3:	long		0x3FA55555,0x55554F5A
7009
7010EM1A2:	long		0x3FC55555,0x55555555,0x00000000,0x00000000
7011
7012EM1B8:	long		0x3EC71DE3,0xA5774682
7013EM1B7:	long		0x3EFA01A0,0x19D7CB68
7014
7015EM1B6:	long		0x3F2A01A0,0x1A019DF3
7016EM1B5:	long		0x3F56C16C,0x16C170E2
7017
7018EM1B4:	long		0x3F811111,0x11111111
7019EM1B3:	long		0x3FA55555,0x55555555
7020
7021EM1B2:	long		0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
7022	long		0x00000000
7023
7024TWO140:	long		0x48B00000,0x00000000
7025TWON140:
7026	long		0x37300000,0x00000000
7027
7028EEXPTBL:
7029	long		0x3FFF0000,0x80000000,0x00000000,0x00000000
7030	long		0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
7031	long		0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
7032	long		0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
7033	long		0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
7034	long		0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
7035	long		0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
7036	long		0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
7037	long		0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
7038	long		0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
7039	long		0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
7040	long		0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
7041	long		0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
7042	long		0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
7043	long		0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
7044	long		0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
7045	long		0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
7046	long		0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
7047	long		0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
7048	long		0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
7049	long		0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
7050	long		0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
7051	long		0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
7052	long		0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
7053	long		0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
7054	long		0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
7055	long		0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
7056	long		0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
7057	long		0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
7058	long		0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
7059	long		0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
7060	long		0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
7061	long		0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
7062	long		0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
7063	long		0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
7064	long		0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
7065	long		0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
7066	long		0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
7067	long		0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
7068	long		0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
7069	long		0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
7070	long		0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
7071	long		0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
7072	long		0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
7073	long		0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
7074	long		0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
7075	long		0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
7076	long		0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
7077	long		0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
7078	long		0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
7079	long		0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
7080	long		0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
7081	long		0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
7082	long		0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
7083	long		0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
7084	long		0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
7085	long		0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
7086	long		0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
7087	long		0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
7088	long		0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
7089	long		0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
7090	long		0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
7091	long		0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
7092	long		0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
7093
7094	set		ADJFLAG,L_SCR2
7095	set		SCALE,FP_SCR0
7096	set		ADJSCALE,FP_SCR1
7097	set		SC,FP_SCR0
7098	set		ONEBYSC,FP_SCR1
7099
7100	global		setox
7101setox:
7102#--entry point for EXP(X), here X is finite, non-zero, and not NaN's
7103
7104#--Step 1.
7105	mov.l		(%a0),%d1		# load part of input X
7106	and.l		&0x7FFF0000,%d1		# biased expo. of X
7107	cmp.l		%d1,&0x3FBE0000		# 2^(-65)
7108	bge.b		EXPC1			# normal case
7109	bra		EXPSM
7110
7111EXPC1:
7112#--The case |X| >= 2^(-65)
7113	mov.w		4(%a0),%d1		# expo. and partial sig. of |X|
7114	cmp.l		%d1,&0x400CB167		# 16380 log2 trunc. 16 bits
7115	blt.b		EXPMAIN			# normal case
7116	bra		EEXPBIG
7117
7118EXPMAIN:
7119#--Step 2.
7120#--This is the normal branch:	2^(-65) <= |X| < 16380 log2.
7121	fmov.x		(%a0),%fp0		# load input from (a0)
7122
7123	fmov.x		%fp0,%fp1
7124	fmul.s		&0x42B8AA3B,%fp0	# 64/log2 * X
7125	fmovm.x		&0xc,-(%sp)		# save fp2 {%fp2/%fp3}
7126	mov.l		&0,ADJFLAG(%a6)
7127	fmov.l		%fp0,%d1		# N = int( X * 64/log2 )
7128	lea		EEXPTBL(%pc),%a1
7129	fmov.l		%d1,%fp0		# convert to floating-format
7130
7131	mov.l		%d1,L_SCR1(%a6)		# save N temporarily
7132	and.l		&0x3F,%d1		# D0 is J = N mod 64
7133	lsl.l		&4,%d1
7134	add.l		%d1,%a1			# address of 2^(J/64)
7135	mov.l		L_SCR1(%a6),%d1
7136	asr.l		&6,%d1			# D0 is M
7137	add.w		&0x3FFF,%d1		# biased expo. of 2^(M)
7138	mov.w		L2(%pc),L_SCR1(%a6)	# prefetch L2, no need in CB
7139
7140EXPCONT1:
7141#--Step 3.
7142#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7143#--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
7144	fmov.x		%fp0,%fp2
7145	fmul.s		&0xBC317218,%fp0	# N * L1, L1 = lead(-log2/64)
7146	fmul.x		L2(%pc),%fp2		# N * L2, L1+L2 = -log2/64
7147	fadd.x		%fp1,%fp0		# X + N*L1
7148	fadd.x		%fp2,%fp0		# fp0 is R, reduced arg.
7149
7150#--Step 4.
7151#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7152#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
7153#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7154#--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
7155
7156	fmov.x		%fp0,%fp1
7157	fmul.x		%fp1,%fp1		# fp1 IS S = R*R
7158
7159	fmov.s		&0x3AB60B70,%fp2	# fp2 IS A5
7160
7161	fmul.x		%fp1,%fp2		# fp2 IS S*A5
7162	fmov.x		%fp1,%fp3
7163	fmul.s		&0x3C088895,%fp3	# fp3 IS S*A4
7164
7165	fadd.d		EEXPA3(%pc),%fp2	# fp2 IS A3+S*A5
7166	fadd.d		EEXPA2(%pc),%fp3	# fp3 IS A2+S*A4
7167
7168	fmul.x		%fp1,%fp2		# fp2 IS S*(A3+S*A5)
7169	mov.w		%d1,SCALE(%a6)		# SCALE is 2^(M) in extended
7170	mov.l		&0x80000000,SCALE+4(%a6)
7171	clr.l		SCALE+8(%a6)
7172
7173	fmul.x		%fp1,%fp3		# fp3 IS S*(A2+S*A4)
7174
7175	fadd.s		&0x3F000000,%fp2	# fp2 IS A1+S*(A3+S*A5)
7176	fmul.x		%fp0,%fp3		# fp3 IS R*S*(A2+S*A4)
7177
7178	fmul.x		%fp1,%fp2		# fp2 IS S*(A1+S*(A3+S*A5))
7179	fadd.x		%fp3,%fp0		# fp0 IS R+R*S*(A2+S*A4),
7180
7181	fmov.x		(%a1)+,%fp1		# fp1 is lead. pt. of 2^(J/64)
7182	fadd.x		%fp2,%fp0		# fp0 is EXP(R) - 1
7183
7184#--Step 5
7185#--final reconstruction process
7186#--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
7187
7188	fmul.x		%fp1,%fp0		# 2^(J/64)*(Exp(R)-1)
7189	fmovm.x		(%sp)+,&0x30		# fp2 restored {%fp2/%fp3}
7190	fadd.s		(%a1),%fp0		# accurate 2^(J/64)
7191
7192	fadd.x		%fp1,%fp0		# 2^(J/64) + 2^(J/64)*...
7193	mov.l		ADJFLAG(%a6),%d1
7194
7195#--Step 6
7196	tst.l		%d1
7197	beq.b		NORMAL
7198ADJUST:
7199	fmul.x		ADJSCALE(%a6),%fp0
7200NORMAL:
7201	fmov.l		%d0,%fpcr		# restore user FPCR
7202	mov.b		&FMUL_OP,%d1		# last inst is MUL
7203	fmul.x		SCALE(%a6),%fp0		# multiply 2^(M)
7204	bra		t_catch
7205
7206EXPSM:
7207#--Step 7
7208	fmovm.x		(%a0),&0x80		# load X
7209	fmov.l		%d0,%fpcr
7210	fadd.s		&0x3F800000,%fp0	# 1+X in user mode
7211	bra		t_pinx2
7212
7213EEXPBIG:
7214#--Step 8
7215	cmp.l		%d1,&0x400CB27C		# 16480 log2
7216	bgt.b		EXP2BIG
7217#--Steps 8.2 -- 8.6
7218	fmov.x		(%a0),%fp0		# load input from (a0)
7219
7220	fmov.x		%fp0,%fp1
7221	fmul.s		&0x42B8AA3B,%fp0	# 64/log2 * X
7222	fmovm.x		&0xc,-(%sp)		# save fp2 {%fp2/%fp3}
7223	mov.l		&1,ADJFLAG(%a6)
7224	fmov.l		%fp0,%d1		# N = int( X * 64/log2 )
7225	lea		EEXPTBL(%pc),%a1
7226	fmov.l		%d1,%fp0		# convert to floating-format
7227	mov.l		%d1,L_SCR1(%a6)		# save N temporarily
7228	and.l		&0x3F,%d1		# D0 is J = N mod 64
7229	lsl.l		&4,%d1
7230	add.l		%d1,%a1			# address of 2^(J/64)
7231	mov.l		L_SCR1(%a6),%d1
7232	asr.l		&6,%d1			# D0 is K
7233	mov.l		%d1,L_SCR1(%a6)		# save K temporarily
7234	asr.l		&1,%d1			# D0 is M1
7235	sub.l		%d1,L_SCR1(%a6)		# a1 is M
7236	add.w		&0x3FFF,%d1		# biased expo. of 2^(M1)
7237	mov.w		%d1,ADJSCALE(%a6)	# ADJSCALE := 2^(M1)
7238	mov.l		&0x80000000,ADJSCALE+4(%a6)
7239	clr.l		ADJSCALE+8(%a6)
7240	mov.l		L_SCR1(%a6),%d1		# D0 is M
7241	add.w		&0x3FFF,%d1		# biased expo. of 2^(M)
7242	bra.w		EXPCONT1		# go back to Step 3
7243
7244EXP2BIG:
7245#--Step 9
7246	tst.b		(%a0)			# is X positive or negative?
7247	bmi		t_unfl2
7248	bra		t_ovfl2
7249
7250	global		setoxd
7251setoxd:
7252#--entry point for EXP(X), X is denormalized
7253	mov.l		(%a0),-(%sp)
7254	andi.l		&0x80000000,(%sp)
7255	ori.l		&0x00800000,(%sp)	# sign(X)*2^(-126)
7256
7257	fmov.s		&0x3F800000,%fp0
7258
7259	fmov.l		%d0,%fpcr
7260	fadd.s		(%sp)+,%fp0
7261	bra		t_pinx2
7262
7263	global		setoxm1
7264setoxm1:
7265#--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
7266
7267#--Step 1.
7268#--Step 1.1
7269	mov.l		(%a0),%d1		# load part of input X
7270	and.l		&0x7FFF0000,%d1		# biased expo. of X
7271	cmp.l		%d1,&0x3FFD0000		# 1/4
7272	bge.b		EM1CON1			# |X| >= 1/4
7273	bra		EM1SM
7274
7275EM1CON1:
7276#--Step 1.3
7277#--The case |X| >= 1/4
7278	mov.w		4(%a0),%d1		# expo. and partial sig. of |X|
7279	cmp.l		%d1,&0x4004C215		# 70log2 rounded up to 16 bits
7280	ble.b		EM1MAIN			# 1/4 <= |X| <= 70log2
7281	bra		EM1BIG
7282
7283EM1MAIN:
7284#--Step 2.
7285#--This is the case:	1/4 <= |X| <= 70 log2.
7286	fmov.x		(%a0),%fp0		# load input from (a0)
7287
7288	fmov.x		%fp0,%fp1
7289	fmul.s		&0x42B8AA3B,%fp0	# 64/log2 * X
7290	fmovm.x		&0xc,-(%sp)		# save fp2 {%fp2/%fp3}
7291	fmov.l		%fp0,%d1		# N = int( X * 64/log2 )
7292	lea		EEXPTBL(%pc),%a1
7293	fmov.l		%d1,%fp0		# convert to floating-format
7294
7295	mov.l		%d1,L_SCR1(%a6)		# save N temporarily
7296	and.l		&0x3F,%d1		# D0 is J = N mod 64
7297	lsl.l		&4,%d1
7298	add.l		%d1,%a1			# address of 2^(J/64)
7299	mov.l		L_SCR1(%a6),%d1
7300	asr.l		&6,%d1			# D0 is M
7301	mov.l		%d1,L_SCR1(%a6)		# save a copy of M
7302
7303#--Step 3.
7304#--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7305#--a0 points to 2^(J/64), D0 and a1 both contain M
7306	fmov.x		%fp0,%fp2
7307	fmul.s		&0xBC317218,%fp0	# N * L1, L1 = lead(-log2/64)
7308	fmul.x		L2(%pc),%fp2		# N * L2, L1+L2 = -log2/64
7309	fadd.x		%fp1,%fp0		# X + N*L1
7310	fadd.x		%fp2,%fp0		# fp0 is R, reduced arg.
7311	add.w		&0x3FFF,%d1		# D0 is biased expo. of 2^M
7312
7313#--Step 4.
7314#--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7315#-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
7316#--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7317#--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
7318
7319	fmov.x		%fp0,%fp1
7320	fmul.x		%fp1,%fp1		# fp1 IS S = R*R
7321
7322	fmov.s		&0x3950097B,%fp2	# fp2 IS a6
7323
7324	fmul.x		%fp1,%fp2		# fp2 IS S*A6
7325	fmov.x		%fp1,%fp3
7326	fmul.s		&0x3AB60B6A,%fp3	# fp3 IS S*A5
7327
7328	fadd.d		EM1A4(%pc),%fp2		# fp2 IS A4+S*A6
7329	fadd.d		EM1A3(%pc),%fp3		# fp3 IS A3+S*A5
7330	mov.w		%d1,SC(%a6)		# SC is 2^(M) in extended
7331	mov.l		&0x80000000,SC+4(%a6)
7332	clr.l		SC+8(%a6)
7333
7334	fmul.x		%fp1,%fp2		# fp2 IS S*(A4+S*A6)
7335	mov.l		L_SCR1(%a6),%d1		# D0 is	M
7336	neg.w		%d1			# D0 is -M
7337	fmul.x		%fp1,%fp3		# fp3 IS S*(A3+S*A5)
7338	add.w		&0x3FFF,%d1		# biased expo. of 2^(-M)
7339	fadd.d		EM1A2(%pc),%fp2		# fp2 IS A2+S*(A4+S*A6)
7340	fadd.s		&0x3F000000,%fp3	# fp3 IS A1+S*(A3+S*A5)
7341
7342	fmul.x		%fp1,%fp2		# fp2 IS S*(A2+S*(A4+S*A6))
7343	or.w		&0x8000,%d1		# signed/expo. of -2^(-M)
7344	mov.w		%d1,ONEBYSC(%a6)	# OnebySc is -2^(-M)
7345	mov.l		&0x80000000,ONEBYSC+4(%a6)
7346	clr.l		ONEBYSC+8(%a6)
7347	fmul.x		%fp3,%fp1		# fp1 IS S*(A1+S*(A3+S*A5))
7348
7349	fmul.x		%fp0,%fp2		# fp2 IS R*S*(A2+S*(A4+S*A6))
7350	fadd.x		%fp1,%fp0		# fp0 IS R+S*(A1+S*(A3+S*A5))
7351
7352	fadd.x		%fp2,%fp0		# fp0 IS EXP(R)-1
7353
7354	fmovm.x		(%sp)+,&0x30		# fp2 restored {%fp2/%fp3}
7355
7356#--Step 5
7357#--Compute 2^(J/64)*p
7358
7359	fmul.x		(%a1),%fp0		# 2^(J/64)*(Exp(R)-1)
7360
7361#--Step 6
7362#--Step 6.1
7363	mov.l		L_SCR1(%a6),%d1		# retrieve M
7364	cmp.l		%d1,&63
7365	ble.b		MLE63
7366#--Step 6.2	M >= 64
7367	fmov.s		12(%a1),%fp1		# fp1 is t
7368	fadd.x		ONEBYSC(%a6),%fp1	# fp1 is t+OnebySc
7369	fadd.x		%fp1,%fp0		# p+(t+OnebySc), fp1 released
7370	fadd.x		(%a1),%fp0		# T+(p+(t+OnebySc))
7371	bra		EM1SCALE
7372MLE63:
7373#--Step 6.3	M <= 63
7374	cmp.l		%d1,&-3
7375	bge.b		MGEN3
7376MLTN3:
7377#--Step 6.4	M <= -4
7378	fadd.s		12(%a1),%fp0		# p+t
7379	fadd.x		(%a1),%fp0		# T+(p+t)
7380	fadd.x		ONEBYSC(%a6),%fp0	# OnebySc + (T+(p+t))
7381	bra		EM1SCALE
7382MGEN3:
7383#--Step 6.5	-3 <= M <= 63
7384	fmov.x		(%a1)+,%fp1		# fp1 is T
7385	fadd.s		(%a1),%fp0		# fp0 is p+t
7386	fadd.x		ONEBYSC(%a6),%fp1	# fp1 is T+OnebySc
7387	fadd.x		%fp1,%fp0		# (T+OnebySc)+(p+t)
7388
7389EM1SCALE:
7390#--Step 6.6
7391	fmov.l		%d0,%fpcr
7392	fmul.x		SC(%a6),%fp0
7393	bra		t_inx2
7394
7395EM1SM:
7396#--Step 7	|X| < 1/4.
7397	cmp.l		%d1,&0x3FBE0000		# 2^(-65)
7398	bge.b		EM1POLY
7399
7400EM1TINY:
7401#--Step 8	|X| < 2^(-65)
7402	cmp.l		%d1,&0x00330000		# 2^(-16312)
7403	blt.b		EM12TINY
7404#--Step 8.2
7405	mov.l		&0x80010000,SC(%a6)	# SC is -2^(-16382)
7406	mov.l		&0x80000000,SC+4(%a6)
7407	clr.l		SC+8(%a6)
7408	fmov.x		(%a0),%fp0
7409	fmov.l		%d0,%fpcr
7410	mov.b		&FADD_OP,%d1		# last inst is ADD
7411	fadd.x		SC(%a6),%fp0
7412	bra		t_catch
7413
7414EM12TINY:
7415#--Step 8.3
7416	fmov.x		(%a0),%fp0
7417	fmul.d		TWO140(%pc),%fp0
7418	mov.l		&0x80010000,SC(%a6)
7419	mov.l		&0x80000000,SC+4(%a6)
7420	clr.l		SC+8(%a6)
7421	fadd.x		SC(%a6),%fp0
7422	fmov.l		%d0,%fpcr
7423	mov.b		&FMUL_OP,%d1		# last inst is MUL
7424	fmul.d		TWON140(%pc),%fp0
7425	bra		t_catch
7426
7427EM1POLY:
7428#--Step 9	exp(X)-1 by a simple polynomial
7429	fmov.x		(%a0),%fp0		# fp0 is X
7430	fmul.x		%fp0,%fp0		# fp0 is S := X*X
7431	fmovm.x		&0xc,-(%sp)		# save fp2 {%fp2/%fp3}
7432	fmov.s		&0x2F30CAA8,%fp1	# fp1 is B12
7433	fmul.x		%fp0,%fp1		# fp1 is S*B12
7434	fmov.s		&0x310F8290,%fp2	# fp2 is B11
7435	fadd.s		&0x32D73220,%fp1	# fp1 is B10+S*B12
7436
7437	fmul.x		%fp0,%fp2		# fp2 is S*B11
7438	fmul.x		%fp0,%fp1		# fp1 is S*(B10 + ...
7439
7440	fadd.s		&0x3493F281,%fp2	# fp2 is B9+S*...
7441	fadd.d		EM1B8(%pc),%fp1		# fp1 is B8+S*...
7442
7443	fmul.x		%fp0,%fp2		# fp2 is S*(B9+...
7444	fmul.x		%fp0,%fp1		# fp1 is S*(B8+...
7445
7446	fadd.d		EM1B7(%pc),%fp2		# fp2 is B7+S*...
7447	fadd.d		EM1B6(%pc),%fp1		# fp1 is B6+S*...
7448
7449	fmul.x		%fp0,%fp2		# fp2 is S*(B7+...
7450	fmul.x		%fp0,%fp1		# fp1 is S*(B6+...
7451
7452	fadd.d		EM1B5(%pc),%fp2		# fp2 is B5+S*...
7453	fadd.d		EM1B4(%pc),%fp1		# fp1 is B4+S*...
7454
7455	fmul.x		%fp0,%fp2		# fp2 is S*(B5+...
7456	fmul.x		%fp0,%fp1		# fp1 is S*(B4+...
7457
7458	fadd.d		EM1B3(%pc),%fp2		# fp2 is B3+S*...
7459	fadd.x		EM1B2(%pc),%fp1		# fp1 is B2+S*...
7460
7461	fmul.x		%fp0,%fp2		# fp2 is S*(B3+...
7462	fmul.x		%fp0,%fp1		# fp1 is S*(B2+...
7463
7464	fmul.x		%fp0,%fp2		# fp2 is S*S*(B3+...)
7465	fmul.x		(%a0),%fp1		# fp1 is X*S*(B2...
7466
7467	fmul.s		&0x3F000000,%fp0	# fp0 is S*B1
7468	fadd.x		%fp2,%fp1		# fp1 is Q
7469
7470	fmovm.x		(%sp)+,&0x30		# fp2 restored {%fp2/%fp3}
7471
7472	fadd.x		%fp1,%fp0		# fp0 is S*B1+Q
7473
7474	fmov.l		%d0,%fpcr
7475	fadd.x		(%a0),%fp0
7476	bra		t_inx2
7477
7478EM1BIG:
7479#--Step 10	|X| > 70 log2
7480	mov.l		(%a0),%d1
7481	cmp.l		%d1,&0
7482	bgt.w		EXPC1
7483#--Step 10.2
7484	fmov.s		&0xBF800000,%fp0	# fp0 is -1
7485	fmov.l		%d0,%fpcr
7486	fadd.s		&0x00800000,%fp0	# -1 + 2^(-126)
7487	bra		t_minx2
7488
7489	global		setoxm1d
7490setoxm1d:
7491#--entry point for EXPM1(X), here X is denormalized
7492#--Step 0.
7493	bra		t_extdnrm
7494
7495#########################################################################
7496# sgetexp():  returns the exponent portion of the input argument.	#
7497#	      The exponent bias is removed and the exponent value is	#
7498#	      returned as an extended precision number in fp0.		#
7499# sgetexpd(): handles denormalized numbers.				#
7500#									#
7501# sgetman():  extracts the mantissa of the input argument. The		#
7502#	      mantissa is converted to an extended precision number w/	#
7503#	      an exponent of $3fff and is returned in fp0. The range of #
7504#	      the result is [1.0 - 2.0).				#
7505# sgetmand(): handles denormalized numbers.				#
7506#									#
7507# INPUT *************************************************************** #
7508#	a0  = pointer to extended precision input			#
7509#									#
7510# OUTPUT ************************************************************** #
7511#	fp0 = exponent(X) or mantissa(X)				#
7512#									#
7513#########################################################################
7514
7515	global		sgetexp
7516sgetexp:
7517	mov.w		SRC_EX(%a0),%d0		# get the exponent
7518	bclr		&0xf,%d0		# clear the sign bit
7519	subi.w		&0x3fff,%d0		# subtract off the bias
7520	fmov.w		%d0,%fp0		# return exp in fp0
7521	blt.b		sgetexpn		# it's negative
7522	rts
7523
7524sgetexpn:
7525	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
7526	rts
7527
7528	global		sgetexpd
7529sgetexpd:
7530	bsr.l		norm			# normalize
7531	neg.w		%d0			# new exp = -(shft amt)
7532	subi.w		&0x3fff,%d0		# subtract off the bias
7533	fmov.w		%d0,%fp0		# return exp in fp0
7534	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
7535	rts
7536
7537	global		sgetman
7538sgetman:
7539	mov.w		SRC_EX(%a0),%d0		# get the exp
7540	ori.w		&0x7fff,%d0		# clear old exp
7541	bclr		&0xe,%d0		# make it the new exp +-3fff
7542
7543# here, we build the result in a tmp location so as not to disturb the input
7544	mov.l		SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
7545	mov.l		SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
7546	mov.w		%d0,FP_SCR0_EX(%a6)	# insert new exponent
7547	fmov.x		FP_SCR0(%a6),%fp0	# put new value back in fp0
7548	bmi.b		sgetmann		# it's negative
7549	rts
7550
7551sgetmann:
7552	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
7553	rts
7554
7555#
7556# For denormalized numbers, shift the mantissa until the j-bit = 1,
7557# then load the exponent with +/1 $3fff.
7558#
7559	global		sgetmand
7560sgetmand:
7561	bsr.l		norm			# normalize exponent
7562	bra.b		sgetman
7563
7564#########################################################################
7565# scosh():  computes the hyperbolic cosine of a normalized input	#
7566# scoshd(): computes the hyperbolic cosine of a denormalized input	#
7567#									#
7568# INPUT ***************************************************************	#
7569#	a0 = pointer to extended precision input			#
7570#	d0 = round precision,mode					#
7571#									#
7572# OUTPUT **************************************************************	#
7573#	fp0 = cosh(X)							#
7574#									#
7575# ACCURACY and MONOTONICITY *******************************************	#
7576#	The returned result is within 3 ulps in 64 significant bit,	#
7577#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently	#
7578#	rounded to double precision. The result is provably monotonic	#
7579#	in double precision.						#
7580#									#
7581# ALGORITHM ***********************************************************	#
7582#									#
7583#	COSH								#
7584#	1. If |X| > 16380 log2, go to 3.				#
7585#									#
7586#	2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae	#
7587#		y = |X|, z = exp(Y), and				#
7588#		cosh(X) = (1/2)*( z + 1/z ).				#
7589#		Exit.							#
7590#									#
7591#	3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5.		#
7592#									#
7593#	4. (16380 log2 < |X| <= 16480 log2)				#
7594#		cosh(X) = sign(X) * exp(|X|)/2.				#
7595#		However, invoking exp(|X|) may cause premature		#
7596#		overflow. Thus, we calculate sinh(X) as follows:	#
7597#		Y	:= |X|						#
7598#		Fact	:=	2**(16380)				#
7599#		Y'	:= Y - 16381 log2				#
7600#		cosh(X) := Fact * exp(Y').				#
7601#		Exit.							#
7602#									#
7603#	5. (|X| > 16480 log2) sinh(X) must overflow. Return		#
7604#		Huge*Huge to generate overflow and an infinity with	#
7605#		the appropriate sign. Huge is the largest finite number	#
7606#		in extended format. Exit.				#
7607#									#
7608#########################################################################
7609
7610TWO16380:
7611	long		0x7FFB0000,0x80000000,0x00000000,0x00000000
7612
7613	global		scosh
7614scosh:
7615	fmov.x		(%a0),%fp0		# LOAD INPUT
7616
7617	mov.l		(%a0),%d1
7618	mov.w		4(%a0),%d1
7619	and.l		&0x7FFFFFFF,%d1
7620	cmp.l		%d1,&0x400CB167
7621	bgt.b		COSHBIG
7622
7623#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7624#--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
7625
7626	fabs.x		%fp0			# |X|
7627
7628	mov.l		%d0,-(%sp)
7629	clr.l		%d0
7630	fmovm.x		&0x01,-(%sp)		# save |X| to stack
7631	lea		(%sp),%a0		# pass ptr to |X|
7632	bsr		setox			# FP0 IS EXP(|X|)
7633	add.l		&0xc,%sp		# erase |X| from stack
7634	fmul.s		&0x3F000000,%fp0	# (1/2)EXP(|X|)
7635	mov.l		(%sp)+,%d0
7636
7637	fmov.s		&0x3E800000,%fp1	# (1/4)
7638	fdiv.x		%fp0,%fp1		# 1/(2 EXP(|X|))
7639
7640	fmov.l		%d0,%fpcr
7641	mov.b		&FADD_OP,%d1		# last inst is ADD
7642	fadd.x		%fp1,%fp0
7643	bra		t_catch
7644
7645COSHBIG:
7646	cmp.l		%d1,&0x400CB2B3
7647	bgt.b		COSHHUGE
7648
7649	fabs.x		%fp0
7650	fsub.d		T1(%pc),%fp0		# (|X|-16381LOG2_LEAD)
7651	fsub.d		T2(%pc),%fp0		# |X| - 16381 LOG2, ACCURATE
7652
7653	mov.l		%d0,-(%sp)
7654	clr.l		%d0
7655	fmovm.x		&0x01,-(%sp)		# save fp0 to stack
7656	lea		(%sp),%a0		# pass ptr to fp0
7657	bsr		setox
7658	add.l		&0xc,%sp		# clear fp0 from stack
7659	mov.l		(%sp)+,%d0
7660
7661	fmov.l		%d0,%fpcr
7662	mov.b		&FMUL_OP,%d1		# last inst is MUL
7663	fmul.x		TWO16380(%pc),%fp0
7664	bra		t_catch
7665
7666COSHHUGE:
7667	bra		t_ovfl2
7668
7669	global		scoshd
7670#--COSH(X) = 1 FOR DENORMALIZED X
7671scoshd:
7672	fmov.s		&0x3F800000,%fp0
7673
7674	fmov.l		%d0,%fpcr
7675	fadd.s		&0x00800000,%fp0
7676	bra		t_pinx2
7677
7678#########################################################################
7679# ssinh():  computes the hyperbolic sine of a normalized input		#
7680# ssinhd(): computes the hyperbolic sine of a denormalized input	#
7681#									#
7682# INPUT *************************************************************** #
7683#	a0 = pointer to extended precision input			#
7684#	d0 = round precision,mode					#
7685#									#
7686# OUTPUT ************************************************************** #
7687#	fp0 = sinh(X)							#
7688#									#
7689# ACCURACY and MONOTONICITY *******************************************	#
7690#	The returned result is within 3 ulps in 64 significant bit,	#
7691#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7692#	rounded to double precision. The result is provably monotonic	#
7693#	in double precision.						#
7694#									#
7695# ALGORITHM *********************************************************** #
7696#									#
7697#       SINH								#
7698#       1. If |X| > 16380 log2, go to 3.				#
7699#									#
7700#       2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula	#
7701#               y = |X|, sgn = sign(X), and z = expm1(Y),		#
7702#               sinh(X) = sgn*(1/2)*( z + z/(1+z) ).			#
7703#          Exit.							#
7704#									#
7705#       3. If |X| > 16480 log2, go to 5.				#
7706#									#
7707#       4. (16380 log2 < |X| <= 16480 log2)				#
7708#               sinh(X) = sign(X) * exp(|X|)/2.				#
7709#          However, invoking exp(|X|) may cause premature overflow.	#
7710#          Thus, we calculate sinh(X) as follows:			#
7711#             Y       := |X|						#
7712#             sgn     := sign(X)					#
7713#             sgnFact := sgn * 2**(16380)				#
7714#             Y'      := Y - 16381 log2					#
7715#             sinh(X) := sgnFact * exp(Y').				#
7716#          Exit.							#
7717#									#
7718#       5. (|X| > 16480 log2) sinh(X) must overflow. Return		#
7719#          sign(X)*Huge*Huge to generate overflow and an infinity with	#
7720#          the appropriate sign. Huge is the largest finite number in	#
7721#          extended format. Exit.					#
7722#									#
7723#########################################################################
7724
7725	global		ssinh
7726ssinh:
7727	fmov.x		(%a0),%fp0		# LOAD INPUT
7728
7729	mov.l		(%a0),%d1
7730	mov.w		4(%a0),%d1
7731	mov.l		%d1,%a1			# save (compacted) operand
7732	and.l		&0x7FFFFFFF,%d1
7733	cmp.l		%d1,&0x400CB167
7734	bgt.b		SINHBIG
7735
7736#--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7737#--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
7738
7739	fabs.x		%fp0			# Y = |X|
7740
7741	movm.l		&0x8040,-(%sp)		# {a1/d0}
7742	fmovm.x		&0x01,-(%sp)		# save Y on stack
7743	lea		(%sp),%a0		# pass ptr to Y
7744	clr.l		%d0
7745	bsr		setoxm1			# FP0 IS Z = EXPM1(Y)
7746	add.l		&0xc,%sp		# clear Y from stack
7747	fmov.l		&0,%fpcr
7748	movm.l		(%sp)+,&0x0201		# {a1/d0}
7749
7750	fmov.x		%fp0,%fp1
7751	fadd.s		&0x3F800000,%fp1	# 1+Z
7752	fmov.x		%fp0,-(%sp)
7753	fdiv.x		%fp1,%fp0		# Z/(1+Z)
7754	mov.l		%a1,%d1
7755	and.l		&0x80000000,%d1
7756	or.l		&0x3F000000,%d1
7757	fadd.x		(%sp)+,%fp0
7758	mov.l		%d1,-(%sp)
7759
7760	fmov.l		%d0,%fpcr
7761	mov.b		&FMUL_OP,%d1		# last inst is MUL
7762	fmul.s		(%sp)+,%fp0		# last fp inst - possible exceptions set
7763	bra		t_catch
7764
7765SINHBIG:
7766	cmp.l		%d1,&0x400CB2B3
7767	bgt		t_ovfl
7768	fabs.x		%fp0
7769	fsub.d		T1(%pc),%fp0		# (|X|-16381LOG2_LEAD)
7770	mov.l		&0,-(%sp)
7771	mov.l		&0x80000000,-(%sp)
7772	mov.l		%a1,%d1
7773	and.l		&0x80000000,%d1
7774	or.l		&0x7FFB0000,%d1
7775	mov.l		%d1,-(%sp)		# EXTENDED FMT
7776	fsub.d		T2(%pc),%fp0		# |X| - 16381 LOG2, ACCURATE
7777
7778	mov.l		%d0,-(%sp)
7779	clr.l		%d0
7780	fmovm.x		&0x01,-(%sp)		# save fp0 on stack
7781	lea		(%sp),%a0		# pass ptr to fp0
7782	bsr		setox
7783	add.l		&0xc,%sp		# clear fp0 from stack
7784
7785	mov.l		(%sp)+,%d0
7786	fmov.l		%d0,%fpcr
7787	mov.b		&FMUL_OP,%d1		# last inst is MUL
7788	fmul.x		(%sp)+,%fp0		# possible exception
7789	bra		t_catch
7790
7791	global		ssinhd
7792#--SINH(X) = X FOR DENORMALIZED X
7793ssinhd:
7794	bra		t_extdnrm
7795
7796#########################################################################
7797# stanh():  computes the hyperbolic tangent of a normalized input	#
7798# stanhd(): computes the hyperbolic tangent of a denormalized input	#
7799#									#
7800# INPUT ***************************************************************	#
7801#	a0 = pointer to extended precision input			#
7802#	d0 = round precision,mode					#
7803#									#
7804# OUTPUT **************************************************************	#
7805#	fp0 = tanh(X)							#
7806#									#
7807# ACCURACY and MONOTONICITY *******************************************	#
7808#	The returned result is within 3 ulps in 64 significant bit,	#
7809#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7810#	rounded to double precision. The result is provably monotonic	#
7811#	in double precision.						#
7812#									#
7813# ALGORITHM ***********************************************************	#
7814#									#
7815#	TANH								#
7816#	1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3.		#
7817#									#
7818#	2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by		#
7819#		sgn := sign(X), y := 2|X|, z := expm1(Y), and		#
7820#		tanh(X) = sgn*( z/(2+z) ).				#
7821#		Exit.							#
7822#									#
7823#	3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1,		#
7824#		go to 7.						#
7825#									#
7826#	4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6.		#
7827#									#
7828#	5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by		#
7829#		sgn := sign(X), y := 2|X|, z := exp(Y),			#
7830#		tanh(X) = sgn - [ sgn*2/(1+z) ].			#
7831#		Exit.							#
7832#									#
7833#	6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we	#
7834#		calculate Tanh(X) by					#
7835#		sgn := sign(X), Tiny := 2**(-126),			#
7836#		tanh(X) := sgn - sgn*Tiny.				#
7837#		Exit.							#
7838#									#
7839#	7. (|X| < 2**(-40)). Tanh(X) = X.	Exit.			#
7840#									#
7841#########################################################################
7842
7843	set		X,FP_SCR0
7844	set		XFRAC,X+4
7845
7846	set		SGN,L_SCR3
7847
7848	set		V,FP_SCR0
7849
7850	global		stanh
7851stanh:
7852	fmov.x		(%a0),%fp0		# LOAD INPUT
7853
7854	fmov.x		%fp0,X(%a6)
7855	mov.l		(%a0),%d1
7856	mov.w		4(%a0),%d1
7857	mov.l		%d1,X(%a6)
7858	and.l		&0x7FFFFFFF,%d1
7859	cmp.l		%d1, &0x3fd78000	# is |X| < 2^(-40)?
7860	blt.w		TANHBORS		# yes
7861	cmp.l		%d1, &0x3fffddce	# is |X| > (5/2)LOG2?
7862	bgt.w		TANHBORS		# yes
7863
7864#--THIS IS THE USUAL CASE
7865#--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
7866
7867	mov.l		X(%a6),%d1
7868	mov.l		%d1,SGN(%a6)
7869	and.l		&0x7FFF0000,%d1
7870	add.l		&0x00010000,%d1		# EXPONENT OF 2|X|
7871	mov.l		%d1,X(%a6)
7872	and.l		&0x80000000,SGN(%a6)
7873	fmov.x		X(%a6),%fp0		# FP0 IS Y = 2|X|
7874
7875	mov.l		%d0,-(%sp)
7876	clr.l		%d0
7877	fmovm.x		&0x1,-(%sp)		# save Y on stack
7878	lea		(%sp),%a0		# pass ptr to Y
7879	bsr		setoxm1			# FP0 IS Z = EXPM1(Y)
7880	add.l		&0xc,%sp		# clear Y from stack
7881	mov.l		(%sp)+,%d0
7882
7883	fmov.x		%fp0,%fp1
7884	fadd.s		&0x40000000,%fp1	# Z+2
7885	mov.l		SGN(%a6),%d1
7886	fmov.x		%fp1,V(%a6)
7887	eor.l		%d1,V(%a6)
7888
7889	fmov.l		%d0,%fpcr		# restore users round prec,mode
7890	fdiv.x		V(%a6),%fp0
7891	bra		t_inx2
7892
7893TANHBORS:
7894	cmp.l		%d1,&0x3FFF8000
7895	blt.w		TANHSM
7896
7897	cmp.l		%d1,&0x40048AA1
7898	bgt.w		TANHHUGE
7899
7900#-- (5/2) LOG2 < |X| < 50 LOG2,
7901#--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
7902#--TANH(X) = SGN -	SGN*2/[EXP(Y)+1].
7903
7904	mov.l		X(%a6),%d1
7905	mov.l		%d1,SGN(%a6)
7906	and.l		&0x7FFF0000,%d1
7907	add.l		&0x00010000,%d1		# EXPO OF 2|X|
7908	mov.l		%d1,X(%a6)		# Y = 2|X|
7909	and.l		&0x80000000,SGN(%a6)
7910	mov.l		SGN(%a6),%d1
7911	fmov.x		X(%a6),%fp0		# Y = 2|X|
7912
7913	mov.l		%d0,-(%sp)
7914	clr.l		%d0
7915	fmovm.x		&0x01,-(%sp)		# save Y on stack
7916	lea		(%sp),%a0		# pass ptr to Y
7917	bsr		setox			# FP0 IS EXP(Y)
7918	add.l		&0xc,%sp		# clear Y from stack
7919	mov.l		(%sp)+,%d0
7920	mov.l		SGN(%a6),%d1
7921	fadd.s		&0x3F800000,%fp0	# EXP(Y)+1
7922
7923	eor.l		&0xC0000000,%d1		# -SIGN(X)*2
7924	fmov.s		%d1,%fp1		# -SIGN(X)*2 IN SGL FMT
7925	fdiv.x		%fp0,%fp1		# -SIGN(X)2 / [EXP(Y)+1 ]
7926
7927	mov.l		SGN(%a6),%d1
7928	or.l		&0x3F800000,%d1		# SGN
7929	fmov.s		%d1,%fp0		# SGN IN SGL FMT
7930
7931	fmov.l		%d0,%fpcr		# restore users round prec,mode
7932	mov.b		&FADD_OP,%d1		# last inst is ADD
7933	fadd.x		%fp1,%fp0
7934	bra		t_inx2
7935
7936TANHSM:
7937	fmov.l		%d0,%fpcr		# restore users round prec,mode
7938	mov.b		&FMOV_OP,%d1		# last inst is MOVE
7939	fmov.x		X(%a6),%fp0		# last inst - possible exception set
7940	bra		t_catch
7941
7942#---RETURN SGN(X) - SGN(X)EPS
7943TANHHUGE:
7944	mov.l		X(%a6),%d1
7945	and.l		&0x80000000,%d1
7946	or.l		&0x3F800000,%d1
7947	fmov.s		%d1,%fp0
7948	and.l		&0x80000000,%d1
7949	eor.l		&0x80800000,%d1		# -SIGN(X)*EPS
7950
7951	fmov.l		%d0,%fpcr		# restore users round prec,mode
7952	fadd.s		%d1,%fp0
7953	bra		t_inx2
7954
7955	global		stanhd
7956#--TANH(X) = X FOR DENORMALIZED X
7957stanhd:
7958	bra		t_extdnrm
7959
7960#########################################################################
7961# slogn():    computes the natural logarithm of a normalized input	#
7962# slognd():   computes the natural logarithm of a denormalized input	#
7963# slognp1():  computes the log(1+X) of a normalized input		#
7964# slognp1d(): computes the log(1+X) of a denormalized input		#
7965#									#
7966# INPUT ***************************************************************	#
7967#	a0 = pointer to extended precision input			#
7968#	d0 = round precision,mode					#
7969#									#
7970# OUTPUT **************************************************************	#
7971#	fp0 = log(X) or log(1+X)					#
7972#									#
7973# ACCURACY and MONOTONICITY *******************************************	#
7974#	The returned result is within 2 ulps in 64 significant bit,	#
7975#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently	#
7976#	rounded to double precision. The result is provably monotonic	#
7977#	in double precision.						#
7978#									#
7979# ALGORITHM ***********************************************************	#
7980#	LOGN:								#
7981#	Step 1. If |X-1| < 1/16, approximate log(X) by an odd		#
7982#		polynomial in u, where u = 2(X-1)/(X+1). Otherwise,	#
7983#		move on to Step 2.					#
7984#									#
7985#	Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first	#
7986#		seven significant bits of Y plus 2**(-7), i.e.		#
7987#		F = 1.xxxxxx1 in base 2 where the six "x" match those	#
7988#		of Y. Note that |Y-F| <= 2**(-7).			#
7989#									#
7990#	Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a		#
7991#		polynomial in u, log(1+u) = poly.			#
7992#									#
7993#	Step 4. Reconstruct						#
7994#		log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u)	#
7995#		by k*log(2) + (log(F) + poly). The values of log(F) are	#
7996#		calculated beforehand and stored in the program.	#
7997#									#
7998#	lognp1:								#
7999#	Step 1: If |X| < 1/16, approximate log(1+X) by an odd		#
8000#		polynomial in u where u = 2X/(2+X). Otherwise, move on	#
8001#		to Step 2.						#
8002#									#
8003#	Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done	#
8004#		in Step 2 of the algorithm for LOGN and compute		#
8005#		log(1+X) as k*log(2) + log(F) + poly where poly		#
8006#		approximates log(1+u), u = (Y-F)/F.			#
8007#									#
8008#	Implementation Notes:						#
8009#	Note 1. There are 64 different possible values for F, thus 64	#
8010#		log(F)'s need to be tabulated. Moreover, the values of	#
8011#		1/F are also tabulated so that the division in (Y-F)/F	#
8012#		can be performed by a multiplication.			#
8013#									#
8014#	Note 2. In Step 2 of lognp1, in order to preserved accuracy,	#
8015#		the value Y-F has to be calculated carefully when	#
8016#		1/2 <= X < 3/2.						#
8017#									#
8018#	Note 3. To fully exploit the pipeline, polynomials are usually	#
8019#		separated into two parts evaluated independently before	#
8020#		being added up.						#
8021#									#
8022#########################################################################
8023LOGOF2:
8024	long		0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8025
8026one:
8027	long		0x3F800000
8028zero:
8029	long		0x00000000
8030infty:
8031	long		0x7F800000
8032negone:
8033	long		0xBF800000
8034
8035LOGA6:
8036	long		0x3FC2499A,0xB5E4040B
8037LOGA5:
8038	long		0xBFC555B5,0x848CB7DB
8039
8040LOGA4:
8041	long		0x3FC99999,0x987D8730
8042LOGA3:
8043	long		0xBFCFFFFF,0xFF6F7E97
8044
8045LOGA2:
8046	long		0x3FD55555,0x555555A4
8047LOGA1:
8048	long		0xBFE00000,0x00000008
8049
8050LOGB5:
8051	long		0x3F175496,0xADD7DAD6
8052LOGB4:
8053	long		0x3F3C71C2,0xFE80C7E0
8054
8055LOGB3:
8056	long		0x3F624924,0x928BCCFF
8057LOGB2:
8058	long		0x3F899999,0x999995EC
8059
8060LOGB1:
8061	long		0x3FB55555,0x55555555
8062TWO:
8063	long		0x40000000,0x00000000
8064
8065LTHOLD:
8066	long		0x3f990000,0x80000000,0x00000000,0x00000000
8067
8068LOGTBL:
8069	long		0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
8070	long		0x3FF70000,0xFF015358,0x833C47E2,0x00000000
8071	long		0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
8072	long		0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
8073	long		0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
8074	long		0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
8075	long		0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
8076	long		0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
8077	long		0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
8078	long		0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
8079	long		0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
8080	long		0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
8081	long		0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
8082	long		0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
8083	long		0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
8084	long		0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
8085	long		0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
8086	long		0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
8087	long		0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
8088	long		0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
8089	long		0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
8090	long		0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
8091	long		0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
8092	long		0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
8093	long		0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
8094	long		0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
8095	long		0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
8096	long		0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
8097	long		0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
8098	long		0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
8099	long		0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
8100	long		0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
8101	long		0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
8102	long		0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
8103	long		0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
8104	long		0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
8105	long		0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
8106	long		0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
8107	long		0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
8108	long		0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
8109	long		0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
8110	long		0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
8111	long		0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
8112	long		0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
8113	long		0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
8114	long		0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
8115	long		0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
8116	long		0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
8117	long		0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
8118	long		0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
8119	long		0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
8120	long		0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
8121	long		0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
8122	long		0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
8123	long		0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
8124	long		0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
8125	long		0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
8126	long		0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
8127	long		0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
8128	long		0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
8129	long		0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
8130	long		0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
8131	long		0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
8132	long		0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
8133	long		0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
8134	long		0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
8135	long		0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
8136	long		0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
8137	long		0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
8138	long		0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
8139	long		0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
8140	long		0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
8141	long		0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
8142	long		0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
8143	long		0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
8144	long		0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
8145	long		0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
8146	long		0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
8147	long		0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
8148	long		0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
8149	long		0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
8150	long		0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
8151	long		0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
8152	long		0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
8153	long		0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
8154	long		0x3FFE0000,0x825EFCED,0x49369330,0x00000000
8155	long		0x3FFE0000,0x9868C809,0x868C8098,0x00000000
8156	long		0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
8157	long		0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
8158	long		0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
8159	long		0x3FFE0000,0x95A02568,0x095A0257,0x00000000
8160	long		0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
8161	long		0x3FFE0000,0x94458094,0x45809446,0x00000000
8162	long		0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
8163	long		0x3FFE0000,0x92F11384,0x0497889C,0x00000000
8164	long		0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
8165	long		0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
8166	long		0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
8167	long		0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
8168	long		0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
8169	long		0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
8170	long		0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
8171	long		0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
8172	long		0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
8173	long		0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
8174	long		0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
8175	long		0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
8176	long		0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
8177	long		0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
8178	long		0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
8179	long		0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
8180	long		0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
8181	long		0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
8182	long		0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
8183	long		0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
8184	long		0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
8185	long		0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
8186	long		0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
8187	long		0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
8188	long		0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
8189	long		0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
8190	long		0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
8191	long		0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
8192	long		0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
8193	long		0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
8194	long		0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
8195	long		0x3FFE0000,0x80808080,0x80808081,0x00000000
8196	long		0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
8197
8198	set		ADJK,L_SCR1
8199
8200	set		X,FP_SCR0
8201	set		XDCARE,X+2
8202	set		XFRAC,X+4
8203
8204	set		F,FP_SCR1
8205	set		FFRAC,F+4
8206
8207	set		KLOG2,FP_SCR0
8208
8209	set		SAVEU,FP_SCR0
8210
8211	global		slogn
8212#--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
8213slogn:
8214	fmov.x		(%a0),%fp0		# LOAD INPUT
8215	mov.l		&0x00000000,ADJK(%a6)
8216
8217LOGBGN:
8218#--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
8219#--A FINITE, NON-ZERO, NORMALIZED NUMBER.
8220
8221	mov.l		(%a0),%d1
8222	mov.w		4(%a0),%d1
8223
8224	mov.l		(%a0),X(%a6)
8225	mov.l		4(%a0),X+4(%a6)
8226	mov.l		8(%a0),X+8(%a6)
8227
8228	cmp.l		%d1,&0			# CHECK IF X IS NEGATIVE
8229	blt.w		LOGNEG			# LOG OF NEGATIVE ARGUMENT IS INVALID
8230# X IS POSITIVE, CHECK IF X IS NEAR 1
8231	cmp.l		%d1,&0x3ffef07d		# IS X < 15/16?
8232	blt.b		LOGMAIN			# YES
8233	cmp.l		%d1,&0x3fff8841		# IS X > 17/16?
8234	ble.w		LOGNEAR1		# NO
8235
8236LOGMAIN:
8237#--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
8238
8239#--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
8240#--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
8241#--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
8242#--			 = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
8243#--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
8244#--LOG(1+U) CAN BE VERY EFFICIENT.
8245#--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
8246#--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
8247
8248#--GET K, Y, F, AND ADDRESS OF 1/F.
8249	asr.l		&8,%d1
8250	asr.l		&8,%d1			# SHIFTED 16 BITS, BIASED EXPO. OF X
8251	sub.l		&0x3FFF,%d1		# THIS IS K
8252	add.l		ADJK(%a6),%d1		# ADJUST K, ORIGINAL INPUT MAY BE  DENORM.
8253	lea		LOGTBL(%pc),%a0		# BASE ADDRESS OF 1/F AND LOG(F)
8254	fmov.l		%d1,%fp1		# CONVERT K TO FLOATING-POINT FORMAT
8255
8256#--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
8257	mov.l		&0x3FFF0000,X(%a6)	# X IS NOW Y, I.E. 2^(-K)*X
8258	mov.l		XFRAC(%a6),FFRAC(%a6)
8259	and.l		&0xFE000000,FFRAC(%a6)	# FIRST 7 BITS OF Y
8260	or.l		&0x01000000,FFRAC(%a6)	# GET F: ATTACH A 1 AT THE EIGHTH BIT
8261	mov.l		FFRAC(%a6),%d1	# READY TO GET ADDRESS OF 1/F
8262	and.l		&0x7E000000,%d1
8263	asr.l		&8,%d1
8264	asr.l		&8,%d1
8265	asr.l		&4,%d1			# SHIFTED 20, D0 IS THE DISPLACEMENT
8266	add.l		%d1,%a0			# A0 IS THE ADDRESS FOR 1/F
8267
8268	fmov.x		X(%a6),%fp0
8269	mov.l		&0x3fff0000,F(%a6)
8270	clr.l		F+8(%a6)
8271	fsub.x		F(%a6),%fp0		# Y-F
8272	fmovm.x		&0xc,-(%sp)		# SAVE FP2-3 WHILE FP0 IS NOT READY
8273#--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
8274#--REGISTERS SAVED: FPCR, FP1, FP2
8275
8276LP1CONT1:
8277#--AN RE-ENTRY POINT FOR LOGNP1
8278	fmul.x		(%a0),%fp0		# FP0 IS U = (Y-F)/F
8279	fmul.x		LOGOF2(%pc),%fp1	# GET K*LOG2 WHILE FP0 IS NOT READY
8280	fmov.x		%fp0,%fp2
8281	fmul.x		%fp2,%fp2		# FP2 IS V=U*U
8282	fmov.x		%fp1,KLOG2(%a6)		# PUT K*LOG2 IN MEMEORY, FREE FP1
8283
8284#--LOG(1+U) IS APPROXIMATED BY
8285#--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
8286#--[U + V*(A1+V*(A3+V*A5))]  +  [U*V*(A2+V*(A4+V*A6))]
8287
8288	fmov.x		%fp2,%fp3
8289	fmov.x		%fp2,%fp1
8290
8291	fmul.d		LOGA6(%pc),%fp1		# V*A6
8292	fmul.d		LOGA5(%pc),%fp2		# V*A5
8293
8294	fadd.d		LOGA4(%pc),%fp1		# A4+V*A6
8295	fadd.d		LOGA3(%pc),%fp2		# A3+V*A5
8296
8297	fmul.x		%fp3,%fp1		# V*(A4+V*A6)
8298	fmul.x		%fp3,%fp2		# V*(A3+V*A5)
8299
8300	fadd.d		LOGA2(%pc),%fp1		# A2+V*(A4+V*A6)
8301	fadd.d		LOGA1(%pc),%fp2		# A1+V*(A3+V*A5)
8302
8303	fmul.x		%fp3,%fp1		# V*(A2+V*(A4+V*A6))
8304	add.l		&16,%a0			# ADDRESS OF LOG(F)
8305	fmul.x		%fp3,%fp2		# V*(A1+V*(A3+V*A5))
8306
8307	fmul.x		%fp0,%fp1		# U*V*(A2+V*(A4+V*A6))
8308	fadd.x		%fp2,%fp0		# U+V*(A1+V*(A3+V*A5))
8309
8310	fadd.x		(%a0),%fp1		# LOG(F)+U*V*(A2+V*(A4+V*A6))
8311	fmovm.x		(%sp)+,&0x30		# RESTORE FP2-3
8312	fadd.x		%fp1,%fp0		# FP0 IS LOG(F) + LOG(1+U)
8313
8314	fmov.l		%d0,%fpcr
8315	fadd.x		KLOG2(%a6),%fp0		# FINAL ADD
8316	bra		t_inx2
8317
8318
8319LOGNEAR1:
8320
8321# if the input is exactly equal to one, then exit through ld_pzero.
8322# if these 2 lines weren't here, the correct answer would be returned
8323# but the INEX2 bit would be set.
8324	fcmp.b		%fp0,&0x1		# is it equal to one?
8325	fbeq.l		ld_pzero		# yes
8326
8327#--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
8328	fmov.x		%fp0,%fp1
8329	fsub.s		one(%pc),%fp1		# FP1 IS X-1
8330	fadd.s		one(%pc),%fp0		# FP0 IS X+1
8331	fadd.x		%fp1,%fp1		# FP1 IS 2(X-1)
8332#--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
8333#--IN U, U = 2(X-1)/(X+1) = FP1/FP0
8334
8335LP1CONT2:
8336#--THIS IS AN RE-ENTRY POINT FOR LOGNP1
8337	fdiv.x		%fp0,%fp1		# FP1 IS U
8338	fmovm.x		&0xc,-(%sp)		# SAVE FP2-3
8339#--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
8340#--LET V=U*U, W=V*V, CALCULATE
8341#--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
8342#--U + U*V*(  [B1 + W*(B3 + W*B5)]  +  [V*(B2 + W*B4)]  )
8343	fmov.x		%fp1,%fp0
8344	fmul.x		%fp0,%fp0		# FP0 IS V
8345	fmov.x		%fp1,SAVEU(%a6)		# STORE U IN MEMORY, FREE FP1
8346	fmov.x		%fp0,%fp1
8347	fmul.x		%fp1,%fp1		# FP1 IS W
8348
8349	fmov.d		LOGB5(%pc),%fp3
8350	fmov.d		LOGB4(%pc),%fp2
8351
8352	fmul.x		%fp1,%fp3		# W*B5
8353	fmul.x		%fp1,%fp2		# W*B4
8354
8355	fadd.d		LOGB3(%pc),%fp3		# B3+W*B5
8356	fadd.d		LOGB2(%pc),%fp2		# B2+W*B4
8357
8358	fmul.x		%fp3,%fp1		# W*(B3+W*B5), FP3 RELEASED
8359
8360	fmul.x		%fp0,%fp2		# V*(B2+W*B4)
8361
8362	fadd.d		LOGB1(%pc),%fp1		# B1+W*(B3+W*B5)
8363	fmul.x		SAVEU(%a6),%fp0		# FP0 IS U*V
8364
8365	fadd.x		%fp2,%fp1		# B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
8366	fmovm.x		(%sp)+,&0x30		# FP2-3 RESTORED
8367
8368	fmul.x		%fp1,%fp0		# U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
8369
8370	fmov.l		%d0,%fpcr
8371	fadd.x		SAVEU(%a6),%fp0
8372	bra		t_inx2
8373
8374#--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
8375LOGNEG:
8376	bra		t_operr
8377
8378	global		slognd
8379slognd:
8380#--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
8381
8382	mov.l		&-100,ADJK(%a6)		# INPUT = 2^(ADJK) * FP0
8383
8384#----normalize the input value by left shifting k bits (k to be determined
8385#----below), adjusting exponent and storing -k to  ADJK
8386#----the value TWOTO100 is no longer needed.
8387#----Note that this code assumes the denormalized input is NON-ZERO.
8388
8389	movm.l		&0x3f00,-(%sp)		# save some registers  {d2-d7}
8390	mov.l		(%a0),%d3		# D3 is exponent of smallest norm. #
8391	mov.l		4(%a0),%d4
8392	mov.l		8(%a0),%d5		# (D4,D5) is (Hi_X,Lo_X)
8393	clr.l		%d2			# D2 used for holding K
8394
8395	tst.l		%d4
8396	bne.b		Hi_not0
8397
8398Hi_0:
8399	mov.l		%d5,%d4
8400	clr.l		%d5
8401	mov.l		&32,%d2
8402	clr.l		%d6
8403	bfffo		%d4{&0:&32},%d6
8404	lsl.l		%d6,%d4
8405	add.l		%d6,%d2			# (D3,D4,D5) is normalized
8406
8407	mov.l		%d3,X(%a6)
8408	mov.l		%d4,XFRAC(%a6)
8409	mov.l		%d5,XFRAC+4(%a6)
8410	neg.l		%d2
8411	mov.l		%d2,ADJK(%a6)
8412	fmov.x		X(%a6),%fp0
8413	movm.l		(%sp)+,&0xfc		# restore registers {d2-d7}
8414	lea		X(%a6),%a0
8415	bra.w		LOGBGN			# begin regular log(X)
8416
8417Hi_not0:
8418	clr.l		%d6
8419	bfffo		%d4{&0:&32},%d6		# find first 1
8420	mov.l		%d6,%d2			# get k
8421	lsl.l		%d6,%d4
8422	mov.l		%d5,%d7			# a copy of D5
8423	lsl.l		%d6,%d5
8424	neg.l		%d6
8425	add.l		&32,%d6
8426	lsr.l		%d6,%d7
8427	or.l		%d7,%d4			# (D3,D4,D5) normalized
8428
8429	mov.l		%d3,X(%a6)
8430	mov.l		%d4,XFRAC(%a6)
8431	mov.l		%d5,XFRAC+4(%a6)
8432	neg.l		%d2
8433	mov.l		%d2,ADJK(%a6)
8434	fmov.x		X(%a6),%fp0
8435	movm.l		(%sp)+,&0xfc		# restore registers {d2-d7}
8436	lea		X(%a6),%a0
8437	bra.w		LOGBGN			# begin regular log(X)
8438
8439	global		slognp1
8440#--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
8441slognp1:
8442	fmov.x		(%a0),%fp0		# LOAD INPUT
8443	fabs.x		%fp0			# test magnitude
8444	fcmp.x		%fp0,LTHOLD(%pc)	# compare with min threshold
8445	fbgt.w		LP1REAL			# if greater, continue
8446	fmov.l		%d0,%fpcr
8447	mov.b		&FMOV_OP,%d1		# last inst is MOVE
8448	fmov.x		(%a0),%fp0		# return signed argument
8449	bra		t_catch
8450
8451LP1REAL:
8452	fmov.x		(%a0),%fp0		# LOAD INPUT
8453	mov.l		&0x00000000,ADJK(%a6)
8454	fmov.x		%fp0,%fp1		# FP1 IS INPUT Z
8455	fadd.s		one(%pc),%fp0		# X := ROUND(1+Z)
8456	fmov.x		%fp0,X(%a6)
8457	mov.w		XFRAC(%a6),XDCARE(%a6)
8458	mov.l		X(%a6),%d1
8459	cmp.l		%d1,&0
8460	ble.w		LP1NEG0			# LOG OF ZERO OR -VE
8461	cmp.l		%d1,&0x3ffe8000		# IS BOUNDS [1/2,3/2]?
8462	blt.w		LOGMAIN
8463	cmp.l		%d1,&0x3fffc000
8464	bgt.w		LOGMAIN
8465#--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
8466#--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
8467#--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
8468
8469LP1NEAR1:
8470#--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
8471	cmp.l		%d1,&0x3ffef07d
8472	blt.w		LP1CARE
8473	cmp.l		%d1,&0x3fff8841
8474	bgt.w		LP1CARE
8475
8476LP1ONE16:
8477#--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
8478#--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
8479	fadd.x		%fp1,%fp1		# FP1 IS 2Z
8480	fadd.s		one(%pc),%fp0		# FP0 IS 1+X
8481#--U = FP1/FP0
8482	bra.w		LP1CONT2
8483
8484LP1CARE:
8485#--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
8486#--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
8487#--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
8488#--THERE ARE ONLY TWO CASES.
8489#--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
8490#--CASE 2: 1+Z > 1, THEN K = 0  AND Y-F = (1-F) + Z
8491#--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
8492#--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
8493
8494	mov.l		XFRAC(%a6),FFRAC(%a6)
8495	and.l		&0xFE000000,FFRAC(%a6)
8496	or.l		&0x01000000,FFRAC(%a6)	# F OBTAINED
8497	cmp.l		%d1,&0x3FFF8000		# SEE IF 1+Z > 1
8498	bge.b		KISZERO
8499
8500KISNEG1:
8501	fmov.s		TWO(%pc),%fp0
8502	mov.l		&0x3fff0000,F(%a6)
8503	clr.l		F+8(%a6)
8504	fsub.x		F(%a6),%fp0		# 2-F
8505	mov.l		FFRAC(%a6),%d1
8506	and.l		&0x7E000000,%d1
8507	asr.l		&8,%d1
8508	asr.l		&8,%d1
8509	asr.l		&4,%d1			# D0 CONTAINS DISPLACEMENT FOR 1/F
8510	fadd.x		%fp1,%fp1		# GET 2Z
8511	fmovm.x		&0xc,-(%sp)		# SAVE FP2  {%fp2/%fp3}
8512	fadd.x		%fp1,%fp0		# FP0 IS Y-F = (2-F)+2Z
8513	lea		LOGTBL(%pc),%a0		# A0 IS ADDRESS OF 1/F
8514	add.l		%d1,%a0
8515	fmov.s		negone(%pc),%fp1	# FP1 IS K = -1
8516	bra.w		LP1CONT1
8517
8518KISZERO:
8519	fmov.s		one(%pc),%fp0
8520	mov.l		&0x3fff0000,F(%a6)
8521	clr.l		F+8(%a6)
8522	fsub.x		F(%a6),%fp0		# 1-F
8523	mov.l		FFRAC(%a6),%d1
8524	and.l		&0x7E000000,%d1
8525	asr.l		&8,%d1
8526	asr.l		&8,%d1
8527	asr.l		&4,%d1
8528	fadd.x		%fp1,%fp0		# FP0 IS Y-F
8529	fmovm.x		&0xc,-(%sp)		# FP2 SAVED {%fp2/%fp3}
8530	lea		LOGTBL(%pc),%a0
8531	add.l		%d1,%a0			# A0 IS ADDRESS OF 1/F
8532	fmov.s		zero(%pc),%fp1		# FP1 IS K = 0
8533	bra.w		LP1CONT1
8534
8535LP1NEG0:
8536#--FPCR SAVED. D0 IS X IN COMPACT FORM.
8537	cmp.l		%d1,&0
8538	blt.b		LP1NEG
8539LP1ZERO:
8540	fmov.s		negone(%pc),%fp0
8541
8542	fmov.l		%d0,%fpcr
8543	bra		t_dz
8544
8545LP1NEG:
8546	fmov.s		zero(%pc),%fp0
8547
8548	fmov.l		%d0,%fpcr
8549	bra		t_operr
8550
8551	global		slognp1d
8552#--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
8553# Simply return the denorm
8554slognp1d:
8555	bra		t_extdnrm
8556
8557#########################################################################
8558# satanh():  computes the inverse hyperbolic tangent of a norm input	#
8559# satanhd(): computes the inverse hyperbolic tangent of a denorm input	#
8560#									#
8561# INPUT ***************************************************************	#
8562#	a0 = pointer to extended precision input			#
8563#	d0 = round precision,mode					#
8564#									#
8565# OUTPUT **************************************************************	#
8566#	fp0 = arctanh(X)						#
8567#									#
8568# ACCURACY and MONOTONICITY *******************************************	#
8569#	The returned result is within 3 ulps in	64 significant bit,	#
8570#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently	#
8571#	rounded to double precision. The result is provably monotonic	#
8572#	in double precision.						#
8573#									#
8574# ALGORITHM ***********************************************************	#
8575#									#
8576#	ATANH								#
8577#	1. If |X| >= 1, go to 3.					#
8578#									#
8579#	2. (|X| < 1) Calculate atanh(X) by				#
8580#		sgn := sign(X)						#
8581#		y := |X|						#
8582#		z := 2y/(1-y)						#
8583#		atanh(X) := sgn * (1/2) * logp1(z)			#
8584#		Exit.							#
8585#									#
8586#	3. If |X| > 1, go to 5.						#
8587#									#
8588#	4. (|X| = 1) Generate infinity with an appropriate sign and	#
8589#		divide-by-zero by					#
8590#		sgn := sign(X)						#
8591#		atan(X) := sgn / (+0).					#
8592#		Exit.							#
8593#									#
8594#	5. (|X| > 1) Generate an invalid operation by 0 * infinity.	#
8595#		Exit.							#
8596#									#
8597#########################################################################
8598
8599	global		satanh
8600satanh:
8601	mov.l		(%a0),%d1
8602	mov.w		4(%a0),%d1
8603	and.l		&0x7FFFFFFF,%d1
8604	cmp.l		%d1,&0x3FFF8000
8605	bge.b		ATANHBIG
8606
8607#--THIS IS THE USUAL CASE, |X| < 1
8608#--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
8609
8610	fabs.x		(%a0),%fp0		# Y = |X|
8611	fmov.x		%fp0,%fp1
8612	fneg.x		%fp1			# -Y
8613	fadd.x		%fp0,%fp0		# 2Y
8614	fadd.s		&0x3F800000,%fp1	# 1-Y
8615	fdiv.x		%fp1,%fp0		# 2Y/(1-Y)
8616	mov.l		(%a0),%d1
8617	and.l		&0x80000000,%d1
8618	or.l		&0x3F000000,%d1		# SIGN(X)*HALF
8619	mov.l		%d1,-(%sp)
8620
8621	mov.l		%d0,-(%sp)		# save rnd prec,mode
8622	clr.l		%d0			# pass ext prec,RN
8623	fmovm.x		&0x01,-(%sp)		# save Z on stack
8624	lea		(%sp),%a0		# pass ptr to Z
8625	bsr		slognp1			# LOG1P(Z)
8626	add.l		&0xc,%sp		# clear Z from stack
8627
8628	mov.l		(%sp)+,%d0		# fetch old prec,mode
8629	fmov.l		%d0,%fpcr		# load it
8630	mov.b		&FMUL_OP,%d1		# last inst is MUL
8631	fmul.s		(%sp)+,%fp0
8632	bra		t_catch
8633
8634ATANHBIG:
8635	fabs.x		(%a0),%fp0		# |X|
8636	fcmp.s		%fp0,&0x3F800000
8637	fbgt		t_operr
8638	bra		t_dz
8639
8640	global		satanhd
8641#--ATANH(X) = X FOR DENORMALIZED X
8642satanhd:
8643	bra		t_extdnrm
8644
8645#########################################################################
8646# slog10():  computes the base-10 logarithm of a normalized input	#
8647# slog10d(): computes the base-10 logarithm of a denormalized input	#
8648# slog2():   computes the base-2 logarithm of a normalized input	#
8649# slog2d():  computes the base-2 logarithm of a denormalized input	#
8650#									#
8651# INPUT *************************************************************** #
8652#	a0 = pointer to extended precision input			#
8653#	d0 = round precision,mode					#
8654#									#
8655# OUTPUT **************************************************************	#
8656#	fp0 = log_10(X) or log_2(X)					#
8657#									#
8658# ACCURACY and MONOTONICITY *******************************************	#
8659#	The returned result is within 1.7 ulps in 64 significant bit,	#
8660#	i.e. within 0.5003 ulp to 53 bits if the result is subsequently	#
8661#	rounded to double precision. The result is provably monotonic	#
8662#	in double precision.						#
8663#									#
8664# ALGORITHM ***********************************************************	#
8665#									#
8666#       slog10d:							#
8667#									#
8668#       Step 0.	If X < 0, create a NaN and raise the invalid operation	#
8669#               flag. Otherwise, save FPCR in D1; set FpCR to default.	#
8670#       Notes:  Default means round-to-nearest mode, no floating-point	#
8671#               traps, and precision control = double extended.		#
8672#									#
8673#       Step 1. Call slognd to obtain Y = log(X), the natural log of X.	#
8674#       Notes:  Even if X is denormalized, log(X) is always normalized.	#
8675#									#
8676#       Step 2.  Compute log_10(X) = log(X) * (1/log(10)).		#
8677#            2.1 Restore the user FPCR					#
8678#            2.2 Return ans := Y * INV_L10.				#
8679#									#
8680#       slog10:								#
8681#									#
8682#       Step 0. If X < 0, create a NaN and raise the invalid operation	#
8683#               flag. Otherwise, save FPCR in D1; set FpCR to default.	#
8684#       Notes:  Default means round-to-nearest mode, no floating-point	#
8685#               traps, and precision control = double extended.		#
8686#									#
8687#       Step 1. Call sLogN to obtain Y = log(X), the natural log of X.	#
8688#									#
8689#       Step 2.   Compute log_10(X) = log(X) * (1/log(10)).		#
8690#            2.1  Restore the user FPCR					#
8691#            2.2  Return ans := Y * INV_L10.				#
8692#									#
8693#       sLog2d:								#
8694#									#
8695#       Step 0. If X < 0, create a NaN and raise the invalid operation	#
8696#               flag. Otherwise, save FPCR in D1; set FpCR to default.	#
8697#       Notes:  Default means round-to-nearest mode, no floating-point	#
8698#               traps, and precision control = double extended.		#
8699#									#
8700#       Step 1. Call slognd to obtain Y = log(X), the natural log of X.	#
8701#       Notes:  Even if X is denormalized, log(X) is always normalized.	#
8702#									#
8703#       Step 2.   Compute log_10(X) = log(X) * (1/log(2)).		#
8704#            2.1  Restore the user FPCR					#
8705#            2.2  Return ans := Y * INV_L2.				#
8706#									#
8707#       sLog2:								#
8708#									#
8709#       Step 0. If X < 0, create a NaN and raise the invalid operation	#
8710#               flag. Otherwise, save FPCR in D1; set FpCR to default.	#
8711#       Notes:  Default means round-to-nearest mode, no floating-point	#
8712#               traps, and precision control = double extended.		#
8713#									#
8714#       Step 1. If X is not an integer power of two, i.e., X != 2^k,	#
8715#               go to Step 3.						#
8716#									#
8717#       Step 2.   Return k.						#
8718#            2.1  Get integer k, X = 2^k.				#
8719#            2.2  Restore the user FPCR.				#
8720#            2.3  Return ans := convert-to-double-extended(k).		#
8721#									#
8722#       Step 3. Call sLogN to obtain Y = log(X), the natural log of X.	#
8723#									#
8724#       Step 4.   Compute log_2(X) = log(X) * (1/log(2)).		#
8725#            4.1  Restore the user FPCR					#
8726#            4.2  Return ans := Y * INV_L2.				#
8727#									#
8728#########################################################################
8729
8730INV_L10:
8731	long		0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
8732
8733INV_L2:
8734	long		0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
8735
8736	global		slog10
8737#--entry point for Log10(X), X is normalized
8738slog10:
8739	fmov.b		&0x1,%fp0
8740	fcmp.x		%fp0,(%a0)		# if operand == 1,
8741	fbeq.l		ld_pzero		# return an EXACT zero
8742
8743	mov.l		(%a0),%d1
8744	blt.w		invalid
8745	mov.l		%d0,-(%sp)
8746	clr.l		%d0
8747	bsr		slogn			# log(X), X normal.
8748	fmov.l		(%sp)+,%fpcr
8749	fmul.x		INV_L10(%pc),%fp0
8750	bra		t_inx2
8751
8752	global		slog10d
8753#--entry point for Log10(X), X is denormalized
8754slog10d:
8755	mov.l		(%a0),%d1
8756	blt.w		invalid
8757	mov.l		%d0,-(%sp)
8758	clr.l		%d0
8759	bsr		slognd			# log(X), X denorm.
8760	fmov.l		(%sp)+,%fpcr
8761	fmul.x		INV_L10(%pc),%fp0
8762	bra		t_minx2
8763
8764	global		slog2
8765#--entry point for Log2(X), X is normalized
8766slog2:
8767	mov.l		(%a0),%d1
8768	blt.w		invalid
8769
8770	mov.l		8(%a0),%d1
8771	bne.b		continue		# X is not 2^k
8772
8773	mov.l		4(%a0),%d1
8774	and.l		&0x7FFFFFFF,%d1
8775	bne.b		continue
8776
8777#--X = 2^k.
8778	mov.w		(%a0),%d1
8779	and.l		&0x00007FFF,%d1
8780	sub.l		&0x3FFF,%d1
8781	beq.l		ld_pzero
8782	fmov.l		%d0,%fpcr
8783	fmov.l		%d1,%fp0
8784	bra		t_inx2
8785
8786continue:
8787	mov.l		%d0,-(%sp)
8788	clr.l		%d0
8789	bsr		slogn			# log(X), X normal.
8790	fmov.l		(%sp)+,%fpcr
8791	fmul.x		INV_L2(%pc),%fp0
8792	bra		t_inx2
8793
8794invalid:
8795	bra		t_operr
8796
8797	global		slog2d
8798#--entry point for Log2(X), X is denormalized
8799slog2d:
8800	mov.l		(%a0),%d1
8801	blt.w		invalid
8802	mov.l		%d0,-(%sp)
8803	clr.l		%d0
8804	bsr		slognd			# log(X), X denorm.
8805	fmov.l		(%sp)+,%fpcr
8806	fmul.x		INV_L2(%pc),%fp0
8807	bra		t_minx2
8808
8809#########################################################################
8810# stwotox():  computes 2**X for a normalized input			#
8811# stwotoxd(): computes 2**X for a denormalized input			#
8812# stentox():  computes 10**X for a normalized input			#
8813# stentoxd(): computes 10**X for a denormalized input			#
8814#									#
8815# INPUT ***************************************************************	#
8816#	a0 = pointer to extended precision input			#
8817#	d0 = round precision,mode					#
8818#									#
8819# OUTPUT **************************************************************	#
8820#	fp0 = 2**X or 10**X						#
8821#									#
8822# ACCURACY and MONOTONICITY *******************************************	#
8823#	The returned result is within 2 ulps in 64 significant bit,	#
8824#	i.e. within 0.5001 ulp to 53 bits if the result is subsequently	#
8825#	rounded to double precision. The result is provably monotonic	#
8826#	in double precision.						#
8827#									#
8828# ALGORITHM ***********************************************************	#
8829#									#
8830#	twotox								#
8831#	1. If |X| > 16480, go to ExpBig.				#
8832#									#
8833#	2. If |X| < 2**(-70), go to ExpSm.				#
8834#									#
8835#	3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore	#
8836#		decompose N as						#
8837#		 N = 64(M + M') + j,  j = 0,1,2,...,63.			#
8838#									#
8839#	4. Overwrite r := r * log2. Then				#
8840#		2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).		#
8841#		Go to expr to compute that expression.			#
8842#									#
8843#	tentox								#
8844#	1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig.	#
8845#									#
8846#	2. If |X| < 2**(-70), go to ExpSm.				#
8847#									#
8848#	3. Set y := X*log_2(10)*64 (base 2 log of 10). Set		#
8849#		N := round-to-int(y). Decompose N as			#
8850#		 N = 64(M + M') + j,  j = 0,1,2,...,63.			#
8851#									#
8852#	4. Define r as							#
8853#		r := ((X - N*L1)-N*L2) * L10				#
8854#		where L1, L2 are the leading and trailing parts of	#
8855#		log_10(2)/64 and L10 is the natural log of 10. Then	#
8856#		10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).		#
8857#		Go to expr to compute that expression.			#
8858#									#
8859#	expr								#
8860#	1. Fetch 2**(j/64) from table as Fact1 and Fact2.		#
8861#									#
8862#	2. Overwrite Fact1 and Fact2 by					#
8863#		Fact1 := 2**(M) * Fact1					#
8864#		Fact2 := 2**(M) * Fact2					#
8865#		Thus Fact1 + Fact2 = 2**(M) * 2**(j/64).		#
8866#									#
8867#	3. Calculate P where 1 + P approximates exp(r):			#
8868#		P = r + r*r*(A1+r*(A2+...+r*A5)).			#
8869#									#
8870#	4. Let AdjFact := 2**(M'). Return				#
8871#		AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ).		#
8872#		Exit.							#
8873#									#
8874#	ExpBig								#
8875#	1. Generate overflow by Huge * Huge if X > 0; otherwise,	#
8876#	        generate underflow by Tiny * Tiny.			#
8877#									#
8878#	ExpSm								#
8879#	1. Return 1 + X.						#
8880#									#
8881#########################################################################
8882
8883L2TEN64:
8884	long		0x406A934F,0x0979A371	# 64LOG10/LOG2
8885L10TWO1:
8886	long		0x3F734413,0x509F8000	# LOG2/64LOG10
8887
8888L10TWO2:
8889	long		0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
8890
8891LOG10:	long		0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
8892
8893LOG2:	long		0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8894
8895EXPA5:	long		0x3F56C16D,0x6F7BD0B2
8896EXPA4:	long		0x3F811112,0x302C712C
8897EXPA3:	long		0x3FA55555,0x55554CC1
8898EXPA2:	long		0x3FC55555,0x55554A54
8899EXPA1:	long		0x3FE00000,0x00000000,0x00000000,0x00000000
8900
8901TEXPTBL:
8902	long		0x3FFF0000,0x80000000,0x00000000,0x3F738000
8903	long		0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
8904	long		0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
8905	long		0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
8906	long		0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
8907	long		0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
8908	long		0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
8909	long		0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
8910	long		0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
8911	long		0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
8912	long		0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
8913	long		0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
8914	long		0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
8915	long		0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
8916	long		0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
8917	long		0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
8918	long		0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
8919	long		0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
8920	long		0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
8921	long		0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
8922	long		0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
8923	long		0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
8924	long		0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
8925	long		0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
8926	long		0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
8927	long		0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
8928	long		0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
8929	long		0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
8930	long		0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
8931	long		0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
8932	long		0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
8933	long		0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
8934	long		0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
8935	long		0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
8936	long		0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
8937	long		0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
8938	long		0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
8939	long		0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
8940	long		0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
8941	long		0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
8942	long		0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
8943	long		0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
8944	long		0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
8945	long		0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
8946	long		0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
8947	long		0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
8948	long		0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
8949	long		0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
8950	long		0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
8951	long		0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
8952	long		0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
8953	long		0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
8954	long		0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
8955	long		0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
8956	long		0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
8957	long		0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
8958	long		0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
8959	long		0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
8960	long		0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
8961	long		0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
8962	long		0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
8963	long		0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
8964	long		0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
8965	long		0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
8966
8967	set		INT,L_SCR1
8968
8969	set		X,FP_SCR0
8970	set		XDCARE,X+2
8971	set		XFRAC,X+4
8972
8973	set		ADJFACT,FP_SCR0
8974
8975	set		FACT1,FP_SCR0
8976	set		FACT1HI,FACT1+4
8977	set		FACT1LOW,FACT1+8
8978
8979	set		FACT2,FP_SCR1
8980	set		FACT2HI,FACT2+4
8981	set		FACT2LOW,FACT2+8
8982
8983	global		stwotox
8984#--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
8985stwotox:
8986	fmovm.x		(%a0),&0x80		# LOAD INPUT
8987
8988	mov.l		(%a0),%d1
8989	mov.w		4(%a0),%d1
8990	fmov.x		%fp0,X(%a6)
8991	and.l		&0x7FFFFFFF,%d1
8992
8993	cmp.l		%d1,&0x3FB98000		# |X| >= 2**(-70)?
8994	bge.b		TWOOK1
8995	bra.w		EXPBORS
8996
8997TWOOK1:
8998	cmp.l		%d1,&0x400D80C0		# |X| > 16480?
8999	ble.b		TWOMAIN
9000	bra.w		EXPBORS
9001
9002TWOMAIN:
9003#--USUAL CASE, 2^(-70) <= |X| <= 16480
9004
9005	fmov.x		%fp0,%fp1
9006	fmul.s		&0x42800000,%fp1	# 64 * X
9007	fmov.l		%fp1,INT(%a6)		# N = ROUND-TO-INT(64 X)
9008	mov.l		%d2,-(%sp)
9009	lea		TEXPTBL(%pc),%a1	# LOAD ADDRESS OF TABLE OF 2^(J/64)
9010	fmov.l		INT(%a6),%fp1		# N --> FLOATING FMT
9011	mov.l		INT(%a6),%d1
9012	mov.l		%d1,%d2
9013	and.l		&0x3F,%d1		# D0 IS J
9014	asl.l		&4,%d1			# DISPLACEMENT FOR 2^(J/64)
9015	add.l		%d1,%a1			# ADDRESS FOR 2^(J/64)
9016	asr.l		&6,%d2			# d2 IS L, N = 64L + J
9017	mov.l		%d2,%d1
9018	asr.l		&1,%d1			# D0 IS M
9019	sub.l		%d1,%d2			# d2 IS M', N = 64(M+M') + J
9020	add.l		&0x3FFF,%d2
9021
9022#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9023#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9024#--ADJFACT = 2^(M').
9025#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9026
9027	fmovm.x		&0x0c,-(%sp)		# save fp2/fp3
9028
9029	fmul.s		&0x3C800000,%fp1	# (1/64)*N
9030	mov.l		(%a1)+,FACT1(%a6)
9031	mov.l		(%a1)+,FACT1HI(%a6)
9032	mov.l		(%a1)+,FACT1LOW(%a6)
9033	mov.w		(%a1)+,FACT2(%a6)
9034
9035	fsub.x		%fp1,%fp0		# X - (1/64)*INT(64 X)
9036
9037	mov.w		(%a1)+,FACT2HI(%a6)
9038	clr.w		FACT2HI+2(%a6)
9039	clr.l		FACT2LOW(%a6)
9040	add.w		%d1,FACT1(%a6)
9041	fmul.x		LOG2(%pc),%fp0		# FP0 IS R
9042	add.w		%d1,FACT2(%a6)
9043
9044	bra.w		expr
9045
9046EXPBORS:
9047#--FPCR, D0 SAVED
9048	cmp.l		%d1,&0x3FFF8000
9049	bgt.b		TEXPBIG
9050
9051#--|X| IS SMALL, RETURN 1 + X
9052
9053	fmov.l		%d0,%fpcr		# restore users round prec,mode
9054	fadd.s		&0x3F800000,%fp0	# RETURN 1 + X
9055	bra		t_pinx2
9056
9057TEXPBIG:
9058#--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
9059#--REGISTERS SAVE SO FAR ARE FPCR AND  D0
9060	mov.l		X(%a6),%d1
9061	cmp.l		%d1,&0
9062	blt.b		EXPNEG
9063
9064	bra		t_ovfl2			# t_ovfl expects positive value
9065
9066EXPNEG:
9067	bra		t_unfl2			# t_unfl expects positive value
9068
9069	global		stwotoxd
9070stwotoxd:
9071#--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
9072
9073	fmov.l		%d0,%fpcr		# set user's rounding mode/precision
9074	fmov.s		&0x3F800000,%fp0	# RETURN 1 + X
9075	mov.l		(%a0),%d1
9076	or.l		&0x00800001,%d1
9077	fadd.s		%d1,%fp0
9078	bra		t_pinx2
9079
9080	global		stentox
9081#--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9082stentox:
9083	fmovm.x		(%a0),&0x80		# LOAD INPUT
9084
9085	mov.l		(%a0),%d1
9086	mov.w		4(%a0),%d1
9087	fmov.x		%fp0,X(%a6)
9088	and.l		&0x7FFFFFFF,%d1
9089
9090	cmp.l		%d1,&0x3FB98000		# |X| >= 2**(-70)?
9091	bge.b		TENOK1
9092	bra.w		EXPBORS
9093
9094TENOK1:
9095	cmp.l		%d1,&0x400B9B07		# |X| <= 16480*log2/log10 ?
9096	ble.b		TENMAIN
9097	bra.w		EXPBORS
9098
9099TENMAIN:
9100#--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
9101
9102	fmov.x		%fp0,%fp1
9103	fmul.d		L2TEN64(%pc),%fp1	# X*64*LOG10/LOG2
9104	fmov.l		%fp1,INT(%a6)		# N=INT(X*64*LOG10/LOG2)
9105	mov.l		%d2,-(%sp)
9106	lea		TEXPTBL(%pc),%a1	# LOAD ADDRESS OF TABLE OF 2^(J/64)
9107	fmov.l		INT(%a6),%fp1		# N --> FLOATING FMT
9108	mov.l		INT(%a6),%d1
9109	mov.l		%d1,%d2
9110	and.l		&0x3F,%d1		# D0 IS J
9111	asl.l		&4,%d1			# DISPLACEMENT FOR 2^(J/64)
9112	add.l		%d1,%a1			# ADDRESS FOR 2^(J/64)
9113	asr.l		&6,%d2			# d2 IS L, N = 64L + J
9114	mov.l		%d2,%d1
9115	asr.l		&1,%d1			# D0 IS M
9116	sub.l		%d1,%d2			# d2 IS M', N = 64(M+M') + J
9117	add.l		&0x3FFF,%d2
9118
9119#--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9120#--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9121#--ADJFACT = 2^(M').
9122#--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9123	fmovm.x		&0x0c,-(%sp)		# save fp2/fp3
9124
9125	fmov.x		%fp1,%fp2
9126
9127	fmul.d		L10TWO1(%pc),%fp1	# N*(LOG2/64LOG10)_LEAD
9128	mov.l		(%a1)+,FACT1(%a6)
9129
9130	fmul.x		L10TWO2(%pc),%fp2	# N*(LOG2/64LOG10)_TRAIL
9131
9132	mov.l		(%a1)+,FACT1HI(%a6)
9133	mov.l		(%a1)+,FACT1LOW(%a6)
9134	fsub.x		%fp1,%fp0		# X - N L_LEAD
9135	mov.w		(%a1)+,FACT2(%a6)
9136
9137	fsub.x		%fp2,%fp0		# X - N L_TRAIL
9138
9139	mov.w		(%a1)+,FACT2HI(%a6)
9140	clr.w		FACT2HI+2(%a6)
9141	clr.l		FACT2LOW(%a6)
9142
9143	fmul.x		LOG10(%pc),%fp0		# FP0 IS R
9144	add.w		%d1,FACT1(%a6)
9145	add.w		%d1,FACT2(%a6)
9146
9147expr:
9148#--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
9149#--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
9150#--FP0 IS R. THE FOLLOWING CODE COMPUTES
9151#--	2**(M'+M) * 2**(J/64) * EXP(R)
9152
9153	fmov.x		%fp0,%fp1
9154	fmul.x		%fp1,%fp1		# FP1 IS S = R*R
9155
9156	fmov.d		EXPA5(%pc),%fp2		# FP2 IS A5
9157	fmov.d		EXPA4(%pc),%fp3		# FP3 IS A4
9158
9159	fmul.x		%fp1,%fp2		# FP2 IS S*A5
9160	fmul.x		%fp1,%fp3		# FP3 IS S*A4
9161
9162	fadd.d		EXPA3(%pc),%fp2		# FP2 IS A3+S*A5
9163	fadd.d		EXPA2(%pc),%fp3		# FP3 IS A2+S*A4
9164
9165	fmul.x		%fp1,%fp2		# FP2 IS S*(A3+S*A5)
9166	fmul.x		%fp1,%fp3		# FP3 IS S*(A2+S*A4)
9167
9168	fadd.d		EXPA1(%pc),%fp2		# FP2 IS A1+S*(A3+S*A5)
9169	fmul.x		%fp0,%fp3		# FP3 IS R*S*(A2+S*A4)
9170
9171	fmul.x		%fp1,%fp2		# FP2 IS S*(A1+S*(A3+S*A5))
9172	fadd.x		%fp3,%fp0		# FP0 IS R+R*S*(A2+S*A4)
9173	fadd.x		%fp2,%fp0		# FP0 IS EXP(R) - 1
9174
9175	fmovm.x		(%sp)+,&0x30		# restore fp2/fp3
9176
9177#--FINAL RECONSTRUCTION PROCESS
9178#--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1)  -  (1 OR 0)
9179
9180	fmul.x		FACT1(%a6),%fp0
9181	fadd.x		FACT2(%a6),%fp0
9182	fadd.x		FACT1(%a6),%fp0
9183
9184	fmov.l		%d0,%fpcr		# restore users round prec,mode
9185	mov.w		%d2,ADJFACT(%a6)	# INSERT EXPONENT
9186	mov.l		(%sp)+,%d2
9187	mov.l		&0x80000000,ADJFACT+4(%a6)
9188	clr.l		ADJFACT+8(%a6)
9189	mov.b		&FMUL_OP,%d1		# last inst is MUL
9190	fmul.x		ADJFACT(%a6),%fp0	# FINAL ADJUSTMENT
9191	bra		t_catch
9192
9193	global		stentoxd
9194stentoxd:
9195#--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
9196
9197	fmov.l		%d0,%fpcr		# set user's rounding mode/precision
9198	fmov.s		&0x3F800000,%fp0	# RETURN 1 + X
9199	mov.l		(%a0),%d1
9200	or.l		&0x00800001,%d1
9201	fadd.s		%d1,%fp0
9202	bra		t_pinx2
9203
9204#########################################################################
9205# sscale(): computes the destination operand scaled by the source	#
9206#	    operand. If the absoulute value of the source operand is	#
9207#	    >= 2^14, an overflow or underflow is returned.		#
9208#									#
9209# INPUT *************************************************************** #
9210#	a0  = pointer to double-extended source operand X		#
9211#	a1  = pointer to double-extended destination operand Y		#
9212#									#
9213# OUTPUT ************************************************************** #
9214#	fp0 =  scale(X,Y)						#
9215#									#
9216#########################################################################
9217
9218set	SIGN,		L_SCR1
9219
9220	global		sscale
9221sscale:
9222	mov.l		%d0,-(%sp)		# store off ctrl bits for now
9223
9224	mov.w		DST_EX(%a1),%d1		# get dst exponent
9225	smi.b		SIGN(%a6)		# use SIGN to hold dst sign
9226	andi.l		&0x00007fff,%d1		# strip sign from dst exp
9227
9228	mov.w		SRC_EX(%a0),%d0		# check src bounds
9229	andi.w		&0x7fff,%d0		# clr src sign bit
9230	cmpi.w		%d0,&0x3fff		# is src ~ ZERO?
9231	blt.w		src_small		# yes
9232	cmpi.w		%d0,&0x400c		# no; is src too big?
9233	bgt.w		src_out			# yes
9234
9235#
9236# Source is within 2^14 range.
9237#
9238src_ok:
9239	fintrz.x	SRC(%a0),%fp0		# calc int of src
9240	fmov.l		%fp0,%d0		# int src to d0
9241# don't want any accrued bits from the fintrz showing up later since
9242# we may need to read the fpsr for the last fp op in t_catch2().
9243	fmov.l		&0x0,%fpsr
9244
9245	tst.b		DST_HI(%a1)		# is dst denormalized?
9246	bmi.b		sok_norm
9247
9248# the dst is a DENORM. normalize the DENORM and add the adjustment to
9249# the src value. then, jump to the norm part of the routine.
9250sok_dnrm:
9251	mov.l		%d0,-(%sp)		# save src for now
9252
9253	mov.w		DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
9254	mov.l		DST_HI(%a1),FP_SCR0_HI(%a6)
9255	mov.l		DST_LO(%a1),FP_SCR0_LO(%a6)
9256
9257	lea		FP_SCR0(%a6),%a0	# pass ptr to DENORM
9258	bsr.l		norm			# normalize the DENORM
9259	neg.l		%d0
9260	add.l		(%sp)+,%d0		# add adjustment to src
9261
9262	fmovm.x		FP_SCR0(%a6),&0x80	# load normalized DENORM
9263
9264	cmpi.w		%d0,&-0x3fff		# is the shft amt really low?
9265	bge.b		sok_norm2		# thank goodness no
9266
9267# the multiply factor that we're trying to create should be a denorm
9268# for the multiply to work. therefore, we're going to actually do a
9269# multiply with a denorm which will cause an unimplemented data type
9270# exception to be put into the machine which will be caught and corrected
9271# later. we don't do this with the DENORMs above because this method
9272# is slower. but, don't fret, I don't see it being used much either.
9273	fmov.l		(%sp)+,%fpcr		# restore user fpcr
9274	mov.l		&0x80000000,%d1		# load normalized mantissa
9275	subi.l		&-0x3fff,%d0		# how many should we shift?
9276	neg.l		%d0			# make it positive
9277	cmpi.b		%d0,&0x20		# is it > 32?
9278	bge.b		sok_dnrm_32		# yes
9279	lsr.l		%d0,%d1			# no; bit stays in upper lw
9280	clr.l		-(%sp)			# insert zero low mantissa
9281	mov.l		%d1,-(%sp)		# insert new high mantissa
9282	clr.l		-(%sp)			# make zero exponent
9283	bra.b		sok_norm_cont
9284sok_dnrm_32:
9285	subi.b		&0x20,%d0		# get shift count
9286	lsr.l		%d0,%d1			# make low mantissa longword
9287	mov.l		%d1,-(%sp)		# insert new low mantissa
9288	clr.l		-(%sp)			# insert zero high mantissa
9289	clr.l		-(%sp)			# make zero exponent
9290	bra.b		sok_norm_cont
9291
9292# the src will force the dst to a DENORM value or worse. so, let's
9293# create an fp multiply that will create the result.
9294sok_norm:
9295	fmovm.x		DST(%a1),&0x80		# load fp0 with normalized src
9296sok_norm2:
9297	fmov.l		(%sp)+,%fpcr		# restore user fpcr
9298
9299	addi.w		&0x3fff,%d0		# turn src amt into exp value
9300	swap		%d0			# put exponent in high word
9301	clr.l		-(%sp)			# insert new exponent
9302	mov.l		&0x80000000,-(%sp)	# insert new high mantissa
9303	mov.l		%d0,-(%sp)		# insert new lo mantissa
9304
9305sok_norm_cont:
9306	fmov.l		%fpcr,%d0		# d0 needs fpcr for t_catch2
9307	mov.b		&FMUL_OP,%d1		# last inst is MUL
9308	fmul.x		(%sp)+,%fp0		# do the multiply
9309	bra		t_catch2		# catch any exceptions
9310
9311#
9312# Source is outside of 2^14 range.  Test the sign and branch
9313# to the appropriate exception handler.
9314#
9315src_out:
9316	mov.l		(%sp)+,%d0		# restore ctrl bits
9317	exg		%a0,%a1			# swap src,dst ptrs
9318	tst.b		SRC_EX(%a1)		# is src negative?
9319	bmi		t_unfl			# yes; underflow
9320	bra		t_ovfl_sc		# no; overflow
9321
9322#
9323# The source input is below 1, so we check for denormalized numbers
9324# and set unfl.
9325#
9326src_small:
9327	tst.b		DST_HI(%a1)		# is dst denormalized?
9328	bpl.b		ssmall_done		# yes
9329
9330	mov.l		(%sp)+,%d0
9331	fmov.l		%d0,%fpcr		# no; load control bits
9332	mov.b		&FMOV_OP,%d1		# last inst is MOVE
9333	fmov.x		DST(%a1),%fp0		# simply return dest
9334	bra		t_catch2
9335ssmall_done:
9336	mov.l		(%sp)+,%d0		# load control bits into d1
9337	mov.l		%a1,%a0			# pass ptr to dst
9338	bra		t_resdnrm
9339
9340#########################################################################
9341# smod(): computes the fp MOD of the input values X,Y.			#
9342# srem(): computes the fp (IEEE) REM of the input values X,Y.		#
9343#									#
9344# INPUT *************************************************************** #
9345#	a0 = pointer to extended precision input X			#
9346#	a1 = pointer to extended precision input Y			#
9347#	d0 = round precision,mode					#
9348#									#
9349#	The input operands X and Y can be either normalized or		#
9350#	denormalized.							#
9351#									#
9352# OUTPUT ************************************************************** #
9353#      fp0 = FREM(X,Y) or FMOD(X,Y)					#
9354#									#
9355# ALGORITHM *********************************************************** #
9356#									#
9357#       Step 1.  Save and strip signs of X and Y: signX := sign(X),	#
9358#                signY := sign(Y), X := |X|, Y := |Y|,			#
9359#                signQ := signX EOR signY. Record whether MOD or REM	#
9360#                is requested.						#
9361#									#
9362#       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.		#
9363#                If (L < 0) then					#
9364#                   R := X, go to Step 4.				#
9365#                else							#
9366#                   R := 2^(-L)X, j := L.				#
9367#                endif							#
9368#									#
9369#       Step 3.  Perform MOD(X,Y)					#
9370#            3.1 If R = Y, go to Step 9.				#
9371#            3.2 If R > Y, then { R := R - Y, Q := Q + 1}		#
9372#            3.3 If j = 0, go to Step 4.				#
9373#            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to	#
9374#                Step 3.1.						#
9375#									#
9376#       Step 4.  At this point, R = X - QY = MOD(X,Y). Set		#
9377#                Last_Subtract := false (used in Step 7 below). If	#
9378#                MOD is requested, go to Step 6.			#
9379#									#
9380#       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested.		#
9381#            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to	#
9382#                Step 6.						#
9383#            5.2 If R > Y/2, then { set Last_Subtract := true,		#
9384#                Q := Q + 1, Y := signY*Y }. Go to Step 6.		#
9385#            5.3 This is the tricky case of R = Y/2. If Q is odd,	#
9386#                then { Q := Q + 1, signX := -signX }.			#
9387#									#
9388#       Step 6.  R := signX*R.						#
9389#									#
9390#       Step 7.  If Last_Subtract = true, R := R - Y.			#
9391#									#
9392#       Step 8.  Return signQ, last 7 bits of Q, and R as required.	#
9393#									#
9394#       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus,		#
9395#                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),		#
9396#                R := 0. Return signQ, last 7 bits of Q, and R.		#
9397#									#
9398#########################################################################
9399
9400	set		Mod_Flag,L_SCR3
9401	set		Sc_Flag,L_SCR3+1
9402
9403	set		SignY,L_SCR2
9404	set		SignX,L_SCR2+2
9405	set		SignQ,L_SCR3+2
9406
9407	set		Y,FP_SCR0
9408	set		Y_Hi,Y+4
9409	set		Y_Lo,Y+8
9410
9411	set		R,FP_SCR1
9412	set		R_Hi,R+4
9413	set		R_Lo,R+8
9414
9415Scale:
9416	long		0x00010000,0x80000000,0x00000000,0x00000000
9417
9418	global		smod
9419smod:
9420	clr.b		FPSR_QBYTE(%a6)
9421	mov.l		%d0,-(%sp)		# save ctrl bits
9422	clr.b		Mod_Flag(%a6)
9423	bra.b		Mod_Rem
9424
9425	global		srem
9426srem:
9427	clr.b		FPSR_QBYTE(%a6)
9428	mov.l		%d0,-(%sp)		# save ctrl bits
9429	mov.b		&0x1,Mod_Flag(%a6)
9430
9431Mod_Rem:
9432#..Save sign of X and Y
9433	movm.l		&0x3f00,-(%sp)		# save data registers
9434	mov.w		SRC_EX(%a0),%d3
9435	mov.w		%d3,SignY(%a6)
9436	and.l		&0x00007FFF,%d3		# Y := |Y|
9437
9438#
9439	mov.l		SRC_HI(%a0),%d4
9440	mov.l		SRC_LO(%a0),%d5		# (D3,D4,D5) is |Y|
9441
9442	tst.l		%d3
9443	bne.b		Y_Normal
9444
9445	mov.l		&0x00003FFE,%d3		# $3FFD + 1
9446	tst.l		%d4
9447	bne.b		HiY_not0
9448
9449HiY_0:
9450	mov.l		%d5,%d4
9451	clr.l		%d5
9452	sub.l		&32,%d3
9453	clr.l		%d6
9454	bfffo		%d4{&0:&32},%d6
9455	lsl.l		%d6,%d4
9456	sub.l		%d6,%d3			# (D3,D4,D5) is normalized
9457#	                                        ...with bias $7FFD
9458	bra.b		Chk_X
9459
9460HiY_not0:
9461	clr.l		%d6
9462	bfffo		%d4{&0:&32},%d6
9463	sub.l		%d6,%d3
9464	lsl.l		%d6,%d4
9465	mov.l		%d5,%d7			# a copy of D5
9466	lsl.l		%d6,%d5
9467	neg.l		%d6
9468	add.l		&32,%d6
9469	lsr.l		%d6,%d7
9470	or.l		%d7,%d4			# (D3,D4,D5) normalized
9471#                                       ...with bias $7FFD
9472	bra.b		Chk_X
9473
9474Y_Normal:
9475	add.l		&0x00003FFE,%d3		# (D3,D4,D5) normalized
9476#                                       ...with bias $7FFD
9477
9478Chk_X:
9479	mov.w		DST_EX(%a1),%d0
9480	mov.w		%d0,SignX(%a6)
9481	mov.w		SignY(%a6),%d1
9482	eor.l		%d0,%d1
9483	and.l		&0x00008000,%d1
9484	mov.w		%d1,SignQ(%a6)		# sign(Q) obtained
9485	and.l		&0x00007FFF,%d0
9486	mov.l		DST_HI(%a1),%d1
9487	mov.l		DST_LO(%a1),%d2		# (D0,D1,D2) is |X|
9488	tst.l		%d0
9489	bne.b		X_Normal
9490	mov.l		&0x00003FFE,%d0
9491	tst.l		%d1
9492	bne.b		HiX_not0
9493
9494HiX_0:
9495	mov.l		%d2,%d1
9496	clr.l		%d2
9497	sub.l		&32,%d0
9498	clr.l		%d6
9499	bfffo		%d1{&0:&32},%d6
9500	lsl.l		%d6,%d1
9501	sub.l		%d6,%d0			# (D0,D1,D2) is normalized
9502#                                       ...with bias $7FFD
9503	bra.b		Init
9504
9505HiX_not0:
9506	clr.l		%d6
9507	bfffo		%d1{&0:&32},%d6
9508	sub.l		%d6,%d0
9509	lsl.l		%d6,%d1
9510	mov.l		%d2,%d7			# a copy of D2
9511	lsl.l		%d6,%d2
9512	neg.l		%d6
9513	add.l		&32,%d6
9514	lsr.l		%d6,%d7
9515	or.l		%d7,%d1			# (D0,D1,D2) normalized
9516#                                       ...with bias $7FFD
9517	bra.b		Init
9518
9519X_Normal:
9520	add.l		&0x00003FFE,%d0		# (D0,D1,D2) normalized
9521#                                       ...with bias $7FFD
9522
9523Init:
9524#
9525	mov.l		%d3,L_SCR1(%a6)		# save biased exp(Y)
9526	mov.l		%d0,-(%sp)		# save biased exp(X)
9527	sub.l		%d3,%d0			# L := expo(X)-expo(Y)
9528
9529	clr.l		%d6			# D6 := carry <- 0
9530	clr.l		%d3			# D3 is Q
9531	mov.l		&0,%a1			# A1 is k; j+k=L, Q=0
9532
9533#..(Carry,D1,D2) is R
9534	tst.l		%d0
9535	bge.b		Mod_Loop_pre
9536
9537#..expo(X) < expo(Y). Thus X = mod(X,Y)
9538#
9539	mov.l		(%sp)+,%d0		# restore d0
9540	bra.w		Get_Mod
9541
9542Mod_Loop_pre:
9543	addq.l		&0x4,%sp		# erase exp(X)
9544#..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L
9545Mod_Loop:
9546	tst.l		%d6			# test carry bit
9547	bgt.b		R_GT_Y
9548
9549#..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
9550	cmp.l		%d1,%d4			# compare hi(R) and hi(Y)
9551	bne.b		R_NE_Y
9552	cmp.l		%d2,%d5			# compare lo(R) and lo(Y)
9553	bne.b		R_NE_Y
9554
9555#..At this point, R = Y
9556	bra.w		Rem_is_0
9557
9558R_NE_Y:
9559#..use the borrow of the previous compare
9560	bcs.b		R_LT_Y			# borrow is set iff R < Y
9561
9562R_GT_Y:
9563#..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
9564#..and Y < (D1,D2) < 2Y. Either way, perform R - Y
9565	sub.l		%d5,%d2			# lo(R) - lo(Y)
9566	subx.l		%d4,%d1			# hi(R) - hi(Y)
9567	clr.l		%d6			# clear carry
9568	addq.l		&1,%d3			# Q := Q + 1
9569
9570R_LT_Y:
9571#..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
9572	tst.l		%d0			# see if j = 0.
9573	beq.b		PostLoop
9574
9575	add.l		%d3,%d3			# Q := 2Q
9576	add.l		%d2,%d2			# lo(R) = 2lo(R)
9577	roxl.l		&1,%d1			# hi(R) = 2hi(R) + carry
9578	scs		%d6			# set Carry if 2(R) overflows
9579	addq.l		&1,%a1			# k := k+1
9580	subq.l		&1,%d0			# j := j - 1
9581#..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
9582
9583	bra.b		Mod_Loop
9584
9585PostLoop:
9586#..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
9587
9588#..normalize R.
9589	mov.l		L_SCR1(%a6),%d0		# new biased expo of R
9590	tst.l		%d1
9591	bne.b		HiR_not0
9592
9593HiR_0:
9594	mov.l		%d2,%d1
9595	clr.l		%d2
9596	sub.l		&32,%d0
9597	clr.l		%d6
9598	bfffo		%d1{&0:&32},%d6
9599	lsl.l		%d6,%d1
9600	sub.l		%d6,%d0			# (D0,D1,D2) is normalized
9601#                                       ...with bias $7FFD
9602	bra.b		Get_Mod
9603
9604HiR_not0:
9605	clr.l		%d6
9606	bfffo		%d1{&0:&32},%d6
9607	bmi.b		Get_Mod			# already normalized
9608	sub.l		%d6,%d0
9609	lsl.l		%d6,%d1
9610	mov.l		%d2,%d7			# a copy of D2
9611	lsl.l		%d6,%d2
9612	neg.l		%d6
9613	add.l		&32,%d6
9614	lsr.l		%d6,%d7
9615	or.l		%d7,%d1			# (D0,D1,D2) normalized
9616
9617#
9618Get_Mod:
9619	cmp.l		%d0,&0x000041FE
9620	bge.b		No_Scale
9621Do_Scale:
9622	mov.w		%d0,R(%a6)
9623	mov.l		%d1,R_Hi(%a6)
9624	mov.l		%d2,R_Lo(%a6)
9625	mov.l		L_SCR1(%a6),%d6
9626	mov.w		%d6,Y(%a6)
9627	mov.l		%d4,Y_Hi(%a6)
9628	mov.l		%d5,Y_Lo(%a6)
9629	fmov.x		R(%a6),%fp0		# no exception
9630	mov.b		&1,Sc_Flag(%a6)
9631	bra.b		ModOrRem
9632No_Scale:
9633	mov.l		%d1,R_Hi(%a6)
9634	mov.l		%d2,R_Lo(%a6)
9635	sub.l		&0x3FFE,%d0
9636	mov.w		%d0,R(%a6)
9637	mov.l		L_SCR1(%a6),%d6
9638	sub.l		&0x3FFE,%d6
9639	mov.l		%d6,L_SCR1(%a6)
9640	fmov.x		R(%a6),%fp0
9641	mov.w		%d6,Y(%a6)
9642	mov.l		%d4,Y_Hi(%a6)
9643	mov.l		%d5,Y_Lo(%a6)
9644	clr.b		Sc_Flag(%a6)
9645
9646#
9647ModOrRem:
9648	tst.b		Mod_Flag(%a6)
9649	beq.b		Fix_Sign
9650
9651	mov.l		L_SCR1(%a6),%d6		# new biased expo(Y)
9652	subq.l		&1,%d6			# biased expo(Y/2)
9653	cmp.l		%d0,%d6
9654	blt.b		Fix_Sign
9655	bgt.b		Last_Sub
9656
9657	cmp.l		%d1,%d4
9658	bne.b		Not_EQ
9659	cmp.l		%d2,%d5
9660	bne.b		Not_EQ
9661	bra.w		Tie_Case
9662
9663Not_EQ:
9664	bcs.b		Fix_Sign
9665
9666Last_Sub:
9667#
9668	fsub.x		Y(%a6),%fp0		# no exceptions
9669	addq.l		&1,%d3			# Q := Q + 1
9670
9671#
9672Fix_Sign:
9673#..Get sign of X
9674	mov.w		SignX(%a6),%d6
9675	bge.b		Get_Q
9676	fneg.x		%fp0
9677
9678#..Get Q
9679#
9680Get_Q:
9681	clr.l		%d6
9682	mov.w		SignQ(%a6),%d6		# D6 is sign(Q)
9683	mov.l		&8,%d7
9684	lsr.l		%d7,%d6
9685	and.l		&0x0000007F,%d3		# 7 bits of Q
9686	or.l		%d6,%d3			# sign and bits of Q
9687#	swap		%d3
9688#	fmov.l		%fpsr,%d6
9689#	and.l		&0xFF00FFFF,%d6
9690#	or.l		%d3,%d6
9691#	fmov.l		%d6,%fpsr		# put Q in fpsr
9692	mov.b		%d3,FPSR_QBYTE(%a6)	# put Q in fpsr
9693
9694#
9695Restore:
9696	movm.l		(%sp)+,&0xfc		#  {%d2-%d7}
9697	mov.l		(%sp)+,%d0
9698	fmov.l		%d0,%fpcr
9699	tst.b		Sc_Flag(%a6)
9700	beq.b		Finish
9701	mov.b		&FMUL_OP,%d1		# last inst is MUL
9702	fmul.x		Scale(%pc),%fp0		# may cause underflow
9703	bra		t_catch2
9704# the '040 package did this apparently to see if the dst operand for the
9705# preceding fmul was a denorm. but, it better not have been since the
9706# algorithm just got done playing with fp0 and expected no exceptions
9707# as a result. trust me...
9708#	bra		t_avoid_unsupp		# check for denorm as a
9709#						;result of the scaling
9710
9711Finish:
9712	mov.b		&FMOV_OP,%d1		# last inst is MOVE
9713	fmov.x		%fp0,%fp0		# capture exceptions & round
9714	bra		t_catch2
9715
9716Rem_is_0:
9717#..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
9718	addq.l		&1,%d3
9719	cmp.l		%d0,&8			# D0 is j
9720	bge.b		Q_Big
9721
9722	lsl.l		%d0,%d3
9723	bra.b		Set_R_0
9724
9725Q_Big:
9726	clr.l		%d3
9727
9728Set_R_0:
9729	fmov.s		&0x00000000,%fp0
9730	clr.b		Sc_Flag(%a6)
9731	bra.w		Fix_Sign
9732
9733Tie_Case:
9734#..Check parity of Q
9735	mov.l		%d3,%d6
9736	and.l		&0x00000001,%d6
9737	tst.l		%d6
9738	beq.w		Fix_Sign		# Q is even
9739
9740#..Q is odd, Q := Q + 1, signX := -signX
9741	addq.l		&1,%d3
9742	mov.w		SignX(%a6),%d6
9743	eor.l		&0x00008000,%d6
9744	mov.w		%d6,SignX(%a6)
9745	bra.w		Fix_Sign
9746
9747#########################################################################
9748# XDEF ****************************************************************	#
9749#	tag(): return the optype of the input ext fp number		#
9750#									#
9751#	This routine is used by the 060FPLSP.				#
9752#									#
9753# XREF ****************************************************************	#
9754#	None								#
9755#									#
9756# INPUT ***************************************************************	#
9757#	a0 = pointer to extended precision operand			#
9758#									#
9759# OUTPUT **************************************************************	#
9760#	d0 = value of type tag						#
9761#		one of: NORM, INF, QNAN, SNAN, DENORM, ZERO		#
9762#									#
9763# ALGORITHM ***********************************************************	#
9764#	Simply test the exponent, j-bit, and mantissa values to		#
9765# determine the type of operand.					#
9766#	If it's an unnormalized zero, alter the operand and force it	#
9767# to be a normal zero.							#
9768#									#
9769#########################################################################
9770
9771	global		tag
9772tag:
9773	mov.w		FTEMP_EX(%a0), %d0	# extract exponent
9774	andi.w		&0x7fff, %d0		# strip off sign
9775	cmpi.w		%d0, &0x7fff		# is (EXP == MAX)?
9776	beq.b		inf_or_nan_x
9777not_inf_or_nan_x:
9778	btst		&0x7,FTEMP_HI(%a0)
9779	beq.b		not_norm_x
9780is_norm_x:
9781	mov.b		&NORM, %d0
9782	rts
9783not_norm_x:
9784	tst.w		%d0			# is exponent = 0?
9785	bne.b		is_unnorm_x
9786not_unnorm_x:
9787	tst.l		FTEMP_HI(%a0)
9788	bne.b		is_denorm_x
9789	tst.l		FTEMP_LO(%a0)
9790	bne.b		is_denorm_x
9791is_zero_x:
9792	mov.b		&ZERO, %d0
9793	rts
9794is_denorm_x:
9795	mov.b		&DENORM, %d0
9796	rts
9797is_unnorm_x:
9798	bsr.l		unnorm_fix		# convert to norm,denorm,or zero
9799	rts
9800is_unnorm_reg_x:
9801	mov.b		&UNNORM, %d0
9802	rts
9803inf_or_nan_x:
9804	tst.l		FTEMP_LO(%a0)
9805	bne.b		is_nan_x
9806	mov.l		FTEMP_HI(%a0), %d0
9807	and.l		&0x7fffffff, %d0	# msb is a don't care!
9808	bne.b		is_nan_x
9809is_inf_x:
9810	mov.b		&INF, %d0
9811	rts
9812is_nan_x:
9813	mov.b		&QNAN, %d0
9814	rts
9815
9816#############################################################
9817
9818qnan:	long		0x7fff0000, 0xffffffff, 0xffffffff
9819
9820#########################################################################
9821# XDEF ****************************************************************	#
9822#	t_dz(): Handle 060FPLSP dz exception for "flogn" emulation.	#
9823#	t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation.	#
9824#									#
9825#	These rouitnes are used by the 060FPLSP package.		#
9826#									#
9827# XREF ****************************************************************	#
9828#	None								#
9829#									#
9830# INPUT ***************************************************************	#
9831#	a0 = pointer to extended precision source operand.		#
9832#									#
9833# OUTPUT **************************************************************	#
9834#	fp0 = default DZ result.					#
9835#									#
9836# ALGORITHM ***********************************************************	#
9837#	Transcendental emulation for the 060FPLSP has detected that	#
9838# a DZ exception should occur for the instruction. If DZ is disabled,	#
9839# return the default result.						#
9840#	If DZ is enabled, the dst operand should be returned unscathed	#
9841# in fp0 while fp1 is used to create a DZ exception so that the		#
9842# operating system can log that such an event occurred.			#
9843#									#
9844#########################################################################
9845
9846	global		t_dz
9847t_dz:
9848	tst.b		SRC_EX(%a0)		# check sign for neg or pos
9849	bpl.b		dz_pinf			# branch if pos sign
9850
9851	global		t_dz2
9852t_dz2:
9853	ori.l		&dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
9854
9855	btst		&dz_bit,FPCR_ENABLE(%a6)
9856	bne.b		dz_minf_ena
9857
9858# dz is disabled. return a -INF.
9859	fmov.s		&0xff800000,%fp0	# return -INF
9860	rts
9861
9862# dz is enabled. create a dz exception so the user can record it
9863# but use fp1 instead. return the dst operand unscathed in fp0.
9864dz_minf_ena:
9865	fmovm.x		EXC_FP0(%a6),&0x80	# return fp0 unscathed
9866	fmov.l		USER_FPCR(%a6),%fpcr
9867	fmov.s		&0xbf800000,%fp1	# load -1
9868	fdiv.s		&0x00000000,%fp1	# -1 / 0
9869	rts
9870
9871dz_pinf:
9872	ori.l		&dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
9873
9874	btst		&dz_bit,FPCR_ENABLE(%a6)
9875	bne.b		dz_pinf_ena
9876
9877# dz is disabled. return a +INF.
9878	fmov.s		&0x7f800000,%fp0	# return +INF
9879	rts
9880
9881# dz is enabled. create a dz exception so the user can record it
9882# but use fp1 instead. return the dst operand unscathed in fp0.
9883dz_pinf_ena:
9884	fmovm.x		EXC_FP0(%a6),&0x80	# return fp0 unscathed
9885	fmov.l		USER_FPCR(%a6),%fpcr
9886	fmov.s		&0x3f800000,%fp1	# load +1
9887	fdiv.s		&0x00000000,%fp1	# +1 / 0
9888	rts
9889
9890#########################################################################
9891# XDEF ****************************************************************	#
9892#	t_operr(): Handle 060FPLSP OPERR exception during emulation.	#
9893#									#
9894#	This routine is used by the 060FPLSP package.			#
9895#									#
9896# XREF ****************************************************************	#
9897#	None.								#
9898#									#
9899# INPUT ***************************************************************	#
9900#	fp1 = source operand						#
9901#									#
9902# OUTPUT **************************************************************	#
9903#	fp0 = default result						#
9904#	fp1 = unchanged							#
9905#									#
9906# ALGORITHM ***********************************************************	#
9907#	An operand error should occur as the result of transcendental	#
9908# emulation in the 060FPLSP. If OPERR is disabled, just return a NAN	#
9909# in fp0. If OPERR is enabled, return the dst operand unscathed in fp0	#
9910# and the source operand in fp1. Use fp2 to create an OPERR exception	#
9911# so that the operating system can log the event.			#
9912#									#
9913#########################################################################
9914
9915	global		t_operr
9916t_operr:
9917	ori.l		&opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
9918
9919	btst		&operr_bit,FPCR_ENABLE(%a6)
9920	bne.b		operr_ena
9921
9922# operr is disabled. return a QNAN in fp0
9923	fmovm.x		qnan(%pc),&0x80		# return QNAN
9924	rts
9925
9926# operr is enabled. create an operr exception so the user can record it
9927# but use fp2 instead. return the dst operand unscathed in fp0.
9928operr_ena:
9929	fmovm.x		EXC_FP0(%a6),&0x80	# return fp0 unscathed
9930	fmov.l		USER_FPCR(%a6),%fpcr
9931	fmovm.x		&0x04,-(%sp)		# save fp2
9932	fmov.s		&0x7f800000,%fp2	# load +INF
9933	fmul.s		&0x00000000,%fp2	# +INF x 0
9934	fmovm.x		(%sp)+,&0x20		# restore fp2
9935	rts
9936
9937pls_huge:
9938	long		0x7ffe0000,0xffffffff,0xffffffff
9939mns_huge:
9940	long		0xfffe0000,0xffffffff,0xffffffff
9941pls_tiny:
9942	long		0x00000000,0x80000000,0x00000000
9943mns_tiny:
9944	long		0x80000000,0x80000000,0x00000000
9945
9946#########################################################################
9947# XDEF ****************************************************************	#
9948#	t_unfl(): Handle 060FPLSP underflow exception during emulation.	#
9949#	t_unfl2(): Handle 060FPLSP underflow exception during		#
9950#	           emulation. result always positive.			#
9951#									#
9952#	This routine is used by the 060FPLSP package.			#
9953#									#
9954# XREF ****************************************************************	#
9955#	None.								#
9956#									#
9957# INPUT ***************************************************************	#
9958#	a0 = pointer to extended precision source operand		#
9959#									#
9960# OUTPUT **************************************************************	#
9961#	fp0 = default underflow result					#
9962#									#
9963# ALGORITHM ***********************************************************	#
9964#	An underflow should occur as the result of transcendental	#
9965# emulation in the 060FPLSP. Create an underflow by using "fmul"	#
9966# and two very small numbers of appropriate sign so the operating	#
9967# system can log the event.						#
9968#									#
9969#########################################################################
9970
9971	global		t_unfl
9972t_unfl:
9973	tst.b		SRC_EX(%a0)
9974	bpl.b		unf_pos
9975
9976	global		t_unfl2
9977t_unfl2:
9978	ori.l		&unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
9979
9980	fmov.l		USER_FPCR(%a6),%fpcr
9981	fmovm.x		mns_tiny(%pc),&0x80
9982	fmul.x		pls_tiny(%pc),%fp0
9983
9984	fmov.l		%fpsr,%d0
9985	rol.l		&0x8,%d0
9986	mov.b		%d0,FPSR_CC(%a6)
9987	rts
9988unf_pos:
9989	ori.w		&unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
9990
9991	fmov.l		USER_FPCR(%a6),%fpcr
9992	fmovm.x		pls_tiny(%pc),&0x80
9993	fmul.x		%fp0,%fp0
9994
9995	fmov.l		%fpsr,%d0
9996	rol.l		&0x8,%d0
9997	mov.b		%d0,FPSR_CC(%a6)
9998	rts
9999
10000#########################################################################
10001# XDEF ****************************************************************	#
10002#	t_ovfl(): Handle 060FPLSP overflow exception during emulation.	#
10003#		  (monadic)						#
10004#	t_ovfl2(): Handle 060FPLSP overflow exception during		#
10005#	           emulation. result always positive. (dyadic)		#
10006#	t_ovfl_sc(): Handle 060FPLSP overflow exception during		#
10007#	             emulation for "fscale".				#
10008#									#
10009#	This routine is used by the 060FPLSP package.			#
10010#									#
10011# XREF ****************************************************************	#
10012#	None.								#
10013#									#
10014# INPUT ***************************************************************	#
10015#	a0 = pointer to extended precision source operand		#
10016#									#
10017# OUTPUT **************************************************************	#
10018#	fp0 = default underflow result					#
10019#									#
10020# ALGORITHM ***********************************************************	#
10021#	An overflow should occur as the result of transcendental	#
10022# emulation in the 060FPLSP. Create an overflow by using "fmul"		#
10023# and two very lareg numbers of appropriate sign so the operating	#
10024# system can log the event.						#
10025#	For t_ovfl_sc() we take special care not to lose the INEX2 bit.	#
10026#									#
10027#########################################################################
10028
10029	global		t_ovfl_sc
10030t_ovfl_sc:
10031	ori.l		&ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
10032
10033	mov.b		%d0,%d1			# fetch rnd prec,mode
10034	andi.b		&0xc0,%d1		# extract prec
10035	beq.w		ovfl_work
10036
10037# dst op is a DENORM. we have to normalize the mantissa to see if the
10038# result would be inexact for the given precision. make a copy of the
10039# dst so we don't screw up the version passed to us.
10040	mov.w		LOCAL_EX(%a0),FP_SCR0_EX(%a6)
10041	mov.l		LOCAL_HI(%a0),FP_SCR0_HI(%a6)
10042	mov.l		LOCAL_LO(%a0),FP_SCR0_LO(%a6)
10043	lea		FP_SCR0(%a6),%a0	# pass ptr to FP_SCR0
10044	movm.l		&0xc080,-(%sp)		# save d0-d1/a0
10045	bsr.l		norm			# normalize mantissa
10046	movm.l		(%sp)+,&0x0103		# restore d0-d1/a0
10047
10048	cmpi.b		%d1,&0x40		# is precision sgl?
10049	bne.b		ovfl_sc_dbl		# no; dbl
10050ovfl_sc_sgl:
10051	tst.l		LOCAL_LO(%a0)		# is lo lw of sgl set?
10052	bne.b		ovfl_sc_inx		# yes
10053	tst.b		3+LOCAL_HI(%a0)		# is lo byte of hi lw set?
10054	bne.b		ovfl_sc_inx		# yes
10055	bra.w		ovfl_work		# don't set INEX2
10056ovfl_sc_dbl:
10057	mov.l		LOCAL_LO(%a0),%d1	# are any of lo 11 bits of
10058	andi.l		&0x7ff,%d1		# dbl mantissa set?
10059	beq.w		ovfl_work		# no; don't set INEX2
10060ovfl_sc_inx:
10061	ori.l		&inex2_mask,USER_FPSR(%a6) # set INEX2
10062	bra.b		ovfl_work		# continue
10063
10064	global		t_ovfl
10065t_ovfl:
10066	ori.w		&ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10067ovfl_work:
10068	tst.b		SRC_EX(%a0)
10069	bpl.b		ovfl_p
10070ovfl_m:
10071	fmov.l		USER_FPCR(%a6),%fpcr
10072	fmovm.x		mns_huge(%pc),&0x80
10073	fmul.x		pls_huge(%pc),%fp0
10074
10075	fmov.l		%fpsr,%d0
10076	rol.l		&0x8,%d0
10077	ori.b		&neg_mask,%d0
10078	mov.b		%d0,FPSR_CC(%a6)
10079	rts
10080ovfl_p:
10081	fmov.l		USER_FPCR(%a6),%fpcr
10082	fmovm.x		pls_huge(%pc),&0x80
10083	fmul.x		pls_huge(%pc),%fp0
10084
10085	fmov.l		%fpsr,%d0
10086	rol.l		&0x8,%d0
10087	mov.b		%d0,FPSR_CC(%a6)
10088	rts
10089
10090	global		t_ovfl2
10091t_ovfl2:
10092	ori.w		&ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10093	fmov.l		USER_FPCR(%a6),%fpcr
10094	fmovm.x		pls_huge(%pc),&0x80
10095	fmul.x		pls_huge(%pc),%fp0
10096
10097	fmov.l		%fpsr,%d0
10098	rol.l		&0x8,%d0
10099	mov.b		%d0,FPSR_CC(%a6)
10100	rts
10101
10102#########################################################################
10103# XDEF ****************************************************************	#
10104#	t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during	#
10105#		   emulation.						#
10106#	t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during	#
10107#		    emulation.						#
10108#									#
10109#	These routines are used by the 060FPLSP package.		#
10110#									#
10111# XREF ****************************************************************	#
10112#	None.								#
10113#									#
10114# INPUT ***************************************************************	#
10115#	fp0 = default underflow or overflow result			#
10116#									#
10117# OUTPUT **************************************************************	#
10118#	fp0 = default result						#
10119#									#
10120# ALGORITHM ***********************************************************	#
10121#	If an overflow or underflow occurred during the last		#
10122# instruction of transcendental 060FPLSP emulation, then it has already	#
10123# occurred and has been logged. Now we need to see if an inexact	#
10124# exception should occur.						#
10125#									#
10126#########################################################################
10127
10128	global		t_catch2
10129t_catch2:
10130	fmov.l		%fpsr,%d0
10131	or.l		%d0,USER_FPSR(%a6)
10132	bra.b		inx2_work
10133
10134	global		t_catch
10135t_catch:
10136	fmov.l		%fpsr,%d0
10137	or.l		%d0,USER_FPSR(%a6)
10138
10139#########################################################################
10140# XDEF ****************************************************************	#
10141#	t_inx2(): Handle inexact 060FPLSP exception during emulation.	#
10142#	t_pinx2(): Handle inexact 060FPLSP exception for "+" results.	#
10143#	t_minx2(): Handle inexact 060FPLSP exception for "-" results.	#
10144#									#
10145# XREF ****************************************************************	#
10146#	None.								#
10147#									#
10148# INPUT ***************************************************************	#
10149#	fp0 = default result						#
10150#									#
10151# OUTPUT **************************************************************	#
10152#	fp0 = default result						#
10153#									#
10154# ALGORITHM ***********************************************************	#
10155#	The last instruction of transcendental emulation for the	#
10156# 060FPLSP should be inexact. So, if inexact is enabled, then we create	#
10157# the event here by adding a large and very small number together	#
10158# so that the operating system can log the event.			#
10159#	Must check, too, if the result was zero, in which case we just	#
10160# set the FPSR bits and return.						#
10161#									#
10162#########################################################################
10163
10164	global		t_inx2
10165t_inx2:
10166	fblt.w		t_minx2
10167	fbeq.w		inx2_zero
10168
10169	global		t_pinx2
10170t_pinx2:
10171	ori.w		&inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
10172	bra.b		inx2_work
10173
10174	global		t_minx2
10175t_minx2:
10176	ori.l		&inx2a_mask+neg_mask,USER_FPSR(%a6)
10177
10178inx2_work:
10179	btst		&inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
10180	bne.b		inx2_work_ena		# yes
10181	rts
10182inx2_work_ena:
10183	fmov.l		USER_FPCR(%a6),%fpcr	# insert user's exceptions
10184	fmov.s		&0x3f800000,%fp1	# load +1
10185	fadd.x		pls_tiny(%pc),%fp1	# cause exception
10186	rts
10187
10188inx2_zero:
10189	mov.b		&z_bmask,FPSR_CC(%a6)
10190	ori.w		&inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
10191	rts
10192
10193#########################################################################
10194# XDEF ****************************************************************	#
10195#	t_extdnrm(): Handle DENORM inputs in 060FPLSP.			#
10196#	t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale".	#
10197#									#
10198#	This routine is used by the 060FPLSP package.			#
10199#									#
10200# XREF ****************************************************************	#
10201#	None.								#
10202#									#
10203# INPUT ***************************************************************	#
10204#	a0 = pointer to extended precision input operand		#
10205#									#
10206# OUTPUT **************************************************************	#
10207#	fp0 = default result						#
10208#									#
10209# ALGORITHM ***********************************************************	#
10210#	For all functions that have a denormalized input and that	#
10211# f(x)=x, this is the entry point.					#
10212#	DENORM value is moved using "fmove" which triggers an exception	#
10213# if enabled so the operating system can log the event.			#
10214#									#
10215#########################################################################
10216
10217	global		t_extdnrm
10218t_extdnrm:
10219	fmov.l		USER_FPCR(%a6),%fpcr
10220	fmov.x		SRC_EX(%a0),%fp0
10221	fmov.l		%fpsr,%d0
10222	ori.l		&unfinx_mask,%d0
10223	or.l		%d0,USER_FPSR(%a6)
10224	rts
10225
10226	global		t_resdnrm
10227t_resdnrm:
10228	fmov.l		USER_FPCR(%a6),%fpcr
10229	fmov.x		SRC_EX(%a0),%fp0
10230	fmov.l		%fpsr,%d0
10231	or.l		%d0,USER_FPSR(%a6)
10232	rts
10233
10234##########################################
10235
10236#
10237# sto_cos:
10238#	This is used by fsincos library emulation. The correct
10239# values are already in fp0 and fp1 so we do nothing here.
10240#
10241	global		sto_cos
10242sto_cos:
10243	rts
10244
10245##########################################
10246
10247#
10248#	dst_qnan --- force result when destination is a NaN
10249#
10250	global		dst_qnan
10251dst_qnan:
10252	fmov.x		DST(%a1),%fp0
10253	tst.b		DST_EX(%a1)
10254	bmi.b		dst_qnan_m
10255dst_qnan_p:
10256	mov.b		&nan_bmask,FPSR_CC(%a6)
10257	rts
10258dst_qnan_m:
10259	mov.b		&nan_bmask+neg_bmask,FPSR_CC(%a6)
10260	rts
10261
10262#
10263#	src_qnan --- force result when source is a NaN
10264#
10265	global		src_qnan
10266src_qnan:
10267	fmov.x		SRC(%a0),%fp0
10268	tst.b		SRC_EX(%a0)
10269	bmi.b		src_qnan_m
10270src_qnan_p:
10271	mov.b		&nan_bmask,FPSR_CC(%a6)
10272	rts
10273src_qnan_m:
10274	mov.b		&nan_bmask+neg_bmask,FPSR_CC(%a6)
10275	rts
10276
10277##########################################
10278
10279#
10280#	Native instruction support
10281#
10282#	Some systems may need entry points even for 68060 native
10283#	instructions.  These routines are provided for
10284#	convenience.
10285#
10286	global		_fadds_
10287_fadds_:
10288	fmov.l		%fpcr,-(%sp)		# save fpcr
10289	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10290	fmov.s		0x8(%sp),%fp0		# load sgl dst
10291	fmov.l		(%sp)+,%fpcr		# restore fpcr
10292	fadd.s		0x8(%sp),%fp0		# fadd w/ sgl src
10293	rts
10294
10295	global		_faddd_
10296_faddd_:
10297	fmov.l		%fpcr,-(%sp)		# save fpcr
10298	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10299	fmov.d		0x8(%sp),%fp0		# load dbl dst
10300	fmov.l		(%sp)+,%fpcr		# restore fpcr
10301	fadd.d		0xc(%sp),%fp0		# fadd w/ dbl src
10302	rts
10303
10304	global		_faddx_
10305_faddx_:
10306	fmovm.x		0x4(%sp),&0x80		# load ext dst
10307	fadd.x		0x10(%sp),%fp0		# fadd w/ ext src
10308	rts
10309
10310	global		_fsubs_
10311_fsubs_:
10312	fmov.l		%fpcr,-(%sp)		# save fpcr
10313	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10314	fmov.s		0x8(%sp),%fp0		# load sgl dst
10315	fmov.l		(%sp)+,%fpcr		# restore fpcr
10316	fsub.s		0x8(%sp),%fp0		# fsub w/ sgl src
10317	rts
10318
10319	global		_fsubd_
10320_fsubd_:
10321	fmov.l		%fpcr,-(%sp)		# save fpcr
10322	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10323	fmov.d		0x8(%sp),%fp0		# load dbl dst
10324	fmov.l		(%sp)+,%fpcr		# restore fpcr
10325	fsub.d		0xc(%sp),%fp0		# fsub w/ dbl src
10326	rts
10327
10328	global		_fsubx_
10329_fsubx_:
10330	fmovm.x		0x4(%sp),&0x80		# load ext dst
10331	fsub.x		0x10(%sp),%fp0		# fsub w/ ext src
10332	rts
10333
10334	global		_fmuls_
10335_fmuls_:
10336	fmov.l		%fpcr,-(%sp)		# save fpcr
10337	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10338	fmov.s		0x8(%sp),%fp0		# load sgl dst
10339	fmov.l		(%sp)+,%fpcr		# restore fpcr
10340	fmul.s		0x8(%sp),%fp0		# fmul w/ sgl src
10341	rts
10342
10343	global		_fmuld_
10344_fmuld_:
10345	fmov.l		%fpcr,-(%sp)		# save fpcr
10346	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10347	fmov.d		0x8(%sp),%fp0		# load dbl dst
10348	fmov.l		(%sp)+,%fpcr		# restore fpcr
10349	fmul.d		0xc(%sp),%fp0		# fmul w/ dbl src
10350	rts
10351
10352	global		_fmulx_
10353_fmulx_:
10354	fmovm.x		0x4(%sp),&0x80		# load ext dst
10355	fmul.x		0x10(%sp),%fp0		# fmul w/ ext src
10356	rts
10357
10358	global		_fdivs_
10359_fdivs_:
10360	fmov.l		%fpcr,-(%sp)		# save fpcr
10361	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10362	fmov.s		0x8(%sp),%fp0		# load sgl dst
10363	fmov.l		(%sp)+,%fpcr		# restore fpcr
10364	fdiv.s		0x8(%sp),%fp0		# fdiv w/ sgl src
10365	rts
10366
10367	global		_fdivd_
10368_fdivd_:
10369	fmov.l		%fpcr,-(%sp)		# save fpcr
10370	fmov.l		&0x00000000,%fpcr	# clear fpcr for load
10371	fmov.d		0x8(%sp),%fp0		# load dbl dst
10372	fmov.l		(%sp)+,%fpcr		# restore fpcr
10373	fdiv.d		0xc(%sp),%fp0		# fdiv w/ dbl src
10374	rts
10375
10376	global		_fdivx_
10377_fdivx_:
10378	fmovm.x		0x4(%sp),&0x80		# load ext dst
10379	fdiv.x		0x10(%sp),%fp0		# fdiv w/ ext src
10380	rts
10381
10382	global		_fabss_
10383_fabss_:
10384	fabs.s		0x4(%sp),%fp0		# fabs w/ sgl src
10385	rts
10386
10387	global		_fabsd_
10388_fabsd_:
10389	fabs.d		0x4(%sp),%fp0		# fabs w/ dbl src
10390	rts
10391
10392	global		_fabsx_
10393_fabsx_:
10394	fabs.x		0x4(%sp),%fp0		# fabs w/ ext src
10395	rts
10396
10397	global		_fnegs_
10398_fnegs_:
10399	fneg.s		0x4(%sp),%fp0		# fneg w/ sgl src
10400	rts
10401
10402	global		_fnegd_
10403_fnegd_:
10404	fneg.d		0x4(%sp),%fp0		# fneg w/ dbl src
10405	rts
10406
10407	global		_fnegx_
10408_fnegx_:
10409	fneg.x		0x4(%sp),%fp0		# fneg w/ ext src
10410	rts
10411
10412	global		_fsqrts_
10413_fsqrts_:
10414	fsqrt.s		0x4(%sp),%fp0		# fsqrt w/ sgl src
10415	rts
10416
10417	global		_fsqrtd_
10418_fsqrtd_:
10419	fsqrt.d		0x4(%sp),%fp0		# fsqrt w/ dbl src
10420	rts
10421
10422	global		_fsqrtx_
10423_fsqrtx_:
10424	fsqrt.x		0x4(%sp),%fp0		# fsqrt w/ ext src
10425	rts
10426
10427	global		_fints_
10428_fints_:
10429	fint.s		0x4(%sp),%fp0		# fint w/ sgl src
10430	rts
10431
10432	global		_fintd_
10433_fintd_:
10434	fint.d		0x4(%sp),%fp0		# fint w/ dbl src
10435	rts
10436
10437	global		_fintx_
10438_fintx_:
10439	fint.x		0x4(%sp),%fp0		# fint w/ ext src
10440	rts
10441
10442	global		_fintrzs_
10443_fintrzs_:
10444	fintrz.s	0x4(%sp),%fp0		# fintrz w/ sgl src
10445	rts
10446
10447	global		_fintrzd_
10448_fintrzd_:
10449	fintrz.d	0x4(%sp),%fp0		# fintrx w/ dbl src
10450	rts
10451
10452	global		_fintrzx_
10453_fintrzx_:
10454	fintrz.x	0x4(%sp),%fp0		# fintrz w/ ext src
10455	rts
10456
10457########################################################################
10458
10459#########################################################################
10460# src_zero(): Return signed zero according to sign of src operand.	#
10461#########################################################################
10462	global		src_zero
10463src_zero:
10464	tst.b		SRC_EX(%a0)		# get sign of src operand
10465	bmi.b		ld_mzero		# if neg, load neg zero
10466
10467#
10468# ld_pzero(): return a positive zero.
10469#
10470	global		ld_pzero
10471ld_pzero:
10472	fmov.s		&0x00000000,%fp0	# load +0
10473	mov.b		&z_bmask,FPSR_CC(%a6)	# set 'Z' ccode bit
10474	rts
10475
10476# ld_mzero(): return a negative zero.
10477	global		ld_mzero
10478ld_mzero:
10479	fmov.s		&0x80000000,%fp0	# load -0
10480	mov.b		&neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
10481	rts
10482
10483#########################################################################
10484# dst_zero(): Return signed zero according to sign of dst operand.	#
10485#########################################################################
10486	global		dst_zero
10487dst_zero:
10488	tst.b		DST_EX(%a1)		# get sign of dst operand
10489	bmi.b		ld_mzero		# if neg, load neg zero
10490	bra.b		ld_pzero		# load positive zero
10491
10492#########################################################################
10493# src_inf(): Return signed inf according to sign of src operand.	#
10494#########################################################################
10495	global		src_inf
10496src_inf:
10497	tst.b		SRC_EX(%a0)		# get sign of src operand
10498	bmi.b		ld_minf			# if negative branch
10499
10500#
10501# ld_pinf(): return a positive infinity.
10502#
10503	global		ld_pinf
10504ld_pinf:
10505	fmov.s		&0x7f800000,%fp0	# load +INF
10506	mov.b		&inf_bmask,FPSR_CC(%a6)	# set 'INF' ccode bit
10507	rts
10508
10509#
10510# ld_minf():return a negative infinity.
10511#
10512	global		ld_minf
10513ld_minf:
10514	fmov.s		&0xff800000,%fp0	# load -INF
10515	mov.b		&neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
10516	rts
10517
10518#########################################################################
10519# dst_inf(): Return signed inf according to sign of dst operand.	#
10520#########################################################################
10521	global		dst_inf
10522dst_inf:
10523	tst.b		DST_EX(%a1)		# get sign of dst operand
10524	bmi.b		ld_minf			# if negative branch
10525	bra.b		ld_pinf
10526
10527	global		szr_inf
10528#################################################################
10529# szr_inf(): Return +ZERO for a negative src operand or		#
10530#	            +INF for a positive src operand.		#
10531#	     Routine used for fetox, ftwotox, and ftentox.	#
10532#################################################################
10533szr_inf:
10534	tst.b		SRC_EX(%a0)		# check sign of source
10535	bmi.b		ld_pzero
10536	bra.b		ld_pinf
10537
10538#########################################################################
10539# sopr_inf(): Return +INF for a positive src operand or			#
10540#	      jump to operand error routine for a negative src operand.	#
10541#	      Routine used for flogn, flognp1, flog10, and flog2.	#
10542#########################################################################
10543	global		sopr_inf
10544sopr_inf:
10545	tst.b		SRC_EX(%a0)		# check sign of source
10546	bmi.w		t_operr
10547	bra.b		ld_pinf
10548
10549#################################################################
10550# setoxm1i(): Return minus one for a negative src operand or	#
10551#	      positive infinity for a positive src operand.	#
10552#	      Routine used for fetoxm1.				#
10553#################################################################
10554	global		setoxm1i
10555setoxm1i:
10556	tst.b		SRC_EX(%a0)		# check sign of source
10557	bmi.b		ld_mone
10558	bra.b		ld_pinf
10559
10560#########################################################################
10561# src_one(): Return signed one according to sign of src operand.	#
10562#########################################################################
10563	global		src_one
10564src_one:
10565	tst.b		SRC_EX(%a0)		# check sign of source
10566	bmi.b		ld_mone
10567
10568#
10569# ld_pone(): return positive one.
10570#
10571	global		ld_pone
10572ld_pone:
10573	fmov.s		&0x3f800000,%fp0	# load +1
10574	clr.b		FPSR_CC(%a6)
10575	rts
10576
10577#
10578# ld_mone(): return negative one.
10579#
10580	global		ld_mone
10581ld_mone:
10582	fmov.s		&0xbf800000,%fp0	# load -1
10583	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' ccode bit
10584	rts
10585
10586ppiby2:	long		0x3fff0000, 0xc90fdaa2, 0x2168c235
10587mpiby2:	long		0xbfff0000, 0xc90fdaa2, 0x2168c235
10588
10589#################################################################
10590# spi_2(): Return signed PI/2 according to sign of src operand.	#
10591#################################################################
10592	global		spi_2
10593spi_2:
10594	tst.b		SRC_EX(%a0)		# check sign of source
10595	bmi.b		ld_mpi2
10596
10597#
10598# ld_ppi2(): return positive PI/2.
10599#
10600	global		ld_ppi2
10601ld_ppi2:
10602	fmov.l		%d0,%fpcr
10603	fmov.x		ppiby2(%pc),%fp0	# load +pi/2
10604	bra.w		t_pinx2			# set INEX2
10605
10606#
10607# ld_mpi2(): return negative PI/2.
10608#
10609	global		ld_mpi2
10610ld_mpi2:
10611	fmov.l		%d0,%fpcr
10612	fmov.x		mpiby2(%pc),%fp0	# load -pi/2
10613	bra.w		t_minx2			# set INEX2
10614
10615####################################################
10616# The following routines give support for fsincos. #
10617####################################################
10618
10619#
10620# ssincosz(): When the src operand is ZERO, store a one in the
10621#	      cosine register and return a ZERO in fp0 w/ the same sign
10622#	      as the src operand.
10623#
10624	global		ssincosz
10625ssincosz:
10626	fmov.s		&0x3f800000,%fp1
10627	tst.b		SRC_EX(%a0)		# test sign
10628	bpl.b		sincoszp
10629	fmov.s		&0x80000000,%fp0	# return sin result in fp0
10630	mov.b		&z_bmask+neg_bmask,FPSR_CC(%a6)
10631	rts
10632sincoszp:
10633	fmov.s		&0x00000000,%fp0	# return sin result in fp0
10634	mov.b		&z_bmask,FPSR_CC(%a6)
10635	rts
10636
10637#
10638# ssincosi(): When the src operand is INF, store a QNAN in the cosine
10639#	      register and jump to the operand error routine for negative
10640#	      src operands.
10641#
10642	global		ssincosi
10643ssincosi:
10644	fmov.x		qnan(%pc),%fp1		# load NAN
10645	bra.w		t_operr
10646
10647#
10648# ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
10649#		 register and branch to the src QNAN routine.
10650#
10651	global		ssincosqnan
10652ssincosqnan:
10653	fmov.x		LOCAL_EX(%a0),%fp1
10654	bra.w		src_qnan
10655
10656########################################################################
10657
10658	global		smod_sdnrm
10659	global		smod_snorm
10660smod_sdnrm:
10661smod_snorm:
10662	mov.b		DTAG(%a6),%d1
10663	beq.l		smod
10664	cmpi.b		%d1,&ZERO
10665	beq.w		smod_zro
10666	cmpi.b		%d1,&INF
10667	beq.l		t_operr
10668	cmpi.b		%d1,&DENORM
10669	beq.l		smod
10670	bra.l		dst_qnan
10671
10672	global		smod_szero
10673smod_szero:
10674	mov.b		DTAG(%a6),%d1
10675	beq.l		t_operr
10676	cmpi.b		%d1,&ZERO
10677	beq.l		t_operr
10678	cmpi.b		%d1,&INF
10679	beq.l		t_operr
10680	cmpi.b		%d1,&DENORM
10681	beq.l		t_operr
10682	bra.l		dst_qnan
10683
10684	global		smod_sinf
10685smod_sinf:
10686	mov.b		DTAG(%a6),%d1
10687	beq.l		smod_fpn
10688	cmpi.b		%d1,&ZERO
10689	beq.l		smod_zro
10690	cmpi.b		%d1,&INF
10691	beq.l		t_operr
10692	cmpi.b		%d1,&DENORM
10693	beq.l		smod_fpn
10694	bra.l		dst_qnan
10695
10696smod_zro:
10697srem_zro:
10698	mov.b		SRC_EX(%a0),%d1		# get src sign
10699	mov.b		DST_EX(%a1),%d0		# get dst sign
10700	eor.b		%d0,%d1			# get qbyte sign
10701	andi.b		&0x80,%d1
10702	mov.b		%d1,FPSR_QBYTE(%a6)
10703	tst.b		%d0
10704	bpl.w		ld_pzero
10705	bra.w		ld_mzero
10706
10707smod_fpn:
10708srem_fpn:
10709	clr.b		FPSR_QBYTE(%a6)
10710	mov.l		%d0,-(%sp)
10711	mov.b		SRC_EX(%a0),%d1		# get src sign
10712	mov.b		DST_EX(%a1),%d0		# get dst sign
10713	eor.b		%d0,%d1			# get qbyte sign
10714	andi.b		&0x80,%d1
10715	mov.b		%d1,FPSR_QBYTE(%a6)
10716	cmpi.b		DTAG(%a6),&DENORM
10717	bne.b		smod_nrm
10718	lea		DST(%a1),%a0
10719	mov.l		(%sp)+,%d0
10720	bra		t_resdnrm
10721smod_nrm:
10722	fmov.l		(%sp)+,%fpcr
10723	fmov.x		DST(%a1),%fp0
10724	tst.b		DST_EX(%a1)
10725	bmi.b		smod_nrm_neg
10726	rts
10727
10728smod_nrm_neg:
10729	mov.b		&neg_bmask,FPSR_CC(%a6)	# set 'N' code
10730	rts
10731
10732#########################################################################
10733	global		srem_snorm
10734	global		srem_sdnrm
10735srem_sdnrm:
10736srem_snorm:
10737	mov.b		DTAG(%a6),%d1
10738	beq.l		srem
10739	cmpi.b		%d1,&ZERO
10740	beq.w		srem_zro
10741	cmpi.b		%d1,&INF
10742	beq.l		t_operr
10743	cmpi.b		%d1,&DENORM
10744	beq.l		srem
10745	bra.l		dst_qnan
10746
10747	global		srem_szero
10748srem_szero:
10749	mov.b		DTAG(%a6),%d1
10750	beq.l		t_operr
10751	cmpi.b		%d1,&ZERO
10752	beq.l		t_operr
10753	cmpi.b		%d1,&INF
10754	beq.l		t_operr
10755	cmpi.b		%d1,&DENORM
10756	beq.l		t_operr
10757	bra.l		dst_qnan
10758
10759	global		srem_sinf
10760srem_sinf:
10761	mov.b		DTAG(%a6),%d1
10762	beq.w		srem_fpn
10763	cmpi.b		%d1,&ZERO
10764	beq.w		srem_zro
10765	cmpi.b		%d1,&INF
10766	beq.l		t_operr
10767	cmpi.b		%d1,&DENORM
10768	beq.l		srem_fpn
10769	bra.l		dst_qnan
10770
10771#########################################################################
10772
10773	global		sscale_snorm
10774	global		sscale_sdnrm
10775sscale_snorm:
10776sscale_sdnrm:
10777	mov.b		DTAG(%a6),%d1
10778	beq.l		sscale
10779	cmpi.b		%d1,&ZERO
10780	beq.l		dst_zero
10781	cmpi.b		%d1,&INF
10782	beq.l		dst_inf
10783	cmpi.b		%d1,&DENORM
10784	beq.l		sscale
10785	bra.l		dst_qnan
10786
10787	global		sscale_szero
10788sscale_szero:
10789	mov.b		DTAG(%a6),%d1
10790	beq.l		sscale
10791	cmpi.b		%d1,&ZERO
10792	beq.l		dst_zero
10793	cmpi.b		%d1,&INF
10794	beq.l		dst_inf
10795	cmpi.b		%d1,&DENORM
10796	beq.l		sscale
10797	bra.l		dst_qnan
10798
10799	global		sscale_sinf
10800sscale_sinf:
10801	mov.b		DTAG(%a6),%d1
10802	beq.l		t_operr
10803	cmpi.b		%d1,&QNAN
10804	beq.l		dst_qnan
10805	bra.l		t_operr
10806
10807########################################################################
10808
10809	global		sop_sqnan
10810sop_sqnan:
10811	mov.b		DTAG(%a6),%d1
10812	cmpi.b		%d1,&QNAN
10813	beq.l		dst_qnan
10814	bra.l		src_qnan
10815
10816#########################################################################
10817# norm(): normalize the mantissa of an extended precision input. the	#
10818#	  input operand should not be normalized already.		#
10819#									#
10820# XDEF ****************************************************************	#
10821#	norm()								#
10822#									#
10823# XREF **************************************************************** #
10824#	none								#
10825#									#
10826# INPUT *************************************************************** #
10827#	a0 = pointer fp extended precision operand to normalize		#
10828#									#
10829# OUTPUT ************************************************************** #
10830#	d0 = number of bit positions the mantissa was shifted		#
10831#	a0 = the input operand's mantissa is normalized; the exponent	#
10832#	     is unchanged.						#
10833#									#
10834#########################################################################
10835	global		norm
10836norm:
10837	mov.l		%d2, -(%sp)		# create some temp regs
10838	mov.l		%d3, -(%sp)
10839
10840	mov.l		FTEMP_HI(%a0), %d0	# load hi(mantissa)
10841	mov.l		FTEMP_LO(%a0), %d1	# load lo(mantissa)
10842
10843	bfffo		%d0{&0:&32}, %d2	# how many places to shift?
10844	beq.b		norm_lo			# hi(man) is all zeroes!
10845
10846norm_hi:
10847	lsl.l		%d2, %d0		# left shift hi(man)
10848	bfextu		%d1{&0:%d2}, %d3	# extract lo bits
10849
10850	or.l		%d3, %d0		# create hi(man)
10851	lsl.l		%d2, %d1		# create lo(man)
10852
10853	mov.l		%d0, FTEMP_HI(%a0)	# store new hi(man)
10854	mov.l		%d1, FTEMP_LO(%a0)	# store new lo(man)
10855
10856	mov.l		%d2, %d0		# return shift amount
10857
10858	mov.l		(%sp)+, %d3		# restore temp regs
10859	mov.l		(%sp)+, %d2
10860
10861	rts
10862
10863norm_lo:
10864	bfffo		%d1{&0:&32}, %d2	# how many places to shift?
10865	lsl.l		%d2, %d1		# shift lo(man)
10866	add.l		&32, %d2		# add 32 to shft amount
10867
10868	mov.l		%d1, FTEMP_HI(%a0)	# store hi(man)
10869	clr.l		FTEMP_LO(%a0)		# lo(man) is now zero
10870
10871	mov.l		%d2, %d0		# return shift amount
10872
10873	mov.l		(%sp)+, %d3		# restore temp regs
10874	mov.l		(%sp)+, %d2
10875
10876	rts
10877
10878#########################################################################
10879# unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO	#
10880#		- returns corresponding optype tag			#
10881#									#
10882# XDEF ****************************************************************	#
10883#	unnorm_fix()							#
10884#									#
10885# XREF **************************************************************** #
10886#	norm() - normalize the mantissa					#
10887#									#
10888# INPUT *************************************************************** #
10889#	a0 = pointer to unnormalized extended precision number		#
10890#									#
10891# OUTPUT ************************************************************** #
10892#	d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO	#
10893#	a0 = input operand has been converted to a norm, denorm, or	#
10894#	     zero; both the exponent and mantissa are changed.		#
10895#									#
10896#########################################################################
10897
10898	global		unnorm_fix
10899unnorm_fix:
10900	bfffo		FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
10901	bne.b		unnorm_shift		# hi(man) is not all zeroes
10902
10903#
10904# hi(man) is all zeroes so see if any bits in lo(man) are set
10905#
10906unnorm_chk_lo:
10907	bfffo		FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
10908	beq.w		unnorm_zero		# yes
10909
10910	add.w		&32, %d0		# no; fix shift distance
10911
10912#
10913# d0 = # shifts needed for complete normalization
10914#
10915unnorm_shift:
10916	clr.l		%d1			# clear top word
10917	mov.w		FTEMP_EX(%a0), %d1	# extract exponent
10918	and.w		&0x7fff, %d1		# strip off sgn
10919
10920	cmp.w		%d0, %d1		# will denorm push exp < 0?
10921	bgt.b		unnorm_nrm_zero		# yes; denorm only until exp = 0
10922
10923#
10924# exponent would not go < 0. therefore, number stays normalized
10925#
10926	sub.w		%d0, %d1		# shift exponent value
10927	mov.w		FTEMP_EX(%a0), %d0	# load old exponent
10928	and.w		&0x8000, %d0		# save old sign
10929	or.w		%d0, %d1		# {sgn,new exp}
10930	mov.w		%d1, FTEMP_EX(%a0)	# insert new exponent
10931
10932	bsr.l		norm			# normalize UNNORM
10933
10934	mov.b		&NORM, %d0		# return new optype tag
10935	rts
10936
10937#
10938# exponent would go < 0, so only denormalize until exp = 0
10939#
10940unnorm_nrm_zero:
10941	cmp.b		%d1, &32		# is exp <= 32?
10942	bgt.b		unnorm_nrm_zero_lrg	# no; go handle large exponent
10943
10944	bfextu		FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
10945	mov.l		%d0, FTEMP_HI(%a0)	# save new hi(man)
10946
10947	mov.l		FTEMP_LO(%a0), %d0	# fetch old lo(man)
10948	lsl.l		%d1, %d0		# extract new lo(man)
10949	mov.l		%d0, FTEMP_LO(%a0)	# save new lo(man)
10950
10951	and.w		&0x8000, FTEMP_EX(%a0)	# set exp = 0
10952
10953	mov.b		&DENORM, %d0		# return new optype tag
10954	rts
10955
10956#
10957# only mantissa bits set are in lo(man)
10958#
10959unnorm_nrm_zero_lrg:
10960	sub.w		&32, %d1		# adjust shft amt by 32
10961
10962	mov.l		FTEMP_LO(%a0), %d0	# fetch old lo(man)
10963	lsl.l		%d1, %d0		# left shift lo(man)
10964
10965	mov.l		%d0, FTEMP_HI(%a0)	# store new hi(man)
10966	clr.l		FTEMP_LO(%a0)		# lo(man) = 0
10967
10968	and.w		&0x8000, FTEMP_EX(%a0)	# set exp = 0
10969
10970	mov.b		&DENORM, %d0		# return new optype tag
10971	rts
10972
10973#
10974# whole mantissa is zero so this UNNORM is actually a zero
10975#
10976unnorm_zero:
10977	and.w		&0x8000, FTEMP_EX(%a0)	# force exponent to zero
10978
10979	mov.b		&ZERO, %d0		# fix optype tag
10980	rts
10981