Test initialisation of MUIA_List_AdjustWidth and MUIA_List_AdjustHeight, and
[AROS.git] / arch / m68k-all / m680x0 / 060sp / dist / fplsp.s
blob1b84b39d8eb98181f3a4ba7eb7733d249f9cffb0
2 # $NetBSD: fplsp.s,v 1.2 2003/02/05 00:02:32 perry Exp $
5 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 # MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
7 # M68000 Hi-Performance Microprocessor Division
8 # M68060 Software Package Production Release
9 #
10 # M68060 Software Package Copyright (C) 1993, 1994, 1995, 1996 Motorola Inc.
11 # All rights reserved.
13 # THE SOFTWARE is provided on an "AS IS" basis and without warranty.
14 # To the maximum extent permitted by applicable law,
15 # MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
16 # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
17 # FOR A PARTICULAR PURPOSE and any warranty against infringement with
18 # regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
19 # and any accompanying written materials.
21 # To the maximum extent permitted by applicable law,
22 # IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
23 # (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
24 # BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
25 # ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
27 # Motorola assumes no responsibility for the maintenance and support
28 # of the SOFTWARE.
30 # You are hereby granted a copyright license to use, modify, and distribute the
31 # SOFTWARE so long as this entire notice is retained without alteration
32 # in any modified and/or redistributed versions, and that such modified
33 # versions are clearly identified as such.
34 # No licenses are granted by implication, estoppel or otherwise under any
35 # patents or trademarks of Motorola, Inc.
36 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 # lfptop.s:
40 # This file is appended to the top of the 060ILSP package
41 # and contains the entry points into the package. The user, in
42 # effect, branches to one of the branch table entries located here.
45 bra.l _facoss_
46 short 0x0000
47 bra.l _facosd_
48 short 0x0000
49 bra.l _facosx_
50 short 0x0000
52 bra.l _fasins_
53 short 0x0000
54 bra.l _fasind_
55 short 0x0000
56 bra.l _fasinx_
57 short 0x0000
59 bra.l _fatans_
60 short 0x0000
61 bra.l _fatand_
62 short 0x0000
63 bra.l _fatanx_
64 short 0x0000
66 bra.l _fatanhs_
67 short 0x0000
68 bra.l _fatanhd_
69 short 0x0000
70 bra.l _fatanhx_
71 short 0x0000
73 bra.l _fcoss_
74 short 0x0000
75 bra.l _fcosd_
76 short 0x0000
77 bra.l _fcosx_
78 short 0x0000
80 bra.l _fcoshs_
81 short 0x0000
82 bra.l _fcoshd_
83 short 0x0000
84 bra.l _fcoshx_
85 short 0x0000
87 bra.l _fetoxs_
88 short 0x0000
89 bra.l _fetoxd_
90 short 0x0000
91 bra.l _fetoxx_
92 short 0x0000
94 bra.l _fetoxm1s_
95 short 0x0000
96 bra.l _fetoxm1d_
97 short 0x0000
98 bra.l _fetoxm1x_
99 short 0x0000
101 bra.l _fgetexps_
102 short 0x0000
103 bra.l _fgetexpd_
104 short 0x0000
105 bra.l _fgetexpx_
106 short 0x0000
108 bra.l _fgetmans_
109 short 0x0000
110 bra.l _fgetmand_
111 short 0x0000
112 bra.l _fgetmanx_
113 short 0x0000
115 bra.l _flog10s_
116 short 0x0000
117 bra.l _flog10d_
118 short 0x0000
119 bra.l _flog10x_
120 short 0x0000
122 bra.l _flog2s_
123 short 0x0000
124 bra.l _flog2d_
125 short 0x0000
126 bra.l _flog2x_
127 short 0x0000
129 bra.l _flogns_
130 short 0x0000
131 bra.l _flognd_
132 short 0x0000
133 bra.l _flognx_
134 short 0x0000
136 bra.l _flognp1s_
137 short 0x0000
138 bra.l _flognp1d_
139 short 0x0000
140 bra.l _flognp1x_
141 short 0x0000
143 bra.l _fmods_
144 short 0x0000
145 bra.l _fmodd_
146 short 0x0000
147 bra.l _fmodx_
148 short 0x0000
150 bra.l _frems_
151 short 0x0000
152 bra.l _fremd_
153 short 0x0000
154 bra.l _fremx_
155 short 0x0000
157 bra.l _fscales_
158 short 0x0000
159 bra.l _fscaled_
160 short 0x0000
161 bra.l _fscalex_
162 short 0x0000
164 bra.l _fsins_
165 short 0x0000
166 bra.l _fsind_
167 short 0x0000
168 bra.l _fsinx_
169 short 0x0000
171 bra.l _fsincoss_
172 short 0x0000
173 bra.l _fsincosd_
174 short 0x0000
175 bra.l _fsincosx_
176 short 0x0000
178 bra.l _fsinhs_
179 short 0x0000
180 bra.l _fsinhd_
181 short 0x0000
182 bra.l _fsinhx_
183 short 0x0000
185 bra.l _ftans_
186 short 0x0000
187 bra.l _ftand_
188 short 0x0000
189 bra.l _ftanx_
190 short 0x0000
192 bra.l _ftanhs_
193 short 0x0000
194 bra.l _ftanhd_
195 short 0x0000
196 bra.l _ftanhx_
197 short 0x0000
199 bra.l _ftentoxs_
200 short 0x0000
201 bra.l _ftentoxd_
202 short 0x0000
203 bra.l _ftentoxx_
204 short 0x0000
206 bra.l _ftwotoxs_
207 short 0x0000
208 bra.l _ftwotoxd_
209 short 0x0000
210 bra.l _ftwotoxx_
211 short 0x0000
213 bra.l _fabss_
214 short 0x0000
215 bra.l _fabsd_
216 short 0x0000
217 bra.l _fabsx_
218 short 0x0000
220 bra.l _fadds_
221 short 0x0000
222 bra.l _faddd_
223 short 0x0000
224 bra.l _faddx_
225 short 0x0000
227 bra.l _fdivs_
228 short 0x0000
229 bra.l _fdivd_
230 short 0x0000
231 bra.l _fdivx_
232 short 0x0000
234 bra.l _fints_
235 short 0x0000
236 bra.l _fintd_
237 short 0x0000
238 bra.l _fintx_
239 short 0x0000
241 bra.l _fintrzs_
242 short 0x0000
243 bra.l _fintrzd_
244 short 0x0000
245 bra.l _fintrzx_
246 short 0x0000
248 bra.l _fmuls_
249 short 0x0000
250 bra.l _fmuld_
251 short 0x0000
252 bra.l _fmulx_
253 short 0x0000
255 bra.l _fnegs_
256 short 0x0000
257 bra.l _fnegd_
258 short 0x0000
259 bra.l _fnegx_
260 short 0x0000
262 bra.l _fsqrts_
263 short 0x0000
264 bra.l _fsqrtd_
265 short 0x0000
266 bra.l _fsqrtx_
267 short 0x0000
269 bra.l _fsubs_
270 short 0x0000
271 bra.l _fsubd_
272 short 0x0000
273 bra.l _fsubx_
274 short 0x0000
276 # leave room for future possible additions
277 align 0x400
280 # This file contains a set of define statements for constants
281 # in order to promote readability within the corecode itself.
284 set LOCAL_SIZE, 192 # stack frame size(bytes)
285 set LV, -LOCAL_SIZE # stack offset
287 set EXC_SR, 0x4 # stack status register
288 set EXC_PC, 0x6 # stack pc
289 set EXC_VOFF, 0xa # stacked vector offset
290 set EXC_EA, 0xc # stacked <ea>
292 set EXC_FP, 0x0 # frame pointer
294 set EXC_AREGS, -68 # offset of all address regs
295 set EXC_DREGS, -100 # offset of all data regs
296 set EXC_FPREGS, -36 # offset of all fp regs
298 set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
299 set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
300 set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
301 set EXC_A5, EXC_AREGS+(5*4)
302 set EXC_A4, EXC_AREGS+(4*4)
303 set EXC_A3, EXC_AREGS+(3*4)
304 set EXC_A2, EXC_AREGS+(2*4)
305 set EXC_A1, EXC_AREGS+(1*4)
306 set EXC_A0, EXC_AREGS+(0*4)
307 set EXC_D7, EXC_DREGS+(7*4)
308 set EXC_D6, EXC_DREGS+(6*4)
309 set EXC_D5, EXC_DREGS+(5*4)
310 set EXC_D4, EXC_DREGS+(4*4)
311 set EXC_D3, EXC_DREGS+(3*4)
312 set EXC_D2, EXC_DREGS+(2*4)
313 set EXC_D1, EXC_DREGS+(1*4)
314 set EXC_D0, EXC_DREGS+(0*4)
316 set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
317 set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
318 set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
320 set FP_SCR1, LV+80 # fp scratch 1
321 set FP_SCR1_EX, FP_SCR1+0
322 set FP_SCR1_SGN, FP_SCR1+2
323 set FP_SCR1_HI, FP_SCR1+4
324 set FP_SCR1_LO, FP_SCR1+8
326 set FP_SCR0, LV+68 # fp scratch 0
327 set FP_SCR0_EX, FP_SCR0+0
328 set FP_SCR0_SGN, FP_SCR0+2
329 set FP_SCR0_HI, FP_SCR0+4
330 set FP_SCR0_LO, FP_SCR0+8
332 set FP_DST, LV+56 # fp destination operand
333 set FP_DST_EX, FP_DST+0
334 set FP_DST_SGN, FP_DST+2
335 set FP_DST_HI, FP_DST+4
336 set FP_DST_LO, FP_DST+8
338 set FP_SRC, LV+44 # fp source operand
339 set FP_SRC_EX, FP_SRC+0
340 set FP_SRC_SGN, FP_SRC+2
341 set FP_SRC_HI, FP_SRC+4
342 set FP_SRC_LO, FP_SRC+8
344 set USER_FPIAR, LV+40 # FP instr address register
346 set USER_FPSR, LV+36 # FP status register
347 set FPSR_CC, USER_FPSR+0 # FPSR condition codes
348 set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
349 set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
350 set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
352 set USER_FPCR, LV+32 # FP control register
353 set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
354 set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
356 set L_SCR3, LV+28 # integer scratch 3
357 set L_SCR2, LV+24 # integer scratch 2
358 set L_SCR1, LV+20 # integer scratch 1
360 set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
362 set EXC_TEMP2, LV+24 # temporary space
363 set EXC_TEMP, LV+16 # temporary space
365 set DTAG, LV+15 # destination operand type
366 set STAG, LV+14 # source operand type
368 set SPCOND_FLG, LV+10 # flag: special case (see below)
370 set EXC_CC, LV+8 # saved condition codes
371 set EXC_EXTWPTR, LV+4 # saved current PC (active)
372 set EXC_EXTWORD, LV+2 # saved extension word
373 set EXC_CMDREG, LV+2 # saved extension word
374 set EXC_OPWORD, LV+0 # saved operation word
376 ################################
378 # Helpful macros
380 set FTEMP, 0 # offsets within an
381 set FTEMP_EX, 0 # extended precision
382 set FTEMP_SGN, 2 # value saved in memory.
383 set FTEMP_HI, 4
384 set FTEMP_LO, 8
385 set FTEMP_GRS, 12
387 set LOCAL, 0 # offsets within an
388 set LOCAL_EX, 0 # extended precision
389 set LOCAL_SGN, 2 # value saved in memory.
390 set LOCAL_HI, 4
391 set LOCAL_LO, 8
392 set LOCAL_GRS, 12
394 set DST, 0 # offsets within an
395 set DST_EX, 0 # extended precision
396 set DST_HI, 4 # value saved in memory.
397 set DST_LO, 8
399 set SRC, 0 # offsets within an
400 set SRC_EX, 0 # extended precision
401 set SRC_HI, 4 # value saved in memory.
402 set SRC_LO, 8
404 set SGL_LO, 0x3f81 # min sgl prec exponent
405 set SGL_HI, 0x407e # max sgl prec exponent
406 set DBL_LO, 0x3c01 # min dbl prec exponent
407 set DBL_HI, 0x43fe # max dbl prec exponent
408 set EXT_LO, 0x0 # min ext prec exponent
409 set EXT_HI, 0x7ffe # max ext prec exponent
411 set EXT_BIAS, 0x3fff # extended precision bias
412 set SGL_BIAS, 0x007f # single precision bias
413 set DBL_BIAS, 0x03ff # double precision bias
415 set NORM, 0x00 # operand type for STAG/DTAG
416 set ZERO, 0x01 # operand type for STAG/DTAG
417 set INF, 0x02 # operand type for STAG/DTAG
418 set QNAN, 0x03 # operand type for STAG/DTAG
419 set DENORM, 0x04 # operand type for STAG/DTAG
420 set SNAN, 0x05 # operand type for STAG/DTAG
421 set UNNORM, 0x06 # operand type for STAG/DTAG
423 ##################
424 # FPSR/FPCR bits #
425 ##################
426 set neg_bit, 0x3 # negative result
427 set z_bit, 0x2 # zero result
428 set inf_bit, 0x1 # infinite result
429 set nan_bit, 0x0 # NAN result
431 set q_sn_bit, 0x7 # sign bit of quotient byte
433 set bsun_bit, 7 # branch on unordered
434 set snan_bit, 6 # signalling NAN
435 set operr_bit, 5 # operand error
436 set ovfl_bit, 4 # overflow
437 set unfl_bit, 3 # underflow
438 set dz_bit, 2 # divide by zero
439 set inex2_bit, 1 # inexact result 2
440 set inex1_bit, 0 # inexact result 1
442 set aiop_bit, 7 # accrued inexact operation bit
443 set aovfl_bit, 6 # accrued overflow bit
444 set aunfl_bit, 5 # accrued underflow bit
445 set adz_bit, 4 # accrued dz bit
446 set ainex_bit, 3 # accrued inexact bit
448 #############################
449 # FPSR individual bit masks #
450 #############################
451 set neg_mask, 0x08000000 # negative bit mask (lw)
452 set inf_mask, 0x02000000 # infinity bit mask (lw)
453 set z_mask, 0x04000000 # zero bit mask (lw)
454 set nan_mask, 0x01000000 # nan bit mask (lw)
456 set neg_bmask, 0x08 # negative bit mask (byte)
457 set inf_bmask, 0x02 # infinity bit mask (byte)
458 set z_bmask, 0x04 # zero bit mask (byte)
459 set nan_bmask, 0x01 # nan bit mask (byte)
461 set bsun_mask, 0x00008000 # bsun exception mask
462 set snan_mask, 0x00004000 # snan exception mask
463 set operr_mask, 0x00002000 # operr exception mask
464 set ovfl_mask, 0x00001000 # overflow exception mask
465 set unfl_mask, 0x00000800 # underflow exception mask
466 set dz_mask, 0x00000400 # dz exception mask
467 set inex2_mask, 0x00000200 # inex2 exception mask
468 set inex1_mask, 0x00000100 # inex1 exception mask
470 set aiop_mask, 0x00000080 # accrued illegal operation
471 set aovfl_mask, 0x00000040 # accrued overflow
472 set aunfl_mask, 0x00000020 # accrued underflow
473 set adz_mask, 0x00000010 # accrued divide by zero
474 set ainex_mask, 0x00000008 # accrued inexact
476 ######################################
477 # FPSR combinations used in the FPSP #
478 ######################################
479 set dzinf_mask, inf_mask+dz_mask+adz_mask
480 set opnan_mask, nan_mask+operr_mask+aiop_mask
481 set nzi_mask, 0x01ffffff #clears N, Z, and I
482 set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
483 set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
484 set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
485 set inx1a_mask, inex1_mask+ainex_mask
486 set inx2a_mask, inex2_mask+ainex_mask
487 set snaniop_mask, nan_mask+snan_mask+aiop_mask
488 set snaniop2_mask, snan_mask+aiop_mask
489 set naniop_mask, nan_mask+aiop_mask
490 set neginf_mask, neg_mask+inf_mask
491 set infaiop_mask, inf_mask+aiop_mask
492 set negz_mask, neg_mask+z_mask
493 set opaop_mask, operr_mask+aiop_mask
494 set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
495 set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
497 #########
498 # misc. #
499 #########
500 set rnd_stky_bit, 29 # stky bit pos in longword
502 set sign_bit, 0x7 # sign bit
503 set signan_bit, 0x6 # signalling nan bit
505 set sgl_thresh, 0x3f81 # minimum sgl exponent
506 set dbl_thresh, 0x3c01 # minimum dbl exponent
508 set x_mode, 0x0 # extended precision
509 set s_mode, 0x4 # single precision
510 set d_mode, 0x8 # double precision
512 set rn_mode, 0x0 # round-to-nearest
513 set rz_mode, 0x1 # round-to-zero
514 set rm_mode, 0x2 # round-tp-minus-infinity
515 set rp_mode, 0x3 # round-to-plus-infinity
517 set mantissalen, 64 # length of mantissa in bits
519 set BYTE, 1 # len(byte) == 1 byte
520 set WORD, 2 # len(word) == 2 bytes
521 set LONG, 4 # len(longword) == 2 bytes
523 set BSUN_VEC, 0xc0 # bsun vector offset
524 set INEX_VEC, 0xc4 # inexact vector offset
525 set DZ_VEC, 0xc8 # dz vector offset
526 set UNFL_VEC, 0xcc # unfl vector offset
527 set OPERR_VEC, 0xd0 # operr vector offset
528 set OVFL_VEC, 0xd4 # ovfl vector offset
529 set SNAN_VEC, 0xd8 # snan vector offset
531 ###########################
532 # SPecial CONDition FLaGs #
533 ###########################
534 set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
535 set fbsun_flg, 0x02 # flag bit: bsun exception
536 set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
537 set mda7_flg, 0x08 # flag bit: -(a7) <ea>
538 set fmovm_flg, 0x40 # flag bit: fmovm instruction
539 set immed_flg, 0x80 # flag bit: &<data> <ea>
541 set ftrapcc_bit, 0x0
542 set fbsun_bit, 0x1
543 set mia7_bit, 0x2
544 set mda7_bit, 0x3
545 set immed_bit, 0x7
547 ##################################
548 # TRANSCENDENTAL "LAST-OP" FLAGS #
549 ##################################
550 set FMUL_OP, 0x0 # fmul instr performed last
551 set FDIV_OP, 0x1 # fdiv performed last
552 set FADD_OP, 0x2 # fadd performed last
553 set FMOV_OP, 0x3 # fmov performed last
555 #############
556 # CONSTANTS #
557 #############
558 T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
559 T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
561 PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
562 PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
564 TWOBYPI:
565 long 0x3FE45F30,0x6DC9C883
567 #########################################################################
568 # MONADIC TEMPLATE #
569 #########################################################################
570 global _fsins_
571 _fsins_:
572 link %a6,&-LOCAL_SIZE
574 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
575 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
576 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
578 fmov.l &0x0,%fpcr # zero FPCR
581 # copy, convert, and tag input argument
583 fmov.s 0x8(%a6),%fp0 # load sgl input
584 fmov.x %fp0,FP_SRC(%a6)
585 lea FP_SRC(%a6),%a0
586 bsr.l tag # fetch operand type
587 mov.b %d0,STAG(%a6)
588 mov.b %d0,%d1
590 andi.l &0x00ff00ff,USER_FPSR(%a6)
592 clr.l %d0
593 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
595 tst.b %d1
596 bne.b _L0_2s
597 bsr.l ssin # operand is a NORM
598 bra.b _L0_6s
599 _L0_2s:
600 cmpi.b %d1,&ZERO # is operand a ZERO?
601 bne.b _L0_3s # no
602 bsr.l src_zero # yes
603 bra.b _L0_6s
604 _L0_3s:
605 cmpi.b %d1,&INF # is operand an INF?
606 bne.b _L0_4s # no
607 bsr.l t_operr # yes
608 bra.b _L0_6s
609 _L0_4s:
610 cmpi.b %d1,&QNAN # is operand a QNAN?
611 bne.b _L0_5s # no
612 bsr.l src_qnan # yes
613 bra.b _L0_6s
614 _L0_5s:
615 bsr.l ssind # operand is a DENORM
616 _L0_6s:
619 # Result is now in FP0
621 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
622 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
623 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
624 unlk %a6
627 global _fsind_
628 _fsind_:
629 link %a6,&-LOCAL_SIZE
631 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
632 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
633 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
635 fmov.l &0x0,%fpcr # zero FPCR
638 # copy, convert, and tag input argument
640 fmov.d 0x8(%a6),%fp0 # load dbl input
641 fmov.x %fp0,FP_SRC(%a6)
642 lea FP_SRC(%a6),%a0
643 bsr.l tag # fetch operand type
644 mov.b %d0,STAG(%a6)
645 mov.b %d0,%d1
647 andi.l &0x00ff00ff,USER_FPSR(%a6)
649 clr.l %d0
650 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
652 mov.b %d1,STAG(%a6)
653 tst.b %d1
654 bne.b _L0_2d
655 bsr.l ssin # operand is a NORM
656 bra.b _L0_6d
657 _L0_2d:
658 cmpi.b %d1,&ZERO # is operand a ZERO?
659 bne.b _L0_3d # no
660 bsr.l src_zero # yes
661 bra.b _L0_6d
662 _L0_3d:
663 cmpi.b %d1,&INF # is operand an INF?
664 bne.b _L0_4d # no
665 bsr.l t_operr # yes
666 bra.b _L0_6d
667 _L0_4d:
668 cmpi.b %d1,&QNAN # is operand a QNAN?
669 bne.b _L0_5d # no
670 bsr.l src_qnan # yes
671 bra.b _L0_6d
672 _L0_5d:
673 bsr.l ssind # operand is a DENORM
674 _L0_6d:
677 # Result is now in FP0
679 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
680 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
681 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
682 unlk %a6
685 global _fsinx_
686 _fsinx_:
687 link %a6,&-LOCAL_SIZE
689 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
690 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
691 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
693 fmov.l &0x0,%fpcr # zero FPCR
696 # copy, convert, and tag input argument
698 lea FP_SRC(%a6),%a0
699 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
700 mov.l 0x8+0x4(%a6),0x4(%a0)
701 mov.l 0x8+0x8(%a6),0x8(%a0)
702 bsr.l tag # fetch operand type
703 mov.b %d0,STAG(%a6)
704 mov.b %d0,%d1
706 andi.l &0x00ff00ff,USER_FPSR(%a6)
708 clr.l %d0
709 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
711 tst.b %d1
712 bne.b _L0_2x
713 bsr.l ssin # operand is a NORM
714 bra.b _L0_6x
715 _L0_2x:
716 cmpi.b %d1,&ZERO # is operand a ZERO?
717 bne.b _L0_3x # no
718 bsr.l src_zero # yes
719 bra.b _L0_6x
720 _L0_3x:
721 cmpi.b %d1,&INF # is operand an INF?
722 bne.b _L0_4x # no
723 bsr.l t_operr # yes
724 bra.b _L0_6x
725 _L0_4x:
726 cmpi.b %d1,&QNAN # is operand a QNAN?
727 bne.b _L0_5x # no
728 bsr.l src_qnan # yes
729 bra.b _L0_6x
730 _L0_5x:
731 bsr.l ssind # operand is a DENORM
732 _L0_6x:
735 # Result is now in FP0
737 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
738 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
739 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
740 unlk %a6
744 #########################################################################
745 # MONADIC TEMPLATE #
746 #########################################################################
747 global _fcoss_
748 _fcoss_:
749 link %a6,&-LOCAL_SIZE
751 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
752 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
753 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
755 fmov.l &0x0,%fpcr # zero FPCR
758 # copy, convert, and tag input argument
760 fmov.s 0x8(%a6),%fp0 # load sgl input
761 fmov.x %fp0,FP_SRC(%a6)
762 lea FP_SRC(%a6),%a0
763 bsr.l tag # fetch operand type
764 mov.b %d0,STAG(%a6)
765 mov.b %d0,%d1
767 andi.l &0x00ff00ff,USER_FPSR(%a6)
769 clr.l %d0
770 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
772 tst.b %d1
773 bne.b _L1_2s
774 bsr.l scos # operand is a NORM
775 bra.b _L1_6s
776 _L1_2s:
777 cmpi.b %d1,&ZERO # is operand a ZERO?
778 bne.b _L1_3s # no
779 bsr.l ld_pone # yes
780 bra.b _L1_6s
781 _L1_3s:
782 cmpi.b %d1,&INF # is operand an INF?
783 bne.b _L1_4s # no
784 bsr.l t_operr # yes
785 bra.b _L1_6s
786 _L1_4s:
787 cmpi.b %d1,&QNAN # is operand a QNAN?
788 bne.b _L1_5s # no
789 bsr.l src_qnan # yes
790 bra.b _L1_6s
791 _L1_5s:
792 bsr.l scosd # operand is a DENORM
793 _L1_6s:
796 # Result is now in FP0
798 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
799 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
800 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
801 unlk %a6
804 global _fcosd_
805 _fcosd_:
806 link %a6,&-LOCAL_SIZE
808 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
809 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
810 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
812 fmov.l &0x0,%fpcr # zero FPCR
815 # copy, convert, and tag input argument
817 fmov.d 0x8(%a6),%fp0 # load dbl input
818 fmov.x %fp0,FP_SRC(%a6)
819 lea FP_SRC(%a6),%a0
820 bsr.l tag # fetch operand type
821 mov.b %d0,STAG(%a6)
822 mov.b %d0,%d1
824 andi.l &0x00ff00ff,USER_FPSR(%a6)
826 clr.l %d0
827 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
829 mov.b %d1,STAG(%a6)
830 tst.b %d1
831 bne.b _L1_2d
832 bsr.l scos # operand is a NORM
833 bra.b _L1_6d
834 _L1_2d:
835 cmpi.b %d1,&ZERO # is operand a ZERO?
836 bne.b _L1_3d # no
837 bsr.l ld_pone # yes
838 bra.b _L1_6d
839 _L1_3d:
840 cmpi.b %d1,&INF # is operand an INF?
841 bne.b _L1_4d # no
842 bsr.l t_operr # yes
843 bra.b _L1_6d
844 _L1_4d:
845 cmpi.b %d1,&QNAN # is operand a QNAN?
846 bne.b _L1_5d # no
847 bsr.l src_qnan # yes
848 bra.b _L1_6d
849 _L1_5d:
850 bsr.l scosd # operand is a DENORM
851 _L1_6d:
854 # Result is now in FP0
856 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
857 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
858 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
859 unlk %a6
862 global _fcosx_
863 _fcosx_:
864 link %a6,&-LOCAL_SIZE
866 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
867 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
868 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
870 fmov.l &0x0,%fpcr # zero FPCR
873 # copy, convert, and tag input argument
875 lea FP_SRC(%a6),%a0
876 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
877 mov.l 0x8+0x4(%a6),0x4(%a0)
878 mov.l 0x8+0x8(%a6),0x8(%a0)
879 bsr.l tag # fetch operand type
880 mov.b %d0,STAG(%a6)
881 mov.b %d0,%d1
883 andi.l &0x00ff00ff,USER_FPSR(%a6)
885 clr.l %d0
886 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
888 tst.b %d1
889 bne.b _L1_2x
890 bsr.l scos # operand is a NORM
891 bra.b _L1_6x
892 _L1_2x:
893 cmpi.b %d1,&ZERO # is operand a ZERO?
894 bne.b _L1_3x # no
895 bsr.l ld_pone # yes
896 bra.b _L1_6x
897 _L1_3x:
898 cmpi.b %d1,&INF # is operand an INF?
899 bne.b _L1_4x # no
900 bsr.l t_operr # yes
901 bra.b _L1_6x
902 _L1_4x:
903 cmpi.b %d1,&QNAN # is operand a QNAN?
904 bne.b _L1_5x # no
905 bsr.l src_qnan # yes
906 bra.b _L1_6x
907 _L1_5x:
908 bsr.l scosd # operand is a DENORM
909 _L1_6x:
912 # Result is now in FP0
914 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
915 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
916 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
917 unlk %a6
921 #########################################################################
922 # MONADIC TEMPLATE #
923 #########################################################################
924 global _fsinhs_
925 _fsinhs_:
926 link %a6,&-LOCAL_SIZE
928 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
929 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
930 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
932 fmov.l &0x0,%fpcr # zero FPCR
935 # copy, convert, and tag input argument
937 fmov.s 0x8(%a6),%fp0 # load sgl input
938 fmov.x %fp0,FP_SRC(%a6)
939 lea FP_SRC(%a6),%a0
940 bsr.l tag # fetch operand type
941 mov.b %d0,STAG(%a6)
942 mov.b %d0,%d1
944 andi.l &0x00ff00ff,USER_FPSR(%a6)
946 clr.l %d0
947 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
949 tst.b %d1
950 bne.b _L2_2s
951 bsr.l ssinh # operand is a NORM
952 bra.b _L2_6s
953 _L2_2s:
954 cmpi.b %d1,&ZERO # is operand a ZERO?
955 bne.b _L2_3s # no
956 bsr.l src_zero # yes
957 bra.b _L2_6s
958 _L2_3s:
959 cmpi.b %d1,&INF # is operand an INF?
960 bne.b _L2_4s # no
961 bsr.l src_inf # yes
962 bra.b _L2_6s
963 _L2_4s:
964 cmpi.b %d1,&QNAN # is operand a QNAN?
965 bne.b _L2_5s # no
966 bsr.l src_qnan # yes
967 bra.b _L2_6s
968 _L2_5s:
969 bsr.l ssinhd # operand is a DENORM
970 _L2_6s:
973 # Result is now in FP0
975 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
976 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
977 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
978 unlk %a6
981 global _fsinhd_
982 _fsinhd_:
983 link %a6,&-LOCAL_SIZE
985 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
986 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
987 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
989 fmov.l &0x0,%fpcr # zero FPCR
992 # copy, convert, and tag input argument
994 fmov.d 0x8(%a6),%fp0 # load dbl input
995 fmov.x %fp0,FP_SRC(%a6)
996 lea FP_SRC(%a6),%a0
997 bsr.l tag # fetch operand type
998 mov.b %d0,STAG(%a6)
999 mov.b %d0,%d1
1001 andi.l &0x00ff00ff,USER_FPSR(%a6)
1003 clr.l %d0
1004 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1006 mov.b %d1,STAG(%a6)
1007 tst.b %d1
1008 bne.b _L2_2d
1009 bsr.l ssinh # operand is a NORM
1010 bra.b _L2_6d
1011 _L2_2d:
1012 cmpi.b %d1,&ZERO # is operand a ZERO?
1013 bne.b _L2_3d # no
1014 bsr.l src_zero # yes
1015 bra.b _L2_6d
1016 _L2_3d:
1017 cmpi.b %d1,&INF # is operand an INF?
1018 bne.b _L2_4d # no
1019 bsr.l src_inf # yes
1020 bra.b _L2_6d
1021 _L2_4d:
1022 cmpi.b %d1,&QNAN # is operand a QNAN?
1023 bne.b _L2_5d # no
1024 bsr.l src_qnan # yes
1025 bra.b _L2_6d
1026 _L2_5d:
1027 bsr.l ssinhd # operand is a DENORM
1028 _L2_6d:
1031 # Result is now in FP0
1033 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1034 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1035 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1036 unlk %a6
1039 global _fsinhx_
1040 _fsinhx_:
1041 link %a6,&-LOCAL_SIZE
1043 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1044 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1045 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1047 fmov.l &0x0,%fpcr # zero FPCR
1050 # copy, convert, and tag input argument
1052 lea FP_SRC(%a6),%a0
1053 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1054 mov.l 0x8+0x4(%a6),0x4(%a0)
1055 mov.l 0x8+0x8(%a6),0x8(%a0)
1056 bsr.l tag # fetch operand type
1057 mov.b %d0,STAG(%a6)
1058 mov.b %d0,%d1
1060 andi.l &0x00ff00ff,USER_FPSR(%a6)
1062 clr.l %d0
1063 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1065 tst.b %d1
1066 bne.b _L2_2x
1067 bsr.l ssinh # operand is a NORM
1068 bra.b _L2_6x
1069 _L2_2x:
1070 cmpi.b %d1,&ZERO # is operand a ZERO?
1071 bne.b _L2_3x # no
1072 bsr.l src_zero # yes
1073 bra.b _L2_6x
1074 _L2_3x:
1075 cmpi.b %d1,&INF # is operand an INF?
1076 bne.b _L2_4x # no
1077 bsr.l src_inf # yes
1078 bra.b _L2_6x
1079 _L2_4x:
1080 cmpi.b %d1,&QNAN # is operand a QNAN?
1081 bne.b _L2_5x # no
1082 bsr.l src_qnan # yes
1083 bra.b _L2_6x
1084 _L2_5x:
1085 bsr.l ssinhd # operand is a DENORM
1086 _L2_6x:
1089 # Result is now in FP0
1091 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1092 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1093 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1094 unlk %a6
1098 #########################################################################
1099 # MONADIC TEMPLATE #
1100 #########################################################################
1101 global _flognp1s_
1102 _flognp1s_:
1103 link %a6,&-LOCAL_SIZE
1105 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1106 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1107 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1109 fmov.l &0x0,%fpcr # zero FPCR
1112 # copy, convert, and tag input argument
1114 fmov.s 0x8(%a6),%fp0 # load sgl input
1115 fmov.x %fp0,FP_SRC(%a6)
1116 lea FP_SRC(%a6),%a0
1117 bsr.l tag # fetch operand type
1118 mov.b %d0,STAG(%a6)
1119 mov.b %d0,%d1
1121 andi.l &0x00ff00ff,USER_FPSR(%a6)
1123 clr.l %d0
1124 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1126 tst.b %d1
1127 bne.b _L3_2s
1128 bsr.l slognp1 # operand is a NORM
1129 bra.b _L3_6s
1130 _L3_2s:
1131 cmpi.b %d1,&ZERO # is operand a ZERO?
1132 bne.b _L3_3s # no
1133 bsr.l src_zero # yes
1134 bra.b _L3_6s
1135 _L3_3s:
1136 cmpi.b %d1,&INF # is operand an INF?
1137 bne.b _L3_4s # no
1138 bsr.l sopr_inf # yes
1139 bra.b _L3_6s
1140 _L3_4s:
1141 cmpi.b %d1,&QNAN # is operand a QNAN?
1142 bne.b _L3_5s # no
1143 bsr.l src_qnan # yes
1144 bra.b _L3_6s
1145 _L3_5s:
1146 bsr.l slognp1d # operand is a DENORM
1147 _L3_6s:
1150 # Result is now in FP0
1152 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1153 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1154 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1155 unlk %a6
1158 global _flognp1d_
1159 _flognp1d_:
1160 link %a6,&-LOCAL_SIZE
1162 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1163 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1164 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1166 fmov.l &0x0,%fpcr # zero FPCR
1169 # copy, convert, and tag input argument
1171 fmov.d 0x8(%a6),%fp0 # load dbl input
1172 fmov.x %fp0,FP_SRC(%a6)
1173 lea FP_SRC(%a6),%a0
1174 bsr.l tag # fetch operand type
1175 mov.b %d0,STAG(%a6)
1176 mov.b %d0,%d1
1178 andi.l &0x00ff00ff,USER_FPSR(%a6)
1180 clr.l %d0
1181 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1183 mov.b %d1,STAG(%a6)
1184 tst.b %d1
1185 bne.b _L3_2d
1186 bsr.l slognp1 # operand is a NORM
1187 bra.b _L3_6d
1188 _L3_2d:
1189 cmpi.b %d1,&ZERO # is operand a ZERO?
1190 bne.b _L3_3d # no
1191 bsr.l src_zero # yes
1192 bra.b _L3_6d
1193 _L3_3d:
1194 cmpi.b %d1,&INF # is operand an INF?
1195 bne.b _L3_4d # no
1196 bsr.l sopr_inf # yes
1197 bra.b _L3_6d
1198 _L3_4d:
1199 cmpi.b %d1,&QNAN # is operand a QNAN?
1200 bne.b _L3_5d # no
1201 bsr.l src_qnan # yes
1202 bra.b _L3_6d
1203 _L3_5d:
1204 bsr.l slognp1d # operand is a DENORM
1205 _L3_6d:
1208 # Result is now in FP0
1210 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1211 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1212 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1213 unlk %a6
1216 global _flognp1x_
1217 _flognp1x_:
1218 link %a6,&-LOCAL_SIZE
1220 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1221 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1222 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1224 fmov.l &0x0,%fpcr # zero FPCR
1227 # copy, convert, and tag input argument
1229 lea FP_SRC(%a6),%a0
1230 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1231 mov.l 0x8+0x4(%a6),0x4(%a0)
1232 mov.l 0x8+0x8(%a6),0x8(%a0)
1233 bsr.l tag # fetch operand type
1234 mov.b %d0,STAG(%a6)
1235 mov.b %d0,%d1
1237 andi.l &0x00ff00ff,USER_FPSR(%a6)
1239 clr.l %d0
1240 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1242 tst.b %d1
1243 bne.b _L3_2x
1244 bsr.l slognp1 # operand is a NORM
1245 bra.b _L3_6x
1246 _L3_2x:
1247 cmpi.b %d1,&ZERO # is operand a ZERO?
1248 bne.b _L3_3x # no
1249 bsr.l src_zero # yes
1250 bra.b _L3_6x
1251 _L3_3x:
1252 cmpi.b %d1,&INF # is operand an INF?
1253 bne.b _L3_4x # no
1254 bsr.l sopr_inf # yes
1255 bra.b _L3_6x
1256 _L3_4x:
1257 cmpi.b %d1,&QNAN # is operand a QNAN?
1258 bne.b _L3_5x # no
1259 bsr.l src_qnan # yes
1260 bra.b _L3_6x
1261 _L3_5x:
1262 bsr.l slognp1d # operand is a DENORM
1263 _L3_6x:
1266 # Result is now in FP0
1268 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1269 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1270 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1271 unlk %a6
1275 #########################################################################
1276 # MONADIC TEMPLATE #
1277 #########################################################################
1278 global _fetoxm1s_
1279 _fetoxm1s_:
1280 link %a6,&-LOCAL_SIZE
1282 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1283 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1284 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1286 fmov.l &0x0,%fpcr # zero FPCR
1289 # copy, convert, and tag input argument
1291 fmov.s 0x8(%a6),%fp0 # load sgl input
1292 fmov.x %fp0,FP_SRC(%a6)
1293 lea FP_SRC(%a6),%a0
1294 bsr.l tag # fetch operand type
1295 mov.b %d0,STAG(%a6)
1296 mov.b %d0,%d1
1298 andi.l &0x00ff00ff,USER_FPSR(%a6)
1300 clr.l %d0
1301 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1303 tst.b %d1
1304 bne.b _L4_2s
1305 bsr.l setoxm1 # operand is a NORM
1306 bra.b _L4_6s
1307 _L4_2s:
1308 cmpi.b %d1,&ZERO # is operand a ZERO?
1309 bne.b _L4_3s # no
1310 bsr.l src_zero # yes
1311 bra.b _L4_6s
1312 _L4_3s:
1313 cmpi.b %d1,&INF # is operand an INF?
1314 bne.b _L4_4s # no
1315 bsr.l setoxm1i # yes
1316 bra.b _L4_6s
1317 _L4_4s:
1318 cmpi.b %d1,&QNAN # is operand a QNAN?
1319 bne.b _L4_5s # no
1320 bsr.l src_qnan # yes
1321 bra.b _L4_6s
1322 _L4_5s:
1323 bsr.l setoxm1d # operand is a DENORM
1324 _L4_6s:
1327 # Result is now in FP0
1329 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1330 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1331 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1332 unlk %a6
1335 global _fetoxm1d_
1336 _fetoxm1d_:
1337 link %a6,&-LOCAL_SIZE
1339 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1340 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1341 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1343 fmov.l &0x0,%fpcr # zero FPCR
1346 # copy, convert, and tag input argument
1348 fmov.d 0x8(%a6),%fp0 # load dbl input
1349 fmov.x %fp0,FP_SRC(%a6)
1350 lea FP_SRC(%a6),%a0
1351 bsr.l tag # fetch operand type
1352 mov.b %d0,STAG(%a6)
1353 mov.b %d0,%d1
1355 andi.l &0x00ff00ff,USER_FPSR(%a6)
1357 clr.l %d0
1358 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1360 mov.b %d1,STAG(%a6)
1361 tst.b %d1
1362 bne.b _L4_2d
1363 bsr.l setoxm1 # operand is a NORM
1364 bra.b _L4_6d
1365 _L4_2d:
1366 cmpi.b %d1,&ZERO # is operand a ZERO?
1367 bne.b _L4_3d # no
1368 bsr.l src_zero # yes
1369 bra.b _L4_6d
1370 _L4_3d:
1371 cmpi.b %d1,&INF # is operand an INF?
1372 bne.b _L4_4d # no
1373 bsr.l setoxm1i # yes
1374 bra.b _L4_6d
1375 _L4_4d:
1376 cmpi.b %d1,&QNAN # is operand a QNAN?
1377 bne.b _L4_5d # no
1378 bsr.l src_qnan # yes
1379 bra.b _L4_6d
1380 _L4_5d:
1381 bsr.l setoxm1d # operand is a DENORM
1382 _L4_6d:
1385 # Result is now in FP0
1387 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1388 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1389 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1390 unlk %a6
1393 global _fetoxm1x_
1394 _fetoxm1x_:
1395 link %a6,&-LOCAL_SIZE
1397 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1398 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1399 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1401 fmov.l &0x0,%fpcr # zero FPCR
1404 # copy, convert, and tag input argument
1406 lea FP_SRC(%a6),%a0
1407 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1408 mov.l 0x8+0x4(%a6),0x4(%a0)
1409 mov.l 0x8+0x8(%a6),0x8(%a0)
1410 bsr.l tag # fetch operand type
1411 mov.b %d0,STAG(%a6)
1412 mov.b %d0,%d1
1414 andi.l &0x00ff00ff,USER_FPSR(%a6)
1416 clr.l %d0
1417 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1419 tst.b %d1
1420 bne.b _L4_2x
1421 bsr.l setoxm1 # operand is a NORM
1422 bra.b _L4_6x
1423 _L4_2x:
1424 cmpi.b %d1,&ZERO # is operand a ZERO?
1425 bne.b _L4_3x # no
1426 bsr.l src_zero # yes
1427 bra.b _L4_6x
1428 _L4_3x:
1429 cmpi.b %d1,&INF # is operand an INF?
1430 bne.b _L4_4x # no
1431 bsr.l setoxm1i # yes
1432 bra.b _L4_6x
1433 _L4_4x:
1434 cmpi.b %d1,&QNAN # is operand a QNAN?
1435 bne.b _L4_5x # no
1436 bsr.l src_qnan # yes
1437 bra.b _L4_6x
1438 _L4_5x:
1439 bsr.l setoxm1d # operand is a DENORM
1440 _L4_6x:
1443 # Result is now in FP0
1445 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1446 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1447 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1448 unlk %a6
1452 #########################################################################
1453 # MONADIC TEMPLATE #
1454 #########################################################################
1455 global _ftanhs_
1456 _ftanhs_:
1457 link %a6,&-LOCAL_SIZE
1459 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1460 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1461 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1463 fmov.l &0x0,%fpcr # zero FPCR
1466 # copy, convert, and tag input argument
1468 fmov.s 0x8(%a6),%fp0 # load sgl input
1469 fmov.x %fp0,FP_SRC(%a6)
1470 lea FP_SRC(%a6),%a0
1471 bsr.l tag # fetch operand type
1472 mov.b %d0,STAG(%a6)
1473 mov.b %d0,%d1
1475 andi.l &0x00ff00ff,USER_FPSR(%a6)
1477 clr.l %d0
1478 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1480 tst.b %d1
1481 bne.b _L5_2s
1482 bsr.l stanh # operand is a NORM
1483 bra.b _L5_6s
1484 _L5_2s:
1485 cmpi.b %d1,&ZERO # is operand a ZERO?
1486 bne.b _L5_3s # no
1487 bsr.l src_zero # yes
1488 bra.b _L5_6s
1489 _L5_3s:
1490 cmpi.b %d1,&INF # is operand an INF?
1491 bne.b _L5_4s # no
1492 bsr.l src_one # yes
1493 bra.b _L5_6s
1494 _L5_4s:
1495 cmpi.b %d1,&QNAN # is operand a QNAN?
1496 bne.b _L5_5s # no
1497 bsr.l src_qnan # yes
1498 bra.b _L5_6s
1499 _L5_5s:
1500 bsr.l stanhd # operand is a DENORM
1501 _L5_6s:
1504 # Result is now in FP0
1506 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1507 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1508 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1509 unlk %a6
1512 global _ftanhd_
1513 _ftanhd_:
1514 link %a6,&-LOCAL_SIZE
1516 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1517 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1518 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1520 fmov.l &0x0,%fpcr # zero FPCR
1523 # copy, convert, and tag input argument
1525 fmov.d 0x8(%a6),%fp0 # load dbl input
1526 fmov.x %fp0,FP_SRC(%a6)
1527 lea FP_SRC(%a6),%a0
1528 bsr.l tag # fetch operand type
1529 mov.b %d0,STAG(%a6)
1530 mov.b %d0,%d1
1532 andi.l &0x00ff00ff,USER_FPSR(%a6)
1534 clr.l %d0
1535 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1537 mov.b %d1,STAG(%a6)
1538 tst.b %d1
1539 bne.b _L5_2d
1540 bsr.l stanh # operand is a NORM
1541 bra.b _L5_6d
1542 _L5_2d:
1543 cmpi.b %d1,&ZERO # is operand a ZERO?
1544 bne.b _L5_3d # no
1545 bsr.l src_zero # yes
1546 bra.b _L5_6d
1547 _L5_3d:
1548 cmpi.b %d1,&INF # is operand an INF?
1549 bne.b _L5_4d # no
1550 bsr.l src_one # yes
1551 bra.b _L5_6d
1552 _L5_4d:
1553 cmpi.b %d1,&QNAN # is operand a QNAN?
1554 bne.b _L5_5d # no
1555 bsr.l src_qnan # yes
1556 bra.b _L5_6d
1557 _L5_5d:
1558 bsr.l stanhd # operand is a DENORM
1559 _L5_6d:
1562 # Result is now in FP0
1564 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1565 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1566 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1567 unlk %a6
1570 global _ftanhx_
1571 _ftanhx_:
1572 link %a6,&-LOCAL_SIZE
1574 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1575 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1576 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1578 fmov.l &0x0,%fpcr # zero FPCR
1581 # copy, convert, and tag input argument
1583 lea FP_SRC(%a6),%a0
1584 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1585 mov.l 0x8+0x4(%a6),0x4(%a0)
1586 mov.l 0x8+0x8(%a6),0x8(%a0)
1587 bsr.l tag # fetch operand type
1588 mov.b %d0,STAG(%a6)
1589 mov.b %d0,%d1
1591 andi.l &0x00ff00ff,USER_FPSR(%a6)
1593 clr.l %d0
1594 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1596 tst.b %d1
1597 bne.b _L5_2x
1598 bsr.l stanh # operand is a NORM
1599 bra.b _L5_6x
1600 _L5_2x:
1601 cmpi.b %d1,&ZERO # is operand a ZERO?
1602 bne.b _L5_3x # no
1603 bsr.l src_zero # yes
1604 bra.b _L5_6x
1605 _L5_3x:
1606 cmpi.b %d1,&INF # is operand an INF?
1607 bne.b _L5_4x # no
1608 bsr.l src_one # yes
1609 bra.b _L5_6x
1610 _L5_4x:
1611 cmpi.b %d1,&QNAN # is operand a QNAN?
1612 bne.b _L5_5x # no
1613 bsr.l src_qnan # yes
1614 bra.b _L5_6x
1615 _L5_5x:
1616 bsr.l stanhd # operand is a DENORM
1617 _L5_6x:
1620 # Result is now in FP0
1622 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1623 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1624 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1625 unlk %a6
1629 #########################################################################
1630 # MONADIC TEMPLATE #
1631 #########################################################################
1632 global _fatans_
1633 _fatans_:
1634 link %a6,&-LOCAL_SIZE
1636 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1637 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1638 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1640 fmov.l &0x0,%fpcr # zero FPCR
1643 # copy, convert, and tag input argument
1645 fmov.s 0x8(%a6),%fp0 # load sgl input
1646 fmov.x %fp0,FP_SRC(%a6)
1647 lea FP_SRC(%a6),%a0
1648 bsr.l tag # fetch operand type
1649 mov.b %d0,STAG(%a6)
1650 mov.b %d0,%d1
1652 andi.l &0x00ff00ff,USER_FPSR(%a6)
1654 clr.l %d0
1655 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1657 tst.b %d1
1658 bne.b _L6_2s
1659 bsr.l satan # operand is a NORM
1660 bra.b _L6_6s
1661 _L6_2s:
1662 cmpi.b %d1,&ZERO # is operand a ZERO?
1663 bne.b _L6_3s # no
1664 bsr.l src_zero # yes
1665 bra.b _L6_6s
1666 _L6_3s:
1667 cmpi.b %d1,&INF # is operand an INF?
1668 bne.b _L6_4s # no
1669 bsr.l spi_2 # yes
1670 bra.b _L6_6s
1671 _L6_4s:
1672 cmpi.b %d1,&QNAN # is operand a QNAN?
1673 bne.b _L6_5s # no
1674 bsr.l src_qnan # yes
1675 bra.b _L6_6s
1676 _L6_5s:
1677 bsr.l satand # operand is a DENORM
1678 _L6_6s:
1681 # Result is now in FP0
1683 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1684 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1685 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1686 unlk %a6
1689 global _fatand_
1690 _fatand_:
1691 link %a6,&-LOCAL_SIZE
1693 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1694 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1695 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1697 fmov.l &0x0,%fpcr # zero FPCR
1700 # copy, convert, and tag input argument
1702 fmov.d 0x8(%a6),%fp0 # load dbl input
1703 fmov.x %fp0,FP_SRC(%a6)
1704 lea FP_SRC(%a6),%a0
1705 bsr.l tag # fetch operand type
1706 mov.b %d0,STAG(%a6)
1707 mov.b %d0,%d1
1709 andi.l &0x00ff00ff,USER_FPSR(%a6)
1711 clr.l %d0
1712 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1714 mov.b %d1,STAG(%a6)
1715 tst.b %d1
1716 bne.b _L6_2d
1717 bsr.l satan # operand is a NORM
1718 bra.b _L6_6d
1719 _L6_2d:
1720 cmpi.b %d1,&ZERO # is operand a ZERO?
1721 bne.b _L6_3d # no
1722 bsr.l src_zero # yes
1723 bra.b _L6_6d
1724 _L6_3d:
1725 cmpi.b %d1,&INF # is operand an INF?
1726 bne.b _L6_4d # no
1727 bsr.l spi_2 # yes
1728 bra.b _L6_6d
1729 _L6_4d:
1730 cmpi.b %d1,&QNAN # is operand a QNAN?
1731 bne.b _L6_5d # no
1732 bsr.l src_qnan # yes
1733 bra.b _L6_6d
1734 _L6_5d:
1735 bsr.l satand # operand is a DENORM
1736 _L6_6d:
1739 # Result is now in FP0
1741 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1742 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1743 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1744 unlk %a6
1747 global _fatanx_
1748 _fatanx_:
1749 link %a6,&-LOCAL_SIZE
1751 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1752 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1753 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1755 fmov.l &0x0,%fpcr # zero FPCR
1758 # copy, convert, and tag input argument
1760 lea FP_SRC(%a6),%a0
1761 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1762 mov.l 0x8+0x4(%a6),0x4(%a0)
1763 mov.l 0x8+0x8(%a6),0x8(%a0)
1764 bsr.l tag # fetch operand type
1765 mov.b %d0,STAG(%a6)
1766 mov.b %d0,%d1
1768 andi.l &0x00ff00ff,USER_FPSR(%a6)
1770 clr.l %d0
1771 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1773 tst.b %d1
1774 bne.b _L6_2x
1775 bsr.l satan # operand is a NORM
1776 bra.b _L6_6x
1777 _L6_2x:
1778 cmpi.b %d1,&ZERO # is operand a ZERO?
1779 bne.b _L6_3x # no
1780 bsr.l src_zero # yes
1781 bra.b _L6_6x
1782 _L6_3x:
1783 cmpi.b %d1,&INF # is operand an INF?
1784 bne.b _L6_4x # no
1785 bsr.l spi_2 # yes
1786 bra.b _L6_6x
1787 _L6_4x:
1788 cmpi.b %d1,&QNAN # is operand a QNAN?
1789 bne.b _L6_5x # no
1790 bsr.l src_qnan # yes
1791 bra.b _L6_6x
1792 _L6_5x:
1793 bsr.l satand # operand is a DENORM
1794 _L6_6x:
1797 # Result is now in FP0
1799 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1800 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1801 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1802 unlk %a6
1806 #########################################################################
1807 # MONADIC TEMPLATE #
1808 #########################################################################
1809 global _fasins_
1810 _fasins_:
1811 link %a6,&-LOCAL_SIZE
1813 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1814 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1815 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1817 fmov.l &0x0,%fpcr # zero FPCR
1820 # copy, convert, and tag input argument
1822 fmov.s 0x8(%a6),%fp0 # load sgl input
1823 fmov.x %fp0,FP_SRC(%a6)
1824 lea FP_SRC(%a6),%a0
1825 bsr.l tag # fetch operand type
1826 mov.b %d0,STAG(%a6)
1827 mov.b %d0,%d1
1829 andi.l &0x00ff00ff,USER_FPSR(%a6)
1831 clr.l %d0
1832 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1834 tst.b %d1
1835 bne.b _L7_2s
1836 bsr.l sasin # operand is a NORM
1837 bra.b _L7_6s
1838 _L7_2s:
1839 cmpi.b %d1,&ZERO # is operand a ZERO?
1840 bne.b _L7_3s # no
1841 bsr.l src_zero # yes
1842 bra.b _L7_6s
1843 _L7_3s:
1844 cmpi.b %d1,&INF # is operand an INF?
1845 bne.b _L7_4s # no
1846 bsr.l t_operr # yes
1847 bra.b _L7_6s
1848 _L7_4s:
1849 cmpi.b %d1,&QNAN # is operand a QNAN?
1850 bne.b _L7_5s # no
1851 bsr.l src_qnan # yes
1852 bra.b _L7_6s
1853 _L7_5s:
1854 bsr.l sasind # operand is a DENORM
1855 _L7_6s:
1858 # Result is now in FP0
1860 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1861 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1862 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1863 unlk %a6
1866 global _fasind_
1867 _fasind_:
1868 link %a6,&-LOCAL_SIZE
1870 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1871 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1872 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1874 fmov.l &0x0,%fpcr # zero FPCR
1877 # copy, convert, and tag input argument
1879 fmov.d 0x8(%a6),%fp0 # load dbl input
1880 fmov.x %fp0,FP_SRC(%a6)
1881 lea FP_SRC(%a6),%a0
1882 bsr.l tag # fetch operand type
1883 mov.b %d0,STAG(%a6)
1884 mov.b %d0,%d1
1886 andi.l &0x00ff00ff,USER_FPSR(%a6)
1888 clr.l %d0
1889 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1891 mov.b %d1,STAG(%a6)
1892 tst.b %d1
1893 bne.b _L7_2d
1894 bsr.l sasin # operand is a NORM
1895 bra.b _L7_6d
1896 _L7_2d:
1897 cmpi.b %d1,&ZERO # is operand a ZERO?
1898 bne.b _L7_3d # no
1899 bsr.l src_zero # yes
1900 bra.b _L7_6d
1901 _L7_3d:
1902 cmpi.b %d1,&INF # is operand an INF?
1903 bne.b _L7_4d # no
1904 bsr.l t_operr # yes
1905 bra.b _L7_6d
1906 _L7_4d:
1907 cmpi.b %d1,&QNAN # is operand a QNAN?
1908 bne.b _L7_5d # no
1909 bsr.l src_qnan # yes
1910 bra.b _L7_6d
1911 _L7_5d:
1912 bsr.l sasind # operand is a DENORM
1913 _L7_6d:
1916 # Result is now in FP0
1918 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1919 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1920 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1921 unlk %a6
1924 global _fasinx_
1925 _fasinx_:
1926 link %a6,&-LOCAL_SIZE
1928 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1929 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1930 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1932 fmov.l &0x0,%fpcr # zero FPCR
1935 # copy, convert, and tag input argument
1937 lea FP_SRC(%a6),%a0
1938 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1939 mov.l 0x8+0x4(%a6),0x4(%a0)
1940 mov.l 0x8+0x8(%a6),0x8(%a0)
1941 bsr.l tag # fetch operand type
1942 mov.b %d0,STAG(%a6)
1943 mov.b %d0,%d1
1945 andi.l &0x00ff00ff,USER_FPSR(%a6)
1947 clr.l %d0
1948 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1950 tst.b %d1
1951 bne.b _L7_2x
1952 bsr.l sasin # operand is a NORM
1953 bra.b _L7_6x
1954 _L7_2x:
1955 cmpi.b %d1,&ZERO # is operand a ZERO?
1956 bne.b _L7_3x # no
1957 bsr.l src_zero # yes
1958 bra.b _L7_6x
1959 _L7_3x:
1960 cmpi.b %d1,&INF # is operand an INF?
1961 bne.b _L7_4x # no
1962 bsr.l t_operr # yes
1963 bra.b _L7_6x
1964 _L7_4x:
1965 cmpi.b %d1,&QNAN # is operand a QNAN?
1966 bne.b _L7_5x # no
1967 bsr.l src_qnan # yes
1968 bra.b _L7_6x
1969 _L7_5x:
1970 bsr.l sasind # operand is a DENORM
1971 _L7_6x:
1974 # Result is now in FP0
1976 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1977 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1978 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1979 unlk %a6
1983 #########################################################################
1984 # MONADIC TEMPLATE #
1985 #########################################################################
1986 global _fatanhs_
1987 _fatanhs_:
1988 link %a6,&-LOCAL_SIZE
1990 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1991 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1992 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1994 fmov.l &0x0,%fpcr # zero FPCR
1997 # copy, convert, and tag input argument
1999 fmov.s 0x8(%a6),%fp0 # load sgl input
2000 fmov.x %fp0,FP_SRC(%a6)
2001 lea FP_SRC(%a6),%a0
2002 bsr.l tag # fetch operand type
2003 mov.b %d0,STAG(%a6)
2004 mov.b %d0,%d1
2006 andi.l &0x00ff00ff,USER_FPSR(%a6)
2008 clr.l %d0
2009 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2011 tst.b %d1
2012 bne.b _L8_2s
2013 bsr.l satanh # operand is a NORM
2014 bra.b _L8_6s
2015 _L8_2s:
2016 cmpi.b %d1,&ZERO # is operand a ZERO?
2017 bne.b _L8_3s # no
2018 bsr.l src_zero # yes
2019 bra.b _L8_6s
2020 _L8_3s:
2021 cmpi.b %d1,&INF # is operand an INF?
2022 bne.b _L8_4s # no
2023 bsr.l t_operr # yes
2024 bra.b _L8_6s
2025 _L8_4s:
2026 cmpi.b %d1,&QNAN # is operand a QNAN?
2027 bne.b _L8_5s # no
2028 bsr.l src_qnan # yes
2029 bra.b _L8_6s
2030 _L8_5s:
2031 bsr.l satanhd # operand is a DENORM
2032 _L8_6s:
2035 # Result is now in FP0
2037 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2038 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2039 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2040 unlk %a6
2043 global _fatanhd_
2044 _fatanhd_:
2045 link %a6,&-LOCAL_SIZE
2047 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2048 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2049 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2051 fmov.l &0x0,%fpcr # zero FPCR
2054 # copy, convert, and tag input argument
2056 fmov.d 0x8(%a6),%fp0 # load dbl input
2057 fmov.x %fp0,FP_SRC(%a6)
2058 lea FP_SRC(%a6),%a0
2059 bsr.l tag # fetch operand type
2060 mov.b %d0,STAG(%a6)
2061 mov.b %d0,%d1
2063 andi.l &0x00ff00ff,USER_FPSR(%a6)
2065 clr.l %d0
2066 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2068 mov.b %d1,STAG(%a6)
2069 tst.b %d1
2070 bne.b _L8_2d
2071 bsr.l satanh # operand is a NORM
2072 bra.b _L8_6d
2073 _L8_2d:
2074 cmpi.b %d1,&ZERO # is operand a ZERO?
2075 bne.b _L8_3d # no
2076 bsr.l src_zero # yes
2077 bra.b _L8_6d
2078 _L8_3d:
2079 cmpi.b %d1,&INF # is operand an INF?
2080 bne.b _L8_4d # no
2081 bsr.l t_operr # yes
2082 bra.b _L8_6d
2083 _L8_4d:
2084 cmpi.b %d1,&QNAN # is operand a QNAN?
2085 bne.b _L8_5d # no
2086 bsr.l src_qnan # yes
2087 bra.b _L8_6d
2088 _L8_5d:
2089 bsr.l satanhd # operand is a DENORM
2090 _L8_6d:
2093 # Result is now in FP0
2095 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2096 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2097 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2098 unlk %a6
2101 global _fatanhx_
2102 _fatanhx_:
2103 link %a6,&-LOCAL_SIZE
2105 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2106 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2107 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2109 fmov.l &0x0,%fpcr # zero FPCR
2112 # copy, convert, and tag input argument
2114 lea FP_SRC(%a6),%a0
2115 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2116 mov.l 0x8+0x4(%a6),0x4(%a0)
2117 mov.l 0x8+0x8(%a6),0x8(%a0)
2118 bsr.l tag # fetch operand type
2119 mov.b %d0,STAG(%a6)
2120 mov.b %d0,%d1
2122 andi.l &0x00ff00ff,USER_FPSR(%a6)
2124 clr.l %d0
2125 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2127 tst.b %d1
2128 bne.b _L8_2x
2129 bsr.l satanh # operand is a NORM
2130 bra.b _L8_6x
2131 _L8_2x:
2132 cmpi.b %d1,&ZERO # is operand a ZERO?
2133 bne.b _L8_3x # no
2134 bsr.l src_zero # yes
2135 bra.b _L8_6x
2136 _L8_3x:
2137 cmpi.b %d1,&INF # is operand an INF?
2138 bne.b _L8_4x # no
2139 bsr.l t_operr # yes
2140 bra.b _L8_6x
2141 _L8_4x:
2142 cmpi.b %d1,&QNAN # is operand a QNAN?
2143 bne.b _L8_5x # no
2144 bsr.l src_qnan # yes
2145 bra.b _L8_6x
2146 _L8_5x:
2147 bsr.l satanhd # operand is a DENORM
2148 _L8_6x:
2151 # Result is now in FP0
2153 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2154 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2155 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2156 unlk %a6
2160 #########################################################################
2161 # MONADIC TEMPLATE #
2162 #########################################################################
2163 global _ftans_
2164 _ftans_:
2165 link %a6,&-LOCAL_SIZE
2167 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2168 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2169 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2171 fmov.l &0x0,%fpcr # zero FPCR
2174 # copy, convert, and tag input argument
2176 fmov.s 0x8(%a6),%fp0 # load sgl input
2177 fmov.x %fp0,FP_SRC(%a6)
2178 lea FP_SRC(%a6),%a0
2179 bsr.l tag # fetch operand type
2180 mov.b %d0,STAG(%a6)
2181 mov.b %d0,%d1
2183 andi.l &0x00ff00ff,USER_FPSR(%a6)
2185 clr.l %d0
2186 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2188 tst.b %d1
2189 bne.b _L9_2s
2190 bsr.l stan # operand is a NORM
2191 bra.b _L9_6s
2192 _L9_2s:
2193 cmpi.b %d1,&ZERO # is operand a ZERO?
2194 bne.b _L9_3s # no
2195 bsr.l src_zero # yes
2196 bra.b _L9_6s
2197 _L9_3s:
2198 cmpi.b %d1,&INF # is operand an INF?
2199 bne.b _L9_4s # no
2200 bsr.l t_operr # yes
2201 bra.b _L9_6s
2202 _L9_4s:
2203 cmpi.b %d1,&QNAN # is operand a QNAN?
2204 bne.b _L9_5s # no
2205 bsr.l src_qnan # yes
2206 bra.b _L9_6s
2207 _L9_5s:
2208 bsr.l stand # operand is a DENORM
2209 _L9_6s:
2212 # Result is now in FP0
2214 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2215 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2216 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2217 unlk %a6
2220 global _ftand_
2221 _ftand_:
2222 link %a6,&-LOCAL_SIZE
2224 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2225 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2226 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2228 fmov.l &0x0,%fpcr # zero FPCR
2231 # copy, convert, and tag input argument
2233 fmov.d 0x8(%a6),%fp0 # load dbl input
2234 fmov.x %fp0,FP_SRC(%a6)
2235 lea FP_SRC(%a6),%a0
2236 bsr.l tag # fetch operand type
2237 mov.b %d0,STAG(%a6)
2238 mov.b %d0,%d1
2240 andi.l &0x00ff00ff,USER_FPSR(%a6)
2242 clr.l %d0
2243 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2245 mov.b %d1,STAG(%a6)
2246 tst.b %d1
2247 bne.b _L9_2d
2248 bsr.l stan # operand is a NORM
2249 bra.b _L9_6d
2250 _L9_2d:
2251 cmpi.b %d1,&ZERO # is operand a ZERO?
2252 bne.b _L9_3d # no
2253 bsr.l src_zero # yes
2254 bra.b _L9_6d
2255 _L9_3d:
2256 cmpi.b %d1,&INF # is operand an INF?
2257 bne.b _L9_4d # no
2258 bsr.l t_operr # yes
2259 bra.b _L9_6d
2260 _L9_4d:
2261 cmpi.b %d1,&QNAN # is operand a QNAN?
2262 bne.b _L9_5d # no
2263 bsr.l src_qnan # yes
2264 bra.b _L9_6d
2265 _L9_5d:
2266 bsr.l stand # operand is a DENORM
2267 _L9_6d:
2270 # Result is now in FP0
2272 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2273 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2274 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2275 unlk %a6
2278 global _ftanx_
2279 _ftanx_:
2280 link %a6,&-LOCAL_SIZE
2282 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2283 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2284 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2286 fmov.l &0x0,%fpcr # zero FPCR
2289 # copy, convert, and tag input argument
2291 lea FP_SRC(%a6),%a0
2292 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2293 mov.l 0x8+0x4(%a6),0x4(%a0)
2294 mov.l 0x8+0x8(%a6),0x8(%a0)
2295 bsr.l tag # fetch operand type
2296 mov.b %d0,STAG(%a6)
2297 mov.b %d0,%d1
2299 andi.l &0x00ff00ff,USER_FPSR(%a6)
2301 clr.l %d0
2302 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2304 tst.b %d1
2305 bne.b _L9_2x
2306 bsr.l stan # operand is a NORM
2307 bra.b _L9_6x
2308 _L9_2x:
2309 cmpi.b %d1,&ZERO # is operand a ZERO?
2310 bne.b _L9_3x # no
2311 bsr.l src_zero # yes
2312 bra.b _L9_6x
2313 _L9_3x:
2314 cmpi.b %d1,&INF # is operand an INF?
2315 bne.b _L9_4x # no
2316 bsr.l t_operr # yes
2317 bra.b _L9_6x
2318 _L9_4x:
2319 cmpi.b %d1,&QNAN # is operand a QNAN?
2320 bne.b _L9_5x # no
2321 bsr.l src_qnan # yes
2322 bra.b _L9_6x
2323 _L9_5x:
2324 bsr.l stand # operand is a DENORM
2325 _L9_6x:
2328 # Result is now in FP0
2330 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2331 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2332 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2333 unlk %a6
2337 #########################################################################
2338 # MONADIC TEMPLATE #
2339 #########################################################################
2340 global _fetoxs_
2341 _fetoxs_:
2342 link %a6,&-LOCAL_SIZE
2344 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2345 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2346 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2348 fmov.l &0x0,%fpcr # zero FPCR
2351 # copy, convert, and tag input argument
2353 fmov.s 0x8(%a6),%fp0 # load sgl input
2354 fmov.x %fp0,FP_SRC(%a6)
2355 lea FP_SRC(%a6),%a0
2356 bsr.l tag # fetch operand type
2357 mov.b %d0,STAG(%a6)
2358 mov.b %d0,%d1
2360 andi.l &0x00ff00ff,USER_FPSR(%a6)
2362 clr.l %d0
2363 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2365 tst.b %d1
2366 bne.b _L10_2s
2367 bsr.l setox # operand is a NORM
2368 bra.b _L10_6s
2369 _L10_2s:
2370 cmpi.b %d1,&ZERO # is operand a ZERO?
2371 bne.b _L10_3s # no
2372 bsr.l ld_pone # yes
2373 bra.b _L10_6s
2374 _L10_3s:
2375 cmpi.b %d1,&INF # is operand an INF?
2376 bne.b _L10_4s # no
2377 bsr.l szr_inf # yes
2378 bra.b _L10_6s
2379 _L10_4s:
2380 cmpi.b %d1,&QNAN # is operand a QNAN?
2381 bne.b _L10_5s # no
2382 bsr.l src_qnan # yes
2383 bra.b _L10_6s
2384 _L10_5s:
2385 bsr.l setoxd # operand is a DENORM
2386 _L10_6s:
2389 # Result is now in FP0
2391 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2392 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2393 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2394 unlk %a6
2397 global _fetoxd_
2398 _fetoxd_:
2399 link %a6,&-LOCAL_SIZE
2401 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2402 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2403 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2405 fmov.l &0x0,%fpcr # zero FPCR
2408 # copy, convert, and tag input argument
2410 fmov.d 0x8(%a6),%fp0 # load dbl input
2411 fmov.x %fp0,FP_SRC(%a6)
2412 lea FP_SRC(%a6),%a0
2413 bsr.l tag # fetch operand type
2414 mov.b %d0,STAG(%a6)
2415 mov.b %d0,%d1
2417 andi.l &0x00ff00ff,USER_FPSR(%a6)
2419 clr.l %d0
2420 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2422 mov.b %d1,STAG(%a6)
2423 tst.b %d1
2424 bne.b _L10_2d
2425 bsr.l setox # operand is a NORM
2426 bra.b _L10_6d
2427 _L10_2d:
2428 cmpi.b %d1,&ZERO # is operand a ZERO?
2429 bne.b _L10_3d # no
2430 bsr.l ld_pone # yes
2431 bra.b _L10_6d
2432 _L10_3d:
2433 cmpi.b %d1,&INF # is operand an INF?
2434 bne.b _L10_4d # no
2435 bsr.l szr_inf # yes
2436 bra.b _L10_6d
2437 _L10_4d:
2438 cmpi.b %d1,&QNAN # is operand a QNAN?
2439 bne.b _L10_5d # no
2440 bsr.l src_qnan # yes
2441 bra.b _L10_6d
2442 _L10_5d:
2443 bsr.l setoxd # operand is a DENORM
2444 _L10_6d:
2447 # Result is now in FP0
2449 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2450 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2451 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2452 unlk %a6
2455 global _fetoxx_
2456 _fetoxx_:
2457 link %a6,&-LOCAL_SIZE
2459 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2460 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2461 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2463 fmov.l &0x0,%fpcr # zero FPCR
2466 # copy, convert, and tag input argument
2468 lea FP_SRC(%a6),%a0
2469 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2470 mov.l 0x8+0x4(%a6),0x4(%a0)
2471 mov.l 0x8+0x8(%a6),0x8(%a0)
2472 bsr.l tag # fetch operand type
2473 mov.b %d0,STAG(%a6)
2474 mov.b %d0,%d1
2476 andi.l &0x00ff00ff,USER_FPSR(%a6)
2478 clr.l %d0
2479 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2481 tst.b %d1
2482 bne.b _L10_2x
2483 bsr.l setox # operand is a NORM
2484 bra.b _L10_6x
2485 _L10_2x:
2486 cmpi.b %d1,&ZERO # is operand a ZERO?
2487 bne.b _L10_3x # no
2488 bsr.l ld_pone # yes
2489 bra.b _L10_6x
2490 _L10_3x:
2491 cmpi.b %d1,&INF # is operand an INF?
2492 bne.b _L10_4x # no
2493 bsr.l szr_inf # yes
2494 bra.b _L10_6x
2495 _L10_4x:
2496 cmpi.b %d1,&QNAN # is operand a QNAN?
2497 bne.b _L10_5x # no
2498 bsr.l src_qnan # yes
2499 bra.b _L10_6x
2500 _L10_5x:
2501 bsr.l setoxd # operand is a DENORM
2502 _L10_6x:
2505 # Result is now in FP0
2507 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2508 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2509 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2510 unlk %a6
2514 #########################################################################
2515 # MONADIC TEMPLATE #
2516 #########################################################################
2517 global _ftwotoxs_
2518 _ftwotoxs_:
2519 link %a6,&-LOCAL_SIZE
2521 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2522 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2523 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2525 fmov.l &0x0,%fpcr # zero FPCR
2528 # copy, convert, and tag input argument
2530 fmov.s 0x8(%a6),%fp0 # load sgl input
2531 fmov.x %fp0,FP_SRC(%a6)
2532 lea FP_SRC(%a6),%a0
2533 bsr.l tag # fetch operand type
2534 mov.b %d0,STAG(%a6)
2535 mov.b %d0,%d1
2537 andi.l &0x00ff00ff,USER_FPSR(%a6)
2539 clr.l %d0
2540 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2542 tst.b %d1
2543 bne.b _L11_2s
2544 bsr.l stwotox # operand is a NORM
2545 bra.b _L11_6s
2546 _L11_2s:
2547 cmpi.b %d1,&ZERO # is operand a ZERO?
2548 bne.b _L11_3s # no
2549 bsr.l ld_pone # yes
2550 bra.b _L11_6s
2551 _L11_3s:
2552 cmpi.b %d1,&INF # is operand an INF?
2553 bne.b _L11_4s # no
2554 bsr.l szr_inf # yes
2555 bra.b _L11_6s
2556 _L11_4s:
2557 cmpi.b %d1,&QNAN # is operand a QNAN?
2558 bne.b _L11_5s # no
2559 bsr.l src_qnan # yes
2560 bra.b _L11_6s
2561 _L11_5s:
2562 bsr.l stwotoxd # operand is a DENORM
2563 _L11_6s:
2566 # Result is now in FP0
2568 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2569 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2570 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2571 unlk %a6
2574 global _ftwotoxd_
2575 _ftwotoxd_:
2576 link %a6,&-LOCAL_SIZE
2578 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2579 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2580 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2582 fmov.l &0x0,%fpcr # zero FPCR
2585 # copy, convert, and tag input argument
2587 fmov.d 0x8(%a6),%fp0 # load dbl input
2588 fmov.x %fp0,FP_SRC(%a6)
2589 lea FP_SRC(%a6),%a0
2590 bsr.l tag # fetch operand type
2591 mov.b %d0,STAG(%a6)
2592 mov.b %d0,%d1
2594 andi.l &0x00ff00ff,USER_FPSR(%a6)
2596 clr.l %d0
2597 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2599 mov.b %d1,STAG(%a6)
2600 tst.b %d1
2601 bne.b _L11_2d
2602 bsr.l stwotox # operand is a NORM
2603 bra.b _L11_6d
2604 _L11_2d:
2605 cmpi.b %d1,&ZERO # is operand a ZERO?
2606 bne.b _L11_3d # no
2607 bsr.l ld_pone # yes
2608 bra.b _L11_6d
2609 _L11_3d:
2610 cmpi.b %d1,&INF # is operand an INF?
2611 bne.b _L11_4d # no
2612 bsr.l szr_inf # yes
2613 bra.b _L11_6d
2614 _L11_4d:
2615 cmpi.b %d1,&QNAN # is operand a QNAN?
2616 bne.b _L11_5d # no
2617 bsr.l src_qnan # yes
2618 bra.b _L11_6d
2619 _L11_5d:
2620 bsr.l stwotoxd # operand is a DENORM
2621 _L11_6d:
2624 # Result is now in FP0
2626 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2627 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2628 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2629 unlk %a6
2632 global _ftwotoxx_
2633 _ftwotoxx_:
2634 link %a6,&-LOCAL_SIZE
2636 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2637 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2638 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2640 fmov.l &0x0,%fpcr # zero FPCR
2643 # copy, convert, and tag input argument
2645 lea FP_SRC(%a6),%a0
2646 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2647 mov.l 0x8+0x4(%a6),0x4(%a0)
2648 mov.l 0x8+0x8(%a6),0x8(%a0)
2649 bsr.l tag # fetch operand type
2650 mov.b %d0,STAG(%a6)
2651 mov.b %d0,%d1
2653 andi.l &0x00ff00ff,USER_FPSR(%a6)
2655 clr.l %d0
2656 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2658 tst.b %d1
2659 bne.b _L11_2x
2660 bsr.l stwotox # operand is a NORM
2661 bra.b _L11_6x
2662 _L11_2x:
2663 cmpi.b %d1,&ZERO # is operand a ZERO?
2664 bne.b _L11_3x # no
2665 bsr.l ld_pone # yes
2666 bra.b _L11_6x
2667 _L11_3x:
2668 cmpi.b %d1,&INF # is operand an INF?
2669 bne.b _L11_4x # no
2670 bsr.l szr_inf # yes
2671 bra.b _L11_6x
2672 _L11_4x:
2673 cmpi.b %d1,&QNAN # is operand a QNAN?
2674 bne.b _L11_5x # no
2675 bsr.l src_qnan # yes
2676 bra.b _L11_6x
2677 _L11_5x:
2678 bsr.l stwotoxd # operand is a DENORM
2679 _L11_6x:
2682 # Result is now in FP0
2684 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2685 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2686 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2687 unlk %a6
2691 #########################################################################
2692 # MONADIC TEMPLATE #
2693 #########################################################################
2694 global _ftentoxs_
2695 _ftentoxs_:
2696 link %a6,&-LOCAL_SIZE
2698 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2699 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2700 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2702 fmov.l &0x0,%fpcr # zero FPCR
2705 # copy, convert, and tag input argument
2707 fmov.s 0x8(%a6),%fp0 # load sgl input
2708 fmov.x %fp0,FP_SRC(%a6)
2709 lea FP_SRC(%a6),%a0
2710 bsr.l tag # fetch operand type
2711 mov.b %d0,STAG(%a6)
2712 mov.b %d0,%d1
2714 andi.l &0x00ff00ff,USER_FPSR(%a6)
2716 clr.l %d0
2717 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2719 tst.b %d1
2720 bne.b _L12_2s
2721 bsr.l stentox # operand is a NORM
2722 bra.b _L12_6s
2723 _L12_2s:
2724 cmpi.b %d1,&ZERO # is operand a ZERO?
2725 bne.b _L12_3s # no
2726 bsr.l ld_pone # yes
2727 bra.b _L12_6s
2728 _L12_3s:
2729 cmpi.b %d1,&INF # is operand an INF?
2730 bne.b _L12_4s # no
2731 bsr.l szr_inf # yes
2732 bra.b _L12_6s
2733 _L12_4s:
2734 cmpi.b %d1,&QNAN # is operand a QNAN?
2735 bne.b _L12_5s # no
2736 bsr.l src_qnan # yes
2737 bra.b _L12_6s
2738 _L12_5s:
2739 bsr.l stentoxd # operand is a DENORM
2740 _L12_6s:
2743 # Result is now in FP0
2745 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2746 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2747 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2748 unlk %a6
2751 global _ftentoxd_
2752 _ftentoxd_:
2753 link %a6,&-LOCAL_SIZE
2755 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2756 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2757 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2759 fmov.l &0x0,%fpcr # zero FPCR
2762 # copy, convert, and tag input argument
2764 fmov.d 0x8(%a6),%fp0 # load dbl input
2765 fmov.x %fp0,FP_SRC(%a6)
2766 lea FP_SRC(%a6),%a0
2767 bsr.l tag # fetch operand type
2768 mov.b %d0,STAG(%a6)
2769 mov.b %d0,%d1
2771 andi.l &0x00ff00ff,USER_FPSR(%a6)
2773 clr.l %d0
2774 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2776 mov.b %d1,STAG(%a6)
2777 tst.b %d1
2778 bne.b _L12_2d
2779 bsr.l stentox # operand is a NORM
2780 bra.b _L12_6d
2781 _L12_2d:
2782 cmpi.b %d1,&ZERO # is operand a ZERO?
2783 bne.b _L12_3d # no
2784 bsr.l ld_pone # yes
2785 bra.b _L12_6d
2786 _L12_3d:
2787 cmpi.b %d1,&INF # is operand an INF?
2788 bne.b _L12_4d # no
2789 bsr.l szr_inf # yes
2790 bra.b _L12_6d
2791 _L12_4d:
2792 cmpi.b %d1,&QNAN # is operand a QNAN?
2793 bne.b _L12_5d # no
2794 bsr.l src_qnan # yes
2795 bra.b _L12_6d
2796 _L12_5d:
2797 bsr.l stentoxd # operand is a DENORM
2798 _L12_6d:
2801 # Result is now in FP0
2803 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2804 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2805 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2806 unlk %a6
2809 global _ftentoxx_
2810 _ftentoxx_:
2811 link %a6,&-LOCAL_SIZE
2813 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2814 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2815 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2817 fmov.l &0x0,%fpcr # zero FPCR
2820 # copy, convert, and tag input argument
2822 lea FP_SRC(%a6),%a0
2823 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2824 mov.l 0x8+0x4(%a6),0x4(%a0)
2825 mov.l 0x8+0x8(%a6),0x8(%a0)
2826 bsr.l tag # fetch operand type
2827 mov.b %d0,STAG(%a6)
2828 mov.b %d0,%d1
2830 andi.l &0x00ff00ff,USER_FPSR(%a6)
2832 clr.l %d0
2833 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2835 tst.b %d1
2836 bne.b _L12_2x
2837 bsr.l stentox # operand is a NORM
2838 bra.b _L12_6x
2839 _L12_2x:
2840 cmpi.b %d1,&ZERO # is operand a ZERO?
2841 bne.b _L12_3x # no
2842 bsr.l ld_pone # yes
2843 bra.b _L12_6x
2844 _L12_3x:
2845 cmpi.b %d1,&INF # is operand an INF?
2846 bne.b _L12_4x # no
2847 bsr.l szr_inf # yes
2848 bra.b _L12_6x
2849 _L12_4x:
2850 cmpi.b %d1,&QNAN # is operand a QNAN?
2851 bne.b _L12_5x # no
2852 bsr.l src_qnan # yes
2853 bra.b _L12_6x
2854 _L12_5x:
2855 bsr.l stentoxd # operand is a DENORM
2856 _L12_6x:
2859 # Result is now in FP0
2861 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2862 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2863 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2864 unlk %a6
2868 #########################################################################
2869 # MONADIC TEMPLATE #
2870 #########################################################################
2871 global _flogns_
2872 _flogns_:
2873 link %a6,&-LOCAL_SIZE
2875 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2876 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2877 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2879 fmov.l &0x0,%fpcr # zero FPCR
2882 # copy, convert, and tag input argument
2884 fmov.s 0x8(%a6),%fp0 # load sgl input
2885 fmov.x %fp0,FP_SRC(%a6)
2886 lea FP_SRC(%a6),%a0
2887 bsr.l tag # fetch operand type
2888 mov.b %d0,STAG(%a6)
2889 mov.b %d0,%d1
2891 andi.l &0x00ff00ff,USER_FPSR(%a6)
2893 clr.l %d0
2894 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2896 tst.b %d1
2897 bne.b _L13_2s
2898 bsr.l slogn # operand is a NORM
2899 bra.b _L13_6s
2900 _L13_2s:
2901 cmpi.b %d1,&ZERO # is operand a ZERO?
2902 bne.b _L13_3s # no
2903 bsr.l t_dz2 # yes
2904 bra.b _L13_6s
2905 _L13_3s:
2906 cmpi.b %d1,&INF # is operand an INF?
2907 bne.b _L13_4s # no
2908 bsr.l sopr_inf # yes
2909 bra.b _L13_6s
2910 _L13_4s:
2911 cmpi.b %d1,&QNAN # is operand a QNAN?
2912 bne.b _L13_5s # no
2913 bsr.l src_qnan # yes
2914 bra.b _L13_6s
2915 _L13_5s:
2916 bsr.l slognd # operand is a DENORM
2917 _L13_6s:
2920 # Result is now in FP0
2922 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2923 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2924 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2925 unlk %a6
2928 global _flognd_
2929 _flognd_:
2930 link %a6,&-LOCAL_SIZE
2932 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2933 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2934 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2936 fmov.l &0x0,%fpcr # zero FPCR
2939 # copy, convert, and tag input argument
2941 fmov.d 0x8(%a6),%fp0 # load dbl input
2942 fmov.x %fp0,FP_SRC(%a6)
2943 lea FP_SRC(%a6),%a0
2944 bsr.l tag # fetch operand type
2945 mov.b %d0,STAG(%a6)
2946 mov.b %d0,%d1
2948 andi.l &0x00ff00ff,USER_FPSR(%a6)
2950 clr.l %d0
2951 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2953 mov.b %d1,STAG(%a6)
2954 tst.b %d1
2955 bne.b _L13_2d
2956 bsr.l slogn # operand is a NORM
2957 bra.b _L13_6d
2958 _L13_2d:
2959 cmpi.b %d1,&ZERO # is operand a ZERO?
2960 bne.b _L13_3d # no
2961 bsr.l t_dz2 # yes
2962 bra.b _L13_6d
2963 _L13_3d:
2964 cmpi.b %d1,&INF # is operand an INF?
2965 bne.b _L13_4d # no
2966 bsr.l sopr_inf # yes
2967 bra.b _L13_6d
2968 _L13_4d:
2969 cmpi.b %d1,&QNAN # is operand a QNAN?
2970 bne.b _L13_5d # no
2971 bsr.l src_qnan # yes
2972 bra.b _L13_6d
2973 _L13_5d:
2974 bsr.l slognd # operand is a DENORM
2975 _L13_6d:
2978 # Result is now in FP0
2980 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2981 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2982 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2983 unlk %a6
2986 global _flognx_
2987 _flognx_:
2988 link %a6,&-LOCAL_SIZE
2990 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2991 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2992 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2994 fmov.l &0x0,%fpcr # zero FPCR
2997 # copy, convert, and tag input argument
2999 lea FP_SRC(%a6),%a0
3000 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3001 mov.l 0x8+0x4(%a6),0x4(%a0)
3002 mov.l 0x8+0x8(%a6),0x8(%a0)
3003 bsr.l tag # fetch operand type
3004 mov.b %d0,STAG(%a6)
3005 mov.b %d0,%d1
3007 andi.l &0x00ff00ff,USER_FPSR(%a6)
3009 clr.l %d0
3010 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3012 tst.b %d1
3013 bne.b _L13_2x
3014 bsr.l slogn # operand is a NORM
3015 bra.b _L13_6x
3016 _L13_2x:
3017 cmpi.b %d1,&ZERO # is operand a ZERO?
3018 bne.b _L13_3x # no
3019 bsr.l t_dz2 # yes
3020 bra.b _L13_6x
3021 _L13_3x:
3022 cmpi.b %d1,&INF # is operand an INF?
3023 bne.b _L13_4x # no
3024 bsr.l sopr_inf # yes
3025 bra.b _L13_6x
3026 _L13_4x:
3027 cmpi.b %d1,&QNAN # is operand a QNAN?
3028 bne.b _L13_5x # no
3029 bsr.l src_qnan # yes
3030 bra.b _L13_6x
3031 _L13_5x:
3032 bsr.l slognd # operand is a DENORM
3033 _L13_6x:
3036 # Result is now in FP0
3038 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3039 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3040 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3041 unlk %a6
3045 #########################################################################
3046 # MONADIC TEMPLATE #
3047 #########################################################################
3048 global _flog10s_
3049 _flog10s_:
3050 link %a6,&-LOCAL_SIZE
3052 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3053 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3054 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3056 fmov.l &0x0,%fpcr # zero FPCR
3059 # copy, convert, and tag input argument
3061 fmov.s 0x8(%a6),%fp0 # load sgl input
3062 fmov.x %fp0,FP_SRC(%a6)
3063 lea FP_SRC(%a6),%a0
3064 bsr.l tag # fetch operand type
3065 mov.b %d0,STAG(%a6)
3066 mov.b %d0,%d1
3068 andi.l &0x00ff00ff,USER_FPSR(%a6)
3070 clr.l %d0
3071 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3073 tst.b %d1
3074 bne.b _L14_2s
3075 bsr.l slog10 # operand is a NORM
3076 bra.b _L14_6s
3077 _L14_2s:
3078 cmpi.b %d1,&ZERO # is operand a ZERO?
3079 bne.b _L14_3s # no
3080 bsr.l t_dz2 # yes
3081 bra.b _L14_6s
3082 _L14_3s:
3083 cmpi.b %d1,&INF # is operand an INF?
3084 bne.b _L14_4s # no
3085 bsr.l sopr_inf # yes
3086 bra.b _L14_6s
3087 _L14_4s:
3088 cmpi.b %d1,&QNAN # is operand a QNAN?
3089 bne.b _L14_5s # no
3090 bsr.l src_qnan # yes
3091 bra.b _L14_6s
3092 _L14_5s:
3093 bsr.l slog10d # operand is a DENORM
3094 _L14_6s:
3097 # Result is now in FP0
3099 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3100 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3101 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3102 unlk %a6
3105 global _flog10d_
3106 _flog10d_:
3107 link %a6,&-LOCAL_SIZE
3109 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3110 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3111 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3113 fmov.l &0x0,%fpcr # zero FPCR
3116 # copy, convert, and tag input argument
3118 fmov.d 0x8(%a6),%fp0 # load dbl input
3119 fmov.x %fp0,FP_SRC(%a6)
3120 lea FP_SRC(%a6),%a0
3121 bsr.l tag # fetch operand type
3122 mov.b %d0,STAG(%a6)
3123 mov.b %d0,%d1
3125 andi.l &0x00ff00ff,USER_FPSR(%a6)
3127 clr.l %d0
3128 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3130 mov.b %d1,STAG(%a6)
3131 tst.b %d1
3132 bne.b _L14_2d
3133 bsr.l slog10 # operand is a NORM
3134 bra.b _L14_6d
3135 _L14_2d:
3136 cmpi.b %d1,&ZERO # is operand a ZERO?
3137 bne.b _L14_3d # no
3138 bsr.l t_dz2 # yes
3139 bra.b _L14_6d
3140 _L14_3d:
3141 cmpi.b %d1,&INF # is operand an INF?
3142 bne.b _L14_4d # no
3143 bsr.l sopr_inf # yes
3144 bra.b _L14_6d
3145 _L14_4d:
3146 cmpi.b %d1,&QNAN # is operand a QNAN?
3147 bne.b _L14_5d # no
3148 bsr.l src_qnan # yes
3149 bra.b _L14_6d
3150 _L14_5d:
3151 bsr.l slog10d # operand is a DENORM
3152 _L14_6d:
3155 # Result is now in FP0
3157 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3158 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3159 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3160 unlk %a6
3163 global _flog10x_
3164 _flog10x_:
3165 link %a6,&-LOCAL_SIZE
3167 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3168 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3169 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3171 fmov.l &0x0,%fpcr # zero FPCR
3174 # copy, convert, and tag input argument
3176 lea FP_SRC(%a6),%a0
3177 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3178 mov.l 0x8+0x4(%a6),0x4(%a0)
3179 mov.l 0x8+0x8(%a6),0x8(%a0)
3180 bsr.l tag # fetch operand type
3181 mov.b %d0,STAG(%a6)
3182 mov.b %d0,%d1
3184 andi.l &0x00ff00ff,USER_FPSR(%a6)
3186 clr.l %d0
3187 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3189 tst.b %d1
3190 bne.b _L14_2x
3191 bsr.l slog10 # operand is a NORM
3192 bra.b _L14_6x
3193 _L14_2x:
3194 cmpi.b %d1,&ZERO # is operand a ZERO?
3195 bne.b _L14_3x # no
3196 bsr.l t_dz2 # yes
3197 bra.b _L14_6x
3198 _L14_3x:
3199 cmpi.b %d1,&INF # is operand an INF?
3200 bne.b _L14_4x # no
3201 bsr.l sopr_inf # yes
3202 bra.b _L14_6x
3203 _L14_4x:
3204 cmpi.b %d1,&QNAN # is operand a QNAN?
3205 bne.b _L14_5x # no
3206 bsr.l src_qnan # yes
3207 bra.b _L14_6x
3208 _L14_5x:
3209 bsr.l slog10d # operand is a DENORM
3210 _L14_6x:
3213 # Result is now in FP0
3215 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3216 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3217 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3218 unlk %a6
3222 #########################################################################
3223 # MONADIC TEMPLATE #
3224 #########################################################################
3225 global _flog2s_
3226 _flog2s_:
3227 link %a6,&-LOCAL_SIZE
3229 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3230 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3231 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3233 fmov.l &0x0,%fpcr # zero FPCR
3236 # copy, convert, and tag input argument
3238 fmov.s 0x8(%a6),%fp0 # load sgl input
3239 fmov.x %fp0,FP_SRC(%a6)
3240 lea FP_SRC(%a6),%a0
3241 bsr.l tag # fetch operand type
3242 mov.b %d0,STAG(%a6)
3243 mov.b %d0,%d1
3245 andi.l &0x00ff00ff,USER_FPSR(%a6)
3247 clr.l %d0
3248 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3250 tst.b %d1
3251 bne.b _L15_2s
3252 bsr.l slog2 # operand is a NORM
3253 bra.b _L15_6s
3254 _L15_2s:
3255 cmpi.b %d1,&ZERO # is operand a ZERO?
3256 bne.b _L15_3s # no
3257 bsr.l t_dz2 # yes
3258 bra.b _L15_6s
3259 _L15_3s:
3260 cmpi.b %d1,&INF # is operand an INF?
3261 bne.b _L15_4s # no
3262 bsr.l sopr_inf # yes
3263 bra.b _L15_6s
3264 _L15_4s:
3265 cmpi.b %d1,&QNAN # is operand a QNAN?
3266 bne.b _L15_5s # no
3267 bsr.l src_qnan # yes
3268 bra.b _L15_6s
3269 _L15_5s:
3270 bsr.l slog2d # operand is a DENORM
3271 _L15_6s:
3274 # Result is now in FP0
3276 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3277 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3278 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3279 unlk %a6
3282 global _flog2d_
3283 _flog2d_:
3284 link %a6,&-LOCAL_SIZE
3286 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3287 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3288 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3290 fmov.l &0x0,%fpcr # zero FPCR
3293 # copy, convert, and tag input argument
3295 fmov.d 0x8(%a6),%fp0 # load dbl input
3296 fmov.x %fp0,FP_SRC(%a6)
3297 lea FP_SRC(%a6),%a0
3298 bsr.l tag # fetch operand type
3299 mov.b %d0,STAG(%a6)
3300 mov.b %d0,%d1
3302 andi.l &0x00ff00ff,USER_FPSR(%a6)
3304 clr.l %d0
3305 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3307 mov.b %d1,STAG(%a6)
3308 tst.b %d1
3309 bne.b _L15_2d
3310 bsr.l slog2 # operand is a NORM
3311 bra.b _L15_6d
3312 _L15_2d:
3313 cmpi.b %d1,&ZERO # is operand a ZERO?
3314 bne.b _L15_3d # no
3315 bsr.l t_dz2 # yes
3316 bra.b _L15_6d
3317 _L15_3d:
3318 cmpi.b %d1,&INF # is operand an INF?
3319 bne.b _L15_4d # no
3320 bsr.l sopr_inf # yes
3321 bra.b _L15_6d
3322 _L15_4d:
3323 cmpi.b %d1,&QNAN # is operand a QNAN?
3324 bne.b _L15_5d # no
3325 bsr.l src_qnan # yes
3326 bra.b _L15_6d
3327 _L15_5d:
3328 bsr.l slog2d # operand is a DENORM
3329 _L15_6d:
3332 # Result is now in FP0
3334 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3335 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3336 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3337 unlk %a6
3340 global _flog2x_
3341 _flog2x_:
3342 link %a6,&-LOCAL_SIZE
3344 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3345 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3346 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3348 fmov.l &0x0,%fpcr # zero FPCR
3351 # copy, convert, and tag input argument
3353 lea FP_SRC(%a6),%a0
3354 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3355 mov.l 0x8+0x4(%a6),0x4(%a0)
3356 mov.l 0x8+0x8(%a6),0x8(%a0)
3357 bsr.l tag # fetch operand type
3358 mov.b %d0,STAG(%a6)
3359 mov.b %d0,%d1
3361 andi.l &0x00ff00ff,USER_FPSR(%a6)
3363 clr.l %d0
3364 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3366 tst.b %d1
3367 bne.b _L15_2x
3368 bsr.l slog2 # operand is a NORM
3369 bra.b _L15_6x
3370 _L15_2x:
3371 cmpi.b %d1,&ZERO # is operand a ZERO?
3372 bne.b _L15_3x # no
3373 bsr.l t_dz2 # yes
3374 bra.b _L15_6x
3375 _L15_3x:
3376 cmpi.b %d1,&INF # is operand an INF?
3377 bne.b _L15_4x # no
3378 bsr.l sopr_inf # yes
3379 bra.b _L15_6x
3380 _L15_4x:
3381 cmpi.b %d1,&QNAN # is operand a QNAN?
3382 bne.b _L15_5x # no
3383 bsr.l src_qnan # yes
3384 bra.b _L15_6x
3385 _L15_5x:
3386 bsr.l slog2d # operand is a DENORM
3387 _L15_6x:
3390 # Result is now in FP0
3392 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3393 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3394 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3395 unlk %a6
3399 #########################################################################
3400 # MONADIC TEMPLATE #
3401 #########################################################################
3402 global _fcoshs_
3403 _fcoshs_:
3404 link %a6,&-LOCAL_SIZE
3406 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3407 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3408 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3410 fmov.l &0x0,%fpcr # zero FPCR
3413 # copy, convert, and tag input argument
3415 fmov.s 0x8(%a6),%fp0 # load sgl input
3416 fmov.x %fp0,FP_SRC(%a6)
3417 lea FP_SRC(%a6),%a0
3418 bsr.l tag # fetch operand type
3419 mov.b %d0,STAG(%a6)
3420 mov.b %d0,%d1
3422 andi.l &0x00ff00ff,USER_FPSR(%a6)
3424 clr.l %d0
3425 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3427 tst.b %d1
3428 bne.b _L16_2s
3429 bsr.l scosh # operand is a NORM
3430 bra.b _L16_6s
3431 _L16_2s:
3432 cmpi.b %d1,&ZERO # is operand a ZERO?
3433 bne.b _L16_3s # no
3434 bsr.l ld_pone # yes
3435 bra.b _L16_6s
3436 _L16_3s:
3437 cmpi.b %d1,&INF # is operand an INF?
3438 bne.b _L16_4s # no
3439 bsr.l ld_pinf # yes
3440 bra.b _L16_6s
3441 _L16_4s:
3442 cmpi.b %d1,&QNAN # is operand a QNAN?
3443 bne.b _L16_5s # no
3444 bsr.l src_qnan # yes
3445 bra.b _L16_6s
3446 _L16_5s:
3447 bsr.l scoshd # operand is a DENORM
3448 _L16_6s:
3451 # Result is now in FP0
3453 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3454 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3455 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3456 unlk %a6
3459 global _fcoshd_
3460 _fcoshd_:
3461 link %a6,&-LOCAL_SIZE
3463 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3464 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3465 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3467 fmov.l &0x0,%fpcr # zero FPCR
3470 # copy, convert, and tag input argument
3472 fmov.d 0x8(%a6),%fp0 # load dbl input
3473 fmov.x %fp0,FP_SRC(%a6)
3474 lea FP_SRC(%a6),%a0
3475 bsr.l tag # fetch operand type
3476 mov.b %d0,STAG(%a6)
3477 mov.b %d0,%d1
3479 andi.l &0x00ff00ff,USER_FPSR(%a6)
3481 clr.l %d0
3482 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3484 mov.b %d1,STAG(%a6)
3485 tst.b %d1
3486 bne.b _L16_2d
3487 bsr.l scosh # operand is a NORM
3488 bra.b _L16_6d
3489 _L16_2d:
3490 cmpi.b %d1,&ZERO # is operand a ZERO?
3491 bne.b _L16_3d # no
3492 bsr.l ld_pone # yes
3493 bra.b _L16_6d
3494 _L16_3d:
3495 cmpi.b %d1,&INF # is operand an INF?
3496 bne.b _L16_4d # no
3497 bsr.l ld_pinf # yes
3498 bra.b _L16_6d
3499 _L16_4d:
3500 cmpi.b %d1,&QNAN # is operand a QNAN?
3501 bne.b _L16_5d # no
3502 bsr.l src_qnan # yes
3503 bra.b _L16_6d
3504 _L16_5d:
3505 bsr.l scoshd # operand is a DENORM
3506 _L16_6d:
3509 # Result is now in FP0
3511 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3512 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3513 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3514 unlk %a6
3517 global _fcoshx_
3518 _fcoshx_:
3519 link %a6,&-LOCAL_SIZE
3521 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3522 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3523 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3525 fmov.l &0x0,%fpcr # zero FPCR
3528 # copy, convert, and tag input argument
3530 lea FP_SRC(%a6),%a0
3531 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3532 mov.l 0x8+0x4(%a6),0x4(%a0)
3533 mov.l 0x8+0x8(%a6),0x8(%a0)
3534 bsr.l tag # fetch operand type
3535 mov.b %d0,STAG(%a6)
3536 mov.b %d0,%d1
3538 andi.l &0x00ff00ff,USER_FPSR(%a6)
3540 clr.l %d0
3541 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3543 tst.b %d1
3544 bne.b _L16_2x
3545 bsr.l scosh # operand is a NORM
3546 bra.b _L16_6x
3547 _L16_2x:
3548 cmpi.b %d1,&ZERO # is operand a ZERO?
3549 bne.b _L16_3x # no
3550 bsr.l ld_pone # yes
3551 bra.b _L16_6x
3552 _L16_3x:
3553 cmpi.b %d1,&INF # is operand an INF?
3554 bne.b _L16_4x # no
3555 bsr.l ld_pinf # yes
3556 bra.b _L16_6x
3557 _L16_4x:
3558 cmpi.b %d1,&QNAN # is operand a QNAN?
3559 bne.b _L16_5x # no
3560 bsr.l src_qnan # yes
3561 bra.b _L16_6x
3562 _L16_5x:
3563 bsr.l scoshd # operand is a DENORM
3564 _L16_6x:
3567 # Result is now in FP0
3569 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3570 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3571 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3572 unlk %a6
3576 #########################################################################
3577 # MONADIC TEMPLATE #
3578 #########################################################################
3579 global _facoss_
3580 _facoss_:
3581 link %a6,&-LOCAL_SIZE
3583 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3584 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3585 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3587 fmov.l &0x0,%fpcr # zero FPCR
3590 # copy, convert, and tag input argument
3592 fmov.s 0x8(%a6),%fp0 # load sgl input
3593 fmov.x %fp0,FP_SRC(%a6)
3594 lea FP_SRC(%a6),%a0
3595 bsr.l tag # fetch operand type
3596 mov.b %d0,STAG(%a6)
3597 mov.b %d0,%d1
3599 andi.l &0x00ff00ff,USER_FPSR(%a6)
3601 clr.l %d0
3602 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3604 tst.b %d1
3605 bne.b _L17_2s
3606 bsr.l sacos # operand is a NORM
3607 bra.b _L17_6s
3608 _L17_2s:
3609 cmpi.b %d1,&ZERO # is operand a ZERO?
3610 bne.b _L17_3s # no
3611 bsr.l ld_ppi2 # yes
3612 bra.b _L17_6s
3613 _L17_3s:
3614 cmpi.b %d1,&INF # is operand an INF?
3615 bne.b _L17_4s # no
3616 bsr.l t_operr # yes
3617 bra.b _L17_6s
3618 _L17_4s:
3619 cmpi.b %d1,&QNAN # is operand a QNAN?
3620 bne.b _L17_5s # no
3621 bsr.l src_qnan # yes
3622 bra.b _L17_6s
3623 _L17_5s:
3624 bsr.l sacosd # operand is a DENORM
3625 _L17_6s:
3628 # Result is now in FP0
3630 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3631 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3632 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3633 unlk %a6
3636 global _facosd_
3637 _facosd_:
3638 link %a6,&-LOCAL_SIZE
3640 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3641 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3642 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3644 fmov.l &0x0,%fpcr # zero FPCR
3647 # copy, convert, and tag input argument
3649 fmov.d 0x8(%a6),%fp0 # load dbl input
3650 fmov.x %fp0,FP_SRC(%a6)
3651 lea FP_SRC(%a6),%a0
3652 bsr.l tag # fetch operand type
3653 mov.b %d0,STAG(%a6)
3654 mov.b %d0,%d1
3656 andi.l &0x00ff00ff,USER_FPSR(%a6)
3658 clr.l %d0
3659 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3661 mov.b %d1,STAG(%a6)
3662 tst.b %d1
3663 bne.b _L17_2d
3664 bsr.l sacos # operand is a NORM
3665 bra.b _L17_6d
3666 _L17_2d:
3667 cmpi.b %d1,&ZERO # is operand a ZERO?
3668 bne.b _L17_3d # no
3669 bsr.l ld_ppi2 # yes
3670 bra.b _L17_6d
3671 _L17_3d:
3672 cmpi.b %d1,&INF # is operand an INF?
3673 bne.b _L17_4d # no
3674 bsr.l t_operr # yes
3675 bra.b _L17_6d
3676 _L17_4d:
3677 cmpi.b %d1,&QNAN # is operand a QNAN?
3678 bne.b _L17_5d # no
3679 bsr.l src_qnan # yes
3680 bra.b _L17_6d
3681 _L17_5d:
3682 bsr.l sacosd # operand is a DENORM
3683 _L17_6d:
3686 # Result is now in FP0
3688 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3689 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3690 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3691 unlk %a6
3694 global _facosx_
3695 _facosx_:
3696 link %a6,&-LOCAL_SIZE
3698 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3699 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3700 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3702 fmov.l &0x0,%fpcr # zero FPCR
3705 # copy, convert, and tag input argument
3707 lea FP_SRC(%a6),%a0
3708 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3709 mov.l 0x8+0x4(%a6),0x4(%a0)
3710 mov.l 0x8+0x8(%a6),0x8(%a0)
3711 bsr.l tag # fetch operand type
3712 mov.b %d0,STAG(%a6)
3713 mov.b %d0,%d1
3715 andi.l &0x00ff00ff,USER_FPSR(%a6)
3717 clr.l %d0
3718 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3720 tst.b %d1
3721 bne.b _L17_2x
3722 bsr.l sacos # operand is a NORM
3723 bra.b _L17_6x
3724 _L17_2x:
3725 cmpi.b %d1,&ZERO # is operand a ZERO?
3726 bne.b _L17_3x # no
3727 bsr.l ld_ppi2 # yes
3728 bra.b _L17_6x
3729 _L17_3x:
3730 cmpi.b %d1,&INF # is operand an INF?
3731 bne.b _L17_4x # no
3732 bsr.l t_operr # yes
3733 bra.b _L17_6x
3734 _L17_4x:
3735 cmpi.b %d1,&QNAN # is operand a QNAN?
3736 bne.b _L17_5x # no
3737 bsr.l src_qnan # yes
3738 bra.b _L17_6x
3739 _L17_5x:
3740 bsr.l sacosd # operand is a DENORM
3741 _L17_6x:
3744 # Result is now in FP0
3746 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3747 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3748 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3749 unlk %a6
3753 #########################################################################
3754 # MONADIC TEMPLATE #
3755 #########################################################################
3756 global _fgetexps_
3757 _fgetexps_:
3758 link %a6,&-LOCAL_SIZE
3760 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3761 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3762 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3764 fmov.l &0x0,%fpcr # zero FPCR
3767 # copy, convert, and tag input argument
3769 fmov.s 0x8(%a6),%fp0 # load sgl input
3770 fmov.x %fp0,FP_SRC(%a6)
3771 lea FP_SRC(%a6),%a0
3772 bsr.l tag # fetch operand type
3773 mov.b %d0,STAG(%a6)
3774 mov.b %d0,%d1
3776 andi.l &0x00ff00ff,USER_FPSR(%a6)
3778 clr.l %d0
3779 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3781 tst.b %d1
3782 bne.b _L18_2s
3783 bsr.l sgetexp # operand is a NORM
3784 bra.b _L18_6s
3785 _L18_2s:
3786 cmpi.b %d1,&ZERO # is operand a ZERO?
3787 bne.b _L18_3s # no
3788 bsr.l src_zero # yes
3789 bra.b _L18_6s
3790 _L18_3s:
3791 cmpi.b %d1,&INF # is operand an INF?
3792 bne.b _L18_4s # no
3793 bsr.l t_operr # yes
3794 bra.b _L18_6s
3795 _L18_4s:
3796 cmpi.b %d1,&QNAN # is operand a QNAN?
3797 bne.b _L18_5s # no
3798 bsr.l src_qnan # yes
3799 bra.b _L18_6s
3800 _L18_5s:
3801 bsr.l sgetexpd # operand is a DENORM
3802 _L18_6s:
3805 # Result is now in FP0
3807 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3808 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3809 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3810 unlk %a6
3813 global _fgetexpd_
3814 _fgetexpd_:
3815 link %a6,&-LOCAL_SIZE
3817 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3818 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3819 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3821 fmov.l &0x0,%fpcr # zero FPCR
3824 # copy, convert, and tag input argument
3826 fmov.d 0x8(%a6),%fp0 # load dbl input
3827 fmov.x %fp0,FP_SRC(%a6)
3828 lea FP_SRC(%a6),%a0
3829 bsr.l tag # fetch operand type
3830 mov.b %d0,STAG(%a6)
3831 mov.b %d0,%d1
3833 andi.l &0x00ff00ff,USER_FPSR(%a6)
3835 clr.l %d0
3836 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3838 mov.b %d1,STAG(%a6)
3839 tst.b %d1
3840 bne.b _L18_2d
3841 bsr.l sgetexp # operand is a NORM
3842 bra.b _L18_6d
3843 _L18_2d:
3844 cmpi.b %d1,&ZERO # is operand a ZERO?
3845 bne.b _L18_3d # no
3846 bsr.l src_zero # yes
3847 bra.b _L18_6d
3848 _L18_3d:
3849 cmpi.b %d1,&INF # is operand an INF?
3850 bne.b _L18_4d # no
3851 bsr.l t_operr # yes
3852 bra.b _L18_6d
3853 _L18_4d:
3854 cmpi.b %d1,&QNAN # is operand a QNAN?
3855 bne.b _L18_5d # no
3856 bsr.l src_qnan # yes
3857 bra.b _L18_6d
3858 _L18_5d:
3859 bsr.l sgetexpd # operand is a DENORM
3860 _L18_6d:
3863 # Result is now in FP0
3865 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3866 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3867 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3868 unlk %a6
3871 global _fgetexpx_
3872 _fgetexpx_:
3873 link %a6,&-LOCAL_SIZE
3875 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3876 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3877 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3879 fmov.l &0x0,%fpcr # zero FPCR
3882 # copy, convert, and tag input argument
3884 lea FP_SRC(%a6),%a0
3885 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3886 mov.l 0x8+0x4(%a6),0x4(%a0)
3887 mov.l 0x8+0x8(%a6),0x8(%a0)
3888 bsr.l tag # fetch operand type
3889 mov.b %d0,STAG(%a6)
3890 mov.b %d0,%d1
3892 andi.l &0x00ff00ff,USER_FPSR(%a6)
3894 clr.l %d0
3895 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3897 tst.b %d1
3898 bne.b _L18_2x
3899 bsr.l sgetexp # operand is a NORM
3900 bra.b _L18_6x
3901 _L18_2x:
3902 cmpi.b %d1,&ZERO # is operand a ZERO?
3903 bne.b _L18_3x # no
3904 bsr.l src_zero # yes
3905 bra.b _L18_6x
3906 _L18_3x:
3907 cmpi.b %d1,&INF # is operand an INF?
3908 bne.b _L18_4x # no
3909 bsr.l t_operr # yes
3910 bra.b _L18_6x
3911 _L18_4x:
3912 cmpi.b %d1,&QNAN # is operand a QNAN?
3913 bne.b _L18_5x # no
3914 bsr.l src_qnan # yes
3915 bra.b _L18_6x
3916 _L18_5x:
3917 bsr.l sgetexpd # operand is a DENORM
3918 _L18_6x:
3921 # Result is now in FP0
3923 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3924 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3925 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3926 unlk %a6
3930 #########################################################################
3931 # MONADIC TEMPLATE #
3932 #########################################################################
3933 global _fgetmans_
3934 _fgetmans_:
3935 link %a6,&-LOCAL_SIZE
3937 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3938 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3939 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3941 fmov.l &0x0,%fpcr # zero FPCR
3944 # copy, convert, and tag input argument
3946 fmov.s 0x8(%a6),%fp0 # load sgl input
3947 fmov.x %fp0,FP_SRC(%a6)
3948 lea FP_SRC(%a6),%a0
3949 bsr.l tag # fetch operand type
3950 mov.b %d0,STAG(%a6)
3951 mov.b %d0,%d1
3953 andi.l &0x00ff00ff,USER_FPSR(%a6)
3955 clr.l %d0
3956 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3958 tst.b %d1
3959 bne.b _L19_2s
3960 bsr.l sgetman # operand is a NORM
3961 bra.b _L19_6s
3962 _L19_2s:
3963 cmpi.b %d1,&ZERO # is operand a ZERO?
3964 bne.b _L19_3s # no
3965 bsr.l src_zero # yes
3966 bra.b _L19_6s
3967 _L19_3s:
3968 cmpi.b %d1,&INF # is operand an INF?
3969 bne.b _L19_4s # no
3970 bsr.l t_operr # yes
3971 bra.b _L19_6s
3972 _L19_4s:
3973 cmpi.b %d1,&QNAN # is operand a QNAN?
3974 bne.b _L19_5s # no
3975 bsr.l src_qnan # yes
3976 bra.b _L19_6s
3977 _L19_5s:
3978 bsr.l sgetmand # operand is a DENORM
3979 _L19_6s:
3982 # Result is now in FP0
3984 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3985 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3986 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3987 unlk %a6
3990 global _fgetmand_
3991 _fgetmand_:
3992 link %a6,&-LOCAL_SIZE
3994 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3995 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3996 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3998 fmov.l &0x0,%fpcr # zero FPCR
4001 # copy, convert, and tag input argument
4003 fmov.d 0x8(%a6),%fp0 # load dbl input
4004 fmov.x %fp0,FP_SRC(%a6)
4005 lea FP_SRC(%a6),%a0
4006 bsr.l tag # fetch operand type
4007 mov.b %d0,STAG(%a6)
4008 mov.b %d0,%d1
4010 andi.l &0x00ff00ff,USER_FPSR(%a6)
4012 clr.l %d0
4013 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4015 mov.b %d1,STAG(%a6)
4016 tst.b %d1
4017 bne.b _L19_2d
4018 bsr.l sgetman # operand is a NORM
4019 bra.b _L19_6d
4020 _L19_2d:
4021 cmpi.b %d1,&ZERO # is operand a ZERO?
4022 bne.b _L19_3d # no
4023 bsr.l src_zero # yes
4024 bra.b _L19_6d
4025 _L19_3d:
4026 cmpi.b %d1,&INF # is operand an INF?
4027 bne.b _L19_4d # no
4028 bsr.l t_operr # yes
4029 bra.b _L19_6d
4030 _L19_4d:
4031 cmpi.b %d1,&QNAN # is operand a QNAN?
4032 bne.b _L19_5d # no
4033 bsr.l src_qnan # yes
4034 bra.b _L19_6d
4035 _L19_5d:
4036 bsr.l sgetmand # operand is a DENORM
4037 _L19_6d:
4040 # Result is now in FP0
4042 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4043 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4044 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4045 unlk %a6
4048 global _fgetmanx_
4049 _fgetmanx_:
4050 link %a6,&-LOCAL_SIZE
4052 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4053 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4054 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4056 fmov.l &0x0,%fpcr # zero FPCR
4059 # copy, convert, and tag input argument
4061 lea FP_SRC(%a6),%a0
4062 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
4063 mov.l 0x8+0x4(%a6),0x4(%a0)
4064 mov.l 0x8+0x8(%a6),0x8(%a0)
4065 bsr.l tag # fetch operand type
4066 mov.b %d0,STAG(%a6)
4067 mov.b %d0,%d1
4069 andi.l &0x00ff00ff,USER_FPSR(%a6)
4071 clr.l %d0
4072 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4074 tst.b %d1
4075 bne.b _L19_2x
4076 bsr.l sgetman # operand is a NORM
4077 bra.b _L19_6x
4078 _L19_2x:
4079 cmpi.b %d1,&ZERO # is operand a ZERO?
4080 bne.b _L19_3x # no
4081 bsr.l src_zero # yes
4082 bra.b _L19_6x
4083 _L19_3x:
4084 cmpi.b %d1,&INF # is operand an INF?
4085 bne.b _L19_4x # no
4086 bsr.l t_operr # yes
4087 bra.b _L19_6x
4088 _L19_4x:
4089 cmpi.b %d1,&QNAN # is operand a QNAN?
4090 bne.b _L19_5x # no
4091 bsr.l src_qnan # yes
4092 bra.b _L19_6x
4093 _L19_5x:
4094 bsr.l sgetmand # operand is a DENORM
4095 _L19_6x:
4098 # Result is now in FP0
4100 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4101 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4102 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4103 unlk %a6
4107 #########################################################################
4108 # MONADIC TEMPLATE #
4109 #########################################################################
4110 global _fsincoss_
4111 _fsincoss_:
4112 link %a6,&-LOCAL_SIZE
4114 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4115 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4116 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4118 fmov.l &0x0,%fpcr # zero FPCR
4121 # copy, convert, and tag input argument
4123 fmov.s 0x8(%a6),%fp0 # load sgl input
4124 fmov.x %fp0,FP_SRC(%a6)
4125 lea FP_SRC(%a6),%a0
4126 bsr.l tag # fetch operand type
4127 mov.b %d0,STAG(%a6)
4128 mov.b %d0,%d1
4130 andi.l &0x00ff00ff,USER_FPSR(%a6)
4132 clr.l %d0
4133 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4135 tst.b %d1
4136 bne.b _L20_2s
4137 bsr.l ssincos # operand is a NORM
4138 bra.b _L20_6s
4139 _L20_2s:
4140 cmpi.b %d1,&ZERO # is operand a ZERO?
4141 bne.b _L20_3s # no
4142 bsr.l ssincosz # yes
4143 bra.b _L20_6s
4144 _L20_3s:
4145 cmpi.b %d1,&INF # is operand an INF?
4146 bne.b _L20_4s # no
4147 bsr.l ssincosi # yes
4148 bra.b _L20_6s
4149 _L20_4s:
4150 cmpi.b %d1,&QNAN # is operand a QNAN?
4151 bne.b _L20_5s # no
4152 bsr.l ssincosqnan # yes
4153 bra.b _L20_6s
4154 _L20_5s:
4155 bsr.l ssincosd # operand is a DENORM
4156 _L20_6s:
4159 # Result is now in FP0
4161 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4162 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4163 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4164 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4165 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4166 unlk %a6
4169 global _fsincosd_
4170 _fsincosd_:
4171 link %a6,&-LOCAL_SIZE
4173 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4174 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4175 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4177 fmov.l &0x0,%fpcr # zero FPCR
4180 # copy, convert, and tag input argument
4182 fmov.d 0x8(%a6),%fp0 # load dbl input
4183 fmov.x %fp0,FP_SRC(%a6)
4184 lea FP_SRC(%a6),%a0
4185 bsr.l tag # fetch operand type
4186 mov.b %d0,STAG(%a6)
4187 mov.b %d0,%d1
4189 andi.l &0x00ff00ff,USER_FPSR(%a6)
4191 clr.l %d0
4192 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4194 mov.b %d1,STAG(%a6)
4195 tst.b %d1
4196 bne.b _L20_2d
4197 bsr.l ssincos # operand is a NORM
4198 bra.b _L20_6d
4199 _L20_2d:
4200 cmpi.b %d1,&ZERO # is operand a ZERO?
4201 bne.b _L20_3d # no
4202 bsr.l ssincosz # yes
4203 bra.b _L20_6d
4204 _L20_3d:
4205 cmpi.b %d1,&INF # is operand an INF?
4206 bne.b _L20_4d # no
4207 bsr.l ssincosi # yes
4208 bra.b _L20_6d
4209 _L20_4d:
4210 cmpi.b %d1,&QNAN # is operand a QNAN?
4211 bne.b _L20_5d # no
4212 bsr.l ssincosqnan # yes
4213 bra.b _L20_6d
4214 _L20_5d:
4215 bsr.l ssincosd # operand is a DENORM
4216 _L20_6d:
4219 # Result is now in FP0
4221 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4222 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4223 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4224 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4225 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4226 unlk %a6
4229 global _fsincosx_
4230 _fsincosx_:
4231 link %a6,&-LOCAL_SIZE
4233 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4234 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4235 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4237 fmov.l &0x0,%fpcr # zero FPCR
4240 # copy, convert, and tag input argument
4242 lea FP_SRC(%a6),%a0
4243 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
4244 mov.l 0x8+0x4(%a6),0x4(%a0)
4245 mov.l 0x8+0x8(%a6),0x8(%a0)
4246 bsr.l tag # fetch operand type
4247 mov.b %d0,STAG(%a6)
4248 mov.b %d0,%d1
4250 andi.l &0x00ff00ff,USER_FPSR(%a6)
4252 clr.l %d0
4253 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4255 tst.b %d1
4256 bne.b _L20_2x
4257 bsr.l ssincos # operand is a NORM
4258 bra.b _L20_6x
4259 _L20_2x:
4260 cmpi.b %d1,&ZERO # is operand a ZERO?
4261 bne.b _L20_3x # no
4262 bsr.l ssincosz # yes
4263 bra.b _L20_6x
4264 _L20_3x:
4265 cmpi.b %d1,&INF # is operand an INF?
4266 bne.b _L20_4x # no
4267 bsr.l ssincosi # yes
4268 bra.b _L20_6x
4269 _L20_4x:
4270 cmpi.b %d1,&QNAN # is operand a QNAN?
4271 bne.b _L20_5x # no
4272 bsr.l ssincosqnan # yes
4273 bra.b _L20_6x
4274 _L20_5x:
4275 bsr.l ssincosd # operand is a DENORM
4276 _L20_6x:
4279 # Result is now in FP0
4281 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4282 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4283 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4284 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4285 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4286 unlk %a6
4290 #########################################################################
4291 # DYADIC TEMPLATE #
4292 #########################################################################
4293 global _frems_
4294 _frems_:
4295 link %a6,&-LOCAL_SIZE
4297 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4298 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4299 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4301 fmov.l &0x0,%fpcr # zero FPCR
4304 # copy, convert, and tag input argument
4306 fmov.s 0x8(%a6),%fp0 # load sgl dst
4307 fmov.x %fp0,FP_DST(%a6)
4308 lea FP_DST(%a6),%a0
4309 bsr.l tag # fetch operand type
4310 mov.b %d0,DTAG(%a6)
4312 fmov.s 0xc(%a6),%fp0 # load sgl src
4313 fmov.x %fp0,FP_SRC(%a6)
4314 lea FP_SRC(%a6),%a0
4315 bsr.l tag # fetch operand type
4316 mov.b %d0,STAG(%a6)
4317 mov.l %d0,%d1
4319 andi.l &0x00ff00ff,USER_FPSR(%a6)
4321 clr.l %d0
4322 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4324 lea FP_SRC(%a6),%a0 # pass ptr to src
4325 lea FP_DST(%a6),%a1 # pass ptr to dst
4327 tst.b %d1
4328 bne.b _L21_2s
4329 bsr.l srem_snorm # operand is a NORM
4330 bra.b _L21_6s
4331 _L21_2s:
4332 cmpi.b %d1,&ZERO # is operand a ZERO?
4333 bne.b _L21_3s # no
4334 bsr.l srem_szero # yes
4335 bra.b _L21_6s
4336 _L21_3s:
4337 cmpi.b %d1,&INF # is operand an INF?
4338 bne.b _L21_4s # no
4339 bsr.l srem_sinf # yes
4340 bra.b _L21_6s
4341 _L21_4s:
4342 cmpi.b %d1,&QNAN # is operand a QNAN?
4343 bne.b _L21_5s # no
4344 bsr.l sop_sqnan # yes
4345 bra.b _L21_6s
4346 _L21_5s:
4347 bsr.l srem_sdnrm # operand is a DENORM
4348 _L21_6s:
4351 # Result is now in FP0
4353 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4354 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4355 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4356 unlk %a6
4359 global _fremd_
4360 _fremd_:
4361 link %a6,&-LOCAL_SIZE
4363 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4364 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4365 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4367 fmov.l &0x0,%fpcr # zero FPCR
4370 # copy, convert, and tag input argument
4372 fmov.d 0x8(%a6),%fp0 # load dbl dst
4373 fmov.x %fp0,FP_DST(%a6)
4374 lea FP_DST(%a6),%a0
4375 bsr.l tag # fetch operand type
4376 mov.b %d0,DTAG(%a6)
4378 fmov.d 0x10(%a6),%fp0 # load dbl src
4379 fmov.x %fp0,FP_SRC(%a6)
4380 lea FP_SRC(%a6),%a0
4381 bsr.l tag # fetch operand type
4382 mov.b %d0,STAG(%a6)
4383 mov.l %d0,%d1
4385 andi.l &0x00ff00ff,USER_FPSR(%a6)
4387 clr.l %d0
4388 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4390 lea FP_SRC(%a6),%a0 # pass ptr to src
4391 lea FP_DST(%a6),%a1 # pass ptr to dst
4393 tst.b %d1
4394 bne.b _L21_2d
4395 bsr.l srem_snorm # operand is a NORM
4396 bra.b _L21_6d
4397 _L21_2d:
4398 cmpi.b %d1,&ZERO # is operand a ZERO?
4399 bne.b _L21_3d # no
4400 bsr.l srem_szero # yes
4401 bra.b _L21_6d
4402 _L21_3d:
4403 cmpi.b %d1,&INF # is operand an INF?
4404 bne.b _L21_4d # no
4405 bsr.l srem_sinf # yes
4406 bra.b _L21_6d
4407 _L21_4d:
4408 cmpi.b %d1,&QNAN # is operand a QNAN?
4409 bne.b _L21_5d # no
4410 bsr.l sop_sqnan # yes
4411 bra.b _L21_6d
4412 _L21_5d:
4413 bsr.l srem_sdnrm # operand is a DENORM
4414 _L21_6d:
4417 # Result is now in FP0
4419 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4420 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4421 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4422 unlk %a6
4425 global _fremx_
4426 _fremx_:
4427 link %a6,&-LOCAL_SIZE
4429 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4430 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4431 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4433 fmov.l &0x0,%fpcr # zero FPCR
4436 # copy, convert, and tag input argument
4438 lea FP_DST(%a6),%a0
4439 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4440 mov.l 0x8+0x4(%a6),0x4(%a0)
4441 mov.l 0x8+0x8(%a6),0x8(%a0)
4442 bsr.l tag # fetch operand type
4443 mov.b %d0,DTAG(%a6)
4445 lea FP_SRC(%a6),%a0
4446 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4447 mov.l 0x14+0x4(%a6),0x4(%a0)
4448 mov.l 0x14+0x8(%a6),0x8(%a0)
4449 bsr.l tag # fetch operand type
4450 mov.b %d0,STAG(%a6)
4451 mov.l %d0,%d1
4453 andi.l &0x00ff00ff,USER_FPSR(%a6)
4455 clr.l %d0
4456 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4458 lea FP_SRC(%a6),%a0 # pass ptr to src
4459 lea FP_DST(%a6),%a1 # pass ptr to dst
4461 tst.b %d1
4462 bne.b _L21_2x
4463 bsr.l srem_snorm # operand is a NORM
4464 bra.b _L21_6x
4465 _L21_2x:
4466 cmpi.b %d1,&ZERO # is operand a ZERO?
4467 bne.b _L21_3x # no
4468 bsr.l srem_szero # yes
4469 bra.b _L21_6x
4470 _L21_3x:
4471 cmpi.b %d1,&INF # is operand an INF?
4472 bne.b _L21_4x # no
4473 bsr.l srem_sinf # yes
4474 bra.b _L21_6x
4475 _L21_4x:
4476 cmpi.b %d1,&QNAN # is operand a QNAN?
4477 bne.b _L21_5x # no
4478 bsr.l sop_sqnan # yes
4479 bra.b _L21_6x
4480 _L21_5x:
4481 bsr.l srem_sdnrm # operand is a DENORM
4482 _L21_6x:
4485 # Result is now in FP0
4487 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4488 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4489 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4490 unlk %a6
4494 #########################################################################
4495 # DYADIC TEMPLATE #
4496 #########################################################################
4497 global _fmods_
4498 _fmods_:
4499 link %a6,&-LOCAL_SIZE
4501 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4502 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4503 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4505 fmov.l &0x0,%fpcr # zero FPCR
4508 # copy, convert, and tag input argument
4510 fmov.s 0x8(%a6),%fp0 # load sgl dst
4511 fmov.x %fp0,FP_DST(%a6)
4512 lea FP_DST(%a6),%a0
4513 bsr.l tag # fetch operand type
4514 mov.b %d0,DTAG(%a6)
4516 fmov.s 0xc(%a6),%fp0 # load sgl src
4517 fmov.x %fp0,FP_SRC(%a6)
4518 lea FP_SRC(%a6),%a0
4519 bsr.l tag # fetch operand type
4520 mov.b %d0,STAG(%a6)
4521 mov.l %d0,%d1
4523 andi.l &0x00ff00ff,USER_FPSR(%a6)
4525 clr.l %d0
4526 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4528 lea FP_SRC(%a6),%a0 # pass ptr to src
4529 lea FP_DST(%a6),%a1 # pass ptr to dst
4531 tst.b %d1
4532 bne.b _L22_2s
4533 bsr.l smod_snorm # operand is a NORM
4534 bra.b _L22_6s
4535 _L22_2s:
4536 cmpi.b %d1,&ZERO # is operand a ZERO?
4537 bne.b _L22_3s # no
4538 bsr.l smod_szero # yes
4539 bra.b _L22_6s
4540 _L22_3s:
4541 cmpi.b %d1,&INF # is operand an INF?
4542 bne.b _L22_4s # no
4543 bsr.l smod_sinf # yes
4544 bra.b _L22_6s
4545 _L22_4s:
4546 cmpi.b %d1,&QNAN # is operand a QNAN?
4547 bne.b _L22_5s # no
4548 bsr.l sop_sqnan # yes
4549 bra.b _L22_6s
4550 _L22_5s:
4551 bsr.l smod_sdnrm # operand is a DENORM
4552 _L22_6s:
4555 # Result is now in FP0
4557 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4558 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4559 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4560 unlk %a6
4563 global _fmodd_
4564 _fmodd_:
4565 link %a6,&-LOCAL_SIZE
4567 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4568 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4569 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4571 fmov.l &0x0,%fpcr # zero FPCR
4574 # copy, convert, and tag input argument
4576 fmov.d 0x8(%a6),%fp0 # load dbl dst
4577 fmov.x %fp0,FP_DST(%a6)
4578 lea FP_DST(%a6),%a0
4579 bsr.l tag # fetch operand type
4580 mov.b %d0,DTAG(%a6)
4582 fmov.d 0x10(%a6),%fp0 # load dbl src
4583 fmov.x %fp0,FP_SRC(%a6)
4584 lea FP_SRC(%a6),%a0
4585 bsr.l tag # fetch operand type
4586 mov.b %d0,STAG(%a6)
4587 mov.l %d0,%d1
4589 andi.l &0x00ff00ff,USER_FPSR(%a6)
4591 clr.l %d0
4592 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4594 lea FP_SRC(%a6),%a0 # pass ptr to src
4595 lea FP_DST(%a6),%a1 # pass ptr to dst
4597 tst.b %d1
4598 bne.b _L22_2d
4599 bsr.l smod_snorm # operand is a NORM
4600 bra.b _L22_6d
4601 _L22_2d:
4602 cmpi.b %d1,&ZERO # is operand a ZERO?
4603 bne.b _L22_3d # no
4604 bsr.l smod_szero # yes
4605 bra.b _L22_6d
4606 _L22_3d:
4607 cmpi.b %d1,&INF # is operand an INF?
4608 bne.b _L22_4d # no
4609 bsr.l smod_sinf # yes
4610 bra.b _L22_6d
4611 _L22_4d:
4612 cmpi.b %d1,&QNAN # is operand a QNAN?
4613 bne.b _L22_5d # no
4614 bsr.l sop_sqnan # yes
4615 bra.b _L22_6d
4616 _L22_5d:
4617 bsr.l smod_sdnrm # operand is a DENORM
4618 _L22_6d:
4621 # Result is now in FP0
4623 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4624 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4625 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4626 unlk %a6
4629 global _fmodx_
4630 _fmodx_:
4631 link %a6,&-LOCAL_SIZE
4633 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4634 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4635 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4637 fmov.l &0x0,%fpcr # zero FPCR
4640 # copy, convert, and tag input argument
4642 lea FP_DST(%a6),%a0
4643 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4644 mov.l 0x8+0x4(%a6),0x4(%a0)
4645 mov.l 0x8+0x8(%a6),0x8(%a0)
4646 bsr.l tag # fetch operand type
4647 mov.b %d0,DTAG(%a6)
4649 lea FP_SRC(%a6),%a0
4650 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4651 mov.l 0x14+0x4(%a6),0x4(%a0)
4652 mov.l 0x14+0x8(%a6),0x8(%a0)
4653 bsr.l tag # fetch operand type
4654 mov.b %d0,STAG(%a6)
4655 mov.l %d0,%d1
4657 andi.l &0x00ff00ff,USER_FPSR(%a6)
4659 clr.l %d0
4660 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4662 lea FP_SRC(%a6),%a0 # pass ptr to src
4663 lea FP_DST(%a6),%a1 # pass ptr to dst
4665 tst.b %d1
4666 bne.b _L22_2x
4667 bsr.l smod_snorm # operand is a NORM
4668 bra.b _L22_6x
4669 _L22_2x:
4670 cmpi.b %d1,&ZERO # is operand a ZERO?
4671 bne.b _L22_3x # no
4672 bsr.l smod_szero # yes
4673 bra.b _L22_6x
4674 _L22_3x:
4675 cmpi.b %d1,&INF # is operand an INF?
4676 bne.b _L22_4x # no
4677 bsr.l smod_sinf # yes
4678 bra.b _L22_6x
4679 _L22_4x:
4680 cmpi.b %d1,&QNAN # is operand a QNAN?
4681 bne.b _L22_5x # no
4682 bsr.l sop_sqnan # yes
4683 bra.b _L22_6x
4684 _L22_5x:
4685 bsr.l smod_sdnrm # operand is a DENORM
4686 _L22_6x:
4689 # Result is now in FP0
4691 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4692 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4693 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4694 unlk %a6
4698 #########################################################################
4699 # DYADIC TEMPLATE #
4700 #########################################################################
4701 global _fscales_
4702 _fscales_:
4703 link %a6,&-LOCAL_SIZE
4705 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4706 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4707 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4709 fmov.l &0x0,%fpcr # zero FPCR
4712 # copy, convert, and tag input argument
4714 fmov.s 0x8(%a6),%fp0 # load sgl dst
4715 fmov.x %fp0,FP_DST(%a6)
4716 lea FP_DST(%a6),%a0
4717 bsr.l tag # fetch operand type
4718 mov.b %d0,DTAG(%a6)
4720 fmov.s 0xc(%a6),%fp0 # load sgl src
4721 fmov.x %fp0,FP_SRC(%a6)
4722 lea FP_SRC(%a6),%a0
4723 bsr.l tag # fetch operand type
4724 mov.b %d0,STAG(%a6)
4725 mov.l %d0,%d1
4727 andi.l &0x00ff00ff,USER_FPSR(%a6)
4729 clr.l %d0
4730 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4732 lea FP_SRC(%a6),%a0 # pass ptr to src
4733 lea FP_DST(%a6),%a1 # pass ptr to dst
4735 tst.b %d1
4736 bne.b _L23_2s
4737 bsr.l sscale_snorm # operand is a NORM
4738 bra.b _L23_6s
4739 _L23_2s:
4740 cmpi.b %d1,&ZERO # is operand a ZERO?
4741 bne.b _L23_3s # no
4742 bsr.l sscale_szero # yes
4743 bra.b _L23_6s
4744 _L23_3s:
4745 cmpi.b %d1,&INF # is operand an INF?
4746 bne.b _L23_4s # no
4747 bsr.l sscale_sinf # yes
4748 bra.b _L23_6s
4749 _L23_4s:
4750 cmpi.b %d1,&QNAN # is operand a QNAN?
4751 bne.b _L23_5s # no
4752 bsr.l sop_sqnan # yes
4753 bra.b _L23_6s
4754 _L23_5s:
4755 bsr.l sscale_sdnrm # operand is a DENORM
4756 _L23_6s:
4759 # Result is now in FP0
4761 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4762 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4763 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4764 unlk %a6
4767 global _fscaled_
4768 _fscaled_:
4769 link %a6,&-LOCAL_SIZE
4771 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4772 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4773 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4775 fmov.l &0x0,%fpcr # zero FPCR
4778 # copy, convert, and tag input argument
4780 fmov.d 0x8(%a6),%fp0 # load dbl dst
4781 fmov.x %fp0,FP_DST(%a6)
4782 lea FP_DST(%a6),%a0
4783 bsr.l tag # fetch operand type
4784 mov.b %d0,DTAG(%a6)
4786 fmov.d 0x10(%a6),%fp0 # load dbl src
4787 fmov.x %fp0,FP_SRC(%a6)
4788 lea FP_SRC(%a6),%a0
4789 bsr.l tag # fetch operand type
4790 mov.b %d0,STAG(%a6)
4791 mov.l %d0,%d1
4793 andi.l &0x00ff00ff,USER_FPSR(%a6)
4795 clr.l %d0
4796 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4798 lea FP_SRC(%a6),%a0 # pass ptr to src
4799 lea FP_DST(%a6),%a1 # pass ptr to dst
4801 tst.b %d1
4802 bne.b _L23_2d
4803 bsr.l sscale_snorm # operand is a NORM
4804 bra.b _L23_6d
4805 _L23_2d:
4806 cmpi.b %d1,&ZERO # is operand a ZERO?
4807 bne.b _L23_3d # no
4808 bsr.l sscale_szero # yes
4809 bra.b _L23_6d
4810 _L23_3d:
4811 cmpi.b %d1,&INF # is operand an INF?
4812 bne.b _L23_4d # no
4813 bsr.l sscale_sinf # yes
4814 bra.b _L23_6d
4815 _L23_4d:
4816 cmpi.b %d1,&QNAN # is operand a QNAN?
4817 bne.b _L23_5d # no
4818 bsr.l sop_sqnan # yes
4819 bra.b _L23_6d
4820 _L23_5d:
4821 bsr.l sscale_sdnrm # operand is a DENORM
4822 _L23_6d:
4825 # Result is now in FP0
4827 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4828 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4829 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4830 unlk %a6
4833 global _fscalex_
4834 _fscalex_:
4835 link %a6,&-LOCAL_SIZE
4837 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4838 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4839 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4841 fmov.l &0x0,%fpcr # zero FPCR
4844 # copy, convert, and tag input argument
4846 lea FP_DST(%a6),%a0
4847 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4848 mov.l 0x8+0x4(%a6),0x4(%a0)
4849 mov.l 0x8+0x8(%a6),0x8(%a0)
4850 bsr.l tag # fetch operand type
4851 mov.b %d0,DTAG(%a6)
4853 lea FP_SRC(%a6),%a0
4854 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4855 mov.l 0x14+0x4(%a6),0x4(%a0)
4856 mov.l 0x14+0x8(%a6),0x8(%a0)
4857 bsr.l tag # fetch operand type
4858 mov.b %d0,STAG(%a6)
4859 mov.l %d0,%d1
4861 andi.l &0x00ff00ff,USER_FPSR(%a6)
4863 clr.l %d0
4864 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4866 lea FP_SRC(%a6),%a0 # pass ptr to src
4867 lea FP_DST(%a6),%a1 # pass ptr to dst
4869 tst.b %d1
4870 bne.b _L23_2x
4871 bsr.l sscale_snorm # operand is a NORM
4872 bra.b _L23_6x
4873 _L23_2x:
4874 cmpi.b %d1,&ZERO # is operand a ZERO?
4875 bne.b _L23_3x # no
4876 bsr.l sscale_szero # yes
4877 bra.b _L23_6x
4878 _L23_3x:
4879 cmpi.b %d1,&INF # is operand an INF?
4880 bne.b _L23_4x # no
4881 bsr.l sscale_sinf # yes
4882 bra.b _L23_6x
4883 _L23_4x:
4884 cmpi.b %d1,&QNAN # is operand a QNAN?
4885 bne.b _L23_5x # no
4886 bsr.l sop_sqnan # yes
4887 bra.b _L23_6x
4888 _L23_5x:
4889 bsr.l sscale_sdnrm # operand is a DENORM
4890 _L23_6x:
4893 # Result is now in FP0
4895 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4896 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4897 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4898 unlk %a6
4902 #########################################################################
4903 # ssin(): computes the sine of a normalized input #
4904 # ssind(): computes the sine of a denormalized input #
4905 # scos(): computes the cosine of a normalized input #
4906 # scosd(): computes the cosine of a denormalized input #
4907 # ssincos(): computes the sine and cosine of a normalized input #
4908 # ssincosd(): computes the sine and cosine of a denormalized input #
4910 # INPUT *************************************************************** #
4911 # a0 = pointer to extended precision input #
4912 # d0 = round precision,mode #
4914 # OUTPUT ************************************************************** #
4915 # fp0 = sin(X) or cos(X) #
4917 # For ssincos(X): #
4918 # fp0 = sin(X) #
4919 # fp1 = cos(X) #
4921 # ACCURACY and MONOTONICITY ******************************************* #
4922 # The returned result is within 1 ulp in 64 significant bit, i.e. #
4923 # within 0.5001 ulp to 53 bits if the result is subsequently #
4924 # rounded to double precision. The result is provably monotonic #
4925 # in double precision. #
4927 # ALGORITHM *********************************************************** #
4929 # SIN and COS: #
4930 # 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1. #
4932 # 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7. #
4934 # 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
4935 # k = N mod 4, so in particular, k = 0,1,2,or 3. #
4936 # Overwrite k by k := k + AdjN. #
4938 # 4. If k is even, go to 6. #
4940 # 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. #
4941 # Return sgn*cos(r) where cos(r) is approximated by an #
4942 # even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)), #
4943 # s = r*r. #
4944 # Exit. #
4946 # 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r) #
4947 # where sin(r) is approximated by an odd polynomial in r #
4948 # r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r. #
4949 # Exit. #
4951 # 7. If |X| > 1, go to 9. #
4953 # 8. (|X|<2**(-40)) If SIN is invoked, return X; #
4954 # otherwise return 1. #
4956 # 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
4957 # go back to 3. #
4959 # SINCOS: #
4960 # 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
4962 # 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
4963 # k = N mod 4, so in particular, k = 0,1,2,or 3. #
4965 # 3. If k is even, go to 5. #
4967 # 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie. #
4968 # j1 exclusive or with the l.s.b. of k. #
4969 # sgn1 := (-1)**j1, sgn2 := (-1)**j2. #
4970 # SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where #
4971 # sin(r) and cos(r) are computed as odd and even #
4972 # polynomials in r, respectively. Exit #
4974 # 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1. #
4975 # SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where #
4976 # sin(r) and cos(r) are computed as odd and even #
4977 # polynomials in r, respectively. Exit #
4979 # 6. If |X| > 1, go to 8. #
4981 # 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit. #
4983 # 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
4984 # go back to 2. #
4986 #########################################################################
4988 SINA7: long 0xBD6AAA77,0xCCC994F5
4989 SINA6: long 0x3DE61209,0x7AAE8DA1
4990 SINA5: long 0xBE5AE645,0x2A118AE4
4991 SINA4: long 0x3EC71DE3,0xA5341531
4992 SINA3: long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
4993 SINA2: long 0x3FF80000,0x88888888,0x888859AF,0x00000000
4994 SINA1: long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
4996 COSB8: long 0x3D2AC4D0,0xD6011EE3
4997 COSB7: long 0xBDA9396F,0x9F45AC19
4998 COSB6: long 0x3E21EED9,0x0612C972
4999 COSB5: long 0xBE927E4F,0xB79D9FCF
5000 COSB4: long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
5001 COSB3: long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
5002 COSB2: long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
5003 COSB1: long 0xBF000000
5005 set INARG,FP_SCR0
5007 set X,FP_SCR0
5008 # set XDCARE,X+2
5009 set XFRAC,X+4
5011 set RPRIME,FP_SCR0
5012 set SPRIME,FP_SCR1
5014 set POSNEG1,L_SCR1
5015 set TWOTO63,L_SCR1
5017 set ENDFLAG,L_SCR2
5018 set INT,L_SCR2
5020 set ADJN,L_SCR3
5022 ############################################
5023 global ssin
5024 ssin:
5025 mov.l &0,ADJN(%a6) # yes; SET ADJN TO 0
5026 bra.b SINBGN
5028 ############################################
5029 global scos
5030 scos:
5031 mov.l &1,ADJN(%a6) # yes; SET ADJN TO 1
5033 ############################################
5034 SINBGN:
5035 #--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
5037 fmov.x (%a0),%fp0 # LOAD INPUT
5038 fmov.x %fp0,X(%a6) # save input at X
5040 # "COMPACTIFY" X
5041 mov.l (%a0),%d1 # put exp in hi word
5042 mov.w 4(%a0),%d1 # fetch hi(man)
5043 and.l &0x7FFFFFFF,%d1 # strip sign
5045 cmpi.l %d1,&0x3FD78000 # is |X| >= 2**(-40)?
5046 bge.b SOK1 # no
5047 bra.w SINSM # yes; input is very small
5049 SOK1:
5050 cmp.l %d1,&0x4004BC7E # is |X| < 15 PI?
5051 blt.b SINMAIN # no
5052 bra.w SREDUCEX # yes; input is very large
5054 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5055 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5056 SINMAIN:
5057 fmov.x %fp0,%fp1
5058 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5060 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5062 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5064 mov.l INT(%a6),%d1 # make a copy of N
5065 asl.l &4,%d1 # N *= 16
5066 add.l %d1,%a1 # tbl_addr = a1 + (N*16)
5068 # A1 IS THE ADDRESS OF N*PIBY2
5069 # ...WHICH IS IN TWO PIECES Y1 & Y2
5070 fsub.x (%a1)+,%fp0 # X-Y1
5071 fsub.s (%a1),%fp0 # fp0 = R = (X-Y1)-Y2
5073 SINCONT:
5074 #--continuation from REDUCEX
5076 #--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
5077 mov.l INT(%a6),%d1
5078 add.l ADJN(%a6),%d1 # SEE IF D0 IS ODD OR EVEN
5079 ror.l &1,%d1 # D0 WAS ODD IFF D0 IS NEGATIVE
5080 cmp.l %d1,&0
5081 blt.w COSPOLY
5083 #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5084 #--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
5085 #--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
5086 #--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
5087 #--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
5088 #--WHERE T=S*S.
5089 #--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
5090 #--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
5091 SINPOLY:
5092 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5094 fmov.x %fp0,X(%a6) # X IS R
5095 fmul.x %fp0,%fp0 # FP0 IS S
5097 fmov.d SINA7(%pc),%fp3
5098 fmov.d SINA6(%pc),%fp2
5100 fmov.x %fp0,%fp1
5101 fmul.x %fp1,%fp1 # FP1 IS T
5103 ror.l &1,%d1
5104 and.l &0x80000000,%d1
5105 # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5106 eor.l %d1,X(%a6) # X IS NOW R'= SGN*R
5108 fmul.x %fp1,%fp3 # TA7
5109 fmul.x %fp1,%fp2 # TA6
5111 fadd.d SINA5(%pc),%fp3 # A5+TA7
5112 fadd.d SINA4(%pc),%fp2 # A4+TA6
5114 fmul.x %fp1,%fp3 # T(A5+TA7)
5115 fmul.x %fp1,%fp2 # T(A4+TA6)
5117 fadd.d SINA3(%pc),%fp3 # A3+T(A5+TA7)
5118 fadd.x SINA2(%pc),%fp2 # A2+T(A4+TA6)
5120 fmul.x %fp3,%fp1 # T(A3+T(A5+TA7))
5122 fmul.x %fp0,%fp2 # S(A2+T(A4+TA6))
5123 fadd.x SINA1(%pc),%fp1 # A1+T(A3+T(A5+TA7))
5124 fmul.x X(%a6),%fp0 # R'*S
5126 fadd.x %fp2,%fp1 # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
5128 fmul.x %fp1,%fp0 # SIN(R')-R'
5130 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5132 fmov.l %d0,%fpcr # restore users round mode,prec
5133 fadd.x X(%a6),%fp0 # last inst - possible exception set
5134 bra t_inx2
5136 #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5137 #--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY
5138 #--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
5139 #--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
5140 #--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
5141 #--WHERE T=S*S.
5142 #--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
5143 #--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
5144 #--AND IS THEREFORE STORED AS SINGLE PRECISION.
5145 COSPOLY:
5146 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5148 fmul.x %fp0,%fp0 # FP0 IS S
5150 fmov.d COSB8(%pc),%fp2
5151 fmov.d COSB7(%pc),%fp3
5153 fmov.x %fp0,%fp1
5154 fmul.x %fp1,%fp1 # FP1 IS T
5156 fmov.x %fp0,X(%a6) # X IS S
5157 ror.l &1,%d1
5158 and.l &0x80000000,%d1
5159 # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5161 fmul.x %fp1,%fp2 # TB8
5163 eor.l %d1,X(%a6) # X IS NOW S'= SGN*S
5164 and.l &0x80000000,%d1
5166 fmul.x %fp1,%fp3 # TB7
5168 or.l &0x3F800000,%d1 # D0 IS SGN IN SINGLE
5169 mov.l %d1,POSNEG1(%a6)
5171 fadd.d COSB6(%pc),%fp2 # B6+TB8
5172 fadd.d COSB5(%pc),%fp3 # B5+TB7
5174 fmul.x %fp1,%fp2 # T(B6+TB8)
5175 fmul.x %fp1,%fp3 # T(B5+TB7)
5177 fadd.d COSB4(%pc),%fp2 # B4+T(B6+TB8)
5178 fadd.x COSB3(%pc),%fp3 # B3+T(B5+TB7)
5180 fmul.x %fp1,%fp2 # T(B4+T(B6+TB8))
5181 fmul.x %fp3,%fp1 # T(B3+T(B5+TB7))
5183 fadd.x COSB2(%pc),%fp2 # B2+T(B4+T(B6+TB8))
5184 fadd.s COSB1(%pc),%fp1 # B1+T(B3+T(B5+TB7))
5186 fmul.x %fp2,%fp0 # S(B2+T(B4+T(B6+TB8)))
5188 fadd.x %fp1,%fp0
5190 fmul.x X(%a6),%fp0
5192 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5194 fmov.l %d0,%fpcr # restore users round mode,prec
5195 fadd.s POSNEG1(%a6),%fp0 # last inst - possible exception set
5196 bra t_inx2
5198 ##############################################
5200 # SINe: Big OR Small?
5201 #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5202 #--IF |X| < 2**(-40), RETURN X OR 1.
5203 SINBORS:
5204 cmp.l %d1,&0x3FFF8000
5205 bgt.l SREDUCEX
5207 SINSM:
5208 mov.l ADJN(%a6),%d1
5209 cmp.l %d1,&0
5210 bgt.b COSTINY
5212 # here, the operation may underflow iff the precision is sgl or dbl.
5213 # extended denorms are handled through another entry point.
5214 SINTINY:
5215 # mov.w &0x0000,XDCARE(%a6) # JUST IN CASE
5217 fmov.l %d0,%fpcr # restore users round mode,prec
5218 mov.b &FMOV_OP,%d1 # last inst is MOVE
5219 fmov.x X(%a6),%fp0 # last inst - possible exception set
5220 bra t_catch
5222 COSTINY:
5223 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5224 fmov.l %d0,%fpcr # restore users round mode,prec
5225 fadd.s &0x80800000,%fp0 # last inst - possible exception set
5226 bra t_pinx2
5228 ################################################
5229 global ssind
5230 #--SIN(X) = X FOR DENORMALIZED X
5231 ssind:
5232 bra t_extdnrm
5234 ############################################
5235 global scosd
5236 #--COS(X) = 1 FOR DENORMALIZED X
5237 scosd:
5238 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5239 bra t_pinx2
5241 ##################################################
5243 global ssincos
5244 ssincos:
5245 #--SET ADJN TO 4
5246 mov.l &4,ADJN(%a6)
5248 fmov.x (%a0),%fp0 # LOAD INPUT
5249 fmov.x %fp0,X(%a6)
5251 mov.l (%a0),%d1
5252 mov.w 4(%a0),%d1
5253 and.l &0x7FFFFFFF,%d1 # COMPACTIFY X
5255 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5256 bge.b SCOK1
5257 bra.w SCSM
5259 SCOK1:
5260 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5261 blt.b SCMAIN
5262 bra.w SREDUCEX
5265 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5266 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5267 SCMAIN:
5268 fmov.x %fp0,%fp1
5270 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5272 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5274 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5276 mov.l INT(%a6),%d1
5277 asl.l &4,%d1
5278 add.l %d1,%a1 # ADDRESS OF N*PIBY2, IN Y1, Y2
5280 fsub.x (%a1)+,%fp0 # X-Y1
5281 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5283 SCCONT:
5284 #--continuation point from REDUCEX
5286 mov.l INT(%a6),%d1
5287 ror.l &1,%d1
5288 cmp.l %d1,&0 # D0 < 0 IFF N IS ODD
5289 bge.w NEVEN
5291 SNODD:
5292 #--REGISTERS SAVED SO FAR: D0, A0, FP2.
5293 fmovm.x &0x04,-(%sp) # save fp2
5295 fmov.x %fp0,RPRIME(%a6)
5296 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5297 fmov.d SINA7(%pc),%fp1 # A7
5298 fmov.d COSB8(%pc),%fp2 # B8
5299 fmul.x %fp0,%fp1 # SA7
5300 fmul.x %fp0,%fp2 # SB8
5302 mov.l %d2,-(%sp)
5303 mov.l %d1,%d2
5304 ror.l &1,%d2
5305 and.l &0x80000000,%d2
5306 eor.l %d1,%d2
5307 and.l &0x80000000,%d2
5309 fadd.d SINA6(%pc),%fp1 # A6+SA7
5310 fadd.d COSB7(%pc),%fp2 # B7+SB8
5312 fmul.x %fp0,%fp1 # S(A6+SA7)
5313 eor.l %d2,RPRIME(%a6)
5314 mov.l (%sp)+,%d2
5315 fmul.x %fp0,%fp2 # S(B7+SB8)
5316 ror.l &1,%d1
5317 and.l &0x80000000,%d1
5318 mov.l &0x3F800000,POSNEG1(%a6)
5319 eor.l %d1,POSNEG1(%a6)
5321 fadd.d SINA5(%pc),%fp1 # A5+S(A6+SA7)
5322 fadd.d COSB6(%pc),%fp2 # B6+S(B7+SB8)
5324 fmul.x %fp0,%fp1 # S(A5+S(A6+SA7))
5325 fmul.x %fp0,%fp2 # S(B6+S(B7+SB8))
5326 fmov.x %fp0,SPRIME(%a6)
5328 fadd.d SINA4(%pc),%fp1 # A4+S(A5+S(A6+SA7))
5329 eor.l %d1,SPRIME(%a6)
5330 fadd.d COSB5(%pc),%fp2 # B5+S(B6+S(B7+SB8))
5332 fmul.x %fp0,%fp1 # S(A4+...)
5333 fmul.x %fp0,%fp2 # S(B5+...)
5335 fadd.d SINA3(%pc),%fp1 # A3+S(A4+...)
5336 fadd.d COSB4(%pc),%fp2 # B4+S(B5+...)
5338 fmul.x %fp0,%fp1 # S(A3+...)
5339 fmul.x %fp0,%fp2 # S(B4+...)
5341 fadd.x SINA2(%pc),%fp1 # A2+S(A3+...)
5342 fadd.x COSB3(%pc),%fp2 # B3+S(B4+...)
5344 fmul.x %fp0,%fp1 # S(A2+...)
5345 fmul.x %fp0,%fp2 # S(B3+...)
5347 fadd.x SINA1(%pc),%fp1 # A1+S(A2+...)
5348 fadd.x COSB2(%pc),%fp2 # B2+S(B3+...)
5350 fmul.x %fp0,%fp1 # S(A1+...)
5351 fmul.x %fp2,%fp0 # S(B2+...)
5353 fmul.x RPRIME(%a6),%fp1 # R'S(A1+...)
5354 fadd.s COSB1(%pc),%fp0 # B1+S(B2...)
5355 fmul.x SPRIME(%a6),%fp0 # S'(B1+S(B2+...))
5357 fmovm.x (%sp)+,&0x20 # restore fp2
5359 fmov.l %d0,%fpcr
5360 fadd.x RPRIME(%a6),%fp1 # COS(X)
5361 bsr sto_cos # store cosine result
5362 fadd.s POSNEG1(%a6),%fp0 # SIN(X)
5363 bra t_inx2
5365 NEVEN:
5366 #--REGISTERS SAVED SO FAR: FP2.
5367 fmovm.x &0x04,-(%sp) # save fp2
5369 fmov.x %fp0,RPRIME(%a6)
5370 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5372 fmov.d COSB8(%pc),%fp1 # B8
5373 fmov.d SINA7(%pc),%fp2 # A7
5375 fmul.x %fp0,%fp1 # SB8
5376 fmov.x %fp0,SPRIME(%a6)
5377 fmul.x %fp0,%fp2 # SA7
5379 ror.l &1,%d1
5380 and.l &0x80000000,%d1
5382 fadd.d COSB7(%pc),%fp1 # B7+SB8
5383 fadd.d SINA6(%pc),%fp2 # A6+SA7
5385 eor.l %d1,RPRIME(%a6)
5386 eor.l %d1,SPRIME(%a6)
5388 fmul.x %fp0,%fp1 # S(B7+SB8)
5390 or.l &0x3F800000,%d1
5391 mov.l %d1,POSNEG1(%a6)
5393 fmul.x %fp0,%fp2 # S(A6+SA7)
5395 fadd.d COSB6(%pc),%fp1 # B6+S(B7+SB8)
5396 fadd.d SINA5(%pc),%fp2 # A5+S(A6+SA7)
5398 fmul.x %fp0,%fp1 # S(B6+S(B7+SB8))
5399 fmul.x %fp0,%fp2 # S(A5+S(A6+SA7))
5401 fadd.d COSB5(%pc),%fp1 # B5+S(B6+S(B7+SB8))
5402 fadd.d SINA4(%pc),%fp2 # A4+S(A5+S(A6+SA7))
5404 fmul.x %fp0,%fp1 # S(B5+...)
5405 fmul.x %fp0,%fp2 # S(A4+...)
5407 fadd.d COSB4(%pc),%fp1 # B4+S(B5+...)
5408 fadd.d SINA3(%pc),%fp2 # A3+S(A4+...)
5410 fmul.x %fp0,%fp1 # S(B4+...)
5411 fmul.x %fp0,%fp2 # S(A3+...)
5413 fadd.x COSB3(%pc),%fp1 # B3+S(B4+...)
5414 fadd.x SINA2(%pc),%fp2 # A2+S(A3+...)
5416 fmul.x %fp0,%fp1 # S(B3+...)
5417 fmul.x %fp0,%fp2 # S(A2+...)
5419 fadd.x COSB2(%pc),%fp1 # B2+S(B3+...)
5420 fadd.x SINA1(%pc),%fp2 # A1+S(A2+...)
5422 fmul.x %fp0,%fp1 # S(B2+...)
5423 fmul.x %fp2,%fp0 # s(a1+...)
5426 fadd.s COSB1(%pc),%fp1 # B1+S(B2...)
5427 fmul.x RPRIME(%a6),%fp0 # R'S(A1+...)
5428 fmul.x SPRIME(%a6),%fp1 # S'(B1+S(B2+...))
5430 fmovm.x (%sp)+,&0x20 # restore fp2
5432 fmov.l %d0,%fpcr
5433 fadd.s POSNEG1(%a6),%fp1 # COS(X)
5434 bsr sto_cos # store cosine result
5435 fadd.x RPRIME(%a6),%fp0 # SIN(X)
5436 bra t_inx2
5438 ################################################
5440 SCBORS:
5441 cmp.l %d1,&0x3FFF8000
5442 bgt.w SREDUCEX
5444 ################################################
5446 SCSM:
5447 # mov.w &0x0000,XDCARE(%a6)
5448 fmov.s &0x3F800000,%fp1
5450 fmov.l %d0,%fpcr
5451 fsub.s &0x00800000,%fp1
5452 bsr sto_cos # store cosine result
5453 fmov.l %fpcr,%d0 # d0 must have fpcr,too
5454 mov.b &FMOV_OP,%d1 # last inst is MOVE
5455 fmov.x X(%a6),%fp0
5456 bra t_catch
5458 ##############################################
5460 global ssincosd
5461 #--SIN AND COS OF X FOR DENORMALIZED X
5462 ssincosd:
5463 mov.l %d0,-(%sp) # save d0
5464 fmov.s &0x3F800000,%fp1
5465 bsr sto_cos # store cosine result
5466 mov.l (%sp)+,%d0 # restore d0
5467 bra t_extdnrm
5469 ############################################
5471 #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5472 #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5473 #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5474 SREDUCEX:
5475 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
5476 mov.l %d2,-(%sp) # save d2
5477 fmov.s &0x00000000,%fp1 # fp1 = 0
5479 #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5480 #--there is a danger of unwanted overflow in first LOOP iteration. In this
5481 #--case, reduce argument by one remainder step to make subsequent reduction
5482 #--safe.
5483 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
5484 bne.b SLOOP # no
5486 # yes; create 2**16383*PI/2
5487 mov.w &0x7ffe,FP_SCR0_EX(%a6)
5488 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
5489 clr.l FP_SCR0_LO(%a6)
5491 # create low half of 2**16383*PI/2 at FP_SCR1
5492 mov.w &0x7fdc,FP_SCR1_EX(%a6)
5493 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
5494 clr.l FP_SCR1_LO(%a6)
5496 ftest.x %fp0 # test sign of argument
5497 fblt.w sred_neg
5499 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
5500 or.b &0x80,FP_SCR1_EX(%a6)
5501 sred_neg:
5502 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
5503 fmov.x %fp0,%fp1 # save high result in fp1
5504 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
5505 fsub.x %fp0,%fp1 # determine low component of result
5506 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
5508 #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5509 #--integer quotient will be stored in N
5510 #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5511 SLOOP:
5512 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
5513 mov.w INARG(%a6),%d1
5514 mov.l %d1,%a1 # save a copy of D0
5515 and.l &0x00007FFF,%d1
5516 sub.l &0x00003FFF,%d1 # d0 = K
5517 cmp.l %d1,&28
5518 ble.b SLASTLOOP
5519 SCONTLOOP:
5520 sub.l &27,%d1 # d0 = L := K-27
5521 mov.b &0,ENDFLAG(%a6)
5522 bra.b SWORK
5523 SLASTLOOP:
5524 clr.l %d1 # d0 = L := 0
5525 mov.b &1,ENDFLAG(%a6)
5527 SWORK:
5528 #--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
5529 #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5531 #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5532 #--2**L * (PIby2_1), 2**L * (PIby2_2)
5534 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
5535 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
5537 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
5538 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
5539 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
5541 fmov.x %fp0,%fp2
5542 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
5544 #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5545 #--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
5546 #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5547 #--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
5548 #--US THE DESIRED VALUE IN FLOATING POINT.
5549 mov.l %a1,%d2
5550 swap %d2
5551 and.l &0x80000000,%d2
5552 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
5553 mov.l %d2,TWOTO63(%a6)
5554 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
5555 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
5556 # fint.x %fp2
5558 #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5559 mov.l %d1,%d2 # d2 = L
5561 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
5562 mov.w %d2,FP_SCR0_EX(%a6)
5563 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
5564 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
5566 add.l &0x00003FDD,%d1
5567 mov.w %d1,FP_SCR1_EX(%a6)
5568 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
5569 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
5571 mov.b ENDFLAG(%a6),%d1
5573 #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5574 #--P2 = 2**(L) * Piby2_2
5575 fmov.x %fp2,%fp4 # fp4 = N
5576 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
5577 fmov.x %fp2,%fp5 # fp5 = N
5578 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
5579 fmov.x %fp4,%fp3 # fp3 = W = N*P1
5581 #--we want P+p = W+w but |p| <= half ulp of P
5582 #--Then, we need to compute A := R-P and a := r-p
5583 fadd.x %fp5,%fp3 # fp3 = P
5584 fsub.x %fp3,%fp4 # fp4 = W-P
5586 fsub.x %fp3,%fp0 # fp0 = A := R - P
5587 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
5589 fmov.x %fp0,%fp3 # fp3 = A
5590 fsub.x %fp4,%fp1 # fp1 = a := r - p
5592 #--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
5593 #--|r| <= half ulp of R.
5594 fadd.x %fp1,%fp0 # fp0 = R := A+a
5595 #--No need to calculate r if this is the last loop
5596 cmp.b %d1,&0
5597 bgt.w SRESTORE
5599 #--Need to calculate r
5600 fsub.x %fp0,%fp3 # fp3 = A-R
5601 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
5602 bra.w SLOOP
5604 SRESTORE:
5605 fmov.l %fp2,INT(%a6)
5606 mov.l (%sp)+,%d2 # restore d2
5607 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
5609 mov.l ADJN(%a6),%d1
5610 cmp.l %d1,&4
5612 blt.w SINCONT
5613 bra.w SCCONT
5615 #########################################################################
5616 # stan(): computes the tangent of a normalized input #
5617 # stand(): computes the tangent of a denormalized input #
5619 # INPUT *************************************************************** #
5620 # a0 = pointer to extended precision input #
5621 # d0 = round precision,mode #
5623 # OUTPUT ************************************************************** #
5624 # fp0 = tan(X) #
5626 # ACCURACY and MONOTONICITY ******************************************* #
5627 # The returned result is within 3 ulp in 64 significant bit, i.e. #
5628 # within 0.5001 ulp to 53 bits if the result is subsequently #
5629 # rounded to double precision. The result is provably monotonic #
5630 # in double precision. #
5632 # ALGORITHM *********************************************************** #
5634 # 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
5636 # 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
5637 # k = N mod 2, so in particular, k = 0 or 1. #
5639 # 3. If k is odd, go to 5. #
5641 # 4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a #
5642 # rational function U/V where #
5643 # U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5644 # V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r. #
5645 # Exit. #
5647 # 4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
5648 # a rational function U/V where #
5649 # U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5650 # V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r, #
5651 # -Cot(r) = -V/U. Exit. #
5653 # 6. If |X| > 1, go to 8. #
5655 # 7. (|X|<2**(-40)) Tan(X) = X. Exit. #
5657 # 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back #
5658 # to 2. #
5660 #########################################################################
5662 TANQ4:
5663 long 0x3EA0B759,0xF50F8688
5664 TANP3:
5665 long 0xBEF2BAA5,0xA8924F04
5667 TANQ3:
5668 long 0xBF346F59,0xB39BA65F,0x00000000,0x00000000
5670 TANP2:
5671 long 0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
5673 TANQ2:
5674 long 0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
5676 TANP1:
5677 long 0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
5679 TANQ1:
5680 long 0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
5682 INVTWOPI:
5683 long 0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
5685 TWOPI1:
5686 long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
5687 TWOPI2:
5688 long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
5690 #--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
5691 #--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
5692 #--MOST 69 BITS LONG.
5693 # global PITBL
5694 PITBL:
5695 long 0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
5696 long 0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
5697 long 0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
5698 long 0xC0040000,0xB6365E22,0xEE46F000,0x21480000
5699 long 0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
5700 long 0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
5701 long 0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
5702 long 0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
5703 long 0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
5704 long 0xC0040000,0x90836524,0x88034B96,0x20B00000
5705 long 0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
5706 long 0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
5707 long 0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
5708 long 0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
5709 long 0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
5710 long 0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
5711 long 0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
5712 long 0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
5713 long 0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
5714 long 0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
5715 long 0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
5716 long 0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
5717 long 0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
5718 long 0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
5719 long 0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
5720 long 0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
5721 long 0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
5722 long 0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
5723 long 0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
5724 long 0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
5725 long 0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
5726 long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
5727 long 0x00000000,0x00000000,0x00000000,0x00000000
5728 long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
5729 long 0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
5730 long 0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
5731 long 0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
5732 long 0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
5733 long 0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
5734 long 0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
5735 long 0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
5736 long 0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
5737 long 0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
5738 long 0x40030000,0x8A3AE64F,0x76F80584,0x21080000
5739 long 0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
5740 long 0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
5741 long 0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
5742 long 0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
5743 long 0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
5744 long 0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
5745 long 0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
5746 long 0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
5747 long 0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
5748 long 0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
5749 long 0x40040000,0x8A3AE64F,0x76F80584,0x21880000
5750 long 0x40040000,0x90836524,0x88034B96,0xA0B00000
5751 long 0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
5752 long 0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
5753 long 0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
5754 long 0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
5755 long 0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
5756 long 0x40040000,0xB6365E22,0xEE46F000,0xA1480000
5757 long 0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
5758 long 0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
5759 long 0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
5761 set INARG,FP_SCR0
5763 set TWOTO63,L_SCR1
5764 set INT,L_SCR1
5765 set ENDFLAG,L_SCR2
5767 global stan
5768 stan:
5769 fmov.x (%a0),%fp0 # LOAD INPUT
5771 mov.l (%a0),%d1
5772 mov.w 4(%a0),%d1
5773 and.l &0x7FFFFFFF,%d1
5775 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5776 bge.b TANOK1
5777 bra.w TANSM
5778 TANOK1:
5779 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5780 blt.b TANMAIN
5781 bra.w REDUCEX
5783 TANMAIN:
5784 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5785 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5786 fmov.x %fp0,%fp1
5787 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5789 lea.l PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5791 fmov.l %fp1,%d1 # CONVERT TO INTEGER
5793 asl.l &4,%d1
5794 add.l %d1,%a1 # ADDRESS N*PIBY2 IN Y1, Y2
5796 fsub.x (%a1)+,%fp0 # X-Y1
5798 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5800 ror.l &5,%d1
5801 and.l &0x80000000,%d1 # D0 WAS ODD IFF D0 < 0
5803 TANCONT:
5804 fmovm.x &0x0c,-(%sp) # save fp2,fp3
5806 cmp.l %d1,&0
5807 blt.w NODD
5809 fmov.x %fp0,%fp1
5810 fmul.x %fp1,%fp1 # S = R*R
5812 fmov.d TANQ4(%pc),%fp3
5813 fmov.d TANP3(%pc),%fp2
5815 fmul.x %fp1,%fp3 # SQ4
5816 fmul.x %fp1,%fp2 # SP3
5818 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5819 fadd.x TANP2(%pc),%fp2 # P2+SP3
5821 fmul.x %fp1,%fp3 # S(Q3+SQ4)
5822 fmul.x %fp1,%fp2 # S(P2+SP3)
5824 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5825 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5827 fmul.x %fp1,%fp3 # S(Q2+S(Q3+SQ4))
5828 fmul.x %fp1,%fp2 # S(P1+S(P2+SP3))
5830 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5831 fmul.x %fp0,%fp2 # RS(P1+S(P2+SP3))
5833 fmul.x %fp3,%fp1 # S(Q1+S(Q2+S(Q3+SQ4)))
5835 fadd.x %fp2,%fp0 # R+RS(P1+S(P2+SP3))
5837 fadd.s &0x3F800000,%fp1 # 1+S(Q1+...)
5839 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5841 fmov.l %d0,%fpcr # restore users round mode,prec
5842 fdiv.x %fp1,%fp0 # last inst - possible exception set
5843 bra t_inx2
5845 NODD:
5846 fmov.x %fp0,%fp1
5847 fmul.x %fp0,%fp0 # S = R*R
5849 fmov.d TANQ4(%pc),%fp3
5850 fmov.d TANP3(%pc),%fp2
5852 fmul.x %fp0,%fp3 # SQ4
5853 fmul.x %fp0,%fp2 # SP3
5855 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5856 fadd.x TANP2(%pc),%fp2 # P2+SP3
5858 fmul.x %fp0,%fp3 # S(Q3+SQ4)
5859 fmul.x %fp0,%fp2 # S(P2+SP3)
5861 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5862 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5864 fmul.x %fp0,%fp3 # S(Q2+S(Q3+SQ4))
5865 fmul.x %fp0,%fp2 # S(P1+S(P2+SP3))
5867 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5868 fmul.x %fp1,%fp2 # RS(P1+S(P2+SP3))
5870 fmul.x %fp3,%fp0 # S(Q1+S(Q2+S(Q3+SQ4)))
5872 fadd.x %fp2,%fp1 # R+RS(P1+S(P2+SP3))
5873 fadd.s &0x3F800000,%fp0 # 1+S(Q1+...)
5875 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5877 fmov.x %fp1,-(%sp)
5878 eor.l &0x80000000,(%sp)
5880 fmov.l %d0,%fpcr # restore users round mode,prec
5881 fdiv.x (%sp)+,%fp0 # last inst - possible exception set
5882 bra t_inx2
5884 TANBORS:
5885 #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5886 #--IF |X| < 2**(-40), RETURN X OR 1.
5887 cmp.l %d1,&0x3FFF8000
5888 bgt.b REDUCEX
5890 TANSM:
5891 fmov.x %fp0,-(%sp)
5892 fmov.l %d0,%fpcr # restore users round mode,prec
5893 mov.b &FMOV_OP,%d1 # last inst is MOVE
5894 fmov.x (%sp)+,%fp0 # last inst - posibble exception set
5895 bra t_catch
5897 global stand
5898 #--TAN(X) = X FOR DENORMALIZED X
5899 stand:
5900 bra t_extdnrm
5902 #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5903 #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5904 #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5905 REDUCEX:
5906 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
5907 mov.l %d2,-(%sp) # save d2
5908 fmov.s &0x00000000,%fp1 # fp1 = 0
5910 #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5911 #--there is a danger of unwanted overflow in first LOOP iteration. In this
5912 #--case, reduce argument by one remainder step to make subsequent reduction
5913 #--safe.
5914 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
5915 bne.b LOOP # no
5917 # yes; create 2**16383*PI/2
5918 mov.w &0x7ffe,FP_SCR0_EX(%a6)
5919 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
5920 clr.l FP_SCR0_LO(%a6)
5922 # create low half of 2**16383*PI/2 at FP_SCR1
5923 mov.w &0x7fdc,FP_SCR1_EX(%a6)
5924 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
5925 clr.l FP_SCR1_LO(%a6)
5927 ftest.x %fp0 # test sign of argument
5928 fblt.w red_neg
5930 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
5931 or.b &0x80,FP_SCR1_EX(%a6)
5932 red_neg:
5933 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
5934 fmov.x %fp0,%fp1 # save high result in fp1
5935 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
5936 fsub.x %fp0,%fp1 # determine low component of result
5937 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
5939 #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5940 #--integer quotient will be stored in N
5941 #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5942 LOOP:
5943 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
5944 mov.w INARG(%a6),%d1
5945 mov.l %d1,%a1 # save a copy of D0
5946 and.l &0x00007FFF,%d1
5947 sub.l &0x00003FFF,%d1 # d0 = K
5948 cmp.l %d1,&28
5949 ble.b LASTLOOP
5950 CONTLOOP:
5951 sub.l &27,%d1 # d0 = L := K-27
5952 mov.b &0,ENDFLAG(%a6)
5953 bra.b WORK
5954 LASTLOOP:
5955 clr.l %d1 # d0 = L := 0
5956 mov.b &1,ENDFLAG(%a6)
5958 WORK:
5959 #--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
5960 #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5962 #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5963 #--2**L * (PIby2_1), 2**L * (PIby2_2)
5965 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
5966 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
5968 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
5969 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
5970 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
5972 fmov.x %fp0,%fp2
5973 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
5975 #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5976 #--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
5977 #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5978 #--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
5979 #--US THE DESIRED VALUE IN FLOATING POINT.
5980 mov.l %a1,%d2
5981 swap %d2
5982 and.l &0x80000000,%d2
5983 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
5984 mov.l %d2,TWOTO63(%a6)
5985 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
5986 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
5987 # fintrz.x %fp2,%fp2
5989 #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5990 mov.l %d1,%d2 # d2 = L
5992 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
5993 mov.w %d2,FP_SCR0_EX(%a6)
5994 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
5995 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
5997 add.l &0x00003FDD,%d1
5998 mov.w %d1,FP_SCR1_EX(%a6)
5999 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
6000 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
6002 mov.b ENDFLAG(%a6),%d1
6004 #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
6005 #--P2 = 2**(L) * Piby2_2
6006 fmov.x %fp2,%fp4 # fp4 = N
6007 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
6008 fmov.x %fp2,%fp5 # fp5 = N
6009 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
6010 fmov.x %fp4,%fp3 # fp3 = W = N*P1
6012 #--we want P+p = W+w but |p| <= half ulp of P
6013 #--Then, we need to compute A := R-P and a := r-p
6014 fadd.x %fp5,%fp3 # fp3 = P
6015 fsub.x %fp3,%fp4 # fp4 = W-P
6017 fsub.x %fp3,%fp0 # fp0 = A := R - P
6018 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
6020 fmov.x %fp0,%fp3 # fp3 = A
6021 fsub.x %fp4,%fp1 # fp1 = a := r - p
6023 #--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
6024 #--|r| <= half ulp of R.
6025 fadd.x %fp1,%fp0 # fp0 = R := A+a
6026 #--No need to calculate r if this is the last loop
6027 cmp.b %d1,&0
6028 bgt.w RESTORE
6030 #--Need to calculate r
6031 fsub.x %fp0,%fp3 # fp3 = A-R
6032 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
6033 bra.w LOOP
6035 RESTORE:
6036 fmov.l %fp2,INT(%a6)
6037 mov.l (%sp)+,%d2 # restore d2
6038 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
6040 mov.l INT(%a6),%d1
6041 ror.l &1,%d1
6043 bra.w TANCONT
6045 #########################################################################
6046 # satan(): computes the arctangent of a normalized number #
6047 # satand(): computes the arctangent of a denormalized number #
6049 # INPUT *************************************************************** #
6050 # a0 = pointer to extended precision input #
6051 # d0 = round precision,mode #
6053 # OUTPUT ************************************************************** #
6054 # fp0 = arctan(X) #
6056 # ACCURACY and MONOTONICITY ******************************************* #
6057 # The returned result is within 2 ulps in 64 significant bit, #
6058 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6059 # rounded to double precision. The result is provably monotonic #
6060 # in double precision. #
6062 # ALGORITHM *********************************************************** #
6063 # Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5. #
6065 # Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x. #
6066 # Note that k = -4, -3,..., or 3. #
6067 # Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5 #
6068 # significant bits of X with a bit-1 attached at the 6-th #
6069 # bit position. Define u to be u = (X-F) / (1 + X*F). #
6071 # Step 3. Approximate arctan(u) by a polynomial poly. #
6073 # Step 4. Return arctan(F) + poly, arctan(F) is fetched from a #
6074 # table of values calculated beforehand. Exit. #
6076 # Step 5. If |X| >= 16, go to Step 7. #
6078 # Step 6. Approximate arctan(X) by an odd polynomial in X. Exit. #
6080 # Step 7. Define X' = -1/X. Approximate arctan(X') by an odd #
6081 # polynomial in X'. #
6082 # Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit. #
6084 #########################################################################
6086 ATANA3: long 0xBFF6687E,0x314987D8
6087 ATANA2: long 0x4002AC69,0x34A26DB3
6088 ATANA1: long 0xBFC2476F,0x4E1DA28E
6090 ATANB6: long 0x3FB34444,0x7F876989
6091 ATANB5: long 0xBFB744EE,0x7FAF45DB
6092 ATANB4: long 0x3FBC71C6,0x46940220
6093 ATANB3: long 0xBFC24924,0x921872F9
6094 ATANB2: long 0x3FC99999,0x99998FA9
6095 ATANB1: long 0xBFD55555,0x55555555
6097 ATANC5: long 0xBFB70BF3,0x98539E6A
6098 ATANC4: long 0x3FBC7187,0x962D1D7D
6099 ATANC3: long 0xBFC24924,0x827107B8
6100 ATANC2: long 0x3FC99999,0x9996263E
6101 ATANC1: long 0xBFD55555,0x55555536
6103 PPIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
6104 NPIBY2: long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
6106 PTINY: long 0x00010000,0x80000000,0x00000000,0x00000000
6107 NTINY: long 0x80010000,0x80000000,0x00000000,0x00000000
6109 ATANTBL:
6110 long 0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
6111 long 0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
6112 long 0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
6113 long 0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
6114 long 0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
6115 long 0x3FFB0000,0xAB98E943,0x62765619,0x00000000
6116 long 0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
6117 long 0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
6118 long 0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
6119 long 0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
6120 long 0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
6121 long 0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
6122 long 0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
6123 long 0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
6124 long 0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
6125 long 0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
6126 long 0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
6127 long 0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
6128 long 0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
6129 long 0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
6130 long 0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
6131 long 0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
6132 long 0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
6133 long 0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
6134 long 0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
6135 long 0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
6136 long 0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
6137 long 0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
6138 long 0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
6139 long 0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
6140 long 0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
6141 long 0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
6142 long 0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
6143 long 0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
6144 long 0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
6145 long 0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
6146 long 0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
6147 long 0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
6148 long 0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
6149 long 0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
6150 long 0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
6151 long 0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
6152 long 0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
6153 long 0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
6154 long 0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
6155 long 0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
6156 long 0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
6157 long 0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
6158 long 0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
6159 long 0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
6160 long 0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
6161 long 0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
6162 long 0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
6163 long 0x3FFE0000,0x97731420,0x365E538C,0x00000000
6164 long 0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
6165 long 0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
6166 long 0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
6167 long 0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
6168 long 0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
6169 long 0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
6170 long 0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
6171 long 0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
6172 long 0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
6173 long 0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
6174 long 0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
6175 long 0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
6176 long 0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
6177 long 0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
6178 long 0x3FFE0000,0xE8771129,0xC4353259,0x00000000
6179 long 0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
6180 long 0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
6181 long 0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
6182 long 0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
6183 long 0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
6184 long 0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
6185 long 0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
6186 long 0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
6187 long 0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
6188 long 0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
6189 long 0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
6190 long 0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
6191 long 0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
6192 long 0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
6193 long 0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
6194 long 0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
6195 long 0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
6196 long 0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
6197 long 0x3FFF0000,0x9F100575,0x006CC571,0x00000000
6198 long 0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
6199 long 0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
6200 long 0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
6201 long 0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
6202 long 0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
6203 long 0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
6204 long 0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
6205 long 0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
6206 long 0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
6207 long 0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
6208 long 0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
6209 long 0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
6210 long 0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
6211 long 0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
6212 long 0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
6213 long 0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
6214 long 0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
6215 long 0x3FFF0000,0xB525529D,0x562246BD,0x00000000
6216 long 0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
6217 long 0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
6218 long 0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
6219 long 0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
6220 long 0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
6221 long 0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
6222 long 0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
6223 long 0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
6224 long 0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
6225 long 0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
6226 long 0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
6227 long 0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
6228 long 0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
6229 long 0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
6230 long 0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
6231 long 0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
6232 long 0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
6233 long 0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
6234 long 0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
6235 long 0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
6236 long 0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
6237 long 0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
6239 set X,FP_SCR0
6240 set XDCARE,X+2
6241 set XFRAC,X+4
6242 set XFRACLO,X+8
6244 set ATANF,FP_SCR1
6245 set ATANFHI,ATANF+4
6246 set ATANFLO,ATANF+8
6248 global satan
6249 #--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
6250 satan:
6251 fmov.x (%a0),%fp0 # LOAD INPUT
6253 mov.l (%a0),%d1
6254 mov.w 4(%a0),%d1
6255 fmov.x %fp0,X(%a6)
6256 and.l &0x7FFFFFFF,%d1
6258 cmp.l %d1,&0x3FFB8000 # |X| >= 1/16?
6259 bge.b ATANOK1
6260 bra.w ATANSM
6262 ATANOK1:
6263 cmp.l %d1,&0x4002FFFF # |X| < 16 ?
6264 ble.b ATANMAIN
6265 bra.w ATANBIG
6267 #--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
6268 #--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
6269 #--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
6270 #--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
6271 #--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
6272 #--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
6273 #--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
6274 #--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
6275 #--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
6276 #--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
6277 #--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
6278 #--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
6279 #--WILL INVOLVE A VERY LONG POLYNOMIAL.
6281 #--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
6282 #--WE CHOSE F TO BE +-2^K * 1.BBBB1
6283 #--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
6284 #--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
6285 #--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
6286 #-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
6288 ATANMAIN:
6290 and.l &0xF8000000,XFRAC(%a6) # FIRST 5 BITS
6291 or.l &0x04000000,XFRAC(%a6) # SET 6-TH BIT TO 1
6292 mov.l &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
6294 fmov.x %fp0,%fp1 # FP1 IS X
6295 fmul.x X(%a6),%fp1 # FP1 IS X*F, NOTE THAT X*F > 0
6296 fsub.x X(%a6),%fp0 # FP0 IS X-F
6297 fadd.s &0x3F800000,%fp1 # FP1 IS 1 + X*F
6298 fdiv.x %fp1,%fp0 # FP0 IS U = (X-F)/(1+X*F)
6300 #--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
6301 #--CREATE ATAN(F) AND STORE IT IN ATANF, AND
6302 #--SAVE REGISTERS FP2.
6304 mov.l %d2,-(%sp) # SAVE d2 TEMPORARILY
6305 mov.l %d1,%d2 # THE EXP AND 16 BITS OF X
6306 and.l &0x00007800,%d1 # 4 VARYING BITS OF F'S FRACTION
6307 and.l &0x7FFF0000,%d2 # EXPONENT OF F
6308 sub.l &0x3FFB0000,%d2 # K+4
6309 asr.l &1,%d2
6310 add.l %d2,%d1 # THE 7 BITS IDENTIFYING F
6311 asr.l &7,%d1 # INDEX INTO TBL OF ATAN(|F|)
6312 lea ATANTBL(%pc),%a1
6313 add.l %d1,%a1 # ADDRESS OF ATAN(|F|)
6314 mov.l (%a1)+,ATANF(%a6)
6315 mov.l (%a1)+,ATANFHI(%a6)
6316 mov.l (%a1)+,ATANFLO(%a6) # ATANF IS NOW ATAN(|F|)
6317 mov.l X(%a6),%d1 # LOAD SIGN AND EXPO. AGAIN
6318 and.l &0x80000000,%d1 # SIGN(F)
6319 or.l %d1,ATANF(%a6) # ATANF IS NOW SIGN(F)*ATAN(|F|)
6320 mov.l (%sp)+,%d2 # RESTORE d2
6322 #--THAT'S ALL I HAVE TO DO FOR NOW,
6323 #--BUT ALAS, THE DIVIDE IS STILL CRANKING!
6325 #--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
6326 #--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
6327 #--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
6328 #--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
6329 #--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.
6330 #--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
6331 #--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
6333 fmovm.x &0x04,-(%sp) # save fp2
6335 fmov.x %fp0,%fp1
6336 fmul.x %fp1,%fp1
6337 fmov.d ATANA3(%pc),%fp2
6338 fadd.x %fp1,%fp2 # A3+V
6339 fmul.x %fp1,%fp2 # V*(A3+V)
6340 fmul.x %fp0,%fp1 # U*V
6341 fadd.d ATANA2(%pc),%fp2 # A2+V*(A3+V)
6342 fmul.d ATANA1(%pc),%fp1 # A1*U*V
6343 fmul.x %fp2,%fp1 # A1*U*V*(A2+V*(A3+V))
6344 fadd.x %fp1,%fp0 # ATAN(U), FP1 RELEASED
6346 fmovm.x (%sp)+,&0x20 # restore fp2
6348 fmov.l %d0,%fpcr # restore users rnd mode,prec
6349 fadd.x ATANF(%a6),%fp0 # ATAN(X)
6350 bra t_inx2
6352 ATANBORS:
6353 #--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
6354 #--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
6355 cmp.l %d1,&0x3FFF8000
6356 bgt.w ATANBIG # I.E. |X| >= 16
6358 ATANSM:
6359 #--|X| <= 1/16
6360 #--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
6361 #--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
6362 #--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
6363 #--WHERE Y = X*X, AND Z = Y*Y.
6365 cmp.l %d1,&0x3FD78000
6366 blt.w ATANTINY
6368 #--COMPUTE POLYNOMIAL
6369 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6371 fmul.x %fp0,%fp0 # FPO IS Y = X*X
6373 fmov.x %fp0,%fp1
6374 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6376 fmov.d ATANB6(%pc),%fp2
6377 fmov.d ATANB5(%pc),%fp3
6379 fmul.x %fp1,%fp2 # Z*B6
6380 fmul.x %fp1,%fp3 # Z*B5
6382 fadd.d ATANB4(%pc),%fp2 # B4+Z*B6
6383 fadd.d ATANB3(%pc),%fp3 # B3+Z*B5
6385 fmul.x %fp1,%fp2 # Z*(B4+Z*B6)
6386 fmul.x %fp3,%fp1 # Z*(B3+Z*B5)
6388 fadd.d ATANB2(%pc),%fp2 # B2+Z*(B4+Z*B6)
6389 fadd.d ATANB1(%pc),%fp1 # B1+Z*(B3+Z*B5)
6391 fmul.x %fp0,%fp2 # Y*(B2+Z*(B4+Z*B6))
6392 fmul.x X(%a6),%fp0 # X*Y
6394 fadd.x %fp2,%fp1 # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
6396 fmul.x %fp1,%fp0 # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
6398 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6400 fmov.l %d0,%fpcr # restore users rnd mode,prec
6401 fadd.x X(%a6),%fp0
6402 bra t_inx2
6404 ATANTINY:
6405 #--|X| < 2^(-40), ATAN(X) = X
6407 fmov.l %d0,%fpcr # restore users rnd mode,prec
6408 mov.b &FMOV_OP,%d1 # last inst is MOVE
6409 fmov.x X(%a6),%fp0 # last inst - possible exception set
6411 bra t_catch
6413 ATANBIG:
6414 #--IF |X| > 2^(100), RETURN SIGN(X)*(PI/2 - TINY). OTHERWISE,
6415 #--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
6416 cmp.l %d1,&0x40638000
6417 bgt.w ATANHUGE
6419 #--APPROXIMATE ATAN(-1/X) BY
6420 #--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
6421 #--THIS CAN BE RE-WRITTEN AS
6422 #--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
6424 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6426 fmov.s &0xBF800000,%fp1 # LOAD -1
6427 fdiv.x %fp0,%fp1 # FP1 IS -1/X
6429 #--DIVIDE IS STILL CRANKING
6431 fmov.x %fp1,%fp0 # FP0 IS X'
6432 fmul.x %fp0,%fp0 # FP0 IS Y = X'*X'
6433 fmov.x %fp1,X(%a6) # X IS REALLY X'
6435 fmov.x %fp0,%fp1
6436 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6438 fmov.d ATANC5(%pc),%fp3
6439 fmov.d ATANC4(%pc),%fp2
6441 fmul.x %fp1,%fp3 # Z*C5
6442 fmul.x %fp1,%fp2 # Z*B4
6444 fadd.d ATANC3(%pc),%fp3 # C3+Z*C5
6445 fadd.d ATANC2(%pc),%fp2 # C2+Z*C4
6447 fmul.x %fp3,%fp1 # Z*(C3+Z*C5), FP3 RELEASED
6448 fmul.x %fp0,%fp2 # Y*(C2+Z*C4)
6450 fadd.d ATANC1(%pc),%fp1 # C1+Z*(C3+Z*C5)
6451 fmul.x X(%a6),%fp0 # X'*Y
6453 fadd.x %fp2,%fp1 # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
6455 fmul.x %fp1,%fp0 # X'*Y*([B1+Z*(B3+Z*B5)]
6456 # ... +[Y*(B2+Z*(B4+Z*B6))])
6457 fadd.x X(%a6),%fp0
6459 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6461 fmov.l %d0,%fpcr # restore users rnd mode,prec
6462 tst.b (%a0)
6463 bpl.b pos_big
6465 neg_big:
6466 fadd.x NPIBY2(%pc),%fp0
6467 bra t_minx2
6469 pos_big:
6470 fadd.x PPIBY2(%pc),%fp0
6471 bra t_pinx2
6473 ATANHUGE:
6474 #--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
6475 tst.b (%a0)
6476 bpl.b pos_huge
6478 neg_huge:
6479 fmov.x NPIBY2(%pc),%fp0
6480 fmov.l %d0,%fpcr
6481 fadd.x PTINY(%pc),%fp0
6482 bra t_minx2
6484 pos_huge:
6485 fmov.x PPIBY2(%pc),%fp0
6486 fmov.l %d0,%fpcr
6487 fadd.x NTINY(%pc),%fp0
6488 bra t_pinx2
6490 global satand
6491 #--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
6492 satand:
6493 bra t_extdnrm
6495 #########################################################################
6496 # sasin(): computes the inverse sine of a normalized input #
6497 # sasind(): computes the inverse sine of a denormalized input #
6499 # INPUT *************************************************************** #
6500 # a0 = pointer to extended precision input #
6501 # d0 = round precision,mode #
6503 # OUTPUT ************************************************************** #
6504 # fp0 = arcsin(X) #
6506 # ACCURACY and MONOTONICITY ******************************************* #
6507 # The returned result is within 3 ulps in 64 significant bit, #
6508 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6509 # rounded to double precision. The result is provably monotonic #
6510 # in double precision. #
6512 # ALGORITHM *********************************************************** #
6514 # ASIN #
6515 # 1. If |X| >= 1, go to 3. #
6517 # 2. (|X| < 1) Calculate asin(X) by #
6518 # z := sqrt( [1-X][1+X] ) #
6519 # asin(X) = atan( x / z ). #
6520 # Exit. #
6522 # 3. If |X| > 1, go to 5. #
6524 # 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
6526 # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6527 # Exit. #
6529 #########################################################################
6531 global sasin
6532 sasin:
6533 fmov.x (%a0),%fp0 # LOAD INPUT
6535 mov.l (%a0),%d1
6536 mov.w 4(%a0),%d1
6537 and.l &0x7FFFFFFF,%d1
6538 cmp.l %d1,&0x3FFF8000
6539 bge.b ASINBIG
6541 # This catch is added here for the '060 QSP. Originally, the call to
6542 # satan() would handle this case by causing the exception which would
6543 # not be caught until gen_except(). Now, with the exceptions being
6544 # detected inside of satan(), the exception would have been handled there
6545 # instead of inside sasin() as expected.
6546 cmp.l %d1,&0x3FD78000
6547 blt.w ASINTINY
6549 #--THIS IS THE USUAL CASE, |X| < 1
6550 #--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
6552 ASINMAIN:
6553 fmov.s &0x3F800000,%fp1
6554 fsub.x %fp0,%fp1 # 1-X
6555 fmovm.x &0x4,-(%sp) # {fp2}
6556 fmov.s &0x3F800000,%fp2
6557 fadd.x %fp0,%fp2 # 1+X
6558 fmul.x %fp2,%fp1 # (1+X)(1-X)
6559 fmovm.x (%sp)+,&0x20 # {fp2}
6560 fsqrt.x %fp1 # SQRT([1-X][1+X])
6561 fdiv.x %fp1,%fp0 # X/SQRT([1-X][1+X])
6562 fmovm.x &0x01,-(%sp) # save X/SQRT(...)
6563 lea (%sp),%a0 # pass ptr to X/SQRT(...)
6564 bsr satan
6565 add.l &0xc,%sp # clear X/SQRT(...) from stack
6566 bra t_inx2
6568 ASINBIG:
6569 fabs.x %fp0 # |X|
6570 fcmp.s %fp0,&0x3F800000
6571 fbgt t_operr # cause an operr exception
6573 #--|X| = 1, ASIN(X) = +- PI/2.
6574 ASINONE:
6575 fmov.x PIBY2(%pc),%fp0
6576 mov.l (%a0),%d1
6577 and.l &0x80000000,%d1 # SIGN BIT OF X
6578 or.l &0x3F800000,%d1 # +-1 IN SGL FORMAT
6579 mov.l %d1,-(%sp) # push SIGN(X) IN SGL-FMT
6580 fmov.l %d0,%fpcr
6581 fmul.s (%sp)+,%fp0
6582 bra t_inx2
6584 #--|X| < 2^(-40), ATAN(X) = X
6585 ASINTINY:
6586 fmov.l %d0,%fpcr # restore users rnd mode,prec
6587 mov.b &FMOV_OP,%d1 # last inst is MOVE
6588 fmov.x (%a0),%fp0 # last inst - possible exception
6589 bra t_catch
6591 global sasind
6592 #--ASIN(X) = X FOR DENORMALIZED X
6593 sasind:
6594 bra t_extdnrm
6596 #########################################################################
6597 # sacos(): computes the inverse cosine of a normalized input #
6598 # sacosd(): computes the inverse cosine of a denormalized input #
6600 # INPUT *************************************************************** #
6601 # a0 = pointer to extended precision input #
6602 # d0 = round precision,mode #
6604 # OUTPUT ************************************************************** #
6605 # fp0 = arccos(X) #
6607 # ACCURACY and MONOTONICITY ******************************************* #
6608 # The returned result is within 3 ulps in 64 significant bit, #
6609 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6610 # rounded to double precision. The result is provably monotonic #
6611 # in double precision. #
6613 # ALGORITHM *********************************************************** #
6615 # ACOS #
6616 # 1. If |X| >= 1, go to 3. #
6618 # 2. (|X| < 1) Calculate acos(X) by #
6619 # z := (1-X) / (1+X) #
6620 # acos(X) = 2 * atan( sqrt(z) ). #
6621 # Exit. #
6623 # 3. If |X| > 1, go to 5. #
6625 # 4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit. #
6627 # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6628 # Exit. #
6630 #########################################################################
6632 global sacos
6633 sacos:
6634 fmov.x (%a0),%fp0 # LOAD INPUT
6636 mov.l (%a0),%d1 # pack exp w/ upper 16 fraction
6637 mov.w 4(%a0),%d1
6638 and.l &0x7FFFFFFF,%d1
6639 cmp.l %d1,&0x3FFF8000
6640 bge.b ACOSBIG
6642 #--THIS IS THE USUAL CASE, |X| < 1
6643 #--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )
6645 ACOSMAIN:
6646 fmov.s &0x3F800000,%fp1
6647 fadd.x %fp0,%fp1 # 1+X
6648 fneg.x %fp0 # -X
6649 fadd.s &0x3F800000,%fp0 # 1-X
6650 fdiv.x %fp1,%fp0 # (1-X)/(1+X)
6651 fsqrt.x %fp0 # SQRT((1-X)/(1+X))
6652 mov.l %d0,-(%sp) # save original users fpcr
6653 clr.l %d0
6654 fmovm.x &0x01,-(%sp) # save SQRT(...) to stack
6655 lea (%sp),%a0 # pass ptr to sqrt
6656 bsr satan # ATAN(SQRT([1-X]/[1+X]))
6657 add.l &0xc,%sp # clear SQRT(...) from stack
6659 fmov.l (%sp)+,%fpcr # restore users round prec,mode
6660 fadd.x %fp0,%fp0 # 2 * ATAN( STUFF )
6661 bra t_pinx2
6663 ACOSBIG:
6664 fabs.x %fp0
6665 fcmp.s %fp0,&0x3F800000
6666 fbgt t_operr # cause an operr exception
6668 #--|X| = 1, ACOS(X) = 0 OR PI
6669 tst.b (%a0) # is X positive or negative?
6670 bpl.b ACOSP1
6672 #--X = -1
6673 #Returns PI and inexact exception
6674 ACOSM1:
6675 fmov.x PI(%pc),%fp0 # load PI
6676 fmov.l %d0,%fpcr # load round mode,prec
6677 fadd.s &0x00800000,%fp0 # add a small value
6678 bra t_pinx2
6680 ACOSP1:
6681 bra ld_pzero # answer is positive zero
6683 global sacosd
6684 #--ACOS(X) = PI/2 FOR DENORMALIZED X
6685 sacosd:
6686 fmov.l %d0,%fpcr # load user's rnd mode/prec
6687 fmov.x PIBY2(%pc),%fp0
6688 bra t_pinx2
6690 #########################################################################
6691 # setox(): computes the exponential for a normalized input #
6692 # setoxd(): computes the exponential for a denormalized input #
6693 # setoxm1(): computes the exponential minus 1 for a normalized input #
6694 # setoxm1d(): computes the exponential minus 1 for a denormalized input #
6696 # INPUT *************************************************************** #
6697 # a0 = pointer to extended precision input #
6698 # d0 = round precision,mode #
6700 # OUTPUT ************************************************************** #
6701 # fp0 = exp(X) or exp(X)-1 #
6703 # ACCURACY and MONOTONICITY ******************************************* #
6704 # The returned result is within 0.85 ulps in 64 significant bit, #
6705 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6706 # rounded to double precision. The result is provably monotonic #
6707 # in double precision. #
6709 # ALGORITHM and IMPLEMENTATION **************************************** #
6711 # setoxd #
6712 # ------ #
6713 # Step 1. Set ans := 1.0 #
6715 # Step 2. Return ans := ans + sign(X)*2^(-126). Exit. #
6716 # Notes: This will always generate one exception -- inexact. #
6719 # setox #
6720 # ----- #
6722 # Step 1. Filter out extreme cases of input argument. #
6723 # 1.1 If |X| >= 2^(-65), go to Step 1.3. #
6724 # 1.2 Go to Step 7. #
6725 # 1.3 If |X| < 16380 log(2), go to Step 2. #
6726 # 1.4 Go to Step 8. #
6727 # Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6728 # To avoid the use of floating-point comparisons, a #
6729 # compact representation of |X| is used. This format is a #
6730 # 32-bit integer, the upper (more significant) 16 bits #
6731 # are the sign and biased exponent field of |X|; the #
6732 # lower 16 bits are the 16 most significant fraction #
6733 # (including the explicit bit) bits of |X|. Consequently, #
6734 # the comparisons in Steps 1.1 and 1.3 can be performed #
6735 # by integer comparison. Note also that the constant #
6736 # 16380 log(2) used in Step 1.3 is also in the compact #
6737 # form. Thus taking the branch to Step 2 guarantees #
6738 # |X| < 16380 log(2). There is no harm to have a small #
6739 # number of cases where |X| is less than, but close to, #
6740 # 16380 log(2) and the branch to Step 9 is taken. #
6742 # Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6743 # 2.1 Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
6744 # was taken) #
6745 # 2.2 N := round-to-nearest-integer( X * 64/log2 ). #
6746 # 2.3 Calculate J = N mod 64; so J = 0,1,2,..., #
6747 # or 63. #
6748 # 2.4 Calculate M = (N - J)/64; so N = 64M + J. #
6749 # 2.5 Calculate the address of the stored value of #
6750 # 2^(J/64). #
6751 # 2.6 Create the value Scale = 2^M. #
6752 # Notes: The calculation in 2.2 is really performed by #
6753 # Z := X * constant #
6754 # N := round-to-nearest-integer(Z) #
6755 # where #
6756 # constant := single-precision( 64/log 2 ). #
6758 # Using a single-precision constant avoids memory #
6759 # access. Another effect of using a single-precision #
6760 # "constant" is that the calculated value Z is #
6762 # Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24). #
6764 # This error has to be considered later in Steps 3 and 4. #
6766 # Step 3. Calculate X - N*log2/64. #
6767 # 3.1 R := X + N*L1, #
6768 # where L1 := single-precision(-log2/64). #
6769 # 3.2 R := R + N*L2, #
6770 # L2 := extended-precision(-log2/64 - L1).#
6771 # Notes: a) The way L1 and L2 are chosen ensures L1+L2 #
6772 # approximate the value -log2/64 to 88 bits of accuracy. #
6773 # b) N*L1 is exact because N is no longer than 22 bits #
6774 # and L1 is no longer than 24 bits. #
6775 # c) The calculation X+N*L1 is also exact due to #
6776 # cancellation. Thus, R is practically X+N(L1+L2) to full #
6777 # 64 bits. #
6778 # d) It is important to estimate how large can |R| be #
6779 # after Step 3.2. #
6781 # N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24) #
6782 # X*64/log2 (1+eps) = N + f, |f| <= 0.5 #
6783 # X*64/log2 - N = f - eps*X 64/log2 #
6784 # X - N*log2/64 = f*log2/64 - eps*X #
6787 # Now |X| <= 16446 log2, thus #
6789 # |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
6790 # <= 0.57 log2/64. #
6791 # This bound will be used in Step 4. #
6793 # Step 4. Approximate exp(R)-1 by a polynomial #
6794 # p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5)))) #
6795 # Notes: a) In order to reduce memory access, the coefficients #
6796 # are made as "short" as possible: A1 (which is 1/2), A4 #
6797 # and A5 are single precision; A2 and A3 are double #
6798 # precision. #
6799 # b) Even with the restrictions above, #
6800 # |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062. #
6801 # Note that 0.0062 is slightly bigger than 0.57 log2/64. #
6802 # c) To fully use the pipeline, p is separated into #
6803 # two independent pieces of roughly equal complexities #
6804 # p = [ R + R*S*(A2 + S*A4) ] + #
6805 # [ S*(A1 + S*(A3 + S*A5)) ] #
6806 # where S = R*R. #
6808 # Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by #
6809 # ans := T + ( T*p + t) #
6810 # where T and t are the stored values for 2^(J/64). #
6811 # Notes: 2^(J/64) is stored as T and t where T+t approximates #
6812 # 2^(J/64) to roughly 85 bits; T is in extended precision #
6813 # and t is in single precision. Note also that T is #
6814 # rounded to 62 bits so that the last two bits of T are #
6815 # zero. The reason for such a special form is that T-1, #
6816 # T-2, and T-8 will all be exact --- a property that will #
6817 # give much more accurate computation of the function #
6818 # EXPM1. #
6820 # Step 6. Reconstruction of exp(X) #
6821 # exp(X) = 2^M * 2^(J/64) * exp(R). #
6822 # 6.1 If AdjFlag = 0, go to 6.3 #
6823 # 6.2 ans := ans * AdjScale #
6824 # 6.3 Restore the user FPCR #
6825 # 6.4 Return ans := ans * Scale. Exit. #
6826 # Notes: If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R, #
6827 # |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will #
6828 # neither overflow nor underflow. If AdjFlag = 1, that #
6829 # means that #
6830 # X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
6831 # Hence, exp(X) may overflow or underflow or neither. #
6832 # When that is the case, AdjScale = 2^(M1) where M1 is #
6833 # approximately M. Thus 6.2 will never cause #
6834 # over/underflow. Possible exception in 6.4 is overflow #
6835 # or underflow. The inexact exception is not generated in #
6836 # 6.4. Although one can argue that the inexact flag #
6837 # should always be raised, to simulate that exception #
6838 # cost to much than the flag is worth in practical uses. #
6840 # Step 7. Return 1 + X. #
6841 # 7.1 ans := X #
6842 # 7.2 Restore user FPCR. #
6843 # 7.3 Return ans := 1 + ans. Exit #
6844 # Notes: For non-zero X, the inexact exception will always be #
6845 # raised by 7.3. That is the only exception raised by 7.3.#
6846 # Note also that we use the FMOVEM instruction to move X #
6847 # in Step 7.1 to avoid unnecessary trapping. (Although #
6848 # the FMOVEM may not seem relevant since X is normalized, #
6849 # the precaution will be useful in the library version of #
6850 # this code where the separate entry for denormalized #
6851 # inputs will be done away with.) #
6853 # Step 8. Handle exp(X) where |X| >= 16380log2. #
6854 # 8.1 If |X| > 16480 log2, go to Step 9. #
6855 # (mimic 2.2 - 2.6) #
6856 # 8.2 N := round-to-integer( X * 64/log2 ) #
6857 # 8.3 Calculate J = N mod 64, J = 0,1,...,63 #
6858 # 8.4 K := (N-J)/64, M1 := truncate(K/2), M = K-M1, #
6859 # AdjFlag := 1. #
6860 # 8.5 Calculate the address of the stored value #
6861 # 2^(J/64). #
6862 # 8.6 Create the values Scale = 2^M, AdjScale = 2^M1. #
6863 # 8.7 Go to Step 3. #
6864 # Notes: Refer to notes for 2.2 - 2.6. #
6866 # Step 9. Handle exp(X), |X| > 16480 log2. #
6867 # 9.1 If X < 0, go to 9.3 #
6868 # 9.2 ans := Huge, go to 9.4 #
6869 # 9.3 ans := Tiny. #
6870 # 9.4 Restore user FPCR. #
6871 # 9.5 Return ans := ans * ans. Exit. #
6872 # Notes: Exp(X) will surely overflow or underflow, depending on #
6873 # X's sign. "Huge" and "Tiny" are respectively large/tiny #
6874 # extended-precision numbers whose square over/underflow #
6875 # with an inexact result. Thus, 9.5 always raises the #
6876 # inexact together with either overflow or underflow. #
6878 # setoxm1d #
6879 # -------- #
6881 # Step 1. Set ans := 0 #
6883 # Step 2. Return ans := X + ans. Exit. #
6884 # Notes: This will return X with the appropriate rounding #
6885 # precision prescribed by the user FPCR. #
6887 # setoxm1 #
6888 # ------- #
6890 # Step 1. Check |X| #
6891 # 1.1 If |X| >= 1/4, go to Step 1.3. #
6892 # 1.2 Go to Step 7. #
6893 # 1.3 If |X| < 70 log(2), go to Step 2. #
6894 # 1.4 Go to Step 10. #
6895 # Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6896 # However, it is conceivable |X| can be small very often #
6897 # because EXPM1 is intended to evaluate exp(X)-1 #
6898 # accurately when |X| is small. For further details on #
6899 # the comparisons, see the notes on Step 1 of setox. #
6901 # Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6902 # 2.1 N := round-to-nearest-integer( X * 64/log2 ). #
6903 # 2.2 Calculate J = N mod 64; so J = 0,1,2,..., #
6904 # or 63. #
6905 # 2.3 Calculate M = (N - J)/64; so N = 64M + J. #
6906 # 2.4 Calculate the address of the stored value of #
6907 # 2^(J/64). #
6908 # 2.5 Create the values Sc = 2^M and #
6909 # OnebySc := -2^(-M). #
6910 # Notes: See the notes on Step 2 of setox. #
6912 # Step 3. Calculate X - N*log2/64. #
6913 # 3.1 R := X + N*L1, #
6914 # where L1 := single-precision(-log2/64). #
6915 # 3.2 R := R + N*L2, #
6916 # L2 := extended-precision(-log2/64 - L1).#
6917 # Notes: Applying the analysis of Step 3 of setox in this case #
6918 # shows that |R| <= 0.0055 (note that |X| <= 70 log2 in #
6919 # this case). #
6921 # Step 4. Approximate exp(R)-1 by a polynomial #
6922 # p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
6923 # Notes: a) In order to reduce memory access, the coefficients #
6924 # are made as "short" as possible: A1 (which is 1/2), A5 #
6925 # and A6 are single precision; A2, A3 and A4 are double #
6926 # precision. #
6927 # b) Even with the restriction above, #
6928 # |p - (exp(R)-1)| < |R| * 2^(-72.7) #
6929 # for all |R| <= 0.0055. #
6930 # c) To fully use the pipeline, p is separated into #
6931 # two independent pieces of roughly equal complexity #
6932 # p = [ R*S*(A2 + S*(A4 + S*A6)) ] + #
6933 # [ R + S*(A1 + S*(A3 + S*A5)) ] #
6934 # where S = R*R. #
6936 # Step 5. Compute 2^(J/64)*p by #
6937 # p := T*p #
6938 # where T and t are the stored values for 2^(J/64). #
6939 # Notes: 2^(J/64) is stored as T and t where T+t approximates #
6940 # 2^(J/64) to roughly 85 bits; T is in extended precision #
6941 # and t is in single precision. Note also that T is #
6942 # rounded to 62 bits so that the last two bits of T are #
6943 # zero. The reason for such a special form is that T-1, #
6944 # T-2, and T-8 will all be exact --- a property that will #
6945 # be exploited in Step 6 below. The total relative error #
6946 # in p is no bigger than 2^(-67.7) compared to the final #
6947 # result. #
6949 # Step 6. Reconstruction of exp(X)-1 #
6950 # exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ). #
6951 # 6.1 If M <= 63, go to Step 6.3. #
6952 # 6.2 ans := T + (p + (t + OnebySc)). Go to 6.6 #
6953 # 6.3 If M >= -3, go to 6.5. #
6954 # 6.4 ans := (T + (p + t)) + OnebySc. Go to 6.6 #
6955 # 6.5 ans := (T + OnebySc) + (p + t). #
6956 # 6.6 Restore user FPCR. #
6957 # 6.7 Return ans := Sc * ans. Exit. #
6958 # Notes: The various arrangements of the expressions give #
6959 # accurate evaluations. #
6961 # Step 7. exp(X)-1 for |X| < 1/4. #
6962 # 7.1 If |X| >= 2^(-65), go to Step 9. #
6963 # 7.2 Go to Step 8. #
6965 # Step 8. Calculate exp(X)-1, |X| < 2^(-65). #
6966 # 8.1 If |X| < 2^(-16312), goto 8.3 #
6967 # 8.2 Restore FPCR; return ans := X - 2^(-16382). #
6968 # Exit. #
6969 # 8.3 X := X * 2^(140). #
6970 # 8.4 Restore FPCR; ans := ans - 2^(-16382). #
6971 # Return ans := ans*2^(140). Exit #
6972 # Notes: The idea is to return "X - tiny" under the user #
6973 # precision and rounding modes. To avoid unnecessary #
6974 # inefficiency, we stay away from denormalized numbers #
6975 # the best we can. For |X| >= 2^(-16312), the #
6976 # straightforward 8.2 generates the inexact exception as #
6977 # the case warrants. #
6979 # Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial #
6980 # p = X + X*X*(B1 + X*(B2 + ... + X*B12)) #
6981 # Notes: a) In order to reduce memory access, the coefficients #
6982 # are made as "short" as possible: B1 (which is 1/2), B9 #
6983 # to B12 are single precision; B3 to B8 are double #
6984 # precision; and B2 is double extended. #
6985 # b) Even with the restriction above, #
6986 # |p - (exp(X)-1)| < |X| 2^(-70.6) #
6987 # for all |X| <= 0.251. #
6988 # Note that 0.251 is slightly bigger than 1/4. #
6989 # c) To fully preserve accuracy, the polynomial is #
6990 # computed as #
6991 # X + ( S*B1 + Q ) where S = X*X and #
6992 # Q = X*S*(B2 + X*(B3 + ... + X*B12)) #
6993 # d) To fully use the pipeline, Q is separated into #
6994 # two independent pieces of roughly equal complexity #
6995 # Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] + #
6996 # [ S*S*(B3 + S*(B5 + ... + S*B11)) ] #
6998 # Step 10. Calculate exp(X)-1 for |X| >= 70 log 2. #
6999 # 10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all #
7000 # practical purposes. Therefore, go to Step 1 of setox. #
7001 # 10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
7002 # purposes. #
7003 # ans := -1 #
7004 # Restore user FPCR #
7005 # Return ans := ans + 2^(-126). Exit. #
7006 # Notes: 10.2 will always create an inexact and return -1 + tiny #
7007 # in the user rounding precision and mode. #
7009 #########################################################################
7011 L2: long 0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
7013 EEXPA3: long 0x3FA55555,0x55554CC1
7014 EEXPA2: long 0x3FC55555,0x55554A54
7016 EM1A4: long 0x3F811111,0x11174385
7017 EM1A3: long 0x3FA55555,0x55554F5A
7019 EM1A2: long 0x3FC55555,0x55555555,0x00000000,0x00000000
7021 EM1B8: long 0x3EC71DE3,0xA5774682
7022 EM1B7: long 0x3EFA01A0,0x19D7CB68
7024 EM1B6: long 0x3F2A01A0,0x1A019DF3
7025 EM1B5: long 0x3F56C16C,0x16C170E2
7027 EM1B4: long 0x3F811111,0x11111111
7028 EM1B3: long 0x3FA55555,0x55555555
7030 EM1B2: long 0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
7031 long 0x00000000
7033 TWO140: long 0x48B00000,0x00000000
7034 TWON140:
7035 long 0x37300000,0x00000000
7037 EEXPTBL:
7038 long 0x3FFF0000,0x80000000,0x00000000,0x00000000
7039 long 0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
7040 long 0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
7041 long 0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
7042 long 0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
7043 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
7044 long 0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
7045 long 0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
7046 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
7047 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
7048 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
7049 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
7050 long 0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
7051 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
7052 long 0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
7053 long 0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
7054 long 0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
7055 long 0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
7056 long 0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
7057 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
7058 long 0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
7059 long 0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
7060 long 0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
7061 long 0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
7062 long 0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
7063 long 0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
7064 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
7065 long 0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
7066 long 0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
7067 long 0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
7068 long 0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
7069 long 0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
7070 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
7071 long 0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
7072 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
7073 long 0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
7074 long 0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
7075 long 0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
7076 long 0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
7077 long 0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
7078 long 0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
7079 long 0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
7080 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
7081 long 0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
7082 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
7083 long 0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
7084 long 0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
7085 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
7086 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
7087 long 0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
7088 long 0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
7089 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
7090 long 0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
7091 long 0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
7092 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
7093 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
7094 long 0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
7095 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
7096 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
7097 long 0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
7098 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
7099 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
7100 long 0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
7101 long 0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
7103 set ADJFLAG,L_SCR2
7104 set SCALE,FP_SCR0
7105 set ADJSCALE,FP_SCR1
7106 set SC,FP_SCR0
7107 set ONEBYSC,FP_SCR1
7109 global setox
7110 setox:
7111 #--entry point for EXP(X), here X is finite, non-zero, and not NaN's
7113 #--Step 1.
7114 mov.l (%a0),%d1 # load part of input X
7115 and.l &0x7FFF0000,%d1 # biased expo. of X
7116 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7117 bge.b EXPC1 # normal case
7118 bra EXPSM
7120 EXPC1:
7121 #--The case |X| >= 2^(-65)
7122 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7123 cmp.l %d1,&0x400CB167 # 16380 log2 trunc. 16 bits
7124 blt.b EXPMAIN # normal case
7125 bra EEXPBIG
7127 EXPMAIN:
7128 #--Step 2.
7129 #--This is the normal branch: 2^(-65) <= |X| < 16380 log2.
7130 fmov.x (%a0),%fp0 # load input from (a0)
7132 fmov.x %fp0,%fp1
7133 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7134 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7135 mov.l &0,ADJFLAG(%a6)
7136 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7137 lea EEXPTBL(%pc),%a1
7138 fmov.l %d1,%fp0 # convert to floating-format
7140 mov.l %d1,L_SCR1(%a6) # save N temporarily
7141 and.l &0x3F,%d1 # D0 is J = N mod 64
7142 lsl.l &4,%d1
7143 add.l %d1,%a1 # address of 2^(J/64)
7144 mov.l L_SCR1(%a6),%d1
7145 asr.l &6,%d1 # D0 is M
7146 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7147 mov.w L2(%pc),L_SCR1(%a6) # prefetch L2, no need in CB
7149 EXPCONT1:
7150 #--Step 3.
7151 #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7152 #--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
7153 fmov.x %fp0,%fp2
7154 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7155 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7156 fadd.x %fp1,%fp0 # X + N*L1
7157 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7159 #--Step 4.
7160 #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7161 #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
7162 #--TO FULLY USE THE PIPELINE, WE COMPUTE S = R*R
7163 #--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
7165 fmov.x %fp0,%fp1
7166 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7168 fmov.s &0x3AB60B70,%fp2 # fp2 IS A5
7170 fmul.x %fp1,%fp2 # fp2 IS S*A5
7171 fmov.x %fp1,%fp3
7172 fmul.s &0x3C088895,%fp3 # fp3 IS S*A4
7174 fadd.d EEXPA3(%pc),%fp2 # fp2 IS A3+S*A5
7175 fadd.d EEXPA2(%pc),%fp3 # fp3 IS A2+S*A4
7177 fmul.x %fp1,%fp2 # fp2 IS S*(A3+S*A5)
7178 mov.w %d1,SCALE(%a6) # SCALE is 2^(M) in extended
7179 mov.l &0x80000000,SCALE+4(%a6)
7180 clr.l SCALE+8(%a6)
7182 fmul.x %fp1,%fp3 # fp3 IS S*(A2+S*A4)
7184 fadd.s &0x3F000000,%fp2 # fp2 IS A1+S*(A3+S*A5)
7185 fmul.x %fp0,%fp3 # fp3 IS R*S*(A2+S*A4)
7187 fmul.x %fp1,%fp2 # fp2 IS S*(A1+S*(A3+S*A5))
7188 fadd.x %fp3,%fp0 # fp0 IS R+R*S*(A2+S*A4),
7190 fmov.x (%a1)+,%fp1 # fp1 is lead. pt. of 2^(J/64)
7191 fadd.x %fp2,%fp0 # fp0 is EXP(R) - 1
7193 #--Step 5
7194 #--final reconstruction process
7195 #--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
7197 fmul.x %fp1,%fp0 # 2^(J/64)*(Exp(R)-1)
7198 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7199 fadd.s (%a1),%fp0 # accurate 2^(J/64)
7201 fadd.x %fp1,%fp0 # 2^(J/64) + 2^(J/64)*...
7202 mov.l ADJFLAG(%a6),%d1
7204 #--Step 6
7205 tst.l %d1
7206 beq.b NORMAL
7207 ADJUST:
7208 fmul.x ADJSCALE(%a6),%fp0
7209 NORMAL:
7210 fmov.l %d0,%fpcr # restore user FPCR
7211 mov.b &FMUL_OP,%d1 # last inst is MUL
7212 fmul.x SCALE(%a6),%fp0 # multiply 2^(M)
7213 bra t_catch
7215 EXPSM:
7216 #--Step 7
7217 fmovm.x (%a0),&0x80 # load X
7218 fmov.l %d0,%fpcr
7219 fadd.s &0x3F800000,%fp0 # 1+X in user mode
7220 bra t_pinx2
7222 EEXPBIG:
7223 #--Step 8
7224 cmp.l %d1,&0x400CB27C # 16480 log2
7225 bgt.b EXP2BIG
7226 #--Steps 8.2 -- 8.6
7227 fmov.x (%a0),%fp0 # load input from (a0)
7229 fmov.x %fp0,%fp1
7230 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7231 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7232 mov.l &1,ADJFLAG(%a6)
7233 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7234 lea EEXPTBL(%pc),%a1
7235 fmov.l %d1,%fp0 # convert to floating-format
7236 mov.l %d1,L_SCR1(%a6) # save N temporarily
7237 and.l &0x3F,%d1 # D0 is J = N mod 64
7238 lsl.l &4,%d1
7239 add.l %d1,%a1 # address of 2^(J/64)
7240 mov.l L_SCR1(%a6),%d1
7241 asr.l &6,%d1 # D0 is K
7242 mov.l %d1,L_SCR1(%a6) # save K temporarily
7243 asr.l &1,%d1 # D0 is M1
7244 sub.l %d1,L_SCR1(%a6) # a1 is M
7245 add.w &0x3FFF,%d1 # biased expo. of 2^(M1)
7246 mov.w %d1,ADJSCALE(%a6) # ADJSCALE := 2^(M1)
7247 mov.l &0x80000000,ADJSCALE+4(%a6)
7248 clr.l ADJSCALE+8(%a6)
7249 mov.l L_SCR1(%a6),%d1 # D0 is M
7250 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7251 bra.w EXPCONT1 # go back to Step 3
7253 EXP2BIG:
7254 #--Step 9
7255 tst.b (%a0) # is X positive or negative?
7256 bmi t_unfl2
7257 bra t_ovfl2
7259 global setoxd
7260 setoxd:
7261 #--entry point for EXP(X), X is denormalized
7262 mov.l (%a0),-(%sp)
7263 andi.l &0x80000000,(%sp)
7264 ori.l &0x00800000,(%sp) # sign(X)*2^(-126)
7266 fmov.s &0x3F800000,%fp0
7268 fmov.l %d0,%fpcr
7269 fadd.s (%sp)+,%fp0
7270 bra t_pinx2
7272 global setoxm1
7273 setoxm1:
7274 #--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
7276 #--Step 1.
7277 #--Step 1.1
7278 mov.l (%a0),%d1 # load part of input X
7279 and.l &0x7FFF0000,%d1 # biased expo. of X
7280 cmp.l %d1,&0x3FFD0000 # 1/4
7281 bge.b EM1CON1 # |X| >= 1/4
7282 bra EM1SM
7284 EM1CON1:
7285 #--Step 1.3
7286 #--The case |X| >= 1/4
7287 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7288 cmp.l %d1,&0x4004C215 # 70log2 rounded up to 16 bits
7289 ble.b EM1MAIN # 1/4 <= |X| <= 70log2
7290 bra EM1BIG
7292 EM1MAIN:
7293 #--Step 2.
7294 #--This is the case: 1/4 <= |X| <= 70 log2.
7295 fmov.x (%a0),%fp0 # load input from (a0)
7297 fmov.x %fp0,%fp1
7298 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7299 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7300 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7301 lea EEXPTBL(%pc),%a1
7302 fmov.l %d1,%fp0 # convert to floating-format
7304 mov.l %d1,L_SCR1(%a6) # save N temporarily
7305 and.l &0x3F,%d1 # D0 is J = N mod 64
7306 lsl.l &4,%d1
7307 add.l %d1,%a1 # address of 2^(J/64)
7308 mov.l L_SCR1(%a6),%d1
7309 asr.l &6,%d1 # D0 is M
7310 mov.l %d1,L_SCR1(%a6) # save a copy of M
7312 #--Step 3.
7313 #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7314 #--a0 points to 2^(J/64), D0 and a1 both contain M
7315 fmov.x %fp0,%fp2
7316 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7317 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7318 fadd.x %fp1,%fp0 # X + N*L1
7319 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7320 add.w &0x3FFF,%d1 # D0 is biased expo. of 2^M
7322 #--Step 4.
7323 #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7324 #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
7325 #--TO FULLY USE THE PIPELINE, WE COMPUTE S = R*R
7326 #--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
7328 fmov.x %fp0,%fp1
7329 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7331 fmov.s &0x3950097B,%fp2 # fp2 IS a6
7333 fmul.x %fp1,%fp2 # fp2 IS S*A6
7334 fmov.x %fp1,%fp3
7335 fmul.s &0x3AB60B6A,%fp3 # fp3 IS S*A5
7337 fadd.d EM1A4(%pc),%fp2 # fp2 IS A4+S*A6
7338 fadd.d EM1A3(%pc),%fp3 # fp3 IS A3+S*A5
7339 mov.w %d1,SC(%a6) # SC is 2^(M) in extended
7340 mov.l &0x80000000,SC+4(%a6)
7341 clr.l SC+8(%a6)
7343 fmul.x %fp1,%fp2 # fp2 IS S*(A4+S*A6)
7344 mov.l L_SCR1(%a6),%d1 # D0 is M
7345 neg.w %d1 # D0 is -M
7346 fmul.x %fp1,%fp3 # fp3 IS S*(A3+S*A5)
7347 add.w &0x3FFF,%d1 # biased expo. of 2^(-M)
7348 fadd.d EM1A2(%pc),%fp2 # fp2 IS A2+S*(A4+S*A6)
7349 fadd.s &0x3F000000,%fp3 # fp3 IS A1+S*(A3+S*A5)
7351 fmul.x %fp1,%fp2 # fp2 IS S*(A2+S*(A4+S*A6))
7352 or.w &0x8000,%d1 # signed/expo. of -2^(-M)
7353 mov.w %d1,ONEBYSC(%a6) # OnebySc is -2^(-M)
7354 mov.l &0x80000000,ONEBYSC+4(%a6)
7355 clr.l ONEBYSC+8(%a6)
7356 fmul.x %fp3,%fp1 # fp1 IS S*(A1+S*(A3+S*A5))
7358 fmul.x %fp0,%fp2 # fp2 IS R*S*(A2+S*(A4+S*A6))
7359 fadd.x %fp1,%fp0 # fp0 IS R+S*(A1+S*(A3+S*A5))
7361 fadd.x %fp2,%fp0 # fp0 IS EXP(R)-1
7363 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7365 #--Step 5
7366 #--Compute 2^(J/64)*p
7368 fmul.x (%a1),%fp0 # 2^(J/64)*(Exp(R)-1)
7370 #--Step 6
7371 #--Step 6.1
7372 mov.l L_SCR1(%a6),%d1 # retrieve M
7373 cmp.l %d1,&63
7374 ble.b MLE63
7375 #--Step 6.2 M >= 64
7376 fmov.s 12(%a1),%fp1 # fp1 is t
7377 fadd.x ONEBYSC(%a6),%fp1 # fp1 is t+OnebySc
7378 fadd.x %fp1,%fp0 # p+(t+OnebySc), fp1 released
7379 fadd.x (%a1),%fp0 # T+(p+(t+OnebySc))
7380 bra EM1SCALE
7381 MLE63:
7382 #--Step 6.3 M <= 63
7383 cmp.l %d1,&-3
7384 bge.b MGEN3
7385 MLTN3:
7386 #--Step 6.4 M <= -4
7387 fadd.s 12(%a1),%fp0 # p+t
7388 fadd.x (%a1),%fp0 # T+(p+t)
7389 fadd.x ONEBYSC(%a6),%fp0 # OnebySc + (T+(p+t))
7390 bra EM1SCALE
7391 MGEN3:
7392 #--Step 6.5 -3 <= M <= 63
7393 fmov.x (%a1)+,%fp1 # fp1 is T
7394 fadd.s (%a1),%fp0 # fp0 is p+t
7395 fadd.x ONEBYSC(%a6),%fp1 # fp1 is T+OnebySc
7396 fadd.x %fp1,%fp0 # (T+OnebySc)+(p+t)
7398 EM1SCALE:
7399 #--Step 6.6
7400 fmov.l %d0,%fpcr
7401 fmul.x SC(%a6),%fp0
7402 bra t_inx2
7404 EM1SM:
7405 #--Step 7 |X| < 1/4.
7406 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7407 bge.b EM1POLY
7409 EM1TINY:
7410 #--Step 8 |X| < 2^(-65)
7411 cmp.l %d1,&0x00330000 # 2^(-16312)
7412 blt.b EM12TINY
7413 #--Step 8.2
7414 mov.l &0x80010000,SC(%a6) # SC is -2^(-16382)
7415 mov.l &0x80000000,SC+4(%a6)
7416 clr.l SC+8(%a6)
7417 fmov.x (%a0),%fp0
7418 fmov.l %d0,%fpcr
7419 mov.b &FADD_OP,%d1 # last inst is ADD
7420 fadd.x SC(%a6),%fp0
7421 bra t_catch
7423 EM12TINY:
7424 #--Step 8.3
7425 fmov.x (%a0),%fp0
7426 fmul.d TWO140(%pc),%fp0
7427 mov.l &0x80010000,SC(%a6)
7428 mov.l &0x80000000,SC+4(%a6)
7429 clr.l SC+8(%a6)
7430 fadd.x SC(%a6),%fp0
7431 fmov.l %d0,%fpcr
7432 mov.b &FMUL_OP,%d1 # last inst is MUL
7433 fmul.d TWON140(%pc),%fp0
7434 bra t_catch
7436 EM1POLY:
7437 #--Step 9 exp(X)-1 by a simple polynomial
7438 fmov.x (%a0),%fp0 # fp0 is X
7439 fmul.x %fp0,%fp0 # fp0 is S := X*X
7440 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7441 fmov.s &0x2F30CAA8,%fp1 # fp1 is B12
7442 fmul.x %fp0,%fp1 # fp1 is S*B12
7443 fmov.s &0x310F8290,%fp2 # fp2 is B11
7444 fadd.s &0x32D73220,%fp1 # fp1 is B10+S*B12
7446 fmul.x %fp0,%fp2 # fp2 is S*B11
7447 fmul.x %fp0,%fp1 # fp1 is S*(B10 + ...
7449 fadd.s &0x3493F281,%fp2 # fp2 is B9+S*...
7450 fadd.d EM1B8(%pc),%fp1 # fp1 is B8+S*...
7452 fmul.x %fp0,%fp2 # fp2 is S*(B9+...
7453 fmul.x %fp0,%fp1 # fp1 is S*(B8+...
7455 fadd.d EM1B7(%pc),%fp2 # fp2 is B7+S*...
7456 fadd.d EM1B6(%pc),%fp1 # fp1 is B6+S*...
7458 fmul.x %fp0,%fp2 # fp2 is S*(B7+...
7459 fmul.x %fp0,%fp1 # fp1 is S*(B6+...
7461 fadd.d EM1B5(%pc),%fp2 # fp2 is B5+S*...
7462 fadd.d EM1B4(%pc),%fp1 # fp1 is B4+S*...
7464 fmul.x %fp0,%fp2 # fp2 is S*(B5+...
7465 fmul.x %fp0,%fp1 # fp1 is S*(B4+...
7467 fadd.d EM1B3(%pc),%fp2 # fp2 is B3+S*...
7468 fadd.x EM1B2(%pc),%fp1 # fp1 is B2+S*...
7470 fmul.x %fp0,%fp2 # fp2 is S*(B3+...
7471 fmul.x %fp0,%fp1 # fp1 is S*(B2+...
7473 fmul.x %fp0,%fp2 # fp2 is S*S*(B3+...)
7474 fmul.x (%a0),%fp1 # fp1 is X*S*(B2...
7476 fmul.s &0x3F000000,%fp0 # fp0 is S*B1
7477 fadd.x %fp2,%fp1 # fp1 is Q
7479 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7481 fadd.x %fp1,%fp0 # fp0 is S*B1+Q
7483 fmov.l %d0,%fpcr
7484 fadd.x (%a0),%fp0
7485 bra t_inx2
7487 EM1BIG:
7488 #--Step 10 |X| > 70 log2
7489 mov.l (%a0),%d1
7490 cmp.l %d1,&0
7491 bgt.w EXPC1
7492 #--Step 10.2
7493 fmov.s &0xBF800000,%fp0 # fp0 is -1
7494 fmov.l %d0,%fpcr
7495 fadd.s &0x00800000,%fp0 # -1 + 2^(-126)
7496 bra t_minx2
7498 global setoxm1d
7499 setoxm1d:
7500 #--entry point for EXPM1(X), here X is denormalized
7501 #--Step 0.
7502 bra t_extdnrm
7504 #########################################################################
7505 # sgetexp(): returns the exponent portion of the input argument. #
7506 # The exponent bias is removed and the exponent value is #
7507 # returned as an extended precision number in fp0. #
7508 # sgetexpd(): handles denormalized numbers. #
7510 # sgetman(): extracts the mantissa of the input argument. The #
7511 # mantissa is converted to an extended precision number w/ #
7512 # an exponent of $3fff and is returned in fp0. The range of #
7513 # the result is [1.0 - 2.0). #
7514 # sgetmand(): handles denormalized numbers. #
7516 # INPUT *************************************************************** #
7517 # a0 = pointer to extended precision input #
7519 # OUTPUT ************************************************************** #
7520 # fp0 = exponent(X) or mantissa(X) #
7522 #########################################################################
7524 global sgetexp
7525 sgetexp:
7526 mov.w SRC_EX(%a0),%d0 # get the exponent
7527 bclr &0xf,%d0 # clear the sign bit
7528 subi.w &0x3fff,%d0 # subtract off the bias
7529 fmov.w %d0,%fp0 # return exp in fp0
7530 blt.b sgetexpn # it's negative
7533 sgetexpn:
7534 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7537 global sgetexpd
7538 sgetexpd:
7539 bsr.l norm # normalize
7540 neg.w %d0 # new exp = -(shft amt)
7541 subi.w &0x3fff,%d0 # subtract off the bias
7542 fmov.w %d0,%fp0 # return exp in fp0
7543 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7546 global sgetman
7547 sgetman:
7548 mov.w SRC_EX(%a0),%d0 # get the exp
7549 ori.w &0x7fff,%d0 # clear old exp
7550 bclr &0xe,%d0 # make it the new exp +-3fff
7552 # here, we build the result in a tmp location so as not to disturb the input
7553 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
7554 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
7555 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
7556 fmov.x FP_SCR0(%a6),%fp0 # put new value back in fp0
7557 bmi.b sgetmann # it's negative
7560 sgetmann:
7561 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7565 # For denormalized numbers, shift the mantissa until the j-bit = 1,
7566 # then load the exponent with +/1 $3fff.
7568 global sgetmand
7569 sgetmand:
7570 bsr.l norm # normalize exponent
7571 bra.b sgetman
7573 #########################################################################
7574 # scosh(): computes the hyperbolic cosine of a normalized input #
7575 # scoshd(): computes the hyperbolic cosine of a denormalized input #
7577 # INPUT *************************************************************** #
7578 # a0 = pointer to extended precision input #
7579 # d0 = round precision,mode #
7581 # OUTPUT ************************************************************** #
7582 # fp0 = cosh(X) #
7584 # ACCURACY and MONOTONICITY ******************************************* #
7585 # The returned result is within 3 ulps in 64 significant bit, #
7586 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7587 # rounded to double precision. The result is provably monotonic #
7588 # in double precision. #
7590 # ALGORITHM *********************************************************** #
7592 # COSH #
7593 # 1. If |X| > 16380 log2, go to 3. #
7595 # 2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae #
7596 # y = |X|, z = exp(Y), and #
7597 # cosh(X) = (1/2)*( z + 1/z ). #
7598 # Exit. #
7600 # 3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5. #
7602 # 4. (16380 log2 < |X| <= 16480 log2) #
7603 # cosh(X) = sign(X) * exp(|X|)/2. #
7604 # However, invoking exp(|X|) may cause premature #
7605 # overflow. Thus, we calculate sinh(X) as follows: #
7606 # Y := |X| #
7607 # Fact := 2**(16380) #
7608 # Y' := Y - 16381 log2 #
7609 # cosh(X) := Fact * exp(Y'). #
7610 # Exit. #
7612 # 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7613 # Huge*Huge to generate overflow and an infinity with #
7614 # the appropriate sign. Huge is the largest finite number #
7615 # in extended format. Exit. #
7617 #########################################################################
7619 TWO16380:
7620 long 0x7FFB0000,0x80000000,0x00000000,0x00000000
7622 global scosh
7623 scosh:
7624 fmov.x (%a0),%fp0 # LOAD INPUT
7626 mov.l (%a0),%d1
7627 mov.w 4(%a0),%d1
7628 and.l &0x7FFFFFFF,%d1
7629 cmp.l %d1,&0x400CB167
7630 bgt.b COSHBIG
7632 #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7633 #--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
7635 fabs.x %fp0 # |X|
7637 mov.l %d0,-(%sp)
7638 clr.l %d0
7639 fmovm.x &0x01,-(%sp) # save |X| to stack
7640 lea (%sp),%a0 # pass ptr to |X|
7641 bsr setox # FP0 IS EXP(|X|)
7642 add.l &0xc,%sp # erase |X| from stack
7643 fmul.s &0x3F000000,%fp0 # (1/2)EXP(|X|)
7644 mov.l (%sp)+,%d0
7646 fmov.s &0x3E800000,%fp1 # (1/4)
7647 fdiv.x %fp0,%fp1 # 1/(2 EXP(|X|))
7649 fmov.l %d0,%fpcr
7650 mov.b &FADD_OP,%d1 # last inst is ADD
7651 fadd.x %fp1,%fp0
7652 bra t_catch
7654 COSHBIG:
7655 cmp.l %d1,&0x400CB2B3
7656 bgt.b COSHHUGE
7658 fabs.x %fp0
7659 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7660 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7662 mov.l %d0,-(%sp)
7663 clr.l %d0
7664 fmovm.x &0x01,-(%sp) # save fp0 to stack
7665 lea (%sp),%a0 # pass ptr to fp0
7666 bsr setox
7667 add.l &0xc,%sp # clear fp0 from stack
7668 mov.l (%sp)+,%d0
7670 fmov.l %d0,%fpcr
7671 mov.b &FMUL_OP,%d1 # last inst is MUL
7672 fmul.x TWO16380(%pc),%fp0
7673 bra t_catch
7675 COSHHUGE:
7676 bra t_ovfl2
7678 global scoshd
7679 #--COSH(X) = 1 FOR DENORMALIZED X
7680 scoshd:
7681 fmov.s &0x3F800000,%fp0
7683 fmov.l %d0,%fpcr
7684 fadd.s &0x00800000,%fp0
7685 bra t_pinx2
7687 #########################################################################
7688 # ssinh(): computes the hyperbolic sine of a normalized input #
7689 # ssinhd(): computes the hyperbolic sine of a denormalized input #
7691 # INPUT *************************************************************** #
7692 # a0 = pointer to extended precision input #
7693 # d0 = round precision,mode #
7695 # OUTPUT ************************************************************** #
7696 # fp0 = sinh(X) #
7698 # ACCURACY and MONOTONICITY ******************************************* #
7699 # The returned result is within 3 ulps in 64 significant bit, #
7700 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7701 # rounded to double precision. The result is provably monotonic #
7702 # in double precision. #
7704 # ALGORITHM *********************************************************** #
7706 # SINH #
7707 # 1. If |X| > 16380 log2, go to 3. #
7709 # 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula #
7710 # y = |X|, sgn = sign(X), and z = expm1(Y), #
7711 # sinh(X) = sgn*(1/2)*( z + z/(1+z) ). #
7712 # Exit. #
7714 # 3. If |X| > 16480 log2, go to 5. #
7716 # 4. (16380 log2 < |X| <= 16480 log2) #
7717 # sinh(X) = sign(X) * exp(|X|)/2. #
7718 # However, invoking exp(|X|) may cause premature overflow. #
7719 # Thus, we calculate sinh(X) as follows: #
7720 # Y := |X| #
7721 # sgn := sign(X) #
7722 # sgnFact := sgn * 2**(16380) #
7723 # Y' := Y - 16381 log2 #
7724 # sinh(X) := sgnFact * exp(Y'). #
7725 # Exit. #
7727 # 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7728 # sign(X)*Huge*Huge to generate overflow and an infinity with #
7729 # the appropriate sign. Huge is the largest finite number in #
7730 # extended format. Exit. #
7732 #########################################################################
7734 global ssinh
7735 ssinh:
7736 fmov.x (%a0),%fp0 # LOAD INPUT
7738 mov.l (%a0),%d1
7739 mov.w 4(%a0),%d1
7740 mov.l %d1,%a1 # save (compacted) operand
7741 and.l &0x7FFFFFFF,%d1
7742 cmp.l %d1,&0x400CB167
7743 bgt.b SINHBIG
7745 #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7746 #--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
7748 fabs.x %fp0 # Y = |X|
7750 movm.l &0x8040,-(%sp) # {a1/d0}
7751 fmovm.x &0x01,-(%sp) # save Y on stack
7752 lea (%sp),%a0 # pass ptr to Y
7753 clr.l %d0
7754 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7755 add.l &0xc,%sp # clear Y from stack
7756 fmov.l &0,%fpcr
7757 movm.l (%sp)+,&0x0201 # {a1/d0}
7759 fmov.x %fp0,%fp1
7760 fadd.s &0x3F800000,%fp1 # 1+Z
7761 fmov.x %fp0,-(%sp)
7762 fdiv.x %fp1,%fp0 # Z/(1+Z)
7763 mov.l %a1,%d1
7764 and.l &0x80000000,%d1
7765 or.l &0x3F000000,%d1
7766 fadd.x (%sp)+,%fp0
7767 mov.l %d1,-(%sp)
7769 fmov.l %d0,%fpcr
7770 mov.b &FMUL_OP,%d1 # last inst is MUL
7771 fmul.s (%sp)+,%fp0 # last fp inst - possible exceptions set
7772 bra t_catch
7774 SINHBIG:
7775 cmp.l %d1,&0x400CB2B3
7776 bgt t_ovfl
7777 fabs.x %fp0
7778 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7779 mov.l &0,-(%sp)
7780 mov.l &0x80000000,-(%sp)
7781 mov.l %a1,%d1
7782 and.l &0x80000000,%d1
7783 or.l &0x7FFB0000,%d1
7784 mov.l %d1,-(%sp) # EXTENDED FMT
7785 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7787 mov.l %d0,-(%sp)
7788 clr.l %d0
7789 fmovm.x &0x01,-(%sp) # save fp0 on stack
7790 lea (%sp),%a0 # pass ptr to fp0
7791 bsr setox
7792 add.l &0xc,%sp # clear fp0 from stack
7794 mov.l (%sp)+,%d0
7795 fmov.l %d0,%fpcr
7796 mov.b &FMUL_OP,%d1 # last inst is MUL
7797 fmul.x (%sp)+,%fp0 # possible exception
7798 bra t_catch
7800 global ssinhd
7801 #--SINH(X) = X FOR DENORMALIZED X
7802 ssinhd:
7803 bra t_extdnrm
7805 #########################################################################
7806 # stanh(): computes the hyperbolic tangent of a normalized input #
7807 # stanhd(): computes the hyperbolic tangent of a denormalized input #
7809 # INPUT *************************************************************** #
7810 # a0 = pointer to extended precision input #
7811 # d0 = round precision,mode #
7813 # OUTPUT ************************************************************** #
7814 # fp0 = tanh(X) #
7816 # ACCURACY and MONOTONICITY ******************************************* #
7817 # The returned result is within 3 ulps in 64 significant bit, #
7818 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7819 # rounded to double precision. The result is provably monotonic #
7820 # in double precision. #
7822 # ALGORITHM *********************************************************** #
7824 # TANH #
7825 # 1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3. #
7827 # 2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by #
7828 # sgn := sign(X), y := 2|X|, z := expm1(Y), and #
7829 # tanh(X) = sgn*( z/(2+z) ). #
7830 # Exit. #
7832 # 3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1, #
7833 # go to 7. #
7835 # 4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6. #
7837 # 5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by #
7838 # sgn := sign(X), y := 2|X|, z := exp(Y), #
7839 # tanh(X) = sgn - [ sgn*2/(1+z) ]. #
7840 # Exit. #
7842 # 6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we #
7843 # calculate Tanh(X) by #
7844 # sgn := sign(X), Tiny := 2**(-126), #
7845 # tanh(X) := sgn - sgn*Tiny. #
7846 # Exit. #
7848 # 7. (|X| < 2**(-40)). Tanh(X) = X. Exit. #
7850 #########################################################################
7852 set X,FP_SCR0
7853 set XFRAC,X+4
7855 set SGN,L_SCR3
7857 set V,FP_SCR0
7859 global stanh
7860 stanh:
7861 fmov.x (%a0),%fp0 # LOAD INPUT
7863 fmov.x %fp0,X(%a6)
7864 mov.l (%a0),%d1
7865 mov.w 4(%a0),%d1
7866 mov.l %d1,X(%a6)
7867 and.l &0x7FFFFFFF,%d1
7868 cmp.l %d1, &0x3fd78000 # is |X| < 2^(-40)?
7869 blt.w TANHBORS # yes
7870 cmp.l %d1, &0x3fffddce # is |X| > (5/2)LOG2?
7871 bgt.w TANHBORS # yes
7873 #--THIS IS THE USUAL CASE
7874 #--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
7876 mov.l X(%a6),%d1
7877 mov.l %d1,SGN(%a6)
7878 and.l &0x7FFF0000,%d1
7879 add.l &0x00010000,%d1 # EXPONENT OF 2|X|
7880 mov.l %d1,X(%a6)
7881 and.l &0x80000000,SGN(%a6)
7882 fmov.x X(%a6),%fp0 # FP0 IS Y = 2|X|
7884 mov.l %d0,-(%sp)
7885 clr.l %d0
7886 fmovm.x &0x1,-(%sp) # save Y on stack
7887 lea (%sp),%a0 # pass ptr to Y
7888 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7889 add.l &0xc,%sp # clear Y from stack
7890 mov.l (%sp)+,%d0
7892 fmov.x %fp0,%fp1
7893 fadd.s &0x40000000,%fp1 # Z+2
7894 mov.l SGN(%a6),%d1
7895 fmov.x %fp1,V(%a6)
7896 eor.l %d1,V(%a6)
7898 fmov.l %d0,%fpcr # restore users round prec,mode
7899 fdiv.x V(%a6),%fp0
7900 bra t_inx2
7902 TANHBORS:
7903 cmp.l %d1,&0x3FFF8000
7904 blt.w TANHSM
7906 cmp.l %d1,&0x40048AA1
7907 bgt.w TANHHUGE
7909 #-- (5/2) LOG2 < |X| < 50 LOG2,
7910 #--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
7911 #--TANH(X) = SGN - SGN*2/[EXP(Y)+1].
7913 mov.l X(%a6),%d1
7914 mov.l %d1,SGN(%a6)
7915 and.l &0x7FFF0000,%d1
7916 add.l &0x00010000,%d1 # EXPO OF 2|X|
7917 mov.l %d1,X(%a6) # Y = 2|X|
7918 and.l &0x80000000,SGN(%a6)
7919 mov.l SGN(%a6),%d1
7920 fmov.x X(%a6),%fp0 # Y = 2|X|
7922 mov.l %d0,-(%sp)
7923 clr.l %d0
7924 fmovm.x &0x01,-(%sp) # save Y on stack
7925 lea (%sp),%a0 # pass ptr to Y
7926 bsr setox # FP0 IS EXP(Y)
7927 add.l &0xc,%sp # clear Y from stack
7928 mov.l (%sp)+,%d0
7929 mov.l SGN(%a6),%d1
7930 fadd.s &0x3F800000,%fp0 # EXP(Y)+1
7932 eor.l &0xC0000000,%d1 # -SIGN(X)*2
7933 fmov.s %d1,%fp1 # -SIGN(X)*2 IN SGL FMT
7934 fdiv.x %fp0,%fp1 # -SIGN(X)2 / [EXP(Y)+1 ]
7936 mov.l SGN(%a6),%d1
7937 or.l &0x3F800000,%d1 # SGN
7938 fmov.s %d1,%fp0 # SGN IN SGL FMT
7940 fmov.l %d0,%fpcr # restore users round prec,mode
7941 mov.b &FADD_OP,%d1 # last inst is ADD
7942 fadd.x %fp1,%fp0
7943 bra t_inx2
7945 TANHSM:
7946 fmov.l %d0,%fpcr # restore users round prec,mode
7947 mov.b &FMOV_OP,%d1 # last inst is MOVE
7948 fmov.x X(%a6),%fp0 # last inst - possible exception set
7949 bra t_catch
7951 #---RETURN SGN(X) - SGN(X)EPS
7952 TANHHUGE:
7953 mov.l X(%a6),%d1
7954 and.l &0x80000000,%d1
7955 or.l &0x3F800000,%d1
7956 fmov.s %d1,%fp0
7957 and.l &0x80000000,%d1
7958 eor.l &0x80800000,%d1 # -SIGN(X)*EPS
7960 fmov.l %d0,%fpcr # restore users round prec,mode
7961 fadd.s %d1,%fp0
7962 bra t_inx2
7964 global stanhd
7965 #--TANH(X) = X FOR DENORMALIZED X
7966 stanhd:
7967 bra t_extdnrm
7969 #########################################################################
7970 # slogn(): computes the natural logarithm of a normalized input #
7971 # slognd(): computes the natural logarithm of a denormalized input #
7972 # slognp1(): computes the log(1+X) of a normalized input #
7973 # slognp1d(): computes the log(1+X) of a denormalized input #
7975 # INPUT *************************************************************** #
7976 # a0 = pointer to extended precision input #
7977 # d0 = round precision,mode #
7979 # OUTPUT ************************************************************** #
7980 # fp0 = log(X) or log(1+X) #
7982 # ACCURACY and MONOTONICITY ******************************************* #
7983 # The returned result is within 2 ulps in 64 significant bit, #
7984 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7985 # rounded to double precision. The result is provably monotonic #
7986 # in double precision. #
7988 # ALGORITHM *********************************************************** #
7989 # LOGN: #
7990 # Step 1. If |X-1| < 1/16, approximate log(X) by an odd #
7991 # polynomial in u, where u = 2(X-1)/(X+1). Otherwise, #
7992 # move on to Step 2. #
7994 # Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
7995 # seven significant bits of Y plus 2**(-7), i.e. #
7996 # F = 1.xxxxxx1 in base 2 where the six "x" match those #
7997 # of Y. Note that |Y-F| <= 2**(-7). #
7999 # Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a #
8000 # polynomial in u, log(1+u) = poly. #
8002 # Step 4. Reconstruct #
8003 # log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
8004 # by k*log(2) + (log(F) + poly). The values of log(F) are #
8005 # calculated beforehand and stored in the program. #
8007 # lognp1: #
8008 # Step 1: If |X| < 1/16, approximate log(1+X) by an odd #
8009 # polynomial in u where u = 2X/(2+X). Otherwise, move on #
8010 # to Step 2. #
8012 # Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done #
8013 # in Step 2 of the algorithm for LOGN and compute #
8014 # log(1+X) as k*log(2) + log(F) + poly where poly #
8015 # approximates log(1+u), u = (Y-F)/F. #
8017 # Implementation Notes: #
8018 # Note 1. There are 64 different possible values for F, thus 64 #
8019 # log(F)'s need to be tabulated. Moreover, the values of #
8020 # 1/F are also tabulated so that the division in (Y-F)/F #
8021 # can be performed by a multiplication. #
8023 # Note 2. In Step 2 of lognp1, in order to preserved accuracy, #
8024 # the value Y-F has to be calculated carefully when #
8025 # 1/2 <= X < 3/2. #
8027 # Note 3. To fully exploit the pipeline, polynomials are usually #
8028 # separated into two parts evaluated independently before #
8029 # being added up. #
8031 #########################################################################
8032 LOGOF2:
8033 long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8035 one:
8036 long 0x3F800000
8037 zero:
8038 long 0x00000000
8039 infty:
8040 long 0x7F800000
8041 negone:
8042 long 0xBF800000
8044 LOGA6:
8045 long 0x3FC2499A,0xB5E4040B
8046 LOGA5:
8047 long 0xBFC555B5,0x848CB7DB
8049 LOGA4:
8050 long 0x3FC99999,0x987D8730
8051 LOGA3:
8052 long 0xBFCFFFFF,0xFF6F7E97
8054 LOGA2:
8055 long 0x3FD55555,0x555555A4
8056 LOGA1:
8057 long 0xBFE00000,0x00000008
8059 LOGB5:
8060 long 0x3F175496,0xADD7DAD6
8061 LOGB4:
8062 long 0x3F3C71C2,0xFE80C7E0
8064 LOGB3:
8065 long 0x3F624924,0x928BCCFF
8066 LOGB2:
8067 long 0x3F899999,0x999995EC
8069 LOGB1:
8070 long 0x3FB55555,0x55555555
8071 TWO:
8072 long 0x40000000,0x00000000
8074 LTHOLD:
8075 long 0x3f990000,0x80000000,0x00000000,0x00000000
8077 LOGTBL:
8078 long 0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
8079 long 0x3FF70000,0xFF015358,0x833C47E2,0x00000000
8080 long 0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
8081 long 0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
8082 long 0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
8083 long 0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
8084 long 0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
8085 long 0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
8086 long 0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
8087 long 0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
8088 long 0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
8089 long 0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
8090 long 0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
8091 long 0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
8092 long 0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
8093 long 0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
8094 long 0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
8095 long 0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
8096 long 0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
8097 long 0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
8098 long 0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
8099 long 0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
8100 long 0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
8101 long 0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
8102 long 0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
8103 long 0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
8104 long 0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
8105 long 0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
8106 long 0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
8107 long 0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
8108 long 0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
8109 long 0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
8110 long 0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
8111 long 0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
8112 long 0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
8113 long 0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
8114 long 0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
8115 long 0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
8116 long 0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
8117 long 0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
8118 long 0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
8119 long 0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
8120 long 0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
8121 long 0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
8122 long 0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
8123 long 0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
8124 long 0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
8125 long 0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
8126 long 0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
8127 long 0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
8128 long 0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
8129 long 0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
8130 long 0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
8131 long 0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
8132 long 0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
8133 long 0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
8134 long 0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
8135 long 0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
8136 long 0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
8137 long 0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
8138 long 0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
8139 long 0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
8140 long 0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
8141 long 0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
8142 long 0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
8143 long 0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
8144 long 0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
8145 long 0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
8146 long 0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
8147 long 0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
8148 long 0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
8149 long 0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
8150 long 0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
8151 long 0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
8152 long 0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
8153 long 0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
8154 long 0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
8155 long 0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
8156 long 0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
8157 long 0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
8158 long 0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
8159 long 0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
8160 long 0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
8161 long 0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
8162 long 0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
8163 long 0x3FFE0000,0x825EFCED,0x49369330,0x00000000
8164 long 0x3FFE0000,0x9868C809,0x868C8098,0x00000000
8165 long 0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
8166 long 0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
8167 long 0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
8168 long 0x3FFE0000,0x95A02568,0x095A0257,0x00000000
8169 long 0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
8170 long 0x3FFE0000,0x94458094,0x45809446,0x00000000
8171 long 0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
8172 long 0x3FFE0000,0x92F11384,0x0497889C,0x00000000
8173 long 0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
8174 long 0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
8175 long 0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
8176 long 0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
8177 long 0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
8178 long 0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
8179 long 0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
8180 long 0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
8181 long 0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
8182 long 0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
8183 long 0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
8184 long 0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
8185 long 0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
8186 long 0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
8187 long 0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
8188 long 0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
8189 long 0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
8190 long 0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
8191 long 0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
8192 long 0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
8193 long 0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
8194 long 0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
8195 long 0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
8196 long 0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
8197 long 0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
8198 long 0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
8199 long 0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
8200 long 0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
8201 long 0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
8202 long 0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
8203 long 0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
8204 long 0x3FFE0000,0x80808080,0x80808081,0x00000000
8205 long 0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
8207 set ADJK,L_SCR1
8209 set X,FP_SCR0
8210 set XDCARE,X+2
8211 set XFRAC,X+4
8213 set F,FP_SCR1
8214 set FFRAC,F+4
8216 set KLOG2,FP_SCR0
8218 set SAVEU,FP_SCR0
8220 global slogn
8221 #--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
8222 slogn:
8223 fmov.x (%a0),%fp0 # LOAD INPUT
8224 mov.l &0x00000000,ADJK(%a6)
8226 LOGBGN:
8227 #--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
8228 #--A FINITE, NON-ZERO, NORMALIZED NUMBER.
8230 mov.l (%a0),%d1
8231 mov.w 4(%a0),%d1
8233 mov.l (%a0),X(%a6)
8234 mov.l 4(%a0),X+4(%a6)
8235 mov.l 8(%a0),X+8(%a6)
8237 cmp.l %d1,&0 # CHECK IF X IS NEGATIVE
8238 blt.w LOGNEG # LOG OF NEGATIVE ARGUMENT IS INVALID
8239 # X IS POSITIVE, CHECK IF X IS NEAR 1
8240 cmp.l %d1,&0x3ffef07d # IS X < 15/16?
8241 blt.b LOGMAIN # YES
8242 cmp.l %d1,&0x3fff8841 # IS X > 17/16?
8243 ble.w LOGNEAR1 # NO
8245 LOGMAIN:
8246 #--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
8248 #--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
8249 #--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
8250 #--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
8251 #-- = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
8252 #--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
8253 #--LOG(1+U) CAN BE VERY EFFICIENT.
8254 #--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
8255 #--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
8257 #--GET K, Y, F, AND ADDRESS OF 1/F.
8258 asr.l &8,%d1
8259 asr.l &8,%d1 # SHIFTED 16 BITS, BIASED EXPO. OF X
8260 sub.l &0x3FFF,%d1 # THIS IS K
8261 add.l ADJK(%a6),%d1 # ADJUST K, ORIGINAL INPUT MAY BE DENORM.
8262 lea LOGTBL(%pc),%a0 # BASE ADDRESS OF 1/F AND LOG(F)
8263 fmov.l %d1,%fp1 # CONVERT K TO FLOATING-POINT FORMAT
8265 #--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
8266 mov.l &0x3FFF0000,X(%a6) # X IS NOW Y, I.E. 2^(-K)*X
8267 mov.l XFRAC(%a6),FFRAC(%a6)
8268 and.l &0xFE000000,FFRAC(%a6) # FIRST 7 BITS OF Y
8269 or.l &0x01000000,FFRAC(%a6) # GET F: ATTACH A 1 AT THE EIGHTH BIT
8270 mov.l FFRAC(%a6),%d1 # READY TO GET ADDRESS OF 1/F
8271 and.l &0x7E000000,%d1
8272 asr.l &8,%d1
8273 asr.l &8,%d1
8274 asr.l &4,%d1 # SHIFTED 20, D0 IS THE DISPLACEMENT
8275 add.l %d1,%a0 # A0 IS THE ADDRESS FOR 1/F
8277 fmov.x X(%a6),%fp0
8278 mov.l &0x3fff0000,F(%a6)
8279 clr.l F+8(%a6)
8280 fsub.x F(%a6),%fp0 # Y-F
8281 fmovm.x &0xc,-(%sp) # SAVE FP2-3 WHILE FP0 IS NOT READY
8282 #--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
8283 #--REGISTERS SAVED: FPCR, FP1, FP2
8285 LP1CONT1:
8286 #--AN RE-ENTRY POINT FOR LOGNP1
8287 fmul.x (%a0),%fp0 # FP0 IS U = (Y-F)/F
8288 fmul.x LOGOF2(%pc),%fp1 # GET K*LOG2 WHILE FP0 IS NOT READY
8289 fmov.x %fp0,%fp2
8290 fmul.x %fp2,%fp2 # FP2 IS V=U*U
8291 fmov.x %fp1,KLOG2(%a6) # PUT K*LOG2 IN MEMEORY, FREE FP1
8293 #--LOG(1+U) IS APPROXIMATED BY
8294 #--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
8295 #--[U + V*(A1+V*(A3+V*A5))] + [U*V*(A2+V*(A4+V*A6))]
8297 fmov.x %fp2,%fp3
8298 fmov.x %fp2,%fp1
8300 fmul.d LOGA6(%pc),%fp1 # V*A6
8301 fmul.d LOGA5(%pc),%fp2 # V*A5
8303 fadd.d LOGA4(%pc),%fp1 # A4+V*A6
8304 fadd.d LOGA3(%pc),%fp2 # A3+V*A5
8306 fmul.x %fp3,%fp1 # V*(A4+V*A6)
8307 fmul.x %fp3,%fp2 # V*(A3+V*A5)
8309 fadd.d LOGA2(%pc),%fp1 # A2+V*(A4+V*A6)
8310 fadd.d LOGA1(%pc),%fp2 # A1+V*(A3+V*A5)
8312 fmul.x %fp3,%fp1 # V*(A2+V*(A4+V*A6))
8313 add.l &16,%a0 # ADDRESS OF LOG(F)
8314 fmul.x %fp3,%fp2 # V*(A1+V*(A3+V*A5))
8316 fmul.x %fp0,%fp1 # U*V*(A2+V*(A4+V*A6))
8317 fadd.x %fp2,%fp0 # U+V*(A1+V*(A3+V*A5))
8319 fadd.x (%a0),%fp1 # LOG(F)+U*V*(A2+V*(A4+V*A6))
8320 fmovm.x (%sp)+,&0x30 # RESTORE FP2-3
8321 fadd.x %fp1,%fp0 # FP0 IS LOG(F) + LOG(1+U)
8323 fmov.l %d0,%fpcr
8324 fadd.x KLOG2(%a6),%fp0 # FINAL ADD
8325 bra t_inx2
8328 LOGNEAR1:
8330 # if the input is exactly equal to one, then exit through ld_pzero.
8331 # if these 2 lines weren't here, the correct answer would be returned
8332 # but the INEX2 bit would be set.
8333 fcmp.b %fp0,&0x1 # is it equal to one?
8334 fbeq.l ld_pzero # yes
8336 #--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
8337 fmov.x %fp0,%fp1
8338 fsub.s one(%pc),%fp1 # FP1 IS X-1
8339 fadd.s one(%pc),%fp0 # FP0 IS X+1
8340 fadd.x %fp1,%fp1 # FP1 IS 2(X-1)
8341 #--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
8342 #--IN U, U = 2(X-1)/(X+1) = FP1/FP0
8344 LP1CONT2:
8345 #--THIS IS AN RE-ENTRY POINT FOR LOGNP1
8346 fdiv.x %fp0,%fp1 # FP1 IS U
8347 fmovm.x &0xc,-(%sp) # SAVE FP2-3
8348 #--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
8349 #--LET V=U*U, W=V*V, CALCULATE
8350 #--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
8351 #--U + U*V*( [B1 + W*(B3 + W*B5)] + [V*(B2 + W*B4)] )
8352 fmov.x %fp1,%fp0
8353 fmul.x %fp0,%fp0 # FP0 IS V
8354 fmov.x %fp1,SAVEU(%a6) # STORE U IN MEMORY, FREE FP1
8355 fmov.x %fp0,%fp1
8356 fmul.x %fp1,%fp1 # FP1 IS W
8358 fmov.d LOGB5(%pc),%fp3
8359 fmov.d LOGB4(%pc),%fp2
8361 fmul.x %fp1,%fp3 # W*B5
8362 fmul.x %fp1,%fp2 # W*B4
8364 fadd.d LOGB3(%pc),%fp3 # B3+W*B5
8365 fadd.d LOGB2(%pc),%fp2 # B2+W*B4
8367 fmul.x %fp3,%fp1 # W*(B3+W*B5), FP3 RELEASED
8369 fmul.x %fp0,%fp2 # V*(B2+W*B4)
8371 fadd.d LOGB1(%pc),%fp1 # B1+W*(B3+W*B5)
8372 fmul.x SAVEU(%a6),%fp0 # FP0 IS U*V
8374 fadd.x %fp2,%fp1 # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
8375 fmovm.x (%sp)+,&0x30 # FP2-3 RESTORED
8377 fmul.x %fp1,%fp0 # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
8379 fmov.l %d0,%fpcr
8380 fadd.x SAVEU(%a6),%fp0
8381 bra t_inx2
8383 #--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
8384 LOGNEG:
8385 bra t_operr
8387 global slognd
8388 slognd:
8389 #--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
8391 mov.l &-100,ADJK(%a6) # INPUT = 2^(ADJK) * FP0
8393 #----normalize the input value by left shifting k bits (k to be determined
8394 #----below), adjusting exponent and storing -k to ADJK
8395 #----the value TWOTO100 is no longer needed.
8396 #----Note that this code assumes the denormalized input is NON-ZERO.
8398 movm.l &0x3f00,-(%sp) # save some registers {d2-d7}
8399 mov.l (%a0),%d3 # D3 is exponent of smallest norm. #
8400 mov.l 4(%a0),%d4
8401 mov.l 8(%a0),%d5 # (D4,D5) is (Hi_X,Lo_X)
8402 clr.l %d2 # D2 used for holding K
8404 tst.l %d4
8405 bne.b Hi_not0
8407 Hi_0:
8408 mov.l %d5,%d4
8409 clr.l %d5
8410 mov.l &32,%d2
8411 clr.l %d6
8412 bfffo %d4{&0:&32},%d6
8413 lsl.l %d6,%d4
8414 add.l %d6,%d2 # (D3,D4,D5) is normalized
8416 mov.l %d3,X(%a6)
8417 mov.l %d4,XFRAC(%a6)
8418 mov.l %d5,XFRAC+4(%a6)
8419 neg.l %d2
8420 mov.l %d2,ADJK(%a6)
8421 fmov.x X(%a6),%fp0
8422 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8423 lea X(%a6),%a0
8424 bra.w LOGBGN # begin regular log(X)
8426 Hi_not0:
8427 clr.l %d6
8428 bfffo %d4{&0:&32},%d6 # find first 1
8429 mov.l %d6,%d2 # get k
8430 lsl.l %d6,%d4
8431 mov.l %d5,%d7 # a copy of D5
8432 lsl.l %d6,%d5
8433 neg.l %d6
8434 add.l &32,%d6
8435 lsr.l %d6,%d7
8436 or.l %d7,%d4 # (D3,D4,D5) normalized
8438 mov.l %d3,X(%a6)
8439 mov.l %d4,XFRAC(%a6)
8440 mov.l %d5,XFRAC+4(%a6)
8441 neg.l %d2
8442 mov.l %d2,ADJK(%a6)
8443 fmov.x X(%a6),%fp0
8444 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8445 lea X(%a6),%a0
8446 bra.w LOGBGN # begin regular log(X)
8448 global slognp1
8449 #--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
8450 slognp1:
8451 fmov.x (%a0),%fp0 # LOAD INPUT
8452 fabs.x %fp0 # test magnitude
8453 fcmp.x %fp0,LTHOLD(%pc) # compare with min threshold
8454 fbgt.w LP1REAL # if greater, continue
8455 fmov.l %d0,%fpcr
8456 mov.b &FMOV_OP,%d1 # last inst is MOVE
8457 fmov.x (%a0),%fp0 # return signed argument
8458 bra t_catch
8460 LP1REAL:
8461 fmov.x (%a0),%fp0 # LOAD INPUT
8462 mov.l &0x00000000,ADJK(%a6)
8463 fmov.x %fp0,%fp1 # FP1 IS INPUT Z
8464 fadd.s one(%pc),%fp0 # X := ROUND(1+Z)
8465 fmov.x %fp0,X(%a6)
8466 mov.w XFRAC(%a6),XDCARE(%a6)
8467 mov.l X(%a6),%d1
8468 cmp.l %d1,&0
8469 ble.w LP1NEG0 # LOG OF ZERO OR -VE
8470 cmp.l %d1,&0x3ffe8000 # IS BOUNDS [1/2,3/2]?
8471 blt.w LOGMAIN
8472 cmp.l %d1,&0x3fffc000
8473 bgt.w LOGMAIN
8474 #--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
8475 #--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
8476 #--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
8478 LP1NEAR1:
8479 #--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
8480 cmp.l %d1,&0x3ffef07d
8481 blt.w LP1CARE
8482 cmp.l %d1,&0x3fff8841
8483 bgt.w LP1CARE
8485 LP1ONE16:
8486 #--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
8487 #--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
8488 fadd.x %fp1,%fp1 # FP1 IS 2Z
8489 fadd.s one(%pc),%fp0 # FP0 IS 1+X
8490 #--U = FP1/FP0
8491 bra.w LP1CONT2
8493 LP1CARE:
8494 #--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
8495 #--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
8496 #--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
8497 #--THERE ARE ONLY TWO CASES.
8498 #--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
8499 #--CASE 2: 1+Z > 1, THEN K = 0 AND Y-F = (1-F) + Z
8500 #--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
8501 #--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
8503 mov.l XFRAC(%a6),FFRAC(%a6)
8504 and.l &0xFE000000,FFRAC(%a6)
8505 or.l &0x01000000,FFRAC(%a6) # F OBTAINED
8506 cmp.l %d1,&0x3FFF8000 # SEE IF 1+Z > 1
8507 bge.b KISZERO
8509 KISNEG1:
8510 fmov.s TWO(%pc),%fp0
8511 mov.l &0x3fff0000,F(%a6)
8512 clr.l F+8(%a6)
8513 fsub.x F(%a6),%fp0 # 2-F
8514 mov.l FFRAC(%a6),%d1
8515 and.l &0x7E000000,%d1
8516 asr.l &8,%d1
8517 asr.l &8,%d1
8518 asr.l &4,%d1 # D0 CONTAINS DISPLACEMENT FOR 1/F
8519 fadd.x %fp1,%fp1 # GET 2Z
8520 fmovm.x &0xc,-(%sp) # SAVE FP2 {%fp2/%fp3}
8521 fadd.x %fp1,%fp0 # FP0 IS Y-F = (2-F)+2Z
8522 lea LOGTBL(%pc),%a0 # A0 IS ADDRESS OF 1/F
8523 add.l %d1,%a0
8524 fmov.s negone(%pc),%fp1 # FP1 IS K = -1
8525 bra.w LP1CONT1
8527 KISZERO:
8528 fmov.s one(%pc),%fp0
8529 mov.l &0x3fff0000,F(%a6)
8530 clr.l F+8(%a6)
8531 fsub.x F(%a6),%fp0 # 1-F
8532 mov.l FFRAC(%a6),%d1
8533 and.l &0x7E000000,%d1
8534 asr.l &8,%d1
8535 asr.l &8,%d1
8536 asr.l &4,%d1
8537 fadd.x %fp1,%fp0 # FP0 IS Y-F
8538 fmovm.x &0xc,-(%sp) # FP2 SAVED {%fp2/%fp3}
8539 lea LOGTBL(%pc),%a0
8540 add.l %d1,%a0 # A0 IS ADDRESS OF 1/F
8541 fmov.s zero(%pc),%fp1 # FP1 IS K = 0
8542 bra.w LP1CONT1
8544 LP1NEG0:
8545 #--FPCR SAVED. D0 IS X IN COMPACT FORM.
8546 cmp.l %d1,&0
8547 blt.b LP1NEG
8548 LP1ZERO:
8549 fmov.s negone(%pc),%fp0
8551 fmov.l %d0,%fpcr
8552 bra t_dz
8554 LP1NEG:
8555 fmov.s zero(%pc),%fp0
8557 fmov.l %d0,%fpcr
8558 bra t_operr
8560 global slognp1d
8561 #--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
8562 # Simply return the denorm
8563 slognp1d:
8564 bra t_extdnrm
8566 #########################################################################
8567 # satanh(): computes the inverse hyperbolic tangent of a norm input #
8568 # satanhd(): computes the inverse hyperbolic tangent of a denorm input #
8570 # INPUT *************************************************************** #
8571 # a0 = pointer to extended precision input #
8572 # d0 = round precision,mode #
8574 # OUTPUT ************************************************************** #
8575 # fp0 = arctanh(X) #
8577 # ACCURACY and MONOTONICITY ******************************************* #
8578 # The returned result is within 3 ulps in 64 significant bit, #
8579 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8580 # rounded to double precision. The result is provably monotonic #
8581 # in double precision. #
8583 # ALGORITHM *********************************************************** #
8585 # ATANH #
8586 # 1. If |X| >= 1, go to 3. #
8588 # 2. (|X| < 1) Calculate atanh(X) by #
8589 # sgn := sign(X) #
8590 # y := |X| #
8591 # z := 2y/(1-y) #
8592 # atanh(X) := sgn * (1/2) * logp1(z) #
8593 # Exit. #
8595 # 3. If |X| > 1, go to 5. #
8597 # 4. (|X| = 1) Generate infinity with an appropriate sign and #
8598 # divide-by-zero by #
8599 # sgn := sign(X) #
8600 # atan(X) := sgn / (+0). #
8601 # Exit. #
8603 # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
8604 # Exit. #
8606 #########################################################################
8608 global satanh
8609 satanh:
8610 mov.l (%a0),%d1
8611 mov.w 4(%a0),%d1
8612 and.l &0x7FFFFFFF,%d1
8613 cmp.l %d1,&0x3FFF8000
8614 bge.b ATANHBIG
8616 #--THIS IS THE USUAL CASE, |X| < 1
8617 #--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
8619 fabs.x (%a0),%fp0 # Y = |X|
8620 fmov.x %fp0,%fp1
8621 fneg.x %fp1 # -Y
8622 fadd.x %fp0,%fp0 # 2Y
8623 fadd.s &0x3F800000,%fp1 # 1-Y
8624 fdiv.x %fp1,%fp0 # 2Y/(1-Y)
8625 mov.l (%a0),%d1
8626 and.l &0x80000000,%d1
8627 or.l &0x3F000000,%d1 # SIGN(X)*HALF
8628 mov.l %d1,-(%sp)
8630 mov.l %d0,-(%sp) # save rnd prec,mode
8631 clr.l %d0 # pass ext prec,RN
8632 fmovm.x &0x01,-(%sp) # save Z on stack
8633 lea (%sp),%a0 # pass ptr to Z
8634 bsr slognp1 # LOG1P(Z)
8635 add.l &0xc,%sp # clear Z from stack
8637 mov.l (%sp)+,%d0 # fetch old prec,mode
8638 fmov.l %d0,%fpcr # load it
8639 mov.b &FMUL_OP,%d1 # last inst is MUL
8640 fmul.s (%sp)+,%fp0
8641 bra t_catch
8643 ATANHBIG:
8644 fabs.x (%a0),%fp0 # |X|
8645 fcmp.s %fp0,&0x3F800000
8646 fbgt t_operr
8647 bra t_dz
8649 global satanhd
8650 #--ATANH(X) = X FOR DENORMALIZED X
8651 satanhd:
8652 bra t_extdnrm
8654 #########################################################################
8655 # slog10(): computes the base-10 logarithm of a normalized input #
8656 # slog10d(): computes the base-10 logarithm of a denormalized input #
8657 # slog2(): computes the base-2 logarithm of a normalized input #
8658 # slog2d(): computes the base-2 logarithm of a denormalized input #
8660 # INPUT *************************************************************** #
8661 # a0 = pointer to extended precision input #
8662 # d0 = round precision,mode #
8664 # OUTPUT ************************************************************** #
8665 # fp0 = log_10(X) or log_2(X) #
8667 # ACCURACY and MONOTONICITY ******************************************* #
8668 # The returned result is within 1.7 ulps in 64 significant bit, #
8669 # i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
8670 # rounded to double precision. The result is provably monotonic #
8671 # in double precision. #
8673 # ALGORITHM *********************************************************** #
8675 # slog10d: #
8677 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8678 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8679 # Notes: Default means round-to-nearest mode, no floating-point #
8680 # traps, and precision control = double extended. #
8682 # Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8683 # Notes: Even if X is denormalized, log(X) is always normalized. #
8685 # Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8686 # 2.1 Restore the user FPCR #
8687 # 2.2 Return ans := Y * INV_L10. #
8689 # slog10: #
8691 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8692 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8693 # Notes: Default means round-to-nearest mode, no floating-point #
8694 # traps, and precision control = double extended. #
8696 # Step 1. Call sLogN to obtain Y = log(X), the natural log of X. #
8698 # Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8699 # 2.1 Restore the user FPCR #
8700 # 2.2 Return ans := Y * INV_L10. #
8702 # sLog2d: #
8704 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8705 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8706 # Notes: Default means round-to-nearest mode, no floating-point #
8707 # traps, and precision control = double extended. #
8709 # Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8710 # Notes: Even if X is denormalized, log(X) is always normalized. #
8712 # Step 2. Compute log_10(X) = log(X) * (1/log(2)). #
8713 # 2.1 Restore the user FPCR #
8714 # 2.2 Return ans := Y * INV_L2. #
8716 # sLog2: #
8718 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8719 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8720 # Notes: Default means round-to-nearest mode, no floating-point #
8721 # traps, and precision control = double extended. #
8723 # Step 1. If X is not an integer power of two, i.e., X != 2^k, #
8724 # go to Step 3. #
8726 # Step 2. Return k. #
8727 # 2.1 Get integer k, X = 2^k. #
8728 # 2.2 Restore the user FPCR. #
8729 # 2.3 Return ans := convert-to-double-extended(k). #
8731 # Step 3. Call sLogN to obtain Y = log(X), the natural log of X. #
8733 # Step 4. Compute log_2(X) = log(X) * (1/log(2)). #
8734 # 4.1 Restore the user FPCR #
8735 # 4.2 Return ans := Y * INV_L2. #
8737 #########################################################################
8739 INV_L10:
8740 long 0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
8742 INV_L2:
8743 long 0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
8745 global slog10
8746 #--entry point for Log10(X), X is normalized
8747 slog10:
8748 fmov.b &0x1,%fp0
8749 fcmp.x %fp0,(%a0) # if operand == 1,
8750 fbeq.l ld_pzero # return an EXACT zero
8752 mov.l (%a0),%d1
8753 blt.w invalid
8754 mov.l %d0,-(%sp)
8755 clr.l %d0
8756 bsr slogn # log(X), X normal.
8757 fmov.l (%sp)+,%fpcr
8758 fmul.x INV_L10(%pc),%fp0
8759 bra t_inx2
8761 global slog10d
8762 #--entry point for Log10(X), X is denormalized
8763 slog10d:
8764 mov.l (%a0),%d1
8765 blt.w invalid
8766 mov.l %d0,-(%sp)
8767 clr.l %d0
8768 bsr slognd # log(X), X denorm.
8769 fmov.l (%sp)+,%fpcr
8770 fmul.x INV_L10(%pc),%fp0
8771 bra t_minx2
8773 global slog2
8774 #--entry point for Log2(X), X is normalized
8775 slog2:
8776 mov.l (%a0),%d1
8777 blt.w invalid
8779 mov.l 8(%a0),%d1
8780 bne.b continue # X is not 2^k
8782 mov.l 4(%a0),%d1
8783 and.l &0x7FFFFFFF,%d1
8784 bne.b continue
8786 #--X = 2^k.
8787 mov.w (%a0),%d1
8788 and.l &0x00007FFF,%d1
8789 sub.l &0x3FFF,%d1
8790 beq.l ld_pzero
8791 fmov.l %d0,%fpcr
8792 fmov.l %d1,%fp0
8793 bra t_inx2
8795 continue:
8796 mov.l %d0,-(%sp)
8797 clr.l %d0
8798 bsr slogn # log(X), X normal.
8799 fmov.l (%sp)+,%fpcr
8800 fmul.x INV_L2(%pc),%fp0
8801 bra t_inx2
8803 invalid:
8804 bra t_operr
8806 global slog2d
8807 #--entry point for Log2(X), X is denormalized
8808 slog2d:
8809 mov.l (%a0),%d1
8810 blt.w invalid
8811 mov.l %d0,-(%sp)
8812 clr.l %d0
8813 bsr slognd # log(X), X denorm.
8814 fmov.l (%sp)+,%fpcr
8815 fmul.x INV_L2(%pc),%fp0
8816 bra t_minx2
8818 #########################################################################
8819 # stwotox(): computes 2**X for a normalized input #
8820 # stwotoxd(): computes 2**X for a denormalized input #
8821 # stentox(): computes 10**X for a normalized input #
8822 # stentoxd(): computes 10**X for a denormalized input #
8824 # INPUT *************************************************************** #
8825 # a0 = pointer to extended precision input #
8826 # d0 = round precision,mode #
8828 # OUTPUT ************************************************************** #
8829 # fp0 = 2**X or 10**X #
8831 # ACCURACY and MONOTONICITY ******************************************* #
8832 # The returned result is within 2 ulps in 64 significant bit, #
8833 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8834 # rounded to double precision. The result is provably monotonic #
8835 # in double precision. #
8837 # ALGORITHM *********************************************************** #
8839 # twotox #
8840 # 1. If |X| > 16480, go to ExpBig. #
8842 # 2. If |X| < 2**(-70), go to ExpSm. #
8844 # 3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore #
8845 # decompose N as #
8846 # N = 64(M + M') + j, j = 0,1,2,...,63. #
8848 # 4. Overwrite r := r * log2. Then #
8849 # 2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8850 # Go to expr to compute that expression. #
8852 # tentox #
8853 # 1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig. #
8855 # 2. If |X| < 2**(-70), go to ExpSm. #
8857 # 3. Set y := X*log_2(10)*64 (base 2 log of 10). Set #
8858 # N := round-to-int(y). Decompose N as #
8859 # N = 64(M + M') + j, j = 0,1,2,...,63. #
8861 # 4. Define r as #
8862 # r := ((X - N*L1)-N*L2) * L10 #
8863 # where L1, L2 are the leading and trailing parts of #
8864 # log_10(2)/64 and L10 is the natural log of 10. Then #
8865 # 10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8866 # Go to expr to compute that expression. #
8868 # expr #
8869 # 1. Fetch 2**(j/64) from table as Fact1 and Fact2. #
8871 # 2. Overwrite Fact1 and Fact2 by #
8872 # Fact1 := 2**(M) * Fact1 #
8873 # Fact2 := 2**(M) * Fact2 #
8874 # Thus Fact1 + Fact2 = 2**(M) * 2**(j/64). #
8876 # 3. Calculate P where 1 + P approximates exp(r): #
8877 # P = r + r*r*(A1+r*(A2+...+r*A5)). #
8879 # 4. Let AdjFact := 2**(M'). Return #
8880 # AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ). #
8881 # Exit. #
8883 # ExpBig #
8884 # 1. Generate overflow by Huge * Huge if X > 0; otherwise, #
8885 # generate underflow by Tiny * Tiny. #
8887 # ExpSm #
8888 # 1. Return 1 + X. #
8890 #########################################################################
8892 L2TEN64:
8893 long 0x406A934F,0x0979A371 # 64LOG10/LOG2
8894 L10TWO1:
8895 long 0x3F734413,0x509F8000 # LOG2/64LOG10
8897 L10TWO2:
8898 long 0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
8900 LOG10: long 0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
8902 LOG2: long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8904 EXPA5: long 0x3F56C16D,0x6F7BD0B2
8905 EXPA4: long 0x3F811112,0x302C712C
8906 EXPA3: long 0x3FA55555,0x55554CC1
8907 EXPA2: long 0x3FC55555,0x55554A54
8908 EXPA1: long 0x3FE00000,0x00000000,0x00000000,0x00000000
8910 TEXPTBL:
8911 long 0x3FFF0000,0x80000000,0x00000000,0x3F738000
8912 long 0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
8913 long 0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
8914 long 0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
8915 long 0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
8916 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
8917 long 0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
8918 long 0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
8919 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
8920 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
8921 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
8922 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
8923 long 0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
8924 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
8925 long 0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
8926 long 0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
8927 long 0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
8928 long 0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
8929 long 0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
8930 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
8931 long 0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
8932 long 0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
8933 long 0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
8934 long 0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
8935 long 0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
8936 long 0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
8937 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
8938 long 0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
8939 long 0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
8940 long 0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
8941 long 0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
8942 long 0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
8943 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
8944 long 0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
8945 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
8946 long 0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
8947 long 0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
8948 long 0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
8949 long 0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
8950 long 0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
8951 long 0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
8952 long 0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
8953 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
8954 long 0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
8955 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
8956 long 0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
8957 long 0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
8958 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
8959 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
8960 long 0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
8961 long 0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
8962 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
8963 long 0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
8964 long 0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
8965 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
8966 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
8967 long 0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
8968 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
8969 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
8970 long 0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
8971 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
8972 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
8973 long 0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
8974 long 0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
8976 set INT,L_SCR1
8978 set X,FP_SCR0
8979 set XDCARE,X+2
8980 set XFRAC,X+4
8982 set ADJFACT,FP_SCR0
8984 set FACT1,FP_SCR0
8985 set FACT1HI,FACT1+4
8986 set FACT1LOW,FACT1+8
8988 set FACT2,FP_SCR1
8989 set FACT2HI,FACT2+4
8990 set FACT2LOW,FACT2+8
8992 global stwotox
8993 #--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
8994 stwotox:
8995 fmovm.x (%a0),&0x80 # LOAD INPUT
8997 mov.l (%a0),%d1
8998 mov.w 4(%a0),%d1
8999 fmov.x %fp0,X(%a6)
9000 and.l &0x7FFFFFFF,%d1
9002 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
9003 bge.b TWOOK1
9004 bra.w EXPBORS
9006 TWOOK1:
9007 cmp.l %d1,&0x400D80C0 # |X| > 16480?
9008 ble.b TWOMAIN
9009 bra.w EXPBORS
9011 TWOMAIN:
9012 #--USUAL CASE, 2^(-70) <= |X| <= 16480
9014 fmov.x %fp0,%fp1
9015 fmul.s &0x42800000,%fp1 # 64 * X
9016 fmov.l %fp1,INT(%a6) # N = ROUND-TO-INT(64 X)
9017 mov.l %d2,-(%sp)
9018 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9019 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9020 mov.l INT(%a6),%d1
9021 mov.l %d1,%d2
9022 and.l &0x3F,%d1 # D0 IS J
9023 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9024 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9025 asr.l &6,%d2 # d2 IS L, N = 64L + J
9026 mov.l %d2,%d1
9027 asr.l &1,%d1 # D0 IS M
9028 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9029 add.l &0x3FFF,%d2
9031 #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9032 #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9033 #--ADJFACT = 2^(M').
9034 #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9036 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9038 fmul.s &0x3C800000,%fp1 # (1/64)*N
9039 mov.l (%a1)+,FACT1(%a6)
9040 mov.l (%a1)+,FACT1HI(%a6)
9041 mov.l (%a1)+,FACT1LOW(%a6)
9042 mov.w (%a1)+,FACT2(%a6)
9044 fsub.x %fp1,%fp0 # X - (1/64)*INT(64 X)
9046 mov.w (%a1)+,FACT2HI(%a6)
9047 clr.w FACT2HI+2(%a6)
9048 clr.l FACT2LOW(%a6)
9049 add.w %d1,FACT1(%a6)
9050 fmul.x LOG2(%pc),%fp0 # FP0 IS R
9051 add.w %d1,FACT2(%a6)
9053 bra.w expr
9055 EXPBORS:
9056 #--FPCR, D0 SAVED
9057 cmp.l %d1,&0x3FFF8000
9058 bgt.b TEXPBIG
9060 #--|X| IS SMALL, RETURN 1 + X
9062 fmov.l %d0,%fpcr # restore users round prec,mode
9063 fadd.s &0x3F800000,%fp0 # RETURN 1 + X
9064 bra t_pinx2
9066 TEXPBIG:
9067 #--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
9068 #--REGISTERS SAVE SO FAR ARE FPCR AND D0
9069 mov.l X(%a6),%d1
9070 cmp.l %d1,&0
9071 blt.b EXPNEG
9073 bra t_ovfl2 # t_ovfl expects positive value
9075 EXPNEG:
9076 bra t_unfl2 # t_unfl expects positive value
9078 global stwotoxd
9079 stwotoxd:
9080 #--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
9082 fmov.l %d0,%fpcr # set user's rounding mode/precision
9083 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9084 mov.l (%a0),%d1
9085 or.l &0x00800001,%d1
9086 fadd.s %d1,%fp0
9087 bra t_pinx2
9089 global stentox
9090 #--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9091 stentox:
9092 fmovm.x (%a0),&0x80 # LOAD INPUT
9094 mov.l (%a0),%d1
9095 mov.w 4(%a0),%d1
9096 fmov.x %fp0,X(%a6)
9097 and.l &0x7FFFFFFF,%d1
9099 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
9100 bge.b TENOK1
9101 bra.w EXPBORS
9103 TENOK1:
9104 cmp.l %d1,&0x400B9B07 # |X| <= 16480*log2/log10 ?
9105 ble.b TENMAIN
9106 bra.w EXPBORS
9108 TENMAIN:
9109 #--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
9111 fmov.x %fp0,%fp1
9112 fmul.d L2TEN64(%pc),%fp1 # X*64*LOG10/LOG2
9113 fmov.l %fp1,INT(%a6) # N=INT(X*64*LOG10/LOG2)
9114 mov.l %d2,-(%sp)
9115 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9116 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9117 mov.l INT(%a6),%d1
9118 mov.l %d1,%d2
9119 and.l &0x3F,%d1 # D0 IS J
9120 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9121 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9122 asr.l &6,%d2 # d2 IS L, N = 64L + J
9123 mov.l %d2,%d1
9124 asr.l &1,%d1 # D0 IS M
9125 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9126 add.l &0x3FFF,%d2
9128 #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9129 #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9130 #--ADJFACT = 2^(M').
9131 #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9132 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9134 fmov.x %fp1,%fp2
9136 fmul.d L10TWO1(%pc),%fp1 # N*(LOG2/64LOG10)_LEAD
9137 mov.l (%a1)+,FACT1(%a6)
9139 fmul.x L10TWO2(%pc),%fp2 # N*(LOG2/64LOG10)_TRAIL
9141 mov.l (%a1)+,FACT1HI(%a6)
9142 mov.l (%a1)+,FACT1LOW(%a6)
9143 fsub.x %fp1,%fp0 # X - N L_LEAD
9144 mov.w (%a1)+,FACT2(%a6)
9146 fsub.x %fp2,%fp0 # X - N L_TRAIL
9148 mov.w (%a1)+,FACT2HI(%a6)
9149 clr.w FACT2HI+2(%a6)
9150 clr.l FACT2LOW(%a6)
9152 fmul.x LOG10(%pc),%fp0 # FP0 IS R
9153 add.w %d1,FACT1(%a6)
9154 add.w %d1,FACT2(%a6)
9156 expr:
9157 #--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
9158 #--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
9159 #--FP0 IS R. THE FOLLOWING CODE COMPUTES
9160 #-- 2**(M'+M) * 2**(J/64) * EXP(R)
9162 fmov.x %fp0,%fp1
9163 fmul.x %fp1,%fp1 # FP1 IS S = R*R
9165 fmov.d EXPA5(%pc),%fp2 # FP2 IS A5
9166 fmov.d EXPA4(%pc),%fp3 # FP3 IS A4
9168 fmul.x %fp1,%fp2 # FP2 IS S*A5
9169 fmul.x %fp1,%fp3 # FP3 IS S*A4
9171 fadd.d EXPA3(%pc),%fp2 # FP2 IS A3+S*A5
9172 fadd.d EXPA2(%pc),%fp3 # FP3 IS A2+S*A4
9174 fmul.x %fp1,%fp2 # FP2 IS S*(A3+S*A5)
9175 fmul.x %fp1,%fp3 # FP3 IS S*(A2+S*A4)
9177 fadd.d EXPA1(%pc),%fp2 # FP2 IS A1+S*(A3+S*A5)
9178 fmul.x %fp0,%fp3 # FP3 IS R*S*(A2+S*A4)
9180 fmul.x %fp1,%fp2 # FP2 IS S*(A1+S*(A3+S*A5))
9181 fadd.x %fp3,%fp0 # FP0 IS R+R*S*(A2+S*A4)
9182 fadd.x %fp2,%fp0 # FP0 IS EXP(R) - 1
9184 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
9186 #--FINAL RECONSTRUCTION PROCESS
9187 #--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1) - (1 OR 0)
9189 fmul.x FACT1(%a6),%fp0
9190 fadd.x FACT2(%a6),%fp0
9191 fadd.x FACT1(%a6),%fp0
9193 fmov.l %d0,%fpcr # restore users round prec,mode
9194 mov.w %d2,ADJFACT(%a6) # INSERT EXPONENT
9195 mov.l (%sp)+,%d2
9196 mov.l &0x80000000,ADJFACT+4(%a6)
9197 clr.l ADJFACT+8(%a6)
9198 mov.b &FMUL_OP,%d1 # last inst is MUL
9199 fmul.x ADJFACT(%a6),%fp0 # FINAL ADJUSTMENT
9200 bra t_catch
9202 global stentoxd
9203 stentoxd:
9204 #--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
9206 fmov.l %d0,%fpcr # set user's rounding mode/precision
9207 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9208 mov.l (%a0),%d1
9209 or.l &0x00800001,%d1
9210 fadd.s %d1,%fp0
9211 bra t_pinx2
9213 #########################################################################
9214 # sscale(): computes the destination operand scaled by the source #
9215 # operand. If the absoulute value of the source operand is #
9216 # >= 2^14, an overflow or underflow is returned. #
9218 # INPUT *************************************************************** #
9219 # a0 = pointer to double-extended source operand X #
9220 # a1 = pointer to double-extended destination operand Y #
9222 # OUTPUT ************************************************************** #
9223 # fp0 = scale(X,Y) #
9225 #########################################################################
9227 set SIGN, L_SCR1
9229 global sscale
9230 sscale:
9231 mov.l %d0,-(%sp) # store off ctrl bits for now
9233 mov.w DST_EX(%a1),%d1 # get dst exponent
9234 smi.b SIGN(%a6) # use SIGN to hold dst sign
9235 andi.l &0x00007fff,%d1 # strip sign from dst exp
9237 mov.w SRC_EX(%a0),%d0 # check src bounds
9238 andi.w &0x7fff,%d0 # clr src sign bit
9239 cmpi.w %d0,&0x3fff # is src ~ ZERO?
9240 blt.w src_small # yes
9241 cmpi.w %d0,&0x400c # no; is src too big?
9242 bgt.w src_out # yes
9245 # Source is within 2^14 range.
9247 src_ok:
9248 fintrz.x SRC(%a0),%fp0 # calc int of src
9249 fmov.l %fp0,%d0 # int src to d0
9250 # don't want any accrued bits from the fintrz showing up later since
9251 # we may need to read the fpsr for the last fp op in t_catch2().
9252 fmov.l &0x0,%fpsr
9254 tst.b DST_HI(%a1) # is dst denormalized?
9255 bmi.b sok_norm
9257 # the dst is a DENORM. normalize the DENORM and add the adjustment to
9258 # the src value. then, jump to the norm part of the routine.
9259 sok_dnrm:
9260 mov.l %d0,-(%sp) # save src for now
9262 mov.w DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
9263 mov.l DST_HI(%a1),FP_SCR0_HI(%a6)
9264 mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
9266 lea FP_SCR0(%a6),%a0 # pass ptr to DENORM
9267 bsr.l norm # normalize the DENORM
9268 neg.l %d0
9269 add.l (%sp)+,%d0 # add adjustment to src
9271 fmovm.x FP_SCR0(%a6),&0x80 # load normalized DENORM
9273 cmpi.w %d0,&-0x3fff # is the shft amt really low?
9274 bge.b sok_norm2 # thank goodness no
9276 # the multiply factor that we're trying to create should be a denorm
9277 # for the multiply to work. therefore, we're going to actually do a
9278 # multiply with a denorm which will cause an unimplemented data type
9279 # exception to be put into the machine which will be caught and corrected
9280 # later. we don't do this with the DENORMs above because this method
9281 # is slower. but, don't fret, I don't see it being used much either.
9282 fmov.l (%sp)+,%fpcr # restore user fpcr
9283 mov.l &0x80000000,%d1 # load normalized mantissa
9284 subi.l &-0x3fff,%d0 # how many should we shift?
9285 neg.l %d0 # make it positive
9286 cmpi.b %d0,&0x20 # is it > 32?
9287 bge.b sok_dnrm_32 # yes
9288 lsr.l %d0,%d1 # no; bit stays in upper lw
9289 clr.l -(%sp) # insert zero low mantissa
9290 mov.l %d1,-(%sp) # insert new high mantissa
9291 clr.l -(%sp) # make zero exponent
9292 bra.b sok_norm_cont
9293 sok_dnrm_32:
9294 subi.b &0x20,%d0 # get shift count
9295 lsr.l %d0,%d1 # make low mantissa longword
9296 mov.l %d1,-(%sp) # insert new low mantissa
9297 clr.l -(%sp) # insert zero high mantissa
9298 clr.l -(%sp) # make zero exponent
9299 bra.b sok_norm_cont
9301 # the src will force the dst to a DENORM value or worse. so, let's
9302 # create an fp multiply that will create the result.
9303 sok_norm:
9304 fmovm.x DST(%a1),&0x80 # load fp0 with normalized src
9305 sok_norm2:
9306 fmov.l (%sp)+,%fpcr # restore user fpcr
9308 addi.w &0x3fff,%d0 # turn src amt into exp value
9309 swap %d0 # put exponent in high word
9310 clr.l -(%sp) # insert new exponent
9311 mov.l &0x80000000,-(%sp) # insert new high mantissa
9312 mov.l %d0,-(%sp) # insert new lo mantissa
9314 sok_norm_cont:
9315 fmov.l %fpcr,%d0 # d0 needs fpcr for t_catch2
9316 mov.b &FMUL_OP,%d1 # last inst is MUL
9317 fmul.x (%sp)+,%fp0 # do the multiply
9318 bra t_catch2 # catch any exceptions
9321 # Source is outside of 2^14 range. Test the sign and branch
9322 # to the appropriate exception handler.
9324 src_out:
9325 mov.l (%sp)+,%d0 # restore ctrl bits
9326 exg %a0,%a1 # swap src,dst ptrs
9327 tst.b SRC_EX(%a1) # is src negative?
9328 bmi t_unfl # yes; underflow
9329 bra t_ovfl_sc # no; overflow
9332 # The source input is below 1, so we check for denormalized numbers
9333 # and set unfl.
9335 src_small:
9336 tst.b DST_HI(%a1) # is dst denormalized?
9337 bpl.b ssmall_done # yes
9339 mov.l (%sp)+,%d0
9340 fmov.l %d0,%fpcr # no; load control bits
9341 mov.b &FMOV_OP,%d1 # last inst is MOVE
9342 fmov.x DST(%a1),%fp0 # simply return dest
9343 bra t_catch2
9344 ssmall_done:
9345 mov.l (%sp)+,%d0 # load control bits into d1
9346 mov.l %a1,%a0 # pass ptr to dst
9347 bra t_resdnrm
9349 #########################################################################
9350 # smod(): computes the fp MOD of the input values X,Y. #
9351 # srem(): computes the fp (IEEE) REM of the input values X,Y. #
9353 # INPUT *************************************************************** #
9354 # a0 = pointer to extended precision input X #
9355 # a1 = pointer to extended precision input Y #
9356 # d0 = round precision,mode #
9358 # The input operands X and Y can be either normalized or #
9359 # denormalized. #
9361 # OUTPUT ************************************************************** #
9362 # fp0 = FREM(X,Y) or FMOD(X,Y) #
9364 # ALGORITHM *********************************************************** #
9366 # Step 1. Save and strip signs of X and Y: signX := sign(X), #
9367 # signY := sign(Y), X := |X|, Y := |Y|, #
9368 # signQ := signX EOR signY. Record whether MOD or REM #
9369 # is requested. #
9371 # Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0. #
9372 # If (L < 0) then #
9373 # R := X, go to Step 4. #
9374 # else #
9375 # R := 2^(-L)X, j := L. #
9376 # endif #
9378 # Step 3. Perform MOD(X,Y) #
9379 # 3.1 If R = Y, go to Step 9. #
9380 # 3.2 If R > Y, then { R := R - Y, Q := Q + 1} #
9381 # 3.3 If j = 0, go to Step 4. #
9382 # 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to #
9383 # Step 3.1. #
9385 # Step 4. At this point, R = X - QY = MOD(X,Y). Set #
9386 # Last_Subtract := false (used in Step 7 below). If #
9387 # MOD is requested, go to Step 6. #
9389 # Step 5. R = MOD(X,Y), but REM(X,Y) is requested. #
9390 # 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to #
9391 # Step 6. #
9392 # 5.2 If R > Y/2, then { set Last_Subtract := true, #
9393 # Q := Q + 1, Y := signY*Y }. Go to Step 6. #
9394 # 5.3 This is the tricky case of R = Y/2. If Q is odd, #
9395 # then { Q := Q + 1, signX := -signX }. #
9397 # Step 6. R := signX*R. #
9399 # Step 7. If Last_Subtract = true, R := R - Y. #
9401 # Step 8. Return signQ, last 7 bits of Q, and R as required. #
9403 # Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus, #
9404 # X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), #
9405 # R := 0. Return signQ, last 7 bits of Q, and R. #
9407 #########################################################################
9409 set Mod_Flag,L_SCR3
9410 set Sc_Flag,L_SCR3+1
9412 set SignY,L_SCR2
9413 set SignX,L_SCR2+2
9414 set SignQ,L_SCR3+2
9416 set Y,FP_SCR0
9417 set Y_Hi,Y+4
9418 set Y_Lo,Y+8
9420 set R,FP_SCR1
9421 set R_Hi,R+4
9422 set R_Lo,R+8
9424 Scale:
9425 long 0x00010000,0x80000000,0x00000000,0x00000000
9427 global smod
9428 smod:
9429 clr.b FPSR_QBYTE(%a6)
9430 mov.l %d0,-(%sp) # save ctrl bits
9431 clr.b Mod_Flag(%a6)
9432 bra.b Mod_Rem
9434 global srem
9435 srem:
9436 clr.b FPSR_QBYTE(%a6)
9437 mov.l %d0,-(%sp) # save ctrl bits
9438 mov.b &0x1,Mod_Flag(%a6)
9440 Mod_Rem:
9441 #..Save sign of X and Y
9442 movm.l &0x3f00,-(%sp) # save data registers
9443 mov.w SRC_EX(%a0),%d3
9444 mov.w %d3,SignY(%a6)
9445 and.l &0x00007FFF,%d3 # Y := |Y|
9448 mov.l SRC_HI(%a0),%d4
9449 mov.l SRC_LO(%a0),%d5 # (D3,D4,D5) is |Y|
9451 tst.l %d3
9452 bne.b Y_Normal
9454 mov.l &0x00003FFE,%d3 # $3FFD + 1
9455 tst.l %d4
9456 bne.b HiY_not0
9458 HiY_0:
9459 mov.l %d5,%d4
9460 clr.l %d5
9461 sub.l &32,%d3
9462 clr.l %d6
9463 bfffo %d4{&0:&32},%d6
9464 lsl.l %d6,%d4
9465 sub.l %d6,%d3 # (D3,D4,D5) is normalized
9466 # ...with bias $7FFD
9467 bra.b Chk_X
9469 HiY_not0:
9470 clr.l %d6
9471 bfffo %d4{&0:&32},%d6
9472 sub.l %d6,%d3
9473 lsl.l %d6,%d4
9474 mov.l %d5,%d7 # a copy of D5
9475 lsl.l %d6,%d5
9476 neg.l %d6
9477 add.l &32,%d6
9478 lsr.l %d6,%d7
9479 or.l %d7,%d4 # (D3,D4,D5) normalized
9480 # ...with bias $7FFD
9481 bra.b Chk_X
9483 Y_Normal:
9484 add.l &0x00003FFE,%d3 # (D3,D4,D5) normalized
9485 # ...with bias $7FFD
9487 Chk_X:
9488 mov.w DST_EX(%a1),%d0
9489 mov.w %d0,SignX(%a6)
9490 mov.w SignY(%a6),%d1
9491 eor.l %d0,%d1
9492 and.l &0x00008000,%d1
9493 mov.w %d1,SignQ(%a6) # sign(Q) obtained
9494 and.l &0x00007FFF,%d0
9495 mov.l DST_HI(%a1),%d1
9496 mov.l DST_LO(%a1),%d2 # (D0,D1,D2) is |X|
9497 tst.l %d0
9498 bne.b X_Normal
9499 mov.l &0x00003FFE,%d0
9500 tst.l %d1
9501 bne.b HiX_not0
9503 HiX_0:
9504 mov.l %d2,%d1
9505 clr.l %d2
9506 sub.l &32,%d0
9507 clr.l %d6
9508 bfffo %d1{&0:&32},%d6
9509 lsl.l %d6,%d1
9510 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9511 # ...with bias $7FFD
9512 bra.b Init
9514 HiX_not0:
9515 clr.l %d6
9516 bfffo %d1{&0:&32},%d6
9517 sub.l %d6,%d0
9518 lsl.l %d6,%d1
9519 mov.l %d2,%d7 # a copy of D2
9520 lsl.l %d6,%d2
9521 neg.l %d6
9522 add.l &32,%d6
9523 lsr.l %d6,%d7
9524 or.l %d7,%d1 # (D0,D1,D2) normalized
9525 # ...with bias $7FFD
9526 bra.b Init
9528 X_Normal:
9529 add.l &0x00003FFE,%d0 # (D0,D1,D2) normalized
9530 # ...with bias $7FFD
9532 Init:
9534 mov.l %d3,L_SCR1(%a6) # save biased exp(Y)
9535 mov.l %d0,-(%sp) # save biased exp(X)
9536 sub.l %d3,%d0 # L := expo(X)-expo(Y)
9538 clr.l %d6 # D6 := carry <- 0
9539 clr.l %d3 # D3 is Q
9540 mov.l &0,%a1 # A1 is k; j+k=L, Q=0
9542 #..(Carry,D1,D2) is R
9543 tst.l %d0
9544 bge.b Mod_Loop_pre
9546 #..expo(X) < expo(Y). Thus X = mod(X,Y)
9548 mov.l (%sp)+,%d0 # restore d0
9549 bra.w Get_Mod
9551 Mod_Loop_pre:
9552 addq.l &0x4,%sp # erase exp(X)
9553 #..At this point R = 2^(-L)X; Q = 0; k = 0; and k+j = L
9554 Mod_Loop:
9555 tst.l %d6 # test carry bit
9556 bgt.b R_GT_Y
9558 #..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
9559 cmp.l %d1,%d4 # compare hi(R) and hi(Y)
9560 bne.b R_NE_Y
9561 cmp.l %d2,%d5 # compare lo(R) and lo(Y)
9562 bne.b R_NE_Y
9564 #..At this point, R = Y
9565 bra.w Rem_is_0
9567 R_NE_Y:
9568 #..use the borrow of the previous compare
9569 bcs.b R_LT_Y # borrow is set iff R < Y
9571 R_GT_Y:
9572 #..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
9573 #..and Y < (D1,D2) < 2Y. Either way, perform R - Y
9574 sub.l %d5,%d2 # lo(R) - lo(Y)
9575 subx.l %d4,%d1 # hi(R) - hi(Y)
9576 clr.l %d6 # clear carry
9577 addq.l &1,%d3 # Q := Q + 1
9579 R_LT_Y:
9580 #..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
9581 tst.l %d0 # see if j = 0.
9582 beq.b PostLoop
9584 add.l %d3,%d3 # Q := 2Q
9585 add.l %d2,%d2 # lo(R) = 2lo(R)
9586 roxl.l &1,%d1 # hi(R) = 2hi(R) + carry
9587 scs %d6 # set Carry if 2(R) overflows
9588 addq.l &1,%a1 # k := k+1
9589 subq.l &1,%d0 # j := j - 1
9590 #..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
9592 bra.b Mod_Loop
9594 PostLoop:
9595 #..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
9597 #..normalize R.
9598 mov.l L_SCR1(%a6),%d0 # new biased expo of R
9599 tst.l %d1
9600 bne.b HiR_not0
9602 HiR_0:
9603 mov.l %d2,%d1
9604 clr.l %d2
9605 sub.l &32,%d0
9606 clr.l %d6
9607 bfffo %d1{&0:&32},%d6
9608 lsl.l %d6,%d1
9609 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9610 # ...with bias $7FFD
9611 bra.b Get_Mod
9613 HiR_not0:
9614 clr.l %d6
9615 bfffo %d1{&0:&32},%d6
9616 bmi.b Get_Mod # already normalized
9617 sub.l %d6,%d0
9618 lsl.l %d6,%d1
9619 mov.l %d2,%d7 # a copy of D2
9620 lsl.l %d6,%d2
9621 neg.l %d6
9622 add.l &32,%d6
9623 lsr.l %d6,%d7
9624 or.l %d7,%d1 # (D0,D1,D2) normalized
9627 Get_Mod:
9628 cmp.l %d0,&0x000041FE
9629 bge.b No_Scale
9630 Do_Scale:
9631 mov.w %d0,R(%a6)
9632 mov.l %d1,R_Hi(%a6)
9633 mov.l %d2,R_Lo(%a6)
9634 mov.l L_SCR1(%a6),%d6
9635 mov.w %d6,Y(%a6)
9636 mov.l %d4,Y_Hi(%a6)
9637 mov.l %d5,Y_Lo(%a6)
9638 fmov.x R(%a6),%fp0 # no exception
9639 mov.b &1,Sc_Flag(%a6)
9640 bra.b ModOrRem
9641 No_Scale:
9642 mov.l %d1,R_Hi(%a6)
9643 mov.l %d2,R_Lo(%a6)
9644 sub.l &0x3FFE,%d0
9645 mov.w %d0,R(%a6)
9646 mov.l L_SCR1(%a6),%d6
9647 sub.l &0x3FFE,%d6
9648 mov.l %d6,L_SCR1(%a6)
9649 fmov.x R(%a6),%fp0
9650 mov.w %d6,Y(%a6)
9651 mov.l %d4,Y_Hi(%a6)
9652 mov.l %d5,Y_Lo(%a6)
9653 clr.b Sc_Flag(%a6)
9656 ModOrRem:
9657 tst.b Mod_Flag(%a6)
9658 beq.b Fix_Sign
9660 mov.l L_SCR1(%a6),%d6 # new biased expo(Y)
9661 subq.l &1,%d6 # biased expo(Y/2)
9662 cmp.l %d0,%d6
9663 blt.b Fix_Sign
9664 bgt.b Last_Sub
9666 cmp.l %d1,%d4
9667 bne.b Not_EQ
9668 cmp.l %d2,%d5
9669 bne.b Not_EQ
9670 bra.w Tie_Case
9672 Not_EQ:
9673 bcs.b Fix_Sign
9675 Last_Sub:
9677 fsub.x Y(%a6),%fp0 # no exceptions
9678 addq.l &1,%d3 # Q := Q + 1
9681 Fix_Sign:
9682 #..Get sign of X
9683 mov.w SignX(%a6),%d6
9684 bge.b Get_Q
9685 fneg.x %fp0
9687 #..Get Q
9689 Get_Q:
9690 clr.l %d6
9691 mov.w SignQ(%a6),%d6 # D6 is sign(Q)
9692 mov.l &8,%d7
9693 lsr.l %d7,%d6
9694 and.l &0x0000007F,%d3 # 7 bits of Q
9695 or.l %d6,%d3 # sign and bits of Q
9696 # swap %d3
9697 # fmov.l %fpsr,%d6
9698 # and.l &0xFF00FFFF,%d6
9699 # or.l %d3,%d6
9700 # fmov.l %d6,%fpsr # put Q in fpsr
9701 mov.b %d3,FPSR_QBYTE(%a6) # put Q in fpsr
9704 Restore:
9705 movm.l (%sp)+,&0xfc # {%d2-%d7}
9706 mov.l (%sp)+,%d0
9707 fmov.l %d0,%fpcr
9708 tst.b Sc_Flag(%a6)
9709 beq.b Finish
9710 mov.b &FMUL_OP,%d1 # last inst is MUL
9711 fmul.x Scale(%pc),%fp0 # may cause underflow
9712 bra t_catch2
9713 # the '040 package did this apparently to see if the dst operand for the
9714 # preceding fmul was a denorm. but, it better not have been since the
9715 # algorithm just got done playing with fp0 and expected no exceptions
9716 # as a result. trust me...
9717 # bra t_avoid_unsupp # check for denorm as a
9718 # ;result of the scaling
9720 Finish:
9721 mov.b &FMOV_OP,%d1 # last inst is MOVE
9722 fmov.x %fp0,%fp0 # capture exceptions & round
9723 bra t_catch2
9725 Rem_is_0:
9726 #..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
9727 addq.l &1,%d3
9728 cmp.l %d0,&8 # D0 is j
9729 bge.b Q_Big
9731 lsl.l %d0,%d3
9732 bra.b Set_R_0
9734 Q_Big:
9735 clr.l %d3
9737 Set_R_0:
9738 fmov.s &0x00000000,%fp0
9739 clr.b Sc_Flag(%a6)
9740 bra.w Fix_Sign
9742 Tie_Case:
9743 #..Check parity of Q
9744 mov.l %d3,%d6
9745 and.l &0x00000001,%d6
9746 tst.l %d6
9747 beq.w Fix_Sign # Q is even
9749 #..Q is odd, Q := Q + 1, signX := -signX
9750 addq.l &1,%d3
9751 mov.w SignX(%a6),%d6
9752 eor.l &0x00008000,%d6
9753 mov.w %d6,SignX(%a6)
9754 bra.w Fix_Sign
9756 #########################################################################
9757 # XDEF **************************************************************** #
9758 # tag(): return the optype of the input ext fp number #
9760 # This routine is used by the 060FPLSP. #
9762 # XREF **************************************************************** #
9763 # None #
9765 # INPUT *************************************************************** #
9766 # a0 = pointer to extended precision operand #
9768 # OUTPUT ************************************************************** #
9769 # d0 = value of type tag #
9770 # one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
9772 # ALGORITHM *********************************************************** #
9773 # Simply test the exponent, j-bit, and mantissa values to #
9774 # determine the type of operand. #
9775 # If it's an unnormalized zero, alter the operand and force it #
9776 # to be a normal zero. #
9778 #########################################################################
9780 global tag
9781 tag:
9782 mov.w FTEMP_EX(%a0), %d0 # extract exponent
9783 andi.w &0x7fff, %d0 # strip off sign
9784 cmpi.w %d0, &0x7fff # is (EXP == MAX)?
9785 beq.b inf_or_nan_x
9786 not_inf_or_nan_x:
9787 btst &0x7,FTEMP_HI(%a0)
9788 beq.b not_norm_x
9789 is_norm_x:
9790 mov.b &NORM, %d0
9792 not_norm_x:
9793 tst.w %d0 # is exponent = 0?
9794 bne.b is_unnorm_x
9795 not_unnorm_x:
9796 tst.l FTEMP_HI(%a0)
9797 bne.b is_denorm_x
9798 tst.l FTEMP_LO(%a0)
9799 bne.b is_denorm_x
9800 is_zero_x:
9801 mov.b &ZERO, %d0
9803 is_denorm_x:
9804 mov.b &DENORM, %d0
9806 is_unnorm_x:
9807 bsr.l unnorm_fix # convert to norm,denorm,or zero
9809 is_unnorm_reg_x:
9810 mov.b &UNNORM, %d0
9812 inf_or_nan_x:
9813 tst.l FTEMP_LO(%a0)
9814 bne.b is_nan_x
9815 mov.l FTEMP_HI(%a0), %d0
9816 and.l &0x7fffffff, %d0 # msb is a don't care!
9817 bne.b is_nan_x
9818 is_inf_x:
9819 mov.b &INF, %d0
9821 is_nan_x:
9822 mov.b &QNAN, %d0
9825 #############################################################
9827 qnan: long 0x7fff0000, 0xffffffff, 0xffffffff
9829 #########################################################################
9830 # XDEF **************************************************************** #
9831 # t_dz(): Handle 060FPLSP dz exception for "flogn" emulation. #
9832 # t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation. #
9834 # These rouitnes are used by the 060FPLSP package. #
9836 # XREF **************************************************************** #
9837 # None #
9839 # INPUT *************************************************************** #
9840 # a0 = pointer to extended precision source operand. #
9842 # OUTPUT ************************************************************** #
9843 # fp0 = default DZ result. #
9845 # ALGORITHM *********************************************************** #
9846 # Transcendental emulation for the 060FPLSP has detected that #
9847 # a DZ exception should occur for the instruction. If DZ is disabled, #
9848 # return the default result. #
9849 # If DZ is enabled, the dst operand should be returned unscathed #
9850 # in fp0 while fp1 is used to create a DZ exception so that the #
9851 # operating system can log that such an event occurred. #
9853 #########################################################################
9855 global t_dz
9856 t_dz:
9857 tst.b SRC_EX(%a0) # check sign for neg or pos
9858 bpl.b dz_pinf # branch if pos sign
9860 global t_dz2
9861 t_dz2:
9862 ori.l &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
9864 btst &dz_bit,FPCR_ENABLE(%a6)
9865 bne.b dz_minf_ena
9867 # dz is disabled. return a -INF.
9868 fmov.s &0xff800000,%fp0 # return -INF
9871 # dz is enabled. create a dz exception so the user can record it
9872 # but use fp1 instead. return the dst operand unscathed in fp0.
9873 dz_minf_ena:
9874 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9875 fmov.l USER_FPCR(%a6),%fpcr
9876 fmov.s &0xbf800000,%fp1 # load -1
9877 fdiv.s &0x00000000,%fp1 # -1 / 0
9880 dz_pinf:
9881 ori.l &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
9883 btst &dz_bit,FPCR_ENABLE(%a6)
9884 bne.b dz_pinf_ena
9886 # dz is disabled. return a +INF.
9887 fmov.s &0x7f800000,%fp0 # return +INF
9890 # dz is enabled. create a dz exception so the user can record it
9891 # but use fp1 instead. return the dst operand unscathed in fp0.
9892 dz_pinf_ena:
9893 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9894 fmov.l USER_FPCR(%a6),%fpcr
9895 fmov.s &0x3f800000,%fp1 # load +1
9896 fdiv.s &0x00000000,%fp1 # +1 / 0
9899 #########################################################################
9900 # XDEF **************************************************************** #
9901 # t_operr(): Handle 060FPLSP OPERR exception during emulation. #
9903 # This routine is used by the 060FPLSP package. #
9905 # XREF **************************************************************** #
9906 # None. #
9908 # INPUT *************************************************************** #
9909 # fp1 = source operand #
9911 # OUTPUT ************************************************************** #
9912 # fp0 = default result #
9913 # fp1 = unchanged #
9915 # ALGORITHM *********************************************************** #
9916 # An operand error should occur as the result of transcendental #
9917 # emulation in the 060FPLSP. If OPERR is disabled, just return a NAN #
9918 # in fp0. If OPERR is enabled, return the dst operand unscathed in fp0 #
9919 # and the source operand in fp1. Use fp2 to create an OPERR exception #
9920 # so that the operating system can log the event. #
9922 #########################################################################
9924 global t_operr
9925 t_operr:
9926 ori.l &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
9928 btst &operr_bit,FPCR_ENABLE(%a6)
9929 bne.b operr_ena
9931 # operr is disabled. return a QNAN in fp0
9932 fmovm.x qnan(%pc),&0x80 # return QNAN
9935 # operr is enabled. create an operr exception so the user can record it
9936 # but use fp2 instead. return the dst operand unscathed in fp0.
9937 operr_ena:
9938 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9939 fmov.l USER_FPCR(%a6),%fpcr
9940 fmovm.x &0x04,-(%sp) # save fp2
9941 fmov.s &0x7f800000,%fp2 # load +INF
9942 fmul.s &0x00000000,%fp2 # +INF x 0
9943 fmovm.x (%sp)+,&0x20 # restore fp2
9946 pls_huge:
9947 long 0x7ffe0000,0xffffffff,0xffffffff
9948 mns_huge:
9949 long 0xfffe0000,0xffffffff,0xffffffff
9950 pls_tiny:
9951 long 0x00000000,0x80000000,0x00000000
9952 mns_tiny:
9953 long 0x80000000,0x80000000,0x00000000
9955 #########################################################################
9956 # XDEF **************************************************************** #
9957 # t_unfl(): Handle 060FPLSP underflow exception during emulation. #
9958 # t_unfl2(): Handle 060FPLSP underflow exception during #
9959 # emulation. result always positive. #
9961 # This routine is used by the 060FPLSP package. #
9963 # XREF **************************************************************** #
9964 # None. #
9966 # INPUT *************************************************************** #
9967 # a0 = pointer to extended precision source operand #
9969 # OUTPUT ************************************************************** #
9970 # fp0 = default underflow result #
9972 # ALGORITHM *********************************************************** #
9973 # An underflow should occur as the result of transcendental #
9974 # emulation in the 060FPLSP. Create an underflow by using "fmul" #
9975 # and two very small numbers of appropriate sign so that the operating #
9976 # system can log the event. #
9978 #########################################################################
9980 global t_unfl
9981 t_unfl:
9982 tst.b SRC_EX(%a0)
9983 bpl.b unf_pos
9985 global t_unfl2
9986 t_unfl2:
9987 ori.l &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
9989 fmov.l USER_FPCR(%a6),%fpcr
9990 fmovm.x mns_tiny(%pc),&0x80
9991 fmul.x pls_tiny(%pc),%fp0
9993 fmov.l %fpsr,%d0
9994 rol.l &0x8,%d0
9995 mov.b %d0,FPSR_CC(%a6)
9997 unf_pos:
9998 ori.w &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
10000 fmov.l USER_FPCR(%a6),%fpcr
10001 fmovm.x pls_tiny(%pc),&0x80
10002 fmul.x %fp0,%fp0
10004 fmov.l %fpsr,%d0
10005 rol.l &0x8,%d0
10006 mov.b %d0,FPSR_CC(%a6)
10009 #########################################################################
10010 # XDEF **************************************************************** #
10011 # t_ovfl(): Handle 060FPLSP overflow exception during emulation. #
10012 # (monadic) #
10013 # t_ovfl2(): Handle 060FPLSP overflow exception during #
10014 # emulation. result always positive. (dyadic) #
10015 # t_ovfl_sc(): Handle 060FPLSP overflow exception during #
10016 # emulation for "fscale". #
10018 # This routine is used by the 060FPLSP package. #
10020 # XREF **************************************************************** #
10021 # None. #
10023 # INPUT *************************************************************** #
10024 # a0 = pointer to extended precision source operand #
10026 # OUTPUT ************************************************************** #
10027 # fp0 = default underflow result #
10029 # ALGORITHM *********************************************************** #
10030 # An overflow should occur as the result of transcendental #
10031 # emulation in the 060FPLSP. Create an overflow by using "fmul" #
10032 # and two very lareg numbers of appropriate sign so that the operating #
10033 # system can log the event. #
10034 # For t_ovfl_sc() we take special care not to lose the INEX2 bit. #
10036 #########################################################################
10038 global t_ovfl_sc
10039 t_ovfl_sc:
10040 ori.l &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
10042 mov.b %d0,%d1 # fetch rnd prec,mode
10043 andi.b &0xc0,%d1 # extract prec
10044 beq.w ovfl_work
10046 # dst op is a DENORM. we have to normalize the mantissa to see if the
10047 # result would be inexact for the given precision. make a copy of the
10048 # dst so we don't screw up the version passed to us.
10049 mov.w LOCAL_EX(%a0),FP_SCR0_EX(%a6)
10050 mov.l LOCAL_HI(%a0),FP_SCR0_HI(%a6)
10051 mov.l LOCAL_LO(%a0),FP_SCR0_LO(%a6)
10052 lea FP_SCR0(%a6),%a0 # pass ptr to FP_SCR0
10053 movm.l &0xc080,-(%sp) # save d0-d1/a0
10054 bsr.l norm # normalize mantissa
10055 movm.l (%sp)+,&0x0103 # restore d0-d1/a0
10057 cmpi.b %d1,&0x40 # is precision sgl?
10058 bne.b ovfl_sc_dbl # no; dbl
10059 ovfl_sc_sgl:
10060 tst.l LOCAL_LO(%a0) # is lo lw of sgl set?
10061 bne.b ovfl_sc_inx # yes
10062 tst.b 3+LOCAL_HI(%a0) # is lo byte of hi lw set?
10063 bne.b ovfl_sc_inx # yes
10064 bra.w ovfl_work # don't set INEX2
10065 ovfl_sc_dbl:
10066 mov.l LOCAL_LO(%a0),%d1 # are any of lo 11 bits of
10067 andi.l &0x7ff,%d1 # dbl mantissa set?
10068 beq.w ovfl_work # no; don't set INEX2
10069 ovfl_sc_inx:
10070 ori.l &inex2_mask,USER_FPSR(%a6) # set INEX2
10071 bra.b ovfl_work # continue
10073 global t_ovfl
10074 t_ovfl:
10075 ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10076 ovfl_work:
10077 tst.b SRC_EX(%a0)
10078 bpl.b ovfl_p
10079 ovfl_m:
10080 fmov.l USER_FPCR(%a6),%fpcr
10081 fmovm.x mns_huge(%pc),&0x80
10082 fmul.x pls_huge(%pc),%fp0
10084 fmov.l %fpsr,%d0
10085 rol.l &0x8,%d0
10086 ori.b &neg_mask,%d0
10087 mov.b %d0,FPSR_CC(%a6)
10089 ovfl_p:
10090 fmov.l USER_FPCR(%a6),%fpcr
10091 fmovm.x pls_huge(%pc),&0x80
10092 fmul.x pls_huge(%pc),%fp0
10094 fmov.l %fpsr,%d0
10095 rol.l &0x8,%d0
10096 mov.b %d0,FPSR_CC(%a6)
10099 global t_ovfl2
10100 t_ovfl2:
10101 ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10102 fmov.l USER_FPCR(%a6),%fpcr
10103 fmovm.x pls_huge(%pc),&0x80
10104 fmul.x pls_huge(%pc),%fp0
10106 fmov.l %fpsr,%d0
10107 rol.l &0x8,%d0
10108 mov.b %d0,FPSR_CC(%a6)
10111 #########################################################################
10112 # XDEF **************************************************************** #
10113 # t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10114 # emulation. #
10115 # t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10116 # emulation. #
10118 # These routines are used by the 060FPLSP package. #
10120 # XREF **************************************************************** #
10121 # None. #
10123 # INPUT *************************************************************** #
10124 # fp0 = default underflow or overflow result #
10126 # OUTPUT ************************************************************** #
10127 # fp0 = default result #
10129 # ALGORITHM *********************************************************** #
10130 # If an overflow or underflow occurred during the last #
10131 # instruction of transcendental 060FPLSP emulation, then it has already #
10132 # occurred and has been logged. Now we need to see if an inexact #
10133 # exception should occur. #
10135 #########################################################################
10137 global t_catch2
10138 t_catch2:
10139 fmov.l %fpsr,%d0
10140 or.l %d0,USER_FPSR(%a6)
10141 bra.b inx2_work
10143 global t_catch
10144 t_catch:
10145 fmov.l %fpsr,%d0
10146 or.l %d0,USER_FPSR(%a6)
10148 #########################################################################
10149 # XDEF **************************************************************** #
10150 # t_inx2(): Handle inexact 060FPLSP exception during emulation. #
10151 # t_pinx2(): Handle inexact 060FPLSP exception for "+" results. #
10152 # t_minx2(): Handle inexact 060FPLSP exception for "-" results. #
10154 # XREF **************************************************************** #
10155 # None. #
10157 # INPUT *************************************************************** #
10158 # fp0 = default result #
10160 # OUTPUT ************************************************************** #
10161 # fp0 = default result #
10163 # ALGORITHM *********************************************************** #
10164 # The last instruction of transcendental emulation for the #
10165 # 060FPLSP should be inexact. So, if inexact is enabled, then we create #
10166 # the event here by adding a large and very small number together #
10167 # so that the operating system can log the event. #
10168 # Must check, too, if the result was zero, in which case we just #
10169 # set the FPSR bits and return. #
10171 #########################################################################
10173 global t_inx2
10174 t_inx2:
10175 fblt.w t_minx2
10176 fbeq.w inx2_zero
10178 global t_pinx2
10179 t_pinx2:
10180 ori.w &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
10181 bra.b inx2_work
10183 global t_minx2
10184 t_minx2:
10185 ori.l &inx2a_mask+neg_mask,USER_FPSR(%a6)
10187 inx2_work:
10188 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
10189 bne.b inx2_work_ena # yes
10190 rts
10191 inx2_work_ena:
10192 fmov.l USER_FPCR(%a6),%fpcr # insert user's exceptions
10193 fmov.s &0x3f800000,%fp1 # load +1
10194 fadd.x pls_tiny(%pc),%fp1 # cause exception
10197 inx2_zero:
10198 mov.b &z_bmask,FPSR_CC(%a6)
10199 ori.w &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
10202 #########################################################################
10203 # XDEF **************************************************************** #
10204 # t_extdnrm(): Handle DENORM inputs in 060FPLSP. #
10205 # t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale". #
10207 # This routine is used by the 060FPLSP package. #
10209 # XREF **************************************************************** #
10210 # None. #
10212 # INPUT *************************************************************** #
10213 # a0 = pointer to extended precision input operand #
10215 # OUTPUT ************************************************************** #
10216 # fp0 = default result #
10218 # ALGORITHM *********************************************************** #
10219 # For all functions that have a denormalized input and that #
10220 # f(x)=x, this is the entry point. #
10221 # DENORM value is moved using "fmove" which triggers an exception #
10222 # if enabled so the operating system can log the event. #
10224 #########################################################################
10226 global t_extdnrm
10227 t_extdnrm:
10228 fmov.l USER_FPCR(%a6),%fpcr
10229 fmov.x SRC_EX(%a0),%fp0
10230 fmov.l %fpsr,%d0
10231 ori.l &unfinx_mask,%d0
10232 or.l %d0,USER_FPSR(%a6)
10235 global t_resdnrm
10236 t_resdnrm:
10237 fmov.l USER_FPCR(%a6),%fpcr
10238 fmov.x SRC_EX(%a0),%fp0
10239 fmov.l %fpsr,%d0
10240 or.l %d0,USER_FPSR(%a6)
10243 ##########################################
10246 # sto_cos:
10247 # This is used by fsincos library emulation. The correct
10248 # values are already in fp0 and fp1 so we do nothing here.
10250 global sto_cos
10251 sto_cos:
10254 ##########################################
10257 # dst_qnan --- force result when destination is a NaN
10259 global dst_qnan
10260 dst_qnan:
10261 fmov.x DST(%a1),%fp0
10262 tst.b DST_EX(%a1)
10263 bmi.b dst_qnan_m
10264 dst_qnan_p:
10265 mov.b &nan_bmask,FPSR_CC(%a6)
10267 dst_qnan_m:
10268 mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
10272 # src_qnan --- force result when source is a NaN
10274 global src_qnan
10275 src_qnan:
10276 fmov.x SRC(%a0),%fp0
10277 tst.b SRC_EX(%a0)
10278 bmi.b src_qnan_m
10279 src_qnan_p:
10280 mov.b &nan_bmask,FPSR_CC(%a6)
10282 src_qnan_m:
10283 mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
10286 ##########################################
10289 # Native instruction support
10291 # Some systems may need entry points even for 68060 native
10292 # instructions. These routines are provided for
10293 # convenience.
10295 global _fadds_
10296 _fadds_:
10297 fmov.l %fpcr,-(%sp) # save fpcr
10298 fmov.l &0x00000000,%fpcr # clear fpcr for load
10299 fmov.s 0x8(%sp),%fp0 # load sgl dst
10300 fmov.l (%sp)+,%fpcr # restore fpcr
10301 fadd.s 0x8(%sp),%fp0 # fadd w/ sgl src
10304 global _faddd_
10305 _faddd_:
10306 fmov.l %fpcr,-(%sp) # save fpcr
10307 fmov.l &0x00000000,%fpcr # clear fpcr for load
10308 fmov.d 0x8(%sp),%fp0 # load dbl dst
10309 fmov.l (%sp)+,%fpcr # restore fpcr
10310 fadd.d 0xc(%sp),%fp0 # fadd w/ dbl src
10313 global _faddx_
10314 _faddx_:
10315 fmovm.x 0x4(%sp),&0x80 # load ext dst
10316 fadd.x 0x10(%sp),%fp0 # fadd w/ ext src
10319 global _fsubs_
10320 _fsubs_:
10321 fmov.l %fpcr,-(%sp) # save fpcr
10322 fmov.l &0x00000000,%fpcr # clear fpcr for load
10323 fmov.s 0x8(%sp),%fp0 # load sgl dst
10324 fmov.l (%sp)+,%fpcr # restore fpcr
10325 fsub.s 0x8(%sp),%fp0 # fsub w/ sgl src
10328 global _fsubd_
10329 _fsubd_:
10330 fmov.l %fpcr,-(%sp) # save fpcr
10331 fmov.l &0x00000000,%fpcr # clear fpcr for load
10332 fmov.d 0x8(%sp),%fp0 # load dbl dst
10333 fmov.l (%sp)+,%fpcr # restore fpcr
10334 fsub.d 0xc(%sp),%fp0 # fsub w/ dbl src
10337 global _fsubx_
10338 _fsubx_:
10339 fmovm.x 0x4(%sp),&0x80 # load ext dst
10340 fsub.x 0x10(%sp),%fp0 # fsub w/ ext src
10343 global _fmuls_
10344 _fmuls_:
10345 fmov.l %fpcr,-(%sp) # save fpcr
10346 fmov.l &0x00000000,%fpcr # clear fpcr for load
10347 fmov.s 0x8(%sp),%fp0 # load sgl dst
10348 fmov.l (%sp)+,%fpcr # restore fpcr
10349 fmul.s 0x8(%sp),%fp0 # fmul w/ sgl src
10352 global _fmuld_
10353 _fmuld_:
10354 fmov.l %fpcr,-(%sp) # save fpcr
10355 fmov.l &0x00000000,%fpcr # clear fpcr for load
10356 fmov.d 0x8(%sp),%fp0 # load dbl dst
10357 fmov.l (%sp)+,%fpcr # restore fpcr
10358 fmul.d 0xc(%sp),%fp0 # fmul w/ dbl src
10361 global _fmulx_
10362 _fmulx_:
10363 fmovm.x 0x4(%sp),&0x80 # load ext dst
10364 fmul.x 0x10(%sp),%fp0 # fmul w/ ext src
10367 global _fdivs_
10368 _fdivs_:
10369 fmov.l %fpcr,-(%sp) # save fpcr
10370 fmov.l &0x00000000,%fpcr # clear fpcr for load
10371 fmov.s 0x8(%sp),%fp0 # load sgl dst
10372 fmov.l (%sp)+,%fpcr # restore fpcr
10373 fdiv.s 0x8(%sp),%fp0 # fdiv w/ sgl src
10376 global _fdivd_
10377 _fdivd_:
10378 fmov.l %fpcr,-(%sp) # save fpcr
10379 fmov.l &0x00000000,%fpcr # clear fpcr for load
10380 fmov.d 0x8(%sp),%fp0 # load dbl dst
10381 fmov.l (%sp)+,%fpcr # restore fpcr
10382 fdiv.d 0xc(%sp),%fp0 # fdiv w/ dbl src
10385 global _fdivx_
10386 _fdivx_:
10387 fmovm.x 0x4(%sp),&0x80 # load ext dst
10388 fdiv.x 0x10(%sp),%fp0 # fdiv w/ ext src
10391 global _fabss_
10392 _fabss_:
10393 fabs.s 0x4(%sp),%fp0 # fabs w/ sgl src
10396 global _fabsd_
10397 _fabsd_:
10398 fabs.d 0x4(%sp),%fp0 # fabs w/ dbl src
10401 global _fabsx_
10402 _fabsx_:
10403 fabs.x 0x4(%sp),%fp0 # fabs w/ ext src
10406 global _fnegs_
10407 _fnegs_:
10408 fneg.s 0x4(%sp),%fp0 # fneg w/ sgl src
10411 global _fnegd_
10412 _fnegd_:
10413 fneg.d 0x4(%sp),%fp0 # fneg w/ dbl src
10416 global _fnegx_
10417 _fnegx_:
10418 fneg.x 0x4(%sp),%fp0 # fneg w/ ext src
10421 global _fsqrts_
10422 _fsqrts_:
10423 fsqrt.s 0x4(%sp),%fp0 # fsqrt w/ sgl src
10426 global _fsqrtd_
10427 _fsqrtd_:
10428 fsqrt.d 0x4(%sp),%fp0 # fsqrt w/ dbl src
10431 global _fsqrtx_
10432 _fsqrtx_:
10433 fsqrt.x 0x4(%sp),%fp0 # fsqrt w/ ext src
10436 global _fints_
10437 _fints_:
10438 fint.s 0x4(%sp),%fp0 # fint w/ sgl src
10441 global _fintd_
10442 _fintd_:
10443 fint.d 0x4(%sp),%fp0 # fint w/ dbl src
10446 global _fintx_
10447 _fintx_:
10448 fint.x 0x4(%sp),%fp0 # fint w/ ext src
10451 global _fintrzs_
10452 _fintrzs_:
10453 fintrz.s 0x4(%sp),%fp0 # fintrz w/ sgl src
10456 global _fintrzd_
10457 _fintrzd_:
10458 fintrz.d 0x4(%sp),%fp0 # fintrx w/ dbl src
10461 global _fintrzx_
10462 _fintrzx_:
10463 fintrz.x 0x4(%sp),%fp0 # fintrz w/ ext src
10466 ########################################################################
10468 #########################################################################
10469 # src_zero(): Return signed zero according to sign of src operand. #
10470 #########################################################################
10471 global src_zero
10472 src_zero:
10473 tst.b SRC_EX(%a0) # get sign of src operand
10474 bmi.b ld_mzero # if neg, load neg zero
10477 # ld_pzero(): return a positive zero.
10479 global ld_pzero
10480 ld_pzero:
10481 fmov.s &0x00000000,%fp0 # load +0
10482 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10485 # ld_mzero(): return a negative zero.
10486 global ld_mzero
10487 ld_mzero:
10488 fmov.s &0x80000000,%fp0 # load -0
10489 mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
10492 #########################################################################
10493 # dst_zero(): Return signed zero according to sign of dst operand. #
10494 #########################################################################
10495 global dst_zero
10496 dst_zero:
10497 tst.b DST_EX(%a1) # get sign of dst operand
10498 bmi.b ld_mzero # if neg, load neg zero
10499 bra.b ld_pzero # load positive zero
10501 #########################################################################
10502 # src_inf(): Return signed inf according to sign of src operand. #
10503 #########################################################################
10504 global src_inf
10505 src_inf:
10506 tst.b SRC_EX(%a0) # get sign of src operand
10507 bmi.b ld_minf # if negative branch
10510 # ld_pinf(): return a positive infinity.
10512 global ld_pinf
10513 ld_pinf:
10514 fmov.s &0x7f800000,%fp0 # load +INF
10515 mov.b &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
10519 # ld_minf():return a negative infinity.
10521 global ld_minf
10522 ld_minf:
10523 fmov.s &0xff800000,%fp0 # load -INF
10524 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
10527 #########################################################################
10528 # dst_inf(): Return signed inf according to sign of dst operand. #
10529 #########################################################################
10530 global dst_inf
10531 dst_inf:
10532 tst.b DST_EX(%a1) # get sign of dst operand
10533 bmi.b ld_minf # if negative branch
10534 bra.b ld_pinf
10536 global szr_inf
10537 #################################################################
10538 # szr_inf(): Return +ZERO for a negative src operand or #
10539 # +INF for a positive src operand. #
10540 # Routine used for fetox, ftwotox, and ftentox. #
10541 #################################################################
10542 szr_inf:
10543 tst.b SRC_EX(%a0) # check sign of source
10544 bmi.b ld_pzero
10545 bra.b ld_pinf
10547 #########################################################################
10548 # sopr_inf(): Return +INF for a positive src operand or #
10549 # jump to operand error routine for a negative src operand. #
10550 # Routine used for flogn, flognp1, flog10, and flog2. #
10551 #########################################################################
10552 global sopr_inf
10553 sopr_inf:
10554 tst.b SRC_EX(%a0) # check sign of source
10555 bmi.w t_operr
10556 bra.b ld_pinf
10558 #################################################################
10559 # setoxm1i(): Return minus one for a negative src operand or #
10560 # positive infinity for a positive src operand. #
10561 # Routine used for fetoxm1. #
10562 #################################################################
10563 global setoxm1i
10564 setoxm1i:
10565 tst.b SRC_EX(%a0) # check sign of source
10566 bmi.b ld_mone
10567 bra.b ld_pinf
10569 #########################################################################
10570 # src_one(): Return signed one according to sign of src operand. #
10571 #########################################################################
10572 global src_one
10573 src_one:
10574 tst.b SRC_EX(%a0) # check sign of source
10575 bmi.b ld_mone
10578 # ld_pone(): return positive one.
10580 global ld_pone
10581 ld_pone:
10582 fmov.s &0x3f800000,%fp0 # load +1
10583 clr.b FPSR_CC(%a6)
10587 # ld_mone(): return negative one.
10589 global ld_mone
10590 ld_mone:
10591 fmov.s &0xbf800000,%fp0 # load -1
10592 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
10595 ppiby2: long 0x3fff0000, 0xc90fdaa2, 0x2168c235
10596 mpiby2: long 0xbfff0000, 0xc90fdaa2, 0x2168c235
10598 #################################################################
10599 # spi_2(): Return signed PI/2 according to sign of src operand. #
10600 #################################################################
10601 global spi_2
10602 spi_2:
10603 tst.b SRC_EX(%a0) # check sign of source
10604 bmi.b ld_mpi2
10607 # ld_ppi2(): return positive PI/2.
10609 global ld_ppi2
10610 ld_ppi2:
10611 fmov.l %d0,%fpcr
10612 fmov.x ppiby2(%pc),%fp0 # load +pi/2
10613 bra.w t_pinx2 # set INEX2
10616 # ld_mpi2(): return negative PI/2.
10618 global ld_mpi2
10619 ld_mpi2:
10620 fmov.l %d0,%fpcr
10621 fmov.x mpiby2(%pc),%fp0 # load -pi/2
10622 bra.w t_minx2 # set INEX2
10624 ####################################################
10625 # The following routines give support for fsincos. #
10626 ####################################################
10629 # ssincosz(): When the src operand is ZERO, store a one in the
10630 # cosine register and return a ZERO in fp0 w/ the same sign
10631 # as the src operand.
10633 global ssincosz
10634 ssincosz:
10635 fmov.s &0x3f800000,%fp1
10636 tst.b SRC_EX(%a0) # test sign
10637 bpl.b sincoszp
10638 fmov.s &0x80000000,%fp0 # return sin result in fp0
10639 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6)
10641 sincoszp:
10642 fmov.s &0x00000000,%fp0 # return sin result in fp0
10643 mov.b &z_bmask,FPSR_CC(%a6)
10647 # ssincosi(): When the src operand is INF, store a QNAN in the cosine
10648 # register and jump to the operand error routine for negative
10649 # src operands.
10651 global ssincosi
10652 ssincosi:
10653 fmov.x qnan(%pc),%fp1 # load NAN
10654 bra.w t_operr
10657 # ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
10658 # register and branch to the src QNAN routine.
10660 global ssincosqnan
10661 ssincosqnan:
10662 fmov.x LOCAL_EX(%a0),%fp1
10663 bra.w src_qnan
10665 ########################################################################
10667 global smod_sdnrm
10668 global smod_snorm
10669 smod_sdnrm:
10670 smod_snorm:
10671 mov.b DTAG(%a6),%d1
10672 beq.l smod
10673 cmpi.b %d1,&ZERO
10674 beq.w smod_zro
10675 cmpi.b %d1,&INF
10676 beq.l t_operr
10677 cmpi.b %d1,&DENORM
10678 beq.l smod
10679 bra.l dst_qnan
10681 global smod_szero
10682 smod_szero:
10683 mov.b DTAG(%a6),%d1
10684 beq.l t_operr
10685 cmpi.b %d1,&ZERO
10686 beq.l t_operr
10687 cmpi.b %d1,&INF
10688 beq.l t_operr
10689 cmpi.b %d1,&DENORM
10690 beq.l t_operr
10691 bra.l dst_qnan
10693 global smod_sinf
10694 smod_sinf:
10695 mov.b DTAG(%a6),%d1
10696 beq.l smod_fpn
10697 cmpi.b %d1,&ZERO
10698 beq.l smod_zro
10699 cmpi.b %d1,&INF
10700 beq.l t_operr
10701 cmpi.b %d1,&DENORM
10702 beq.l smod_fpn
10703 bra.l dst_qnan
10705 smod_zro:
10706 srem_zro:
10707 mov.b SRC_EX(%a0),%d1 # get src sign
10708 mov.b DST_EX(%a1),%d0 # get dst sign
10709 eor.b %d0,%d1 # get qbyte sign
10710 andi.b &0x80,%d1
10711 mov.b %d1,FPSR_QBYTE(%a6)
10712 tst.b %d0
10713 bpl.w ld_pzero
10714 bra.w ld_mzero
10716 smod_fpn:
10717 srem_fpn:
10718 clr.b FPSR_QBYTE(%a6)
10719 mov.l %d0,-(%sp)
10720 mov.b SRC_EX(%a0),%d1 # get src sign
10721 mov.b DST_EX(%a1),%d0 # get dst sign
10722 eor.b %d0,%d1 # get qbyte sign
10723 andi.b &0x80,%d1
10724 mov.b %d1,FPSR_QBYTE(%a6)
10725 cmpi.b DTAG(%a6),&DENORM
10726 bne.b smod_nrm
10727 lea DST(%a1),%a0
10728 mov.l (%sp)+,%d0
10729 bra t_resdnrm
10730 smod_nrm:
10731 fmov.l (%sp)+,%fpcr
10732 fmov.x DST(%a1),%fp0
10733 tst.b DST_EX(%a1)
10734 bmi.b smod_nrm_neg
10737 smod_nrm_neg:
10738 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' code
10741 #########################################################################
10742 global srem_snorm
10743 global srem_sdnrm
10744 srem_sdnrm:
10745 srem_snorm:
10746 mov.b DTAG(%a6),%d1
10747 beq.l srem
10748 cmpi.b %d1,&ZERO
10749 beq.w srem_zro
10750 cmpi.b %d1,&INF
10751 beq.l t_operr
10752 cmpi.b %d1,&DENORM
10753 beq.l srem
10754 bra.l dst_qnan
10756 global srem_szero
10757 srem_szero:
10758 mov.b DTAG(%a6),%d1
10759 beq.l t_operr
10760 cmpi.b %d1,&ZERO
10761 beq.l t_operr
10762 cmpi.b %d1,&INF
10763 beq.l t_operr
10764 cmpi.b %d1,&DENORM
10765 beq.l t_operr
10766 bra.l dst_qnan
10768 global srem_sinf
10769 srem_sinf:
10770 mov.b DTAG(%a6),%d1
10771 beq.w srem_fpn
10772 cmpi.b %d1,&ZERO
10773 beq.w srem_zro
10774 cmpi.b %d1,&INF
10775 beq.l t_operr
10776 cmpi.b %d1,&DENORM
10777 beq.l srem_fpn
10778 bra.l dst_qnan
10780 #########################################################################
10782 global sscale_snorm
10783 global sscale_sdnrm
10784 sscale_snorm:
10785 sscale_sdnrm:
10786 mov.b DTAG(%a6),%d1
10787 beq.l sscale
10788 cmpi.b %d1,&ZERO
10789 beq.l dst_zero
10790 cmpi.b %d1,&INF
10791 beq.l dst_inf
10792 cmpi.b %d1,&DENORM
10793 beq.l sscale
10794 bra.l dst_qnan
10796 global sscale_szero
10797 sscale_szero:
10798 mov.b DTAG(%a6),%d1
10799 beq.l sscale
10800 cmpi.b %d1,&ZERO
10801 beq.l dst_zero
10802 cmpi.b %d1,&INF
10803 beq.l dst_inf
10804 cmpi.b %d1,&DENORM
10805 beq.l sscale
10806 bra.l dst_qnan
10808 global sscale_sinf
10809 sscale_sinf:
10810 mov.b DTAG(%a6),%d1
10811 beq.l t_operr
10812 cmpi.b %d1,&QNAN
10813 beq.l dst_qnan
10814 bra.l t_operr
10816 ########################################################################
10818 global sop_sqnan
10819 sop_sqnan:
10820 mov.b DTAG(%a6),%d1
10821 cmpi.b %d1,&QNAN
10822 beq.l dst_qnan
10823 bra.l src_qnan
10825 #########################################################################
10826 # norm(): normalize the mantissa of an extended precision input. the #
10827 # input operand should not be normalized already. #
10829 # XDEF **************************************************************** #
10830 # norm() #
10832 # XREF **************************************************************** #
10833 # none #
10835 # INPUT *************************************************************** #
10836 # a0 = pointer fp extended precision operand to normalize #
10838 # OUTPUT ************************************************************** #
10839 # d0 = number of bit positions the mantissa was shifted #
10840 # a0 = the input operand's mantissa is normalized; the exponent #
10841 # is unchanged. #
10843 #########################################################################
10844 global norm
10845 norm:
10846 mov.l %d2, -(%sp) # create some temp regs
10847 mov.l %d3, -(%sp)
10849 mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
10850 mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
10852 bfffo %d0{&0:&32}, %d2 # how many places to shift?
10853 beq.b norm_lo # hi(man) is all zeroes!
10855 norm_hi:
10856 lsl.l %d2, %d0 # left shift hi(man)
10857 bfextu %d1{&0:%d2}, %d3 # extract lo bits
10859 or.l %d3, %d0 # create hi(man)
10860 lsl.l %d2, %d1 # create lo(man)
10862 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
10863 mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
10865 mov.l %d2, %d0 # return shift amount
10867 mov.l (%sp)+, %d3 # restore temp regs
10868 mov.l (%sp)+, %d2
10872 norm_lo:
10873 bfffo %d1{&0:&32}, %d2 # how many places to shift?
10874 lsl.l %d2, %d1 # shift lo(man)
10875 add.l &32, %d2 # add 32 to shft amount
10877 mov.l %d1, FTEMP_HI(%a0) # store hi(man)
10878 clr.l FTEMP_LO(%a0) # lo(man) is now zero
10880 mov.l %d2, %d0 # return shift amount
10882 mov.l (%sp)+, %d3 # restore temp regs
10883 mov.l (%sp)+, %d2
10887 #########################################################################
10888 # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
10889 # - returns corresponding optype tag #
10891 # XDEF **************************************************************** #
10892 # unnorm_fix() #
10894 # XREF **************************************************************** #
10895 # norm() - normalize the mantissa #
10897 # INPUT *************************************************************** #
10898 # a0 = pointer to unnormalized extended precision number #
10900 # OUTPUT ************************************************************** #
10901 # d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
10902 # a0 = input operand has been converted to a norm, denorm, or #
10903 # zero; both the exponent and mantissa are changed. #
10905 #########################################################################
10907 global unnorm_fix
10908 unnorm_fix:
10909 bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
10910 bne.b unnorm_shift # hi(man) is not all zeroes
10913 # hi(man) is all zeroes so see if any bits in lo(man) are set
10915 unnorm_chk_lo:
10916 bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
10917 beq.w unnorm_zero # yes
10919 add.w &32, %d0 # no; fix shift distance
10922 # d0 = # shifts needed for complete normalization
10924 unnorm_shift:
10925 clr.l %d1 # clear top word
10926 mov.w FTEMP_EX(%a0), %d1 # extract exponent
10927 and.w &0x7fff, %d1 # strip off sgn
10929 cmp.w %d0, %d1 # will denorm push exp < 0?
10930 bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
10933 # exponent would not go < 0. therefore, number stays normalized
10935 sub.w %d0, %d1 # shift exponent value
10936 mov.w FTEMP_EX(%a0), %d0 # load old exponent
10937 and.w &0x8000, %d0 # save old sign
10938 or.w %d0, %d1 # {sgn,new exp}
10939 mov.w %d1, FTEMP_EX(%a0) # insert new exponent
10941 bsr.l norm # normalize UNNORM
10943 mov.b &NORM, %d0 # return new optype tag
10947 # exponent would go < 0, so only denormalize until exp = 0
10949 unnorm_nrm_zero:
10950 cmp.b %d1, &32 # is exp <= 32?
10951 bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
10953 bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
10954 mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
10956 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
10957 lsl.l %d1, %d0 # extract new lo(man)
10958 mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
10960 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
10962 mov.b &DENORM, %d0 # return new optype tag
10966 # only mantissa bits set are in lo(man)
10968 unnorm_nrm_zero_lrg:
10969 sub.w &32, %d1 # adjust shft amt by 32
10971 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
10972 lsl.l %d1, %d0 # left shift lo(man)
10974 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
10975 clr.l FTEMP_LO(%a0) # lo(man) = 0
10977 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
10979 mov.b &DENORM, %d0 # return new optype tag
10983 # whole mantissa is zero so this UNNORM is actually a zero
10985 unnorm_zero:
10986 and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
10988 mov.b &ZERO, %d0 # fix optype tag