Pull cpuidle into release branch
[pandora-kernel.git] / arch / m68k / ifpsp060 / src / fplsp.S
1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
3 M68000 Hi-Performance Microprocessor Division
4 M68060 Software Package
5 Production Release P1.00 -- October 10, 1994
6
7 M68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
8
9 THE SOFTWARE is provided on an "AS IS" basis and without warranty.
10 To the maximum extent permitted by applicable law,
11 MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
12 INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
13 and any warranty against infringement with regard to the SOFTWARE
14 (INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
15
16 To the maximum extent permitted by applicable law,
17 IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18 (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
19 BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
20 ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
21 Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
22
23 You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
24 so long as this entire notice is retained without alteration in any modified and/or
25 redistributed versions, and that such modified versions are clearly identified as such.
26 No licenses are granted by implication, estoppel or otherwise under any patents
27 or trademarks of Motorola, Inc.
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29 #
30 # lfptop.s:
31 #       This file is appended to the top of the 060ILSP package
32 # and contains the entry points into the package. The user, in
33 # effect, branches to one of the branch table entries located here.
34 #
35
36         bra.l   _facoss_
37         short   0x0000
38         bra.l   _facosd_
39         short   0x0000
40         bra.l   _facosx_
41         short   0x0000
42
43         bra.l   _fasins_
44         short   0x0000
45         bra.l   _fasind_
46         short   0x0000
47         bra.l   _fasinx_
48         short   0x0000
49
50         bra.l   _fatans_
51         short   0x0000
52         bra.l   _fatand_
53         short   0x0000
54         bra.l   _fatanx_
55         short   0x0000
56
57         bra.l   _fatanhs_
58         short   0x0000
59         bra.l   _fatanhd_
60         short   0x0000
61         bra.l   _fatanhx_
62         short   0x0000
63
64         bra.l   _fcoss_
65         short   0x0000
66         bra.l   _fcosd_
67         short   0x0000
68         bra.l   _fcosx_
69         short   0x0000
70
71         bra.l   _fcoshs_
72         short   0x0000
73         bra.l   _fcoshd_
74         short   0x0000
75         bra.l   _fcoshx_
76         short   0x0000
77
78         bra.l   _fetoxs_
79         short   0x0000
80         bra.l   _fetoxd_
81         short   0x0000
82         bra.l   _fetoxx_
83         short   0x0000
84
85         bra.l   _fetoxm1s_
86         short   0x0000
87         bra.l   _fetoxm1d_
88         short   0x0000
89         bra.l   _fetoxm1x_
90         short   0x0000
91
92         bra.l   _fgetexps_
93         short   0x0000
94         bra.l   _fgetexpd_
95         short   0x0000
96         bra.l   _fgetexpx_
97         short   0x0000
98
99         bra.l   _fgetmans_
100         short   0x0000
101         bra.l   _fgetmand_
102         short   0x0000
103         bra.l   _fgetmanx_
104         short   0x0000
105
106         bra.l   _flog10s_
107         short   0x0000
108         bra.l   _flog10d_
109         short   0x0000
110         bra.l   _flog10x_
111         short   0x0000
112
113         bra.l   _flog2s_
114         short   0x0000
115         bra.l   _flog2d_
116         short   0x0000
117         bra.l   _flog2x_
118         short   0x0000
119
120         bra.l   _flogns_
121         short   0x0000
122         bra.l   _flognd_
123         short   0x0000
124         bra.l   _flognx_
125         short   0x0000
126
127         bra.l   _flognp1s_
128         short   0x0000
129         bra.l   _flognp1d_
130         short   0x0000
131         bra.l   _flognp1x_
132         short   0x0000
133
134         bra.l   _fmods_
135         short   0x0000
136         bra.l   _fmodd_
137         short   0x0000
138         bra.l   _fmodx_
139         short   0x0000
140
141         bra.l   _frems_
142         short   0x0000
143         bra.l   _fremd_
144         short   0x0000
145         bra.l   _fremx_
146         short   0x0000
147
148         bra.l   _fscales_
149         short   0x0000
150         bra.l   _fscaled_
151         short   0x0000
152         bra.l   _fscalex_
153         short   0x0000
154
155         bra.l   _fsins_
156         short   0x0000
157         bra.l   _fsind_
158         short   0x0000
159         bra.l   _fsinx_
160         short   0x0000
161
162         bra.l   _fsincoss_
163         short   0x0000
164         bra.l   _fsincosd_
165         short   0x0000
166         bra.l   _fsincosx_
167         short   0x0000
168
169         bra.l   _fsinhs_
170         short   0x0000
171         bra.l   _fsinhd_
172         short   0x0000
173         bra.l   _fsinhx_
174         short   0x0000
175
176         bra.l   _ftans_
177         short   0x0000
178         bra.l   _ftand_
179         short   0x0000
180         bra.l   _ftanx_
181         short   0x0000
182
183         bra.l   _ftanhs_
184         short   0x0000
185         bra.l   _ftanhd_
186         short   0x0000
187         bra.l   _ftanhx_
188         short   0x0000
189
190         bra.l   _ftentoxs_
191         short   0x0000
192         bra.l   _ftentoxd_
193         short   0x0000
194         bra.l   _ftentoxx_
195         short   0x0000
196
197         bra.l   _ftwotoxs_
198         short   0x0000
199         bra.l   _ftwotoxd_
200         short   0x0000
201         bra.l   _ftwotoxx_
202         short   0x0000
203
204         bra.l   _fabss_
205         short   0x0000
206         bra.l   _fabsd_
207         short   0x0000
208         bra.l   _fabsx_
209         short   0x0000
210
211         bra.l   _fadds_
212         short   0x0000
213         bra.l   _faddd_
214         short   0x0000
215         bra.l   _faddx_
216         short   0x0000
217
218         bra.l   _fdivs_
219         short   0x0000
220         bra.l   _fdivd_
221         short   0x0000
222         bra.l   _fdivx_
223         short   0x0000
224
225         bra.l   _fints_
226         short   0x0000
227         bra.l   _fintd_
228         short   0x0000
229         bra.l   _fintx_
230         short   0x0000
231
232         bra.l   _fintrzs_
233         short   0x0000
234         bra.l   _fintrzd_
235         short   0x0000
236         bra.l   _fintrzx_
237         short   0x0000
238
239         bra.l   _fmuls_
240         short   0x0000
241         bra.l   _fmuld_
242         short   0x0000
243         bra.l   _fmulx_
244         short   0x0000
245
246         bra.l   _fnegs_
247         short   0x0000
248         bra.l   _fnegd_
249         short   0x0000
250         bra.l   _fnegx_
251         short   0x0000
252
253         bra.l   _fsqrts_
254         short   0x0000
255         bra.l   _fsqrtd_
256         short   0x0000
257         bra.l   _fsqrtx_
258         short   0x0000
259
260         bra.l   _fsubs_
261         short   0x0000
262         bra.l   _fsubd_
263         short   0x0000
264         bra.l   _fsubx_
265         short   0x0000
266
267 # leave room for future possible additions
268         align   0x400
269
270 #
271 # This file contains a set of define statements for constants
272 # in order to promote readability within the corecode itself.
273 #
274
275 set LOCAL_SIZE,         192                     # stack frame size(bytes)
276 set LV,                 -LOCAL_SIZE             # stack offset
277
278 set EXC_SR,             0x4                     # stack status register
279 set EXC_PC,             0x6                     # stack pc
280 set EXC_VOFF,           0xa                     # stacked vector offset
281 set EXC_EA,             0xc                     # stacked <ea>
282
283 set EXC_FP,             0x0                     # frame pointer
284
285 set EXC_AREGS,          -68                     # offset of all address regs
286 set EXC_DREGS,          -100                    # offset of all data regs
287 set EXC_FPREGS,         -36                     # offset of all fp regs
288
289 set EXC_A7,             EXC_AREGS+(7*4)         # offset of saved a7
290 set OLD_A7,             EXC_AREGS+(6*4)         # extra copy of saved a7
291 set EXC_A6,             EXC_AREGS+(6*4)         # offset of saved a6
292 set EXC_A5,             EXC_AREGS+(5*4)
293 set EXC_A4,             EXC_AREGS+(4*4)
294 set EXC_A3,             EXC_AREGS+(3*4)
295 set EXC_A2,             EXC_AREGS+(2*4)
296 set EXC_A1,             EXC_AREGS+(1*4)
297 set EXC_A0,             EXC_AREGS+(0*4)
298 set EXC_D7,             EXC_DREGS+(7*4)
299 set EXC_D6,             EXC_DREGS+(6*4)
300 set EXC_D5,             EXC_DREGS+(5*4)
301 set EXC_D4,             EXC_DREGS+(4*4)
302 set EXC_D3,             EXC_DREGS+(3*4)
303 set EXC_D2,             EXC_DREGS+(2*4)
304 set EXC_D1,             EXC_DREGS+(1*4)
305 set EXC_D0,             EXC_DREGS+(0*4)
306
307 set EXC_FP0,            EXC_FPREGS+(0*12)       # offset of saved fp0
308 set EXC_FP1,            EXC_FPREGS+(1*12)       # offset of saved fp1
309 set EXC_FP2,            EXC_FPREGS+(2*12)       # offset of saved fp2 (not used)
310
311 set FP_SCR1,            LV+80                   # fp scratch 1
312 set FP_SCR1_EX,         FP_SCR1+0
313 set FP_SCR1_SGN,        FP_SCR1+2
314 set FP_SCR1_HI,         FP_SCR1+4
315 set FP_SCR1_LO,         FP_SCR1+8
316
317 set FP_SCR0,            LV+68                   # fp scratch 0
318 set FP_SCR0_EX,         FP_SCR0+0
319 set FP_SCR0_SGN,        FP_SCR0+2
320 set FP_SCR0_HI,         FP_SCR0+4
321 set FP_SCR0_LO,         FP_SCR0+8
322
323 set FP_DST,             LV+56                   # fp destination operand
324 set FP_DST_EX,          FP_DST+0
325 set FP_DST_SGN,         FP_DST+2
326 set FP_DST_HI,          FP_DST+4
327 set FP_DST_LO,          FP_DST+8
328
329 set FP_SRC,             LV+44                   # fp source operand
330 set FP_SRC_EX,          FP_SRC+0
331 set FP_SRC_SGN,         FP_SRC+2
332 set FP_SRC_HI,          FP_SRC+4
333 set FP_SRC_LO,          FP_SRC+8
334
335 set USER_FPIAR,         LV+40                   # FP instr address register
336
337 set USER_FPSR,          LV+36                   # FP status register
338 set FPSR_CC,            USER_FPSR+0             # FPSR condition codes
339 set FPSR_QBYTE,         USER_FPSR+1             # FPSR qoutient byte
340 set FPSR_EXCEPT,        USER_FPSR+2             # FPSR exception status byte
341 set FPSR_AEXCEPT,       USER_FPSR+3             # FPSR accrued exception byte
342
343 set USER_FPCR,          LV+32                   # FP control register
344 set FPCR_ENABLE,        USER_FPCR+2             # FPCR exception enable
345 set FPCR_MODE,          USER_FPCR+3             # FPCR rounding mode control
346
347 set L_SCR3,             LV+28                   # integer scratch 3
348 set L_SCR2,             LV+24                   # integer scratch 2
349 set L_SCR1,             LV+20                   # integer scratch 1
350
351 set STORE_FLG,          LV+19                   # flag: operand store (ie. not fcmp/ftst)
352
353 set EXC_TEMP2,          LV+24                   # temporary space
354 set EXC_TEMP,           LV+16                   # temporary space
355
356 set DTAG,               LV+15                   # destination operand type
357 set STAG,               LV+14                   # source operand type
358
359 set SPCOND_FLG,         LV+10                   # flag: special case (see below)
360
361 set EXC_CC,             LV+8                    # saved condition codes
362 set EXC_EXTWPTR,        LV+4                    # saved current PC (active)
363 set EXC_EXTWORD,        LV+2                    # saved extension word
364 set EXC_CMDREG,         LV+2                    # saved extension word
365 set EXC_OPWORD,         LV+0                    # saved operation word
366
367 ################################
368
369 # Helpful macros
370
371 set FTEMP,              0                       # offsets within an
372 set FTEMP_EX,           0                       # extended precision
373 set FTEMP_SGN,          2                       # value saved in memory.
374 set FTEMP_HI,           4
375 set FTEMP_LO,           8
376 set FTEMP_GRS,          12
377
378 set LOCAL,              0                       # offsets within an
379 set LOCAL_EX,           0                       # extended precision
380 set LOCAL_SGN,          2                       # value saved in memory.
381 set LOCAL_HI,           4
382 set LOCAL_LO,           8
383 set LOCAL_GRS,          12
384
385 set DST,                0                       # offsets within an
386 set DST_EX,             0                       # extended precision
387 set DST_HI,             4                       # value saved in memory.
388 set DST_LO,             8
389
390 set SRC,                0                       # offsets within an
391 set SRC_EX,             0                       # extended precision
392 set SRC_HI,             4                       # value saved in memory.
393 set SRC_LO,             8
394
395 set SGL_LO,             0x3f81                  # min sgl prec exponent
396 set SGL_HI,             0x407e                  # max sgl prec exponent
397 set DBL_LO,             0x3c01                  # min dbl prec exponent
398 set DBL_HI,             0x43fe                  # max dbl prec exponent
399 set EXT_LO,             0x0                     # min ext prec exponent
400 set EXT_HI,             0x7ffe                  # max ext prec exponent
401
402 set EXT_BIAS,           0x3fff                  # extended precision bias
403 set SGL_BIAS,           0x007f                  # single precision bias
404 set DBL_BIAS,           0x03ff                  # double precision bias
405
406 set NORM,               0x00                    # operand type for STAG/DTAG
407 set ZERO,               0x01                    # operand type for STAG/DTAG
408 set INF,                0x02                    # operand type for STAG/DTAG
409 set QNAN,               0x03                    # operand type for STAG/DTAG
410 set DENORM,             0x04                    # operand type for STAG/DTAG
411 set SNAN,               0x05                    # operand type for STAG/DTAG
412 set UNNORM,             0x06                    # operand type for STAG/DTAG
413
414 ##################
415 # FPSR/FPCR bits #
416 ##################
417 set neg_bit,            0x3                     # negative result
418 set z_bit,              0x2                     # zero result
419 set inf_bit,            0x1                     # infinite result
420 set nan_bit,            0x0                     # NAN result
421
422 set q_sn_bit,           0x7                     # sign bit of quotient byte
423
424 set bsun_bit,           7                       # branch on unordered
425 set snan_bit,           6                       # signalling NAN
426 set operr_bit,          5                       # operand error
427 set ovfl_bit,           4                       # overflow
428 set unfl_bit,           3                       # underflow
429 set dz_bit,             2                       # divide by zero
430 set inex2_bit,          1                       # inexact result 2
431 set inex1_bit,          0                       # inexact result 1
432
433 set aiop_bit,           7                       # accrued inexact operation bit
434 set aovfl_bit,          6                       # accrued overflow bit
435 set aunfl_bit,          5                       # accrued underflow bit
436 set adz_bit,            4                       # accrued dz bit
437 set ainex_bit,          3                       # accrued inexact bit
438
439 #############################
440 # FPSR individual bit masks #
441 #############################
442 set neg_mask,           0x08000000              # negative bit mask (lw)
443 set inf_mask,           0x02000000              # infinity bit mask (lw)
444 set z_mask,             0x04000000              # zero bit mask (lw)
445 set nan_mask,           0x01000000              # nan bit mask (lw)
446
447 set neg_bmask,          0x08                    # negative bit mask (byte)
448 set inf_bmask,          0x02                    # infinity bit mask (byte)
449 set z_bmask,            0x04                    # zero bit mask (byte)
450 set nan_bmask,          0x01                    # nan bit mask (byte)
451
452 set bsun_mask,          0x00008000              # bsun exception mask
453 set snan_mask,          0x00004000              # snan exception mask
454 set operr_mask,         0x00002000              # operr exception mask
455 set ovfl_mask,          0x00001000              # overflow exception mask
456 set unfl_mask,          0x00000800              # underflow exception mask
457 set dz_mask,            0x00000400              # dz exception mask
458 set inex2_mask,         0x00000200              # inex2 exception mask
459 set inex1_mask,         0x00000100              # inex1 exception mask
460
461 set aiop_mask,          0x00000080              # accrued illegal operation
462 set aovfl_mask,         0x00000040              # accrued overflow
463 set aunfl_mask,         0x00000020              # accrued underflow
464 set adz_mask,           0x00000010              # accrued divide by zero
465 set ainex_mask,         0x00000008              # accrued inexact
466
467 ######################################
468 # FPSR combinations used in the FPSP #
469 ######################################
470 set dzinf_mask,         inf_mask+dz_mask+adz_mask
471 set opnan_mask,         nan_mask+operr_mask+aiop_mask
472 set nzi_mask,           0x01ffffff              #clears N, Z, and I
473 set unfinx_mask,        unfl_mask+inex2_mask+aunfl_mask+ainex_mask
474 set unf2inx_mask,       unfl_mask+inex2_mask+ainex_mask
475 set ovfinx_mask,        ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
476 set inx1a_mask,         inex1_mask+ainex_mask
477 set inx2a_mask,         inex2_mask+ainex_mask
478 set snaniop_mask,       nan_mask+snan_mask+aiop_mask
479 set snaniop2_mask,      snan_mask+aiop_mask
480 set naniop_mask,        nan_mask+aiop_mask
481 set neginf_mask,        neg_mask+inf_mask
482 set infaiop_mask,       inf_mask+aiop_mask
483 set negz_mask,          neg_mask+z_mask
484 set opaop_mask,         operr_mask+aiop_mask
485 set unfl_inx_mask,      unfl_mask+aunfl_mask+ainex_mask
486 set ovfl_inx_mask,      ovfl_mask+aovfl_mask+ainex_mask
487
488 #########
489 # misc. #
490 #########
491 set rnd_stky_bit,       29                      # stky bit pos in longword
492
493 set sign_bit,           0x7                     # sign bit
494 set signan_bit,         0x6                     # signalling nan bit
495
496 set sgl_thresh,         0x3f81                  # minimum sgl exponent
497 set dbl_thresh,         0x3c01                  # minimum dbl exponent
498
499 set x_mode,             0x0                     # extended precision
500 set s_mode,             0x4                     # single precision
501 set d_mode,             0x8                     # double precision
502
503 set rn_mode,            0x0                     # round-to-nearest
504 set rz_mode,            0x1                     # round-to-zero
505 set rm_mode,            0x2                     # round-tp-minus-infinity
506 set rp_mode,            0x3                     # round-to-plus-infinity
507
508 set mantissalen,        64                      # length of mantissa in bits
509
510 set BYTE,               1                       # len(byte) == 1 byte
511 set WORD,               2                       # len(word) == 2 bytes
512 set LONG,               4                       # len(longword) == 2 bytes
513
514 set BSUN_VEC,           0xc0                    # bsun    vector offset
515 set INEX_VEC,           0xc4                    # inexact vector offset
516 set DZ_VEC,             0xc8                    # dz      vector offset
517 set UNFL_VEC,           0xcc                    # unfl    vector offset
518 set OPERR_VEC,          0xd0                    # operr   vector offset
519 set OVFL_VEC,           0xd4                    # ovfl    vector offset
520 set SNAN_VEC,           0xd8                    # snan    vector offset
521
522 ###########################
523 # SPecial CONDition FLaGs #
524 ###########################
525 set ftrapcc_flg,        0x01                    # flag bit: ftrapcc exception
526 set fbsun_flg,          0x02                    # flag bit: bsun exception
527 set mia7_flg,           0x04                    # flag bit: (a7)+ <ea>
528 set mda7_flg,           0x08                    # flag bit: -(a7) <ea>
529 set fmovm_flg,          0x40                    # flag bit: fmovm instruction
530 set immed_flg,          0x80                    # flag bit: &<data> <ea>
531
532 set ftrapcc_bit,        0x0
533 set fbsun_bit,          0x1
534 set mia7_bit,           0x2
535 set mda7_bit,           0x3
536 set immed_bit,          0x7
537
538 ##################################
539 # TRANSCENDENTAL "LAST-OP" FLAGS #
540 ##################################
541 set FMUL_OP,            0x0                     # fmul instr performed last
542 set FDIV_OP,            0x1                     # fdiv performed last
543 set FADD_OP,            0x2                     # fadd performed last
544 set FMOV_OP,            0x3                     # fmov performed last
545
546 #############
547 # CONSTANTS #
548 #############
549 T1:     long            0x40C62D38,0xD3D64634   # 16381 LOG2 LEAD
550 T2:     long            0x3D6F90AE,0xB1E75CC7   # 16381 LOG2 TRAIL
551
552 PI:     long            0x40000000,0xC90FDAA2,0x2168C235,0x00000000
553 PIBY2:  long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
554
555 TWOBYPI:
556         long            0x3FE45F30,0x6DC9C883
557
558 #########################################################################
559 # MONADIC TEMPLATE                                                      #
560 #########################################################################
561         global          _fsins_
562 _fsins_:
563         link            %a6,&-LOCAL_SIZE
564
565         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
566         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
567         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
568
569         fmov.l          &0x0,%fpcr              # zero FPCR
570
571 #
572 #       copy, convert, and tag input argument
573 #
574         fmov.s          0x8(%a6),%fp0           # load sgl input
575         fmov.x          %fp0,FP_SRC(%a6)
576         lea             FP_SRC(%a6),%a0
577         bsr.l           tag                     # fetch operand type
578         mov.b           %d0,STAG(%a6)
579         mov.b           %d0,%d1
580
581         andi.l          &0x00ff00ff,USER_FPSR(%a6)
582
583         clr.l           %d0
584         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
585
586         tst.b           %d1
587         bne.b           _L0_2s
588         bsr.l           ssin                    # operand is a NORM
589         bra.b           _L0_6s
590 _L0_2s:
591         cmpi.b          %d1,&ZERO               # is operand a ZERO?
592         bne.b           _L0_3s                  # no
593         bsr.l           src_zero                        # yes
594         bra.b           _L0_6s
595 _L0_3s:
596         cmpi.b          %d1,&INF                # is operand an INF?
597         bne.b           _L0_4s                  # no
598         bsr.l           t_operr                 # yes
599         bra.b           _L0_6s
600 _L0_4s:
601         cmpi.b          %d1,&QNAN               # is operand a QNAN?
602         bne.b           _L0_5s                  # no
603         bsr.l           src_qnan                        # yes
604         bra.b           _L0_6s
605 _L0_5s:
606         bsr.l           ssind                   # operand is a DENORM
607 _L0_6s:
608
609 #
610 #       Result is now in FP0
611 #
612         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
613         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
614         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
615         unlk            %a6
616         rts
617
618         global          _fsind_
619 _fsind_:
620         link            %a6,&-LOCAL_SIZE
621
622         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
623         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
624         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
625
626         fmov.l          &0x0,%fpcr              # zero FPCR
627
628 #
629 #       copy, convert, and tag input argument
630 #
631         fmov.d          0x8(%a6),%fp0           # load dbl input
632         fmov.x          %fp0,FP_SRC(%a6)
633         lea             FP_SRC(%a6),%a0
634         bsr.l           tag                     # fetch operand type
635         mov.b           %d0,STAG(%a6)
636         mov.b           %d0,%d1
637
638         andi.l          &0x00ff00ff,USER_FPSR(%a6)
639
640         clr.l           %d0
641         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
642
643         mov.b           %d1,STAG(%a6)
644         tst.b           %d1
645         bne.b           _L0_2d
646         bsr.l           ssin                    # operand is a NORM
647         bra.b           _L0_6d
648 _L0_2d:
649         cmpi.b          %d1,&ZERO               # is operand a ZERO?
650         bne.b           _L0_3d                  # no
651         bsr.l           src_zero                        # yes
652         bra.b           _L0_6d
653 _L0_3d:
654         cmpi.b          %d1,&INF                # is operand an INF?
655         bne.b           _L0_4d                  # no
656         bsr.l           t_operr                 # yes
657         bra.b           _L0_6d
658 _L0_4d:
659         cmpi.b          %d1,&QNAN               # is operand a QNAN?
660         bne.b           _L0_5d                  # no
661         bsr.l           src_qnan                        # yes
662         bra.b           _L0_6d
663 _L0_5d:
664         bsr.l           ssind                   # operand is a DENORM
665 _L0_6d:
666
667 #
668 #       Result is now in FP0
669 #
670         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
671         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
672         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
673         unlk            %a6
674         rts
675
676         global          _fsinx_
677 _fsinx_:
678         link            %a6,&-LOCAL_SIZE
679
680         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
681         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
682         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
683
684         fmov.l          &0x0,%fpcr              # zero FPCR
685
686 #
687 #       copy, convert, and tag input argument
688 #
689         lea             FP_SRC(%a6),%a0
690         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
691         mov.l           0x8+0x4(%a6),0x4(%a0)
692         mov.l           0x8+0x8(%a6),0x8(%a0)
693         bsr.l           tag                     # fetch operand type
694         mov.b           %d0,STAG(%a6)
695         mov.b           %d0,%d1
696
697         andi.l          &0x00ff00ff,USER_FPSR(%a6)
698
699         clr.l           %d0
700         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
701
702         tst.b           %d1
703         bne.b           _L0_2x
704         bsr.l           ssin                    # operand is a NORM
705         bra.b           _L0_6x
706 _L0_2x:
707         cmpi.b          %d1,&ZERO               # is operand a ZERO?
708         bne.b           _L0_3x                  # no
709         bsr.l           src_zero                        # yes
710         bra.b           _L0_6x
711 _L0_3x:
712         cmpi.b          %d1,&INF                # is operand an INF?
713         bne.b           _L0_4x                  # no
714         bsr.l           t_operr                 # yes
715         bra.b           _L0_6x
716 _L0_4x:
717         cmpi.b          %d1,&QNAN               # is operand a QNAN?
718         bne.b           _L0_5x                  # no
719         bsr.l           src_qnan                        # yes
720         bra.b           _L0_6x
721 _L0_5x:
722         bsr.l           ssind                   # operand is a DENORM
723 _L0_6x:
724
725 #
726 #       Result is now in FP0
727 #
728         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
729         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
730         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
731         unlk            %a6
732         rts
733
734
735 #########################################################################
736 # MONADIC TEMPLATE                                                      #
737 #########################################################################
738         global          _fcoss_
739 _fcoss_:
740         link            %a6,&-LOCAL_SIZE
741
742         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
743         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
744         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
745
746         fmov.l          &0x0,%fpcr              # zero FPCR
747
748 #
749 #       copy, convert, and tag input argument
750 #
751         fmov.s          0x8(%a6),%fp0           # load sgl input
752         fmov.x          %fp0,FP_SRC(%a6)
753         lea             FP_SRC(%a6),%a0
754         bsr.l           tag                     # fetch operand type
755         mov.b           %d0,STAG(%a6)
756         mov.b           %d0,%d1
757
758         andi.l          &0x00ff00ff,USER_FPSR(%a6)
759
760         clr.l           %d0
761         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
762
763         tst.b           %d1
764         bne.b           _L1_2s
765         bsr.l           scos                    # operand is a NORM
766         bra.b           _L1_6s
767 _L1_2s:
768         cmpi.b          %d1,&ZERO               # is operand a ZERO?
769         bne.b           _L1_3s                  # no
770         bsr.l           ld_pone                 # yes
771         bra.b           _L1_6s
772 _L1_3s:
773         cmpi.b          %d1,&INF                # is operand an INF?
774         bne.b           _L1_4s                  # no
775         bsr.l           t_operr                 # yes
776         bra.b           _L1_6s
777 _L1_4s:
778         cmpi.b          %d1,&QNAN               # is operand a QNAN?
779         bne.b           _L1_5s                  # no
780         bsr.l           src_qnan                        # yes
781         bra.b           _L1_6s
782 _L1_5s:
783         bsr.l           scosd                   # operand is a DENORM
784 _L1_6s:
785
786 #
787 #       Result is now in FP0
788 #
789         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
790         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
791         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
792         unlk            %a6
793         rts
794
795         global          _fcosd_
796 _fcosd_:
797         link            %a6,&-LOCAL_SIZE
798
799         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
800         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
801         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
802
803         fmov.l          &0x0,%fpcr              # zero FPCR
804
805 #
806 #       copy, convert, and tag input argument
807 #
808         fmov.d          0x8(%a6),%fp0           # load dbl input
809         fmov.x          %fp0,FP_SRC(%a6)
810         lea             FP_SRC(%a6),%a0
811         bsr.l           tag                     # fetch operand type
812         mov.b           %d0,STAG(%a6)
813         mov.b           %d0,%d1
814
815         andi.l          &0x00ff00ff,USER_FPSR(%a6)
816
817         clr.l           %d0
818         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
819
820         mov.b           %d1,STAG(%a6)
821         tst.b           %d1
822         bne.b           _L1_2d
823         bsr.l           scos                    # operand is a NORM
824         bra.b           _L1_6d
825 _L1_2d:
826         cmpi.b          %d1,&ZERO               # is operand a ZERO?
827         bne.b           _L1_3d                  # no
828         bsr.l           ld_pone                 # yes
829         bra.b           _L1_6d
830 _L1_3d:
831         cmpi.b          %d1,&INF                # is operand an INF?
832         bne.b           _L1_4d                  # no
833         bsr.l           t_operr                 # yes
834         bra.b           _L1_6d
835 _L1_4d:
836         cmpi.b          %d1,&QNAN               # is operand a QNAN?
837         bne.b           _L1_5d                  # no
838         bsr.l           src_qnan                        # yes
839         bra.b           _L1_6d
840 _L1_5d:
841         bsr.l           scosd                   # operand is a DENORM
842 _L1_6d:
843
844 #
845 #       Result is now in FP0
846 #
847         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
848         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
849         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
850         unlk            %a6
851         rts
852
853         global          _fcosx_
854 _fcosx_:
855         link            %a6,&-LOCAL_SIZE
856
857         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
858         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
859         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
860
861         fmov.l          &0x0,%fpcr              # zero FPCR
862
863 #
864 #       copy, convert, and tag input argument
865 #
866         lea             FP_SRC(%a6),%a0
867         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
868         mov.l           0x8+0x4(%a6),0x4(%a0)
869         mov.l           0x8+0x8(%a6),0x8(%a0)
870         bsr.l           tag                     # fetch operand type
871         mov.b           %d0,STAG(%a6)
872         mov.b           %d0,%d1
873
874         andi.l          &0x00ff00ff,USER_FPSR(%a6)
875
876         clr.l           %d0
877         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
878
879         tst.b           %d1
880         bne.b           _L1_2x
881         bsr.l           scos                    # operand is a NORM
882         bra.b           _L1_6x
883 _L1_2x:
884         cmpi.b          %d1,&ZERO               # is operand a ZERO?
885         bne.b           _L1_3x                  # no
886         bsr.l           ld_pone                 # yes
887         bra.b           _L1_6x
888 _L1_3x:
889         cmpi.b          %d1,&INF                # is operand an INF?
890         bne.b           _L1_4x                  # no
891         bsr.l           t_operr                 # yes
892         bra.b           _L1_6x
893 _L1_4x:
894         cmpi.b          %d1,&QNAN               # is operand a QNAN?
895         bne.b           _L1_5x                  # no
896         bsr.l           src_qnan                        # yes
897         bra.b           _L1_6x
898 _L1_5x:
899         bsr.l           scosd                   # operand is a DENORM
900 _L1_6x:
901
902 #
903 #       Result is now in FP0
904 #
905         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
906         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
907         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
908         unlk            %a6
909         rts
910
911
912 #########################################################################
913 # MONADIC TEMPLATE                                                      #
914 #########################################################################
915         global          _fsinhs_
916 _fsinhs_:
917         link            %a6,&-LOCAL_SIZE
918
919         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
920         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
921         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
922
923         fmov.l          &0x0,%fpcr              # zero FPCR
924
925 #
926 #       copy, convert, and tag input argument
927 #
928         fmov.s          0x8(%a6),%fp0           # load sgl input
929         fmov.x          %fp0,FP_SRC(%a6)
930         lea             FP_SRC(%a6),%a0
931         bsr.l           tag                     # fetch operand type
932         mov.b           %d0,STAG(%a6)
933         mov.b           %d0,%d1
934
935         andi.l          &0x00ff00ff,USER_FPSR(%a6)
936
937         clr.l           %d0
938         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
939
940         tst.b           %d1
941         bne.b           _L2_2s
942         bsr.l           ssinh                   # operand is a NORM
943         bra.b           _L2_6s
944 _L2_2s:
945         cmpi.b          %d1,&ZERO               # is operand a ZERO?
946         bne.b           _L2_3s                  # no
947         bsr.l           src_zero                        # yes
948         bra.b           _L2_6s
949 _L2_3s:
950         cmpi.b          %d1,&INF                # is operand an INF?
951         bne.b           _L2_4s                  # no
952         bsr.l           src_inf                 # yes
953         bra.b           _L2_6s
954 _L2_4s:
955         cmpi.b          %d1,&QNAN               # is operand a QNAN?
956         bne.b           _L2_5s                  # no
957         bsr.l           src_qnan                        # yes
958         bra.b           _L2_6s
959 _L2_5s:
960         bsr.l           ssinhd                  # operand is a DENORM
961 _L2_6s:
962
963 #
964 #       Result is now in FP0
965 #
966         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
967         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
968         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
969         unlk            %a6
970         rts
971
972         global          _fsinhd_
973 _fsinhd_:
974         link            %a6,&-LOCAL_SIZE
975
976         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
977         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
978         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
979
980         fmov.l          &0x0,%fpcr              # zero FPCR
981
982 #
983 #       copy, convert, and tag input argument
984 #
985         fmov.d          0x8(%a6),%fp0           # load dbl input
986         fmov.x          %fp0,FP_SRC(%a6)
987         lea             FP_SRC(%a6),%a0
988         bsr.l           tag                     # fetch operand type
989         mov.b           %d0,STAG(%a6)
990         mov.b           %d0,%d1
991
992         andi.l          &0x00ff00ff,USER_FPSR(%a6)
993
994         clr.l           %d0
995         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
996
997         mov.b           %d1,STAG(%a6)
998         tst.b           %d1
999         bne.b           _L2_2d
1000         bsr.l           ssinh                   # operand is a NORM
1001         bra.b           _L2_6d
1002 _L2_2d:
1003         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1004         bne.b           _L2_3d                  # no
1005         bsr.l           src_zero                        # yes
1006         bra.b           _L2_6d
1007 _L2_3d:
1008         cmpi.b          %d1,&INF                # is operand an INF?
1009         bne.b           _L2_4d                  # no
1010         bsr.l           src_inf                 # yes
1011         bra.b           _L2_6d
1012 _L2_4d:
1013         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1014         bne.b           _L2_5d                  # no
1015         bsr.l           src_qnan                        # yes
1016         bra.b           _L2_6d
1017 _L2_5d:
1018         bsr.l           ssinhd                  # operand is a DENORM
1019 _L2_6d:
1020
1021 #
1022 #       Result is now in FP0
1023 #
1024         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1025         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1026         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1027         unlk            %a6
1028         rts
1029
1030         global          _fsinhx_
1031 _fsinhx_:
1032         link            %a6,&-LOCAL_SIZE
1033
1034         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1035         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1036         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1037
1038         fmov.l          &0x0,%fpcr              # zero FPCR
1039
1040 #
1041 #       copy, convert, and tag input argument
1042 #
1043         lea             FP_SRC(%a6),%a0
1044         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1045         mov.l           0x8+0x4(%a6),0x4(%a0)
1046         mov.l           0x8+0x8(%a6),0x8(%a0)
1047         bsr.l           tag                     # fetch operand type
1048         mov.b           %d0,STAG(%a6)
1049         mov.b           %d0,%d1
1050
1051         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1052
1053         clr.l           %d0
1054         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1055
1056         tst.b           %d1
1057         bne.b           _L2_2x
1058         bsr.l           ssinh                   # operand is a NORM
1059         bra.b           _L2_6x
1060 _L2_2x:
1061         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1062         bne.b           _L2_3x                  # no
1063         bsr.l           src_zero                        # yes
1064         bra.b           _L2_6x
1065 _L2_3x:
1066         cmpi.b          %d1,&INF                # is operand an INF?
1067         bne.b           _L2_4x                  # no
1068         bsr.l           src_inf                 # yes
1069         bra.b           _L2_6x
1070 _L2_4x:
1071         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1072         bne.b           _L2_5x                  # no
1073         bsr.l           src_qnan                        # yes
1074         bra.b           _L2_6x
1075 _L2_5x:
1076         bsr.l           ssinhd                  # operand is a DENORM
1077 _L2_6x:
1078
1079 #
1080 #       Result is now in FP0
1081 #
1082         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1083         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1084         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1085         unlk            %a6
1086         rts
1087
1088
1089 #########################################################################
1090 # MONADIC TEMPLATE                                                      #
1091 #########################################################################
1092         global          _flognp1s_
1093 _flognp1s_:
1094         link            %a6,&-LOCAL_SIZE
1095
1096         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1097         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1098         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1099
1100         fmov.l          &0x0,%fpcr              # zero FPCR
1101
1102 #
1103 #       copy, convert, and tag input argument
1104 #
1105         fmov.s          0x8(%a6),%fp0           # load sgl input
1106         fmov.x          %fp0,FP_SRC(%a6)
1107         lea             FP_SRC(%a6),%a0
1108         bsr.l           tag                     # fetch operand type
1109         mov.b           %d0,STAG(%a6)
1110         mov.b           %d0,%d1
1111
1112         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1113
1114         clr.l           %d0
1115         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1116
1117         tst.b           %d1
1118         bne.b           _L3_2s
1119         bsr.l           slognp1                 # operand is a NORM
1120         bra.b           _L3_6s
1121 _L3_2s:
1122         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1123         bne.b           _L3_3s                  # no
1124         bsr.l           src_zero                        # yes
1125         bra.b           _L3_6s
1126 _L3_3s:
1127         cmpi.b          %d1,&INF                # is operand an INF?
1128         bne.b           _L3_4s                  # no
1129         bsr.l           sopr_inf                        # yes
1130         bra.b           _L3_6s
1131 _L3_4s:
1132         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1133         bne.b           _L3_5s                  # no
1134         bsr.l           src_qnan                        # yes
1135         bra.b           _L3_6s
1136 _L3_5s:
1137         bsr.l           slognp1d                        # operand is a DENORM
1138 _L3_6s:
1139
1140 #
1141 #       Result is now in FP0
1142 #
1143         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1144         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1145         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1146         unlk            %a6
1147         rts
1148
1149         global          _flognp1d_
1150 _flognp1d_:
1151         link            %a6,&-LOCAL_SIZE
1152
1153         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1154         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1155         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1156
1157         fmov.l          &0x0,%fpcr              # zero FPCR
1158
1159 #
1160 #       copy, convert, and tag input argument
1161 #
1162         fmov.d          0x8(%a6),%fp0           # load dbl input
1163         fmov.x          %fp0,FP_SRC(%a6)
1164         lea             FP_SRC(%a6),%a0
1165         bsr.l           tag                     # fetch operand type
1166         mov.b           %d0,STAG(%a6)
1167         mov.b           %d0,%d1
1168
1169         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1170
1171         clr.l           %d0
1172         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1173
1174         mov.b           %d1,STAG(%a6)
1175         tst.b           %d1
1176         bne.b           _L3_2d
1177         bsr.l           slognp1                 # operand is a NORM
1178         bra.b           _L3_6d
1179 _L3_2d:
1180         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1181         bne.b           _L3_3d                  # no
1182         bsr.l           src_zero                        # yes
1183         bra.b           _L3_6d
1184 _L3_3d:
1185         cmpi.b          %d1,&INF                # is operand an INF?
1186         bne.b           _L3_4d                  # no
1187         bsr.l           sopr_inf                        # yes
1188         bra.b           _L3_6d
1189 _L3_4d:
1190         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1191         bne.b           _L3_5d                  # no
1192         bsr.l           src_qnan                        # yes
1193         bra.b           _L3_6d
1194 _L3_5d:
1195         bsr.l           slognp1d                        # operand is a DENORM
1196 _L3_6d:
1197
1198 #
1199 #       Result is now in FP0
1200 #
1201         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1202         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1203         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1204         unlk            %a6
1205         rts
1206
1207         global          _flognp1x_
1208 _flognp1x_:
1209         link            %a6,&-LOCAL_SIZE
1210
1211         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1212         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1213         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1214
1215         fmov.l          &0x0,%fpcr              # zero FPCR
1216
1217 #
1218 #       copy, convert, and tag input argument
1219 #
1220         lea             FP_SRC(%a6),%a0
1221         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1222         mov.l           0x8+0x4(%a6),0x4(%a0)
1223         mov.l           0x8+0x8(%a6),0x8(%a0)
1224         bsr.l           tag                     # fetch operand type
1225         mov.b           %d0,STAG(%a6)
1226         mov.b           %d0,%d1
1227
1228         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1229
1230         clr.l           %d0
1231         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1232
1233         tst.b           %d1
1234         bne.b           _L3_2x
1235         bsr.l           slognp1                 # operand is a NORM
1236         bra.b           _L3_6x
1237 _L3_2x:
1238         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1239         bne.b           _L3_3x                  # no
1240         bsr.l           src_zero                        # yes
1241         bra.b           _L3_6x
1242 _L3_3x:
1243         cmpi.b          %d1,&INF                # is operand an INF?
1244         bne.b           _L3_4x                  # no
1245         bsr.l           sopr_inf                        # yes
1246         bra.b           _L3_6x
1247 _L3_4x:
1248         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1249         bne.b           _L3_5x                  # no
1250         bsr.l           src_qnan                        # yes
1251         bra.b           _L3_6x
1252 _L3_5x:
1253         bsr.l           slognp1d                        # operand is a DENORM
1254 _L3_6x:
1255
1256 #
1257 #       Result is now in FP0
1258 #
1259         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1260         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1261         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1262         unlk            %a6
1263         rts
1264
1265
1266 #########################################################################
1267 # MONADIC TEMPLATE                                                      #
1268 #########################################################################
1269         global          _fetoxm1s_
1270 _fetoxm1s_:
1271         link            %a6,&-LOCAL_SIZE
1272
1273         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1274         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1275         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1276
1277         fmov.l          &0x0,%fpcr              # zero FPCR
1278
1279 #
1280 #       copy, convert, and tag input argument
1281 #
1282         fmov.s          0x8(%a6),%fp0           # load sgl input
1283         fmov.x          %fp0,FP_SRC(%a6)
1284         lea             FP_SRC(%a6),%a0
1285         bsr.l           tag                     # fetch operand type
1286         mov.b           %d0,STAG(%a6)
1287         mov.b           %d0,%d1
1288
1289         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1290
1291         clr.l           %d0
1292         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1293
1294         tst.b           %d1
1295         bne.b           _L4_2s
1296         bsr.l           setoxm1                 # operand is a NORM
1297         bra.b           _L4_6s
1298 _L4_2s:
1299         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1300         bne.b           _L4_3s                  # no
1301         bsr.l           src_zero                        # yes
1302         bra.b           _L4_6s
1303 _L4_3s:
1304         cmpi.b          %d1,&INF                # is operand an INF?
1305         bne.b           _L4_4s                  # no
1306         bsr.l           setoxm1i                        # yes
1307         bra.b           _L4_6s
1308 _L4_4s:
1309         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1310         bne.b           _L4_5s                  # no
1311         bsr.l           src_qnan                        # yes
1312         bra.b           _L4_6s
1313 _L4_5s:
1314         bsr.l           setoxm1d                        # operand is a DENORM
1315 _L4_6s:
1316
1317 #
1318 #       Result is now in FP0
1319 #
1320         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1321         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1322         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1323         unlk            %a6
1324         rts
1325
1326         global          _fetoxm1d_
1327 _fetoxm1d_:
1328         link            %a6,&-LOCAL_SIZE
1329
1330         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1331         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1332         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1333
1334         fmov.l          &0x0,%fpcr              # zero FPCR
1335
1336 #
1337 #       copy, convert, and tag input argument
1338 #
1339         fmov.d          0x8(%a6),%fp0           # load dbl input
1340         fmov.x          %fp0,FP_SRC(%a6)
1341         lea             FP_SRC(%a6),%a0
1342         bsr.l           tag                     # fetch operand type
1343         mov.b           %d0,STAG(%a6)
1344         mov.b           %d0,%d1
1345
1346         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1347
1348         clr.l           %d0
1349         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1350
1351         mov.b           %d1,STAG(%a6)
1352         tst.b           %d1
1353         bne.b           _L4_2d
1354         bsr.l           setoxm1                 # operand is a NORM
1355         bra.b           _L4_6d
1356 _L4_2d:
1357         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1358         bne.b           _L4_3d                  # no
1359         bsr.l           src_zero                        # yes
1360         bra.b           _L4_6d
1361 _L4_3d:
1362         cmpi.b          %d1,&INF                # is operand an INF?
1363         bne.b           _L4_4d                  # no
1364         bsr.l           setoxm1i                        # yes
1365         bra.b           _L4_6d
1366 _L4_4d:
1367         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1368         bne.b           _L4_5d                  # no
1369         bsr.l           src_qnan                        # yes
1370         bra.b           _L4_6d
1371 _L4_5d:
1372         bsr.l           setoxm1d                        # operand is a DENORM
1373 _L4_6d:
1374
1375 #
1376 #       Result is now in FP0
1377 #
1378         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1379         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1380         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1381         unlk            %a6
1382         rts
1383
1384         global          _fetoxm1x_
1385 _fetoxm1x_:
1386         link            %a6,&-LOCAL_SIZE
1387
1388         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1389         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1390         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1391
1392         fmov.l          &0x0,%fpcr              # zero FPCR
1393
1394 #
1395 #       copy, convert, and tag input argument
1396 #
1397         lea             FP_SRC(%a6),%a0
1398         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1399         mov.l           0x8+0x4(%a6),0x4(%a0)
1400         mov.l           0x8+0x8(%a6),0x8(%a0)
1401         bsr.l           tag                     # fetch operand type
1402         mov.b           %d0,STAG(%a6)
1403         mov.b           %d0,%d1
1404
1405         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1406
1407         clr.l           %d0
1408         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1409
1410         tst.b           %d1
1411         bne.b           _L4_2x
1412         bsr.l           setoxm1                 # operand is a NORM
1413         bra.b           _L4_6x
1414 _L4_2x:
1415         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1416         bne.b           _L4_3x                  # no
1417         bsr.l           src_zero                        # yes
1418         bra.b           _L4_6x
1419 _L4_3x:
1420         cmpi.b          %d1,&INF                # is operand an INF?
1421         bne.b           _L4_4x                  # no
1422         bsr.l           setoxm1i                        # yes
1423         bra.b           _L4_6x
1424 _L4_4x:
1425         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1426         bne.b           _L4_5x                  # no
1427         bsr.l           src_qnan                        # yes
1428         bra.b           _L4_6x
1429 _L4_5x:
1430         bsr.l           setoxm1d                        # operand is a DENORM
1431 _L4_6x:
1432
1433 #
1434 #       Result is now in FP0
1435 #
1436         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1437         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1438         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1439         unlk            %a6
1440         rts
1441
1442
1443 #########################################################################
1444 # MONADIC TEMPLATE                                                      #
1445 #########################################################################
1446         global          _ftanhs_
1447 _ftanhs_:
1448         link            %a6,&-LOCAL_SIZE
1449
1450         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1451         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1452         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1453
1454         fmov.l          &0x0,%fpcr              # zero FPCR
1455
1456 #
1457 #       copy, convert, and tag input argument
1458 #
1459         fmov.s          0x8(%a6),%fp0           # load sgl input
1460         fmov.x          %fp0,FP_SRC(%a6)
1461         lea             FP_SRC(%a6),%a0
1462         bsr.l           tag                     # fetch operand type
1463         mov.b           %d0,STAG(%a6)
1464         mov.b           %d0,%d1
1465
1466         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1467
1468         clr.l           %d0
1469         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1470
1471         tst.b           %d1
1472         bne.b           _L5_2s
1473         bsr.l           stanh                   # operand is a NORM
1474         bra.b           _L5_6s
1475 _L5_2s:
1476         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1477         bne.b           _L5_3s                  # no
1478         bsr.l           src_zero                        # yes
1479         bra.b           _L5_6s
1480 _L5_3s:
1481         cmpi.b          %d1,&INF                # is operand an INF?
1482         bne.b           _L5_4s                  # no
1483         bsr.l           src_one                 # yes
1484         bra.b           _L5_6s
1485 _L5_4s:
1486         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1487         bne.b           _L5_5s                  # no
1488         bsr.l           src_qnan                        # yes
1489         bra.b           _L5_6s
1490 _L5_5s:
1491         bsr.l           stanhd                  # operand is a DENORM
1492 _L5_6s:
1493
1494 #
1495 #       Result is now in FP0
1496 #
1497         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1498         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1499         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1500         unlk            %a6
1501         rts
1502
1503         global          _ftanhd_
1504 _ftanhd_:
1505         link            %a6,&-LOCAL_SIZE
1506
1507         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1508         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1509         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1510
1511         fmov.l          &0x0,%fpcr              # zero FPCR
1512
1513 #
1514 #       copy, convert, and tag input argument
1515 #
1516         fmov.d          0x8(%a6),%fp0           # load dbl input
1517         fmov.x          %fp0,FP_SRC(%a6)
1518         lea             FP_SRC(%a6),%a0
1519         bsr.l           tag                     # fetch operand type
1520         mov.b           %d0,STAG(%a6)
1521         mov.b           %d0,%d1
1522
1523         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1524
1525         clr.l           %d0
1526         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1527
1528         mov.b           %d1,STAG(%a6)
1529         tst.b           %d1
1530         bne.b           _L5_2d
1531         bsr.l           stanh                   # operand is a NORM
1532         bra.b           _L5_6d
1533 _L5_2d:
1534         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1535         bne.b           _L5_3d                  # no
1536         bsr.l           src_zero                        # yes
1537         bra.b           _L5_6d
1538 _L5_3d:
1539         cmpi.b          %d1,&INF                # is operand an INF?
1540         bne.b           _L5_4d                  # no
1541         bsr.l           src_one                 # yes
1542         bra.b           _L5_6d
1543 _L5_4d:
1544         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1545         bne.b           _L5_5d                  # no
1546         bsr.l           src_qnan                        # yes
1547         bra.b           _L5_6d
1548 _L5_5d:
1549         bsr.l           stanhd                  # operand is a DENORM
1550 _L5_6d:
1551
1552 #
1553 #       Result is now in FP0
1554 #
1555         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1556         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1557         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1558         unlk            %a6
1559         rts
1560
1561         global          _ftanhx_
1562 _ftanhx_:
1563         link            %a6,&-LOCAL_SIZE
1564
1565         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1566         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1567         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1568
1569         fmov.l          &0x0,%fpcr              # zero FPCR
1570
1571 #
1572 #       copy, convert, and tag input argument
1573 #
1574         lea             FP_SRC(%a6),%a0
1575         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1576         mov.l           0x8+0x4(%a6),0x4(%a0)
1577         mov.l           0x8+0x8(%a6),0x8(%a0)
1578         bsr.l           tag                     # fetch operand type
1579         mov.b           %d0,STAG(%a6)
1580         mov.b           %d0,%d1
1581
1582         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1583
1584         clr.l           %d0
1585         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1586
1587         tst.b           %d1
1588         bne.b           _L5_2x
1589         bsr.l           stanh                   # operand is a NORM
1590         bra.b           _L5_6x
1591 _L5_2x:
1592         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1593         bne.b           _L5_3x                  # no
1594         bsr.l           src_zero                        # yes
1595         bra.b           _L5_6x
1596 _L5_3x:
1597         cmpi.b          %d1,&INF                # is operand an INF?
1598         bne.b           _L5_4x                  # no
1599         bsr.l           src_one                 # yes
1600         bra.b           _L5_6x
1601 _L5_4x:
1602         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1603         bne.b           _L5_5x                  # no
1604         bsr.l           src_qnan                        # yes
1605         bra.b           _L5_6x
1606 _L5_5x:
1607         bsr.l           stanhd                  # operand is a DENORM
1608 _L5_6x:
1609
1610 #
1611 #       Result is now in FP0
1612 #
1613         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1614         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1615         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1616         unlk            %a6
1617         rts
1618
1619
1620 #########################################################################
1621 # MONADIC TEMPLATE                                                      #
1622 #########################################################################
1623         global          _fatans_
1624 _fatans_:
1625         link            %a6,&-LOCAL_SIZE
1626
1627         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1628         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1629         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1630
1631         fmov.l          &0x0,%fpcr              # zero FPCR
1632
1633 #
1634 #       copy, convert, and tag input argument
1635 #
1636         fmov.s          0x8(%a6),%fp0           # load sgl input
1637         fmov.x          %fp0,FP_SRC(%a6)
1638         lea             FP_SRC(%a6),%a0
1639         bsr.l           tag                     # fetch operand type
1640         mov.b           %d0,STAG(%a6)
1641         mov.b           %d0,%d1
1642
1643         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1644
1645         clr.l           %d0
1646         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1647
1648         tst.b           %d1
1649         bne.b           _L6_2s
1650         bsr.l           satan                   # operand is a NORM
1651         bra.b           _L6_6s
1652 _L6_2s:
1653         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1654         bne.b           _L6_3s                  # no
1655         bsr.l           src_zero                        # yes
1656         bra.b           _L6_6s
1657 _L6_3s:
1658         cmpi.b          %d1,&INF                # is operand an INF?
1659         bne.b           _L6_4s                  # no
1660         bsr.l           spi_2                   # yes
1661         bra.b           _L6_6s
1662 _L6_4s:
1663         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1664         bne.b           _L6_5s                  # no
1665         bsr.l           src_qnan                        # yes
1666         bra.b           _L6_6s
1667 _L6_5s:
1668         bsr.l           satand                  # operand is a DENORM
1669 _L6_6s:
1670
1671 #
1672 #       Result is now in FP0
1673 #
1674         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1675         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1676         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1677         unlk            %a6
1678         rts
1679
1680         global          _fatand_
1681 _fatand_:
1682         link            %a6,&-LOCAL_SIZE
1683
1684         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1685         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1686         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1687
1688         fmov.l          &0x0,%fpcr              # zero FPCR
1689
1690 #
1691 #       copy, convert, and tag input argument
1692 #
1693         fmov.d          0x8(%a6),%fp0           # load dbl input
1694         fmov.x          %fp0,FP_SRC(%a6)
1695         lea             FP_SRC(%a6),%a0
1696         bsr.l           tag                     # fetch operand type
1697         mov.b           %d0,STAG(%a6)
1698         mov.b           %d0,%d1
1699
1700         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1701
1702         clr.l           %d0
1703         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1704
1705         mov.b           %d1,STAG(%a6)
1706         tst.b           %d1
1707         bne.b           _L6_2d
1708         bsr.l           satan                   # operand is a NORM
1709         bra.b           _L6_6d
1710 _L6_2d:
1711         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1712         bne.b           _L6_3d                  # no
1713         bsr.l           src_zero                        # yes
1714         bra.b           _L6_6d
1715 _L6_3d:
1716         cmpi.b          %d1,&INF                # is operand an INF?
1717         bne.b           _L6_4d                  # no
1718         bsr.l           spi_2                   # yes
1719         bra.b           _L6_6d
1720 _L6_4d:
1721         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1722         bne.b           _L6_5d                  # no
1723         bsr.l           src_qnan                        # yes
1724         bra.b           _L6_6d
1725 _L6_5d:
1726         bsr.l           satand                  # operand is a DENORM
1727 _L6_6d:
1728
1729 #
1730 #       Result is now in FP0
1731 #
1732         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1733         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1734         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1735         unlk            %a6
1736         rts
1737
1738         global          _fatanx_
1739 _fatanx_:
1740         link            %a6,&-LOCAL_SIZE
1741
1742         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1743         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1744         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1745
1746         fmov.l          &0x0,%fpcr              # zero FPCR
1747
1748 #
1749 #       copy, convert, and tag input argument
1750 #
1751         lea             FP_SRC(%a6),%a0
1752         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1753         mov.l           0x8+0x4(%a6),0x4(%a0)
1754         mov.l           0x8+0x8(%a6),0x8(%a0)
1755         bsr.l           tag                     # fetch operand type
1756         mov.b           %d0,STAG(%a6)
1757         mov.b           %d0,%d1
1758
1759         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1760
1761         clr.l           %d0
1762         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1763
1764         tst.b           %d1
1765         bne.b           _L6_2x
1766         bsr.l           satan                   # operand is a NORM
1767         bra.b           _L6_6x
1768 _L6_2x:
1769         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1770         bne.b           _L6_3x                  # no
1771         bsr.l           src_zero                        # yes
1772         bra.b           _L6_6x
1773 _L6_3x:
1774         cmpi.b          %d1,&INF                # is operand an INF?
1775         bne.b           _L6_4x                  # no
1776         bsr.l           spi_2                   # yes
1777         bra.b           _L6_6x
1778 _L6_4x:
1779         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1780         bne.b           _L6_5x                  # no
1781         bsr.l           src_qnan                        # yes
1782         bra.b           _L6_6x
1783 _L6_5x:
1784         bsr.l           satand                  # operand is a DENORM
1785 _L6_6x:
1786
1787 #
1788 #       Result is now in FP0
1789 #
1790         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1791         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1792         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1793         unlk            %a6
1794         rts
1795
1796
1797 #########################################################################
1798 # MONADIC TEMPLATE                                                      #
1799 #########################################################################
1800         global          _fasins_
1801 _fasins_:
1802         link            %a6,&-LOCAL_SIZE
1803
1804         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1805         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1806         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1807
1808         fmov.l          &0x0,%fpcr              # zero FPCR
1809
1810 #
1811 #       copy, convert, and tag input argument
1812 #
1813         fmov.s          0x8(%a6),%fp0           # load sgl input
1814         fmov.x          %fp0,FP_SRC(%a6)
1815         lea             FP_SRC(%a6),%a0
1816         bsr.l           tag                     # fetch operand type
1817         mov.b           %d0,STAG(%a6)
1818         mov.b           %d0,%d1
1819
1820         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1821
1822         clr.l           %d0
1823         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1824
1825         tst.b           %d1
1826         bne.b           _L7_2s
1827         bsr.l           sasin                   # operand is a NORM
1828         bra.b           _L7_6s
1829 _L7_2s:
1830         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1831         bne.b           _L7_3s                  # no
1832         bsr.l           src_zero                        # yes
1833         bra.b           _L7_6s
1834 _L7_3s:
1835         cmpi.b          %d1,&INF                # is operand an INF?
1836         bne.b           _L7_4s                  # no
1837         bsr.l           t_operr                 # yes
1838         bra.b           _L7_6s
1839 _L7_4s:
1840         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1841         bne.b           _L7_5s                  # no
1842         bsr.l           src_qnan                        # yes
1843         bra.b           _L7_6s
1844 _L7_5s:
1845         bsr.l           sasind                  # operand is a DENORM
1846 _L7_6s:
1847
1848 #
1849 #       Result is now in FP0
1850 #
1851         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1852         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1853         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1854         unlk            %a6
1855         rts
1856
1857         global          _fasind_
1858 _fasind_:
1859         link            %a6,&-LOCAL_SIZE
1860
1861         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1862         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1863         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1864
1865         fmov.l          &0x0,%fpcr              # zero FPCR
1866
1867 #
1868 #       copy, convert, and tag input argument
1869 #
1870         fmov.d          0x8(%a6),%fp0           # load dbl input
1871         fmov.x          %fp0,FP_SRC(%a6)
1872         lea             FP_SRC(%a6),%a0
1873         bsr.l           tag                     # fetch operand type
1874         mov.b           %d0,STAG(%a6)
1875         mov.b           %d0,%d1
1876
1877         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1878
1879         clr.l           %d0
1880         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1881
1882         mov.b           %d1,STAG(%a6)
1883         tst.b           %d1
1884         bne.b           _L7_2d
1885         bsr.l           sasin                   # operand is a NORM
1886         bra.b           _L7_6d
1887 _L7_2d:
1888         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1889         bne.b           _L7_3d                  # no
1890         bsr.l           src_zero                        # yes
1891         bra.b           _L7_6d
1892 _L7_3d:
1893         cmpi.b          %d1,&INF                # is operand an INF?
1894         bne.b           _L7_4d                  # no
1895         bsr.l           t_operr                 # yes
1896         bra.b           _L7_6d
1897 _L7_4d:
1898         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1899         bne.b           _L7_5d                  # no
1900         bsr.l           src_qnan                        # yes
1901         bra.b           _L7_6d
1902 _L7_5d:
1903         bsr.l           sasind                  # operand is a DENORM
1904 _L7_6d:
1905
1906 #
1907 #       Result is now in FP0
1908 #
1909         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1910         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1911         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1912         unlk            %a6
1913         rts
1914
1915         global          _fasinx_
1916 _fasinx_:
1917         link            %a6,&-LOCAL_SIZE
1918
1919         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1920         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1921         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1922
1923         fmov.l          &0x0,%fpcr              # zero FPCR
1924
1925 #
1926 #       copy, convert, and tag input argument
1927 #
1928         lea             FP_SRC(%a6),%a0
1929         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
1930         mov.l           0x8+0x4(%a6),0x4(%a0)
1931         mov.l           0x8+0x8(%a6),0x8(%a0)
1932         bsr.l           tag                     # fetch operand type
1933         mov.b           %d0,STAG(%a6)
1934         mov.b           %d0,%d1
1935
1936         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1937
1938         clr.l           %d0
1939         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
1940
1941         tst.b           %d1
1942         bne.b           _L7_2x
1943         bsr.l           sasin                   # operand is a NORM
1944         bra.b           _L7_6x
1945 _L7_2x:
1946         cmpi.b          %d1,&ZERO               # is operand a ZERO?
1947         bne.b           _L7_3x                  # no
1948         bsr.l           src_zero                        # yes
1949         bra.b           _L7_6x
1950 _L7_3x:
1951         cmpi.b          %d1,&INF                # is operand an INF?
1952         bne.b           _L7_4x                  # no
1953         bsr.l           t_operr                 # yes
1954         bra.b           _L7_6x
1955 _L7_4x:
1956         cmpi.b          %d1,&QNAN               # is operand a QNAN?
1957         bne.b           _L7_5x                  # no
1958         bsr.l           src_qnan                        # yes
1959         bra.b           _L7_6x
1960 _L7_5x:
1961         bsr.l           sasind                  # operand is a DENORM
1962 _L7_6x:
1963
1964 #
1965 #       Result is now in FP0
1966 #
1967         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
1968         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1969         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
1970         unlk            %a6
1971         rts
1972
1973
1974 #########################################################################
1975 # MONADIC TEMPLATE                                                      #
1976 #########################################################################
1977         global          _fatanhs_
1978 _fatanhs_:
1979         link            %a6,&-LOCAL_SIZE
1980
1981         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
1982         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1983         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
1984
1985         fmov.l          &0x0,%fpcr              # zero FPCR
1986
1987 #
1988 #       copy, convert, and tag input argument
1989 #
1990         fmov.s          0x8(%a6),%fp0           # load sgl input
1991         fmov.x          %fp0,FP_SRC(%a6)
1992         lea             FP_SRC(%a6),%a0
1993         bsr.l           tag                     # fetch operand type
1994         mov.b           %d0,STAG(%a6)
1995         mov.b           %d0,%d1
1996
1997         andi.l          &0x00ff00ff,USER_FPSR(%a6)
1998
1999         clr.l           %d0
2000         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2001
2002         tst.b           %d1
2003         bne.b           _L8_2s
2004         bsr.l           satanh                  # operand is a NORM
2005         bra.b           _L8_6s
2006 _L8_2s:
2007         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2008         bne.b           _L8_3s                  # no
2009         bsr.l           src_zero                        # yes
2010         bra.b           _L8_6s
2011 _L8_3s:
2012         cmpi.b          %d1,&INF                # is operand an INF?
2013         bne.b           _L8_4s                  # no
2014         bsr.l           t_operr                 # yes
2015         bra.b           _L8_6s
2016 _L8_4s:
2017         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2018         bne.b           _L8_5s                  # no
2019         bsr.l           src_qnan                        # yes
2020         bra.b           _L8_6s
2021 _L8_5s:
2022         bsr.l           satanhd                 # operand is a DENORM
2023 _L8_6s:
2024
2025 #
2026 #       Result is now in FP0
2027 #
2028         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2029         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2030         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2031         unlk            %a6
2032         rts
2033
2034         global          _fatanhd_
2035 _fatanhd_:
2036         link            %a6,&-LOCAL_SIZE
2037
2038         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2039         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2040         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2041
2042         fmov.l          &0x0,%fpcr              # zero FPCR
2043
2044 #
2045 #       copy, convert, and tag input argument
2046 #
2047         fmov.d          0x8(%a6),%fp0           # load dbl input
2048         fmov.x          %fp0,FP_SRC(%a6)
2049         lea             FP_SRC(%a6),%a0
2050         bsr.l           tag                     # fetch operand type
2051         mov.b           %d0,STAG(%a6)
2052         mov.b           %d0,%d1
2053
2054         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2055
2056         clr.l           %d0
2057         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2058
2059         mov.b           %d1,STAG(%a6)
2060         tst.b           %d1
2061         bne.b           _L8_2d
2062         bsr.l           satanh                  # operand is a NORM
2063         bra.b           _L8_6d
2064 _L8_2d:
2065         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2066         bne.b           _L8_3d                  # no
2067         bsr.l           src_zero                        # yes
2068         bra.b           _L8_6d
2069 _L8_3d:
2070         cmpi.b          %d1,&INF                # is operand an INF?
2071         bne.b           _L8_4d                  # no
2072         bsr.l           t_operr                 # yes
2073         bra.b           _L8_6d
2074 _L8_4d:
2075         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2076         bne.b           _L8_5d                  # no
2077         bsr.l           src_qnan                        # yes
2078         bra.b           _L8_6d
2079 _L8_5d:
2080         bsr.l           satanhd                 # operand is a DENORM
2081 _L8_6d:
2082
2083 #
2084 #       Result is now in FP0
2085 #
2086         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2087         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2088         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2089         unlk            %a6
2090         rts
2091
2092         global          _fatanhx_
2093 _fatanhx_:
2094         link            %a6,&-LOCAL_SIZE
2095
2096         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2097         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2098         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2099
2100         fmov.l          &0x0,%fpcr              # zero FPCR
2101
2102 #
2103 #       copy, convert, and tag input argument
2104 #
2105         lea             FP_SRC(%a6),%a0
2106         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2107         mov.l           0x8+0x4(%a6),0x4(%a0)
2108         mov.l           0x8+0x8(%a6),0x8(%a0)
2109         bsr.l           tag                     # fetch operand type
2110         mov.b           %d0,STAG(%a6)
2111         mov.b           %d0,%d1
2112
2113         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2114
2115         clr.l           %d0
2116         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2117
2118         tst.b           %d1
2119         bne.b           _L8_2x
2120         bsr.l           satanh                  # operand is a NORM
2121         bra.b           _L8_6x
2122 _L8_2x:
2123         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2124         bne.b           _L8_3x                  # no
2125         bsr.l           src_zero                        # yes
2126         bra.b           _L8_6x
2127 _L8_3x:
2128         cmpi.b          %d1,&INF                # is operand an INF?
2129         bne.b           _L8_4x                  # no
2130         bsr.l           t_operr                 # yes
2131         bra.b           _L8_6x
2132 _L8_4x:
2133         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2134         bne.b           _L8_5x                  # no
2135         bsr.l           src_qnan                        # yes
2136         bra.b           _L8_6x
2137 _L8_5x:
2138         bsr.l           satanhd                 # operand is a DENORM
2139 _L8_6x:
2140
2141 #
2142 #       Result is now in FP0
2143 #
2144         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2145         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2146         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2147         unlk            %a6
2148         rts
2149
2150
2151 #########################################################################
2152 # MONADIC TEMPLATE                                                      #
2153 #########################################################################
2154         global          _ftans_
2155 _ftans_:
2156         link            %a6,&-LOCAL_SIZE
2157
2158         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2159         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2160         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2161
2162         fmov.l          &0x0,%fpcr              # zero FPCR
2163
2164 #
2165 #       copy, convert, and tag input argument
2166 #
2167         fmov.s          0x8(%a6),%fp0           # load sgl input
2168         fmov.x          %fp0,FP_SRC(%a6)
2169         lea             FP_SRC(%a6),%a0
2170         bsr.l           tag                     # fetch operand type
2171         mov.b           %d0,STAG(%a6)
2172         mov.b           %d0,%d1
2173
2174         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2175
2176         clr.l           %d0
2177         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2178
2179         tst.b           %d1
2180         bne.b           _L9_2s
2181         bsr.l           stan                    # operand is a NORM
2182         bra.b           _L9_6s
2183 _L9_2s:
2184         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2185         bne.b           _L9_3s                  # no
2186         bsr.l           src_zero                        # yes
2187         bra.b           _L9_6s
2188 _L9_3s:
2189         cmpi.b          %d1,&INF                # is operand an INF?
2190         bne.b           _L9_4s                  # no
2191         bsr.l           t_operr                 # yes
2192         bra.b           _L9_6s
2193 _L9_4s:
2194         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2195         bne.b           _L9_5s                  # no
2196         bsr.l           src_qnan                        # yes
2197         bra.b           _L9_6s
2198 _L9_5s:
2199         bsr.l           stand                   # operand is a DENORM
2200 _L9_6s:
2201
2202 #
2203 #       Result is now in FP0
2204 #
2205         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2206         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2207         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2208         unlk            %a6
2209         rts
2210
2211         global          _ftand_
2212 _ftand_:
2213         link            %a6,&-LOCAL_SIZE
2214
2215         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2216         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2217         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2218
2219         fmov.l          &0x0,%fpcr              # zero FPCR
2220
2221 #
2222 #       copy, convert, and tag input argument
2223 #
2224         fmov.d          0x8(%a6),%fp0           # load dbl input
2225         fmov.x          %fp0,FP_SRC(%a6)
2226         lea             FP_SRC(%a6),%a0
2227         bsr.l           tag                     # fetch operand type
2228         mov.b           %d0,STAG(%a6)
2229         mov.b           %d0,%d1
2230
2231         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2232
2233         clr.l           %d0
2234         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2235
2236         mov.b           %d1,STAG(%a6)
2237         tst.b           %d1
2238         bne.b           _L9_2d
2239         bsr.l           stan                    # operand is a NORM
2240         bra.b           _L9_6d
2241 _L9_2d:
2242         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2243         bne.b           _L9_3d                  # no
2244         bsr.l           src_zero                        # yes
2245         bra.b           _L9_6d
2246 _L9_3d:
2247         cmpi.b          %d1,&INF                # is operand an INF?
2248         bne.b           _L9_4d                  # no
2249         bsr.l           t_operr                 # yes
2250         bra.b           _L9_6d
2251 _L9_4d:
2252         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2253         bne.b           _L9_5d                  # no
2254         bsr.l           src_qnan                        # yes
2255         bra.b           _L9_6d
2256 _L9_5d:
2257         bsr.l           stand                   # operand is a DENORM
2258 _L9_6d:
2259
2260 #
2261 #       Result is now in FP0
2262 #
2263         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2264         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2265         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2266         unlk            %a6
2267         rts
2268
2269         global          _ftanx_
2270 _ftanx_:
2271         link            %a6,&-LOCAL_SIZE
2272
2273         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2274         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2275         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2276
2277         fmov.l          &0x0,%fpcr              # zero FPCR
2278
2279 #
2280 #       copy, convert, and tag input argument
2281 #
2282         lea             FP_SRC(%a6),%a0
2283         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2284         mov.l           0x8+0x4(%a6),0x4(%a0)
2285         mov.l           0x8+0x8(%a6),0x8(%a0)
2286         bsr.l           tag                     # fetch operand type
2287         mov.b           %d0,STAG(%a6)
2288         mov.b           %d0,%d1
2289
2290         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2291
2292         clr.l           %d0
2293         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2294
2295         tst.b           %d1
2296         bne.b           _L9_2x
2297         bsr.l           stan                    # operand is a NORM
2298         bra.b           _L9_6x
2299 _L9_2x:
2300         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2301         bne.b           _L9_3x                  # no
2302         bsr.l           src_zero                        # yes
2303         bra.b           _L9_6x
2304 _L9_3x:
2305         cmpi.b          %d1,&INF                # is operand an INF?
2306         bne.b           _L9_4x                  # no
2307         bsr.l           t_operr                 # yes
2308         bra.b           _L9_6x
2309 _L9_4x:
2310         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2311         bne.b           _L9_5x                  # no
2312         bsr.l           src_qnan                        # yes
2313         bra.b           _L9_6x
2314 _L9_5x:
2315         bsr.l           stand                   # operand is a DENORM
2316 _L9_6x:
2317
2318 #
2319 #       Result is now in FP0
2320 #
2321         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2322         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2323         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2324         unlk            %a6
2325         rts
2326
2327
2328 #########################################################################
2329 # MONADIC TEMPLATE                                                      #
2330 #########################################################################
2331         global          _fetoxs_
2332 _fetoxs_:
2333         link            %a6,&-LOCAL_SIZE
2334
2335         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2336         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2337         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2338
2339         fmov.l          &0x0,%fpcr              # zero FPCR
2340
2341 #
2342 #       copy, convert, and tag input argument
2343 #
2344         fmov.s          0x8(%a6),%fp0           # load sgl input
2345         fmov.x          %fp0,FP_SRC(%a6)
2346         lea             FP_SRC(%a6),%a0
2347         bsr.l           tag                     # fetch operand type
2348         mov.b           %d0,STAG(%a6)
2349         mov.b           %d0,%d1
2350
2351         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2352
2353         clr.l           %d0
2354         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2355
2356         tst.b           %d1
2357         bne.b           _L10_2s
2358         bsr.l           setox                   # operand is a NORM
2359         bra.b           _L10_6s
2360 _L10_2s:
2361         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2362         bne.b           _L10_3s                 # no
2363         bsr.l           ld_pone                 # yes
2364         bra.b           _L10_6s
2365 _L10_3s:
2366         cmpi.b          %d1,&INF                # is operand an INF?
2367         bne.b           _L10_4s                 # no
2368         bsr.l           szr_inf                 # yes
2369         bra.b           _L10_6s
2370 _L10_4s:
2371         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2372         bne.b           _L10_5s                 # no
2373         bsr.l           src_qnan                        # yes
2374         bra.b           _L10_6s
2375 _L10_5s:
2376         bsr.l           setoxd                  # operand is a DENORM
2377 _L10_6s:
2378
2379 #
2380 #       Result is now in FP0
2381 #
2382         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2383         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2384         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2385         unlk            %a6
2386         rts
2387
2388         global          _fetoxd_
2389 _fetoxd_:
2390         link            %a6,&-LOCAL_SIZE
2391
2392         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2393         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2394         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2395
2396         fmov.l          &0x0,%fpcr              # zero FPCR
2397
2398 #
2399 #       copy, convert, and tag input argument
2400 #
2401         fmov.d          0x8(%a6),%fp0           # load dbl input
2402         fmov.x          %fp0,FP_SRC(%a6)
2403         lea             FP_SRC(%a6),%a0
2404         bsr.l           tag                     # fetch operand type
2405         mov.b           %d0,STAG(%a6)
2406         mov.b           %d0,%d1
2407
2408         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2409
2410         clr.l           %d0
2411         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2412
2413         mov.b           %d1,STAG(%a6)
2414         tst.b           %d1
2415         bne.b           _L10_2d
2416         bsr.l           setox                   # operand is a NORM
2417         bra.b           _L10_6d
2418 _L10_2d:
2419         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2420         bne.b           _L10_3d                 # no
2421         bsr.l           ld_pone                 # yes
2422         bra.b           _L10_6d
2423 _L10_3d:
2424         cmpi.b          %d1,&INF                # is operand an INF?
2425         bne.b           _L10_4d                 # no
2426         bsr.l           szr_inf                 # yes
2427         bra.b           _L10_6d
2428 _L10_4d:
2429         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2430         bne.b           _L10_5d                 # no
2431         bsr.l           src_qnan                        # yes
2432         bra.b           _L10_6d
2433 _L10_5d:
2434         bsr.l           setoxd                  # operand is a DENORM
2435 _L10_6d:
2436
2437 #
2438 #       Result is now in FP0
2439 #
2440         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2441         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2442         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2443         unlk            %a6
2444         rts
2445
2446         global          _fetoxx_
2447 _fetoxx_:
2448         link            %a6,&-LOCAL_SIZE
2449
2450         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2451         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2452         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2453
2454         fmov.l          &0x0,%fpcr              # zero FPCR
2455
2456 #
2457 #       copy, convert, and tag input argument
2458 #
2459         lea             FP_SRC(%a6),%a0
2460         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2461         mov.l           0x8+0x4(%a6),0x4(%a0)
2462         mov.l           0x8+0x8(%a6),0x8(%a0)
2463         bsr.l           tag                     # fetch operand type
2464         mov.b           %d0,STAG(%a6)
2465         mov.b           %d0,%d1
2466
2467         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2468
2469         clr.l           %d0
2470         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2471
2472         tst.b           %d1
2473         bne.b           _L10_2x
2474         bsr.l           setox                   # operand is a NORM
2475         bra.b           _L10_6x
2476 _L10_2x:
2477         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2478         bne.b           _L10_3x                 # no
2479         bsr.l           ld_pone                 # yes
2480         bra.b           _L10_6x
2481 _L10_3x:
2482         cmpi.b          %d1,&INF                # is operand an INF?
2483         bne.b           _L10_4x                 # no
2484         bsr.l           szr_inf                 # yes
2485         bra.b           _L10_6x
2486 _L10_4x:
2487         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2488         bne.b           _L10_5x                 # no
2489         bsr.l           src_qnan                        # yes
2490         bra.b           _L10_6x
2491 _L10_5x:
2492         bsr.l           setoxd                  # operand is a DENORM
2493 _L10_6x:
2494
2495 #
2496 #       Result is now in FP0
2497 #
2498         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2499         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2500         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2501         unlk            %a6
2502         rts
2503
2504
2505 #########################################################################
2506 # MONADIC TEMPLATE                                                      #
2507 #########################################################################
2508         global          _ftwotoxs_
2509 _ftwotoxs_:
2510         link            %a6,&-LOCAL_SIZE
2511
2512         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2513         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2514         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2515
2516         fmov.l          &0x0,%fpcr              # zero FPCR
2517
2518 #
2519 #       copy, convert, and tag input argument
2520 #
2521         fmov.s          0x8(%a6),%fp0           # load sgl input
2522         fmov.x          %fp0,FP_SRC(%a6)
2523         lea             FP_SRC(%a6),%a0
2524         bsr.l           tag                     # fetch operand type
2525         mov.b           %d0,STAG(%a6)
2526         mov.b           %d0,%d1
2527
2528         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2529
2530         clr.l           %d0
2531         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2532
2533         tst.b           %d1
2534         bne.b           _L11_2s
2535         bsr.l           stwotox                 # operand is a NORM
2536         bra.b           _L11_6s
2537 _L11_2s:
2538         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2539         bne.b           _L11_3s                 # no
2540         bsr.l           ld_pone                 # yes
2541         bra.b           _L11_6s
2542 _L11_3s:
2543         cmpi.b          %d1,&INF                # is operand an INF?
2544         bne.b           _L11_4s                 # no
2545         bsr.l           szr_inf                 # yes
2546         bra.b           _L11_6s
2547 _L11_4s:
2548         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2549         bne.b           _L11_5s                 # no
2550         bsr.l           src_qnan                        # yes
2551         bra.b           _L11_6s
2552 _L11_5s:
2553         bsr.l           stwotoxd                        # operand is a DENORM
2554 _L11_6s:
2555
2556 #
2557 #       Result is now in FP0
2558 #
2559         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2560         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2561         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2562         unlk            %a6
2563         rts
2564
2565         global          _ftwotoxd_
2566 _ftwotoxd_:
2567         link            %a6,&-LOCAL_SIZE
2568
2569         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2570         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2571         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2572
2573         fmov.l          &0x0,%fpcr              # zero FPCR
2574
2575 #
2576 #       copy, convert, and tag input argument
2577 #
2578         fmov.d          0x8(%a6),%fp0           # load dbl input
2579         fmov.x          %fp0,FP_SRC(%a6)
2580         lea             FP_SRC(%a6),%a0
2581         bsr.l           tag                     # fetch operand type
2582         mov.b           %d0,STAG(%a6)
2583         mov.b           %d0,%d1
2584
2585         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2586
2587         clr.l           %d0
2588         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2589
2590         mov.b           %d1,STAG(%a6)
2591         tst.b           %d1
2592         bne.b           _L11_2d
2593         bsr.l           stwotox                 # operand is a NORM
2594         bra.b           _L11_6d
2595 _L11_2d:
2596         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2597         bne.b           _L11_3d                 # no
2598         bsr.l           ld_pone                 # yes
2599         bra.b           _L11_6d
2600 _L11_3d:
2601         cmpi.b          %d1,&INF                # is operand an INF?
2602         bne.b           _L11_4d                 # no
2603         bsr.l           szr_inf                 # yes
2604         bra.b           _L11_6d
2605 _L11_4d:
2606         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2607         bne.b           _L11_5d                 # no
2608         bsr.l           src_qnan                        # yes
2609         bra.b           _L11_6d
2610 _L11_5d:
2611         bsr.l           stwotoxd                        # operand is a DENORM
2612 _L11_6d:
2613
2614 #
2615 #       Result is now in FP0
2616 #
2617         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2618         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2619         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2620         unlk            %a6
2621         rts
2622
2623         global          _ftwotoxx_
2624 _ftwotoxx_:
2625         link            %a6,&-LOCAL_SIZE
2626
2627         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2628         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2629         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2630
2631         fmov.l          &0x0,%fpcr              # zero FPCR
2632
2633 #
2634 #       copy, convert, and tag input argument
2635 #
2636         lea             FP_SRC(%a6),%a0
2637         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2638         mov.l           0x8+0x4(%a6),0x4(%a0)
2639         mov.l           0x8+0x8(%a6),0x8(%a0)
2640         bsr.l           tag                     # fetch operand type
2641         mov.b           %d0,STAG(%a6)
2642         mov.b           %d0,%d1
2643
2644         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2645
2646         clr.l           %d0
2647         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2648
2649         tst.b           %d1
2650         bne.b           _L11_2x
2651         bsr.l           stwotox                 # operand is a NORM
2652         bra.b           _L11_6x
2653 _L11_2x:
2654         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2655         bne.b           _L11_3x                 # no
2656         bsr.l           ld_pone                 # yes
2657         bra.b           _L11_6x
2658 _L11_3x:
2659         cmpi.b          %d1,&INF                # is operand an INF?
2660         bne.b           _L11_4x                 # no
2661         bsr.l           szr_inf                 # yes
2662         bra.b           _L11_6x
2663 _L11_4x:
2664         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2665         bne.b           _L11_5x                 # no
2666         bsr.l           src_qnan                        # yes
2667         bra.b           _L11_6x
2668 _L11_5x:
2669         bsr.l           stwotoxd                        # operand is a DENORM
2670 _L11_6x:
2671
2672 #
2673 #       Result is now in FP0
2674 #
2675         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2676         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2677         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2678         unlk            %a6
2679         rts
2680
2681
2682 #########################################################################
2683 # MONADIC TEMPLATE                                                      #
2684 #########################################################################
2685         global          _ftentoxs_
2686 _ftentoxs_:
2687         link            %a6,&-LOCAL_SIZE
2688
2689         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2690         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2691         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2692
2693         fmov.l          &0x0,%fpcr              # zero FPCR
2694
2695 #
2696 #       copy, convert, and tag input argument
2697 #
2698         fmov.s          0x8(%a6),%fp0           # load sgl input
2699         fmov.x          %fp0,FP_SRC(%a6)
2700         lea             FP_SRC(%a6),%a0
2701         bsr.l           tag                     # fetch operand type
2702         mov.b           %d0,STAG(%a6)
2703         mov.b           %d0,%d1
2704
2705         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2706
2707         clr.l           %d0
2708         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2709
2710         tst.b           %d1
2711         bne.b           _L12_2s
2712         bsr.l           stentox                 # operand is a NORM
2713         bra.b           _L12_6s
2714 _L12_2s:
2715         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2716         bne.b           _L12_3s                 # no
2717         bsr.l           ld_pone                 # yes
2718         bra.b           _L12_6s
2719 _L12_3s:
2720         cmpi.b          %d1,&INF                # is operand an INF?
2721         bne.b           _L12_4s                 # no
2722         bsr.l           szr_inf                 # yes
2723         bra.b           _L12_6s
2724 _L12_4s:
2725         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2726         bne.b           _L12_5s                 # no
2727         bsr.l           src_qnan                        # yes
2728         bra.b           _L12_6s
2729 _L12_5s:
2730         bsr.l           stentoxd                        # operand is a DENORM
2731 _L12_6s:
2732
2733 #
2734 #       Result is now in FP0
2735 #
2736         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2737         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2738         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2739         unlk            %a6
2740         rts
2741
2742         global          _ftentoxd_
2743 _ftentoxd_:
2744         link            %a6,&-LOCAL_SIZE
2745
2746         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2747         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2748         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2749
2750         fmov.l          &0x0,%fpcr              # zero FPCR
2751
2752 #
2753 #       copy, convert, and tag input argument
2754 #
2755         fmov.d          0x8(%a6),%fp0           # load dbl input
2756         fmov.x          %fp0,FP_SRC(%a6)
2757         lea             FP_SRC(%a6),%a0
2758         bsr.l           tag                     # fetch operand type
2759         mov.b           %d0,STAG(%a6)
2760         mov.b           %d0,%d1
2761
2762         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2763
2764         clr.l           %d0
2765         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2766
2767         mov.b           %d1,STAG(%a6)
2768         tst.b           %d1
2769         bne.b           _L12_2d
2770         bsr.l           stentox                 # operand is a NORM
2771         bra.b           _L12_6d
2772 _L12_2d:
2773         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2774         bne.b           _L12_3d                 # no
2775         bsr.l           ld_pone                 # yes
2776         bra.b           _L12_6d
2777 _L12_3d:
2778         cmpi.b          %d1,&INF                # is operand an INF?
2779         bne.b           _L12_4d                 # no
2780         bsr.l           szr_inf                 # yes
2781         bra.b           _L12_6d
2782 _L12_4d:
2783         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2784         bne.b           _L12_5d                 # no
2785         bsr.l           src_qnan                        # yes
2786         bra.b           _L12_6d
2787 _L12_5d:
2788         bsr.l           stentoxd                        # operand is a DENORM
2789 _L12_6d:
2790
2791 #
2792 #       Result is now in FP0
2793 #
2794         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2795         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2796         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2797         unlk            %a6
2798         rts
2799
2800         global          _ftentoxx_
2801 _ftentoxx_:
2802         link            %a6,&-LOCAL_SIZE
2803
2804         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2805         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2806         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2807
2808         fmov.l          &0x0,%fpcr              # zero FPCR
2809
2810 #
2811 #       copy, convert, and tag input argument
2812 #
2813         lea             FP_SRC(%a6),%a0
2814         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2815         mov.l           0x8+0x4(%a6),0x4(%a0)
2816         mov.l           0x8+0x8(%a6),0x8(%a0)
2817         bsr.l           tag                     # fetch operand type
2818         mov.b           %d0,STAG(%a6)
2819         mov.b           %d0,%d1
2820
2821         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2822
2823         clr.l           %d0
2824         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2825
2826         tst.b           %d1
2827         bne.b           _L12_2x
2828         bsr.l           stentox                 # operand is a NORM
2829         bra.b           _L12_6x
2830 _L12_2x:
2831         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2832         bne.b           _L12_3x                 # no
2833         bsr.l           ld_pone                 # yes
2834         bra.b           _L12_6x
2835 _L12_3x:
2836         cmpi.b          %d1,&INF                # is operand an INF?
2837         bne.b           _L12_4x                 # no
2838         bsr.l           szr_inf                 # yes
2839         bra.b           _L12_6x
2840 _L12_4x:
2841         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2842         bne.b           _L12_5x                 # no
2843         bsr.l           src_qnan                        # yes
2844         bra.b           _L12_6x
2845 _L12_5x:
2846         bsr.l           stentoxd                        # operand is a DENORM
2847 _L12_6x:
2848
2849 #
2850 #       Result is now in FP0
2851 #
2852         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2853         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2854         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2855         unlk            %a6
2856         rts
2857
2858
2859 #########################################################################
2860 # MONADIC TEMPLATE                                                      #
2861 #########################################################################
2862         global          _flogns_
2863 _flogns_:
2864         link            %a6,&-LOCAL_SIZE
2865
2866         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2867         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2868         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2869
2870         fmov.l          &0x0,%fpcr              # zero FPCR
2871
2872 #
2873 #       copy, convert, and tag input argument
2874 #
2875         fmov.s          0x8(%a6),%fp0           # load sgl input
2876         fmov.x          %fp0,FP_SRC(%a6)
2877         lea             FP_SRC(%a6),%a0
2878         bsr.l           tag                     # fetch operand type
2879         mov.b           %d0,STAG(%a6)
2880         mov.b           %d0,%d1
2881
2882         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2883
2884         clr.l           %d0
2885         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2886
2887         tst.b           %d1
2888         bne.b           _L13_2s
2889         bsr.l           slogn                   # operand is a NORM
2890         bra.b           _L13_6s
2891 _L13_2s:
2892         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2893         bne.b           _L13_3s                 # no
2894         bsr.l           t_dz2                   # yes
2895         bra.b           _L13_6s
2896 _L13_3s:
2897         cmpi.b          %d1,&INF                # is operand an INF?
2898         bne.b           _L13_4s                 # no
2899         bsr.l           sopr_inf                        # yes
2900         bra.b           _L13_6s
2901 _L13_4s:
2902         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2903         bne.b           _L13_5s                 # no
2904         bsr.l           src_qnan                        # yes
2905         bra.b           _L13_6s
2906 _L13_5s:
2907         bsr.l           slognd                  # operand is a DENORM
2908 _L13_6s:
2909
2910 #
2911 #       Result is now in FP0
2912 #
2913         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2914         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2915         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2916         unlk            %a6
2917         rts
2918
2919         global          _flognd_
2920 _flognd_:
2921         link            %a6,&-LOCAL_SIZE
2922
2923         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2924         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2925         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2926
2927         fmov.l          &0x0,%fpcr              # zero FPCR
2928
2929 #
2930 #       copy, convert, and tag input argument
2931 #
2932         fmov.d          0x8(%a6),%fp0           # load dbl input
2933         fmov.x          %fp0,FP_SRC(%a6)
2934         lea             FP_SRC(%a6),%a0
2935         bsr.l           tag                     # fetch operand type
2936         mov.b           %d0,STAG(%a6)
2937         mov.b           %d0,%d1
2938
2939         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2940
2941         clr.l           %d0
2942         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
2943
2944         mov.b           %d1,STAG(%a6)
2945         tst.b           %d1
2946         bne.b           _L13_2d
2947         bsr.l           slogn                   # operand is a NORM
2948         bra.b           _L13_6d
2949 _L13_2d:
2950         cmpi.b          %d1,&ZERO               # is operand a ZERO?
2951         bne.b           _L13_3d                 # no
2952         bsr.l           t_dz2                   # yes
2953         bra.b           _L13_6d
2954 _L13_3d:
2955         cmpi.b          %d1,&INF                # is operand an INF?
2956         bne.b           _L13_4d                 # no
2957         bsr.l           sopr_inf                        # yes
2958         bra.b           _L13_6d
2959 _L13_4d:
2960         cmpi.b          %d1,&QNAN               # is operand a QNAN?
2961         bne.b           _L13_5d                 # no
2962         bsr.l           src_qnan                        # yes
2963         bra.b           _L13_6d
2964 _L13_5d:
2965         bsr.l           slognd                  # operand is a DENORM
2966 _L13_6d:
2967
2968 #
2969 #       Result is now in FP0
2970 #
2971         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
2972         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2973         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
2974         unlk            %a6
2975         rts
2976
2977         global          _flognx_
2978 _flognx_:
2979         link            %a6,&-LOCAL_SIZE
2980
2981         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
2982         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2983         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
2984
2985         fmov.l          &0x0,%fpcr              # zero FPCR
2986
2987 #
2988 #       copy, convert, and tag input argument
2989 #
2990         lea             FP_SRC(%a6),%a0
2991         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
2992         mov.l           0x8+0x4(%a6),0x4(%a0)
2993         mov.l           0x8+0x8(%a6),0x8(%a0)
2994         bsr.l           tag                     # fetch operand type
2995         mov.b           %d0,STAG(%a6)
2996         mov.b           %d0,%d1
2997
2998         andi.l          &0x00ff00ff,USER_FPSR(%a6)
2999
3000         clr.l           %d0
3001         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3002
3003         tst.b           %d1
3004         bne.b           _L13_2x
3005         bsr.l           slogn                   # operand is a NORM
3006         bra.b           _L13_6x
3007 _L13_2x:
3008         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3009         bne.b           _L13_3x                 # no
3010         bsr.l           t_dz2                   # yes
3011         bra.b           _L13_6x
3012 _L13_3x:
3013         cmpi.b          %d1,&INF                # is operand an INF?
3014         bne.b           _L13_4x                 # no
3015         bsr.l           sopr_inf                        # yes
3016         bra.b           _L13_6x
3017 _L13_4x:
3018         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3019         bne.b           _L13_5x                 # no
3020         bsr.l           src_qnan                        # yes
3021         bra.b           _L13_6x
3022 _L13_5x:
3023         bsr.l           slognd                  # operand is a DENORM
3024 _L13_6x:
3025
3026 #
3027 #       Result is now in FP0
3028 #
3029         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3030         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3031         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3032         unlk            %a6
3033         rts
3034
3035
3036 #########################################################################
3037 # MONADIC TEMPLATE                                                      #
3038 #########################################################################
3039         global          _flog10s_
3040 _flog10s_:
3041         link            %a6,&-LOCAL_SIZE
3042
3043         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3044         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3045         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3046
3047         fmov.l          &0x0,%fpcr              # zero FPCR
3048
3049 #
3050 #       copy, convert, and tag input argument
3051 #
3052         fmov.s          0x8(%a6),%fp0           # load sgl input
3053         fmov.x          %fp0,FP_SRC(%a6)
3054         lea             FP_SRC(%a6),%a0
3055         bsr.l           tag                     # fetch operand type
3056         mov.b           %d0,STAG(%a6)
3057         mov.b           %d0,%d1
3058
3059         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3060
3061         clr.l           %d0
3062         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3063
3064         tst.b           %d1
3065         bne.b           _L14_2s
3066         bsr.l           slog10                  # operand is a NORM
3067         bra.b           _L14_6s
3068 _L14_2s:
3069         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3070         bne.b           _L14_3s                 # no
3071         bsr.l           t_dz2                   # yes
3072         bra.b           _L14_6s
3073 _L14_3s:
3074         cmpi.b          %d1,&INF                # is operand an INF?
3075         bne.b           _L14_4s                 # no
3076         bsr.l           sopr_inf                        # yes
3077         bra.b           _L14_6s
3078 _L14_4s:
3079         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3080         bne.b           _L14_5s                 # no
3081         bsr.l           src_qnan                        # yes
3082         bra.b           _L14_6s
3083 _L14_5s:
3084         bsr.l           slog10d                 # operand is a DENORM
3085 _L14_6s:
3086
3087 #
3088 #       Result is now in FP0
3089 #
3090         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3091         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3092         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3093         unlk            %a6
3094         rts
3095
3096         global          _flog10d_
3097 _flog10d_:
3098         link            %a6,&-LOCAL_SIZE
3099
3100         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3101         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3102         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3103
3104         fmov.l          &0x0,%fpcr              # zero FPCR
3105
3106 #
3107 #       copy, convert, and tag input argument
3108 #
3109         fmov.d          0x8(%a6),%fp0           # load dbl input
3110         fmov.x          %fp0,FP_SRC(%a6)
3111         lea             FP_SRC(%a6),%a0
3112         bsr.l           tag                     # fetch operand type
3113         mov.b           %d0,STAG(%a6)
3114         mov.b           %d0,%d1
3115
3116         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3117
3118         clr.l           %d0
3119         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3120
3121         mov.b           %d1,STAG(%a6)
3122         tst.b           %d1
3123         bne.b           _L14_2d
3124         bsr.l           slog10                  # operand is a NORM
3125         bra.b           _L14_6d
3126 _L14_2d:
3127         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3128         bne.b           _L14_3d                 # no
3129         bsr.l           t_dz2                   # yes
3130         bra.b           _L14_6d
3131 _L14_3d:
3132         cmpi.b          %d1,&INF                # is operand an INF?
3133         bne.b           _L14_4d                 # no
3134         bsr.l           sopr_inf                        # yes
3135         bra.b           _L14_6d
3136 _L14_4d:
3137         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3138         bne.b           _L14_5d                 # no
3139         bsr.l           src_qnan                        # yes
3140         bra.b           _L14_6d
3141 _L14_5d:
3142         bsr.l           slog10d                 # operand is a DENORM
3143 _L14_6d:
3144
3145 #
3146 #       Result is now in FP0
3147 #
3148         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3149         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3150         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3151         unlk            %a6
3152         rts
3153
3154         global          _flog10x_
3155 _flog10x_:
3156         link            %a6,&-LOCAL_SIZE
3157
3158         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3159         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3160         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3161
3162         fmov.l          &0x0,%fpcr              # zero FPCR
3163
3164 #
3165 #       copy, convert, and tag input argument
3166 #
3167         lea             FP_SRC(%a6),%a0
3168         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3169         mov.l           0x8+0x4(%a6),0x4(%a0)
3170         mov.l           0x8+0x8(%a6),0x8(%a0)
3171         bsr.l           tag                     # fetch operand type
3172         mov.b           %d0,STAG(%a6)
3173         mov.b           %d0,%d1
3174
3175         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3176
3177         clr.l           %d0
3178         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3179
3180         tst.b           %d1
3181         bne.b           _L14_2x
3182         bsr.l           slog10                  # operand is a NORM
3183         bra.b           _L14_6x
3184 _L14_2x:
3185         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3186         bne.b           _L14_3x                 # no
3187         bsr.l           t_dz2                   # yes
3188         bra.b           _L14_6x
3189 _L14_3x:
3190         cmpi.b          %d1,&INF                # is operand an INF?
3191         bne.b           _L14_4x                 # no
3192         bsr.l           sopr_inf                        # yes
3193         bra.b           _L14_6x
3194 _L14_4x:
3195         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3196         bne.b           _L14_5x                 # no
3197         bsr.l           src_qnan                        # yes
3198         bra.b           _L14_6x
3199 _L14_5x:
3200         bsr.l           slog10d                 # operand is a DENORM
3201 _L14_6x:
3202
3203 #
3204 #       Result is now in FP0
3205 #
3206         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3207         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3208         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3209         unlk            %a6
3210         rts
3211
3212
3213 #########################################################################
3214 # MONADIC TEMPLATE                                                      #
3215 #########################################################################
3216         global          _flog2s_
3217 _flog2s_:
3218         link            %a6,&-LOCAL_SIZE
3219
3220         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3221         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3222         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3223
3224         fmov.l          &0x0,%fpcr              # zero FPCR
3225
3226 #
3227 #       copy, convert, and tag input argument
3228 #
3229         fmov.s          0x8(%a6),%fp0           # load sgl input
3230         fmov.x          %fp0,FP_SRC(%a6)
3231         lea             FP_SRC(%a6),%a0
3232         bsr.l           tag                     # fetch operand type
3233         mov.b           %d0,STAG(%a6)
3234         mov.b           %d0,%d1
3235
3236         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3237
3238         clr.l           %d0
3239         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3240
3241         tst.b           %d1
3242         bne.b           _L15_2s
3243         bsr.l           slog2                   # operand is a NORM
3244         bra.b           _L15_6s
3245 _L15_2s:
3246         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3247         bne.b           _L15_3s                 # no
3248         bsr.l           t_dz2                   # yes
3249         bra.b           _L15_6s
3250 _L15_3s:
3251         cmpi.b          %d1,&INF                # is operand an INF?
3252         bne.b           _L15_4s                 # no
3253         bsr.l           sopr_inf                        # yes
3254         bra.b           _L15_6s
3255 _L15_4s:
3256         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3257         bne.b           _L15_5s                 # no
3258         bsr.l           src_qnan                        # yes
3259         bra.b           _L15_6s
3260 _L15_5s:
3261         bsr.l           slog2d                  # operand is a DENORM
3262 _L15_6s:
3263
3264 #
3265 #       Result is now in FP0
3266 #
3267         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3268         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3269         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3270         unlk            %a6
3271         rts
3272
3273         global          _flog2d_
3274 _flog2d_:
3275         link            %a6,&-LOCAL_SIZE
3276
3277         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3278         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3279         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3280
3281         fmov.l          &0x0,%fpcr              # zero FPCR
3282
3283 #
3284 #       copy, convert, and tag input argument
3285 #
3286         fmov.d          0x8(%a6),%fp0           # load dbl input
3287         fmov.x          %fp0,FP_SRC(%a6)
3288         lea             FP_SRC(%a6),%a0
3289         bsr.l           tag                     # fetch operand type
3290         mov.b           %d0,STAG(%a6)
3291         mov.b           %d0,%d1
3292
3293         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3294
3295         clr.l           %d0
3296         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3297
3298         mov.b           %d1,STAG(%a6)
3299         tst.b           %d1
3300         bne.b           _L15_2d
3301         bsr.l           slog2                   # operand is a NORM
3302         bra.b           _L15_6d
3303 _L15_2d:
3304         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3305         bne.b           _L15_3d                 # no
3306         bsr.l           t_dz2                   # yes
3307         bra.b           _L15_6d
3308 _L15_3d:
3309         cmpi.b          %d1,&INF                # is operand an INF?
3310         bne.b           _L15_4d                 # no
3311         bsr.l           sopr_inf                        # yes
3312         bra.b           _L15_6d
3313 _L15_4d:
3314         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3315         bne.b           _L15_5d                 # no
3316         bsr.l           src_qnan                        # yes
3317         bra.b           _L15_6d
3318 _L15_5d:
3319         bsr.l           slog2d                  # operand is a DENORM
3320 _L15_6d:
3321
3322 #
3323 #       Result is now in FP0
3324 #
3325         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3326         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3327         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3328         unlk            %a6
3329         rts
3330
3331         global          _flog2x_
3332 _flog2x_:
3333         link            %a6,&-LOCAL_SIZE
3334
3335         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3336         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3337         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3338
3339         fmov.l          &0x0,%fpcr              # zero FPCR
3340
3341 #
3342 #       copy, convert, and tag input argument
3343 #
3344         lea             FP_SRC(%a6),%a0
3345         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3346         mov.l           0x8+0x4(%a6),0x4(%a0)
3347         mov.l           0x8+0x8(%a6),0x8(%a0)
3348         bsr.l           tag                     # fetch operand type
3349         mov.b           %d0,STAG(%a6)
3350         mov.b           %d0,%d1
3351
3352         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3353
3354         clr.l           %d0
3355         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3356
3357         tst.b           %d1
3358         bne.b           _L15_2x
3359         bsr.l           slog2                   # operand is a NORM
3360         bra.b           _L15_6x
3361 _L15_2x:
3362         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3363         bne.b           _L15_3x                 # no
3364         bsr.l           t_dz2                   # yes
3365         bra.b           _L15_6x
3366 _L15_3x:
3367         cmpi.b          %d1,&INF                # is operand an INF?
3368         bne.b           _L15_4x                 # no
3369         bsr.l           sopr_inf                        # yes
3370         bra.b           _L15_6x
3371 _L15_4x:
3372         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3373         bne.b           _L15_5x                 # no
3374         bsr.l           src_qnan                        # yes
3375         bra.b           _L15_6x
3376 _L15_5x:
3377         bsr.l           slog2d                  # operand is a DENORM
3378 _L15_6x:
3379
3380 #
3381 #       Result is now in FP0
3382 #
3383         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3384         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3385         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3386         unlk            %a6
3387         rts
3388
3389
3390 #########################################################################
3391 # MONADIC TEMPLATE                                                      #
3392 #########################################################################
3393         global          _fcoshs_
3394 _fcoshs_:
3395         link            %a6,&-LOCAL_SIZE
3396
3397         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3398         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3399         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3400
3401         fmov.l          &0x0,%fpcr              # zero FPCR
3402
3403 #
3404 #       copy, convert, and tag input argument
3405 #
3406         fmov.s          0x8(%a6),%fp0           # load sgl input
3407         fmov.x          %fp0,FP_SRC(%a6)
3408         lea             FP_SRC(%a6),%a0
3409         bsr.l           tag                     # fetch operand type
3410         mov.b           %d0,STAG(%a6)
3411         mov.b           %d0,%d1
3412
3413         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3414
3415         clr.l           %d0
3416         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3417
3418         tst.b           %d1
3419         bne.b           _L16_2s
3420         bsr.l           scosh                   # operand is a NORM
3421         bra.b           _L16_6s
3422 _L16_2s:
3423         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3424         bne.b           _L16_3s                 # no
3425         bsr.l           ld_pone                 # yes
3426         bra.b           _L16_6s
3427 _L16_3s:
3428         cmpi.b          %d1,&INF                # is operand an INF?
3429         bne.b           _L16_4s                 # no
3430         bsr.l           ld_pinf                 # yes
3431         bra.b           _L16_6s
3432 _L16_4s:
3433         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3434         bne.b           _L16_5s                 # no
3435         bsr.l           src_qnan                        # yes
3436         bra.b           _L16_6s
3437 _L16_5s:
3438         bsr.l           scoshd                  # operand is a DENORM
3439 _L16_6s:
3440
3441 #
3442 #       Result is now in FP0
3443 #
3444         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3445         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3446         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3447         unlk            %a6
3448         rts
3449
3450         global          _fcoshd_
3451 _fcoshd_:
3452         link            %a6,&-LOCAL_SIZE
3453
3454         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3455         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3456         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3457
3458         fmov.l          &0x0,%fpcr              # zero FPCR
3459
3460 #
3461 #       copy, convert, and tag input argument
3462 #
3463         fmov.d          0x8(%a6),%fp0           # load dbl input
3464         fmov.x          %fp0,FP_SRC(%a6)
3465         lea             FP_SRC(%a6),%a0
3466         bsr.l           tag                     # fetch operand type
3467         mov.b           %d0,STAG(%a6)
3468         mov.b           %d0,%d1
3469
3470         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3471
3472         clr.l           %d0
3473         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3474
3475         mov.b           %d1,STAG(%a6)
3476         tst.b           %d1
3477         bne.b           _L16_2d
3478         bsr.l           scosh                   # operand is a NORM
3479         bra.b           _L16_6d
3480 _L16_2d:
3481         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3482         bne.b           _L16_3d                 # no
3483         bsr.l           ld_pone                 # yes
3484         bra.b           _L16_6d
3485 _L16_3d:
3486         cmpi.b          %d1,&INF                # is operand an INF?
3487         bne.b           _L16_4d                 # no
3488         bsr.l           ld_pinf                 # yes
3489         bra.b           _L16_6d
3490 _L16_4d:
3491         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3492         bne.b           _L16_5d                 # no
3493         bsr.l           src_qnan                        # yes
3494         bra.b           _L16_6d
3495 _L16_5d:
3496         bsr.l           scoshd                  # operand is a DENORM
3497 _L16_6d:
3498
3499 #
3500 #       Result is now in FP0
3501 #
3502         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3503         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3504         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3505         unlk            %a6
3506         rts
3507
3508         global          _fcoshx_
3509 _fcoshx_:
3510         link            %a6,&-LOCAL_SIZE
3511
3512         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3513         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3514         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3515
3516         fmov.l          &0x0,%fpcr              # zero FPCR
3517
3518 #
3519 #       copy, convert, and tag input argument
3520 #
3521         lea             FP_SRC(%a6),%a0
3522         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3523         mov.l           0x8+0x4(%a6),0x4(%a0)
3524         mov.l           0x8+0x8(%a6),0x8(%a0)
3525         bsr.l           tag                     # fetch operand type
3526         mov.b           %d0,STAG(%a6)
3527         mov.b           %d0,%d1
3528
3529         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3530
3531         clr.l           %d0
3532         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3533
3534         tst.b           %d1
3535         bne.b           _L16_2x
3536         bsr.l           scosh                   # operand is a NORM
3537         bra.b           _L16_6x
3538 _L16_2x:
3539         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3540         bne.b           _L16_3x                 # no
3541         bsr.l           ld_pone                 # yes
3542         bra.b           _L16_6x
3543 _L16_3x:
3544         cmpi.b          %d1,&INF                # is operand an INF?
3545         bne.b           _L16_4x                 # no
3546         bsr.l           ld_pinf                 # yes
3547         bra.b           _L16_6x
3548 _L16_4x:
3549         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3550         bne.b           _L16_5x                 # no
3551         bsr.l           src_qnan                        # yes
3552         bra.b           _L16_6x
3553 _L16_5x:
3554         bsr.l           scoshd                  # operand is a DENORM
3555 _L16_6x:
3556
3557 #
3558 #       Result is now in FP0
3559 #
3560         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3561         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3562         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3563         unlk            %a6
3564         rts
3565
3566
3567 #########################################################################
3568 # MONADIC TEMPLATE                                                      #
3569 #########################################################################
3570         global          _facoss_
3571 _facoss_:
3572         link            %a6,&-LOCAL_SIZE
3573
3574         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3575         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3576         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3577
3578         fmov.l          &0x0,%fpcr              # zero FPCR
3579
3580 #
3581 #       copy, convert, and tag input argument
3582 #
3583         fmov.s          0x8(%a6),%fp0           # load sgl input
3584         fmov.x          %fp0,FP_SRC(%a6)
3585         lea             FP_SRC(%a6),%a0
3586         bsr.l           tag                     # fetch operand type
3587         mov.b           %d0,STAG(%a6)
3588         mov.b           %d0,%d1
3589
3590         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3591
3592         clr.l           %d0
3593         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3594
3595         tst.b           %d1
3596         bne.b           _L17_2s
3597         bsr.l           sacos                   # operand is a NORM
3598         bra.b           _L17_6s
3599 _L17_2s:
3600         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3601         bne.b           _L17_3s                 # no
3602         bsr.l           ld_ppi2                 # yes
3603         bra.b           _L17_6s
3604 _L17_3s:
3605         cmpi.b          %d1,&INF                # is operand an INF?
3606         bne.b           _L17_4s                 # no
3607         bsr.l           t_operr                 # yes
3608         bra.b           _L17_6s
3609 _L17_4s:
3610         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3611         bne.b           _L17_5s                 # no
3612         bsr.l           src_qnan                        # yes
3613         bra.b           _L17_6s
3614 _L17_5s:
3615         bsr.l           sacosd                  # operand is a DENORM
3616 _L17_6s:
3617
3618 #
3619 #       Result is now in FP0
3620 #
3621         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3622         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3623         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3624         unlk            %a6
3625         rts
3626
3627         global          _facosd_
3628 _facosd_:
3629         link            %a6,&-LOCAL_SIZE
3630
3631         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3632         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3633         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3634
3635         fmov.l          &0x0,%fpcr              # zero FPCR
3636
3637 #
3638 #       copy, convert, and tag input argument
3639 #
3640         fmov.d          0x8(%a6),%fp0           # load dbl input
3641         fmov.x          %fp0,FP_SRC(%a6)
3642         lea             FP_SRC(%a6),%a0
3643         bsr.l           tag                     # fetch operand type
3644         mov.b           %d0,STAG(%a6)
3645         mov.b           %d0,%d1
3646
3647         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3648
3649         clr.l           %d0
3650         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3651
3652         mov.b           %d1,STAG(%a6)
3653         tst.b           %d1
3654         bne.b           _L17_2d
3655         bsr.l           sacos                   # operand is a NORM
3656         bra.b           _L17_6d
3657 _L17_2d:
3658         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3659         bne.b           _L17_3d                 # no
3660         bsr.l           ld_ppi2                 # yes
3661         bra.b           _L17_6d
3662 _L17_3d:
3663         cmpi.b          %d1,&INF                # is operand an INF?
3664         bne.b           _L17_4d                 # no
3665         bsr.l           t_operr                 # yes
3666         bra.b           _L17_6d
3667 _L17_4d:
3668         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3669         bne.b           _L17_5d                 # no
3670         bsr.l           src_qnan                        # yes
3671         bra.b           _L17_6d
3672 _L17_5d:
3673         bsr.l           sacosd                  # operand is a DENORM
3674 _L17_6d:
3675
3676 #
3677 #       Result is now in FP0
3678 #
3679         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3680         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3681         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3682         unlk            %a6
3683         rts
3684
3685         global          _facosx_
3686 _facosx_:
3687         link            %a6,&-LOCAL_SIZE
3688
3689         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3690         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3691         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3692
3693         fmov.l          &0x0,%fpcr              # zero FPCR
3694
3695 #
3696 #       copy, convert, and tag input argument
3697 #
3698         lea             FP_SRC(%a6),%a0
3699         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3700         mov.l           0x8+0x4(%a6),0x4(%a0)
3701         mov.l           0x8+0x8(%a6),0x8(%a0)
3702         bsr.l           tag                     # fetch operand type
3703         mov.b           %d0,STAG(%a6)
3704         mov.b           %d0,%d1
3705
3706         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3707
3708         clr.l           %d0
3709         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3710
3711         tst.b           %d1
3712         bne.b           _L17_2x
3713         bsr.l           sacos                   # operand is a NORM
3714         bra.b           _L17_6x
3715 _L17_2x:
3716         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3717         bne.b           _L17_3x                 # no
3718         bsr.l           ld_ppi2                 # yes
3719         bra.b           _L17_6x
3720 _L17_3x:
3721         cmpi.b          %d1,&INF                # is operand an INF?
3722         bne.b           _L17_4x                 # no
3723         bsr.l           t_operr                 # yes
3724         bra.b           _L17_6x
3725 _L17_4x:
3726         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3727         bne.b           _L17_5x                 # no
3728         bsr.l           src_qnan                        # yes
3729         bra.b           _L17_6x
3730 _L17_5x:
3731         bsr.l           sacosd                  # operand is a DENORM
3732 _L17_6x:
3733
3734 #
3735 #       Result is now in FP0
3736 #
3737         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3738         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3739         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3740         unlk            %a6
3741         rts
3742
3743
3744 #########################################################################
3745 # MONADIC TEMPLATE                                                      #
3746 #########################################################################
3747         global          _fgetexps_
3748 _fgetexps_:
3749         link            %a6,&-LOCAL_SIZE
3750
3751         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3752         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3753         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3754
3755         fmov.l          &0x0,%fpcr              # zero FPCR
3756
3757 #
3758 #       copy, convert, and tag input argument
3759 #
3760         fmov.s          0x8(%a6),%fp0           # load sgl input
3761         fmov.x          %fp0,FP_SRC(%a6)
3762         lea             FP_SRC(%a6),%a0
3763         bsr.l           tag                     # fetch operand type
3764         mov.b           %d0,STAG(%a6)
3765         mov.b           %d0,%d1
3766
3767         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3768
3769         clr.l           %d0
3770         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3771
3772         tst.b           %d1
3773         bne.b           _L18_2s
3774         bsr.l           sgetexp                 # operand is a NORM
3775         bra.b           _L18_6s
3776 _L18_2s:
3777         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3778         bne.b           _L18_3s                 # no
3779         bsr.l           src_zero                        # yes
3780         bra.b           _L18_6s
3781 _L18_3s:
3782         cmpi.b          %d1,&INF                # is operand an INF?
3783         bne.b           _L18_4s                 # no
3784         bsr.l           t_operr                 # yes
3785         bra.b           _L18_6s
3786 _L18_4s:
3787         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3788         bne.b           _L18_5s                 # no
3789         bsr.l           src_qnan                        # yes
3790         bra.b           _L18_6s
3791 _L18_5s:
3792         bsr.l           sgetexpd                        # operand is a DENORM
3793 _L18_6s:
3794
3795 #
3796 #       Result is now in FP0
3797 #
3798         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3799         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3800         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3801         unlk            %a6
3802         rts
3803
3804         global          _fgetexpd_
3805 _fgetexpd_:
3806         link            %a6,&-LOCAL_SIZE
3807
3808         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3809         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3810         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3811
3812         fmov.l          &0x0,%fpcr              # zero FPCR
3813
3814 #
3815 #       copy, convert, and tag input argument
3816 #
3817         fmov.d          0x8(%a6),%fp0           # load dbl input
3818         fmov.x          %fp0,FP_SRC(%a6)
3819         lea             FP_SRC(%a6),%a0
3820         bsr.l           tag                     # fetch operand type
3821         mov.b           %d0,STAG(%a6)
3822         mov.b           %d0,%d1
3823
3824         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3825
3826         clr.l           %d0
3827         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3828
3829         mov.b           %d1,STAG(%a6)
3830         tst.b           %d1
3831         bne.b           _L18_2d
3832         bsr.l           sgetexp                 # operand is a NORM
3833         bra.b           _L18_6d
3834 _L18_2d:
3835         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3836         bne.b           _L18_3d                 # no
3837         bsr.l           src_zero                        # yes
3838         bra.b           _L18_6d
3839 _L18_3d:
3840         cmpi.b          %d1,&INF                # is operand an INF?
3841         bne.b           _L18_4d                 # no
3842         bsr.l           t_operr                 # yes
3843         bra.b           _L18_6d
3844 _L18_4d:
3845         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3846         bne.b           _L18_5d                 # no
3847         bsr.l           src_qnan                        # yes
3848         bra.b           _L18_6d
3849 _L18_5d:
3850         bsr.l           sgetexpd                        # operand is a DENORM
3851 _L18_6d:
3852
3853 #
3854 #       Result is now in FP0
3855 #
3856         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3857         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3858         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3859         unlk            %a6
3860         rts
3861
3862         global          _fgetexpx_
3863 _fgetexpx_:
3864         link            %a6,&-LOCAL_SIZE
3865
3866         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3867         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3868         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3869
3870         fmov.l          &0x0,%fpcr              # zero FPCR
3871
3872 #
3873 #       copy, convert, and tag input argument
3874 #
3875         lea             FP_SRC(%a6),%a0
3876         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
3877         mov.l           0x8+0x4(%a6),0x4(%a0)
3878         mov.l           0x8+0x8(%a6),0x8(%a0)
3879         bsr.l           tag                     # fetch operand type
3880         mov.b           %d0,STAG(%a6)
3881         mov.b           %d0,%d1
3882
3883         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3884
3885         clr.l           %d0
3886         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3887
3888         tst.b           %d1
3889         bne.b           _L18_2x
3890         bsr.l           sgetexp                 # operand is a NORM
3891         bra.b           _L18_6x
3892 _L18_2x:
3893         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3894         bne.b           _L18_3x                 # no
3895         bsr.l           src_zero                        # yes
3896         bra.b           _L18_6x
3897 _L18_3x:
3898         cmpi.b          %d1,&INF                # is operand an INF?
3899         bne.b           _L18_4x                 # no
3900         bsr.l           t_operr                 # yes
3901         bra.b           _L18_6x
3902 _L18_4x:
3903         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3904         bne.b           _L18_5x                 # no
3905         bsr.l           src_qnan                        # yes
3906         bra.b           _L18_6x
3907 _L18_5x:
3908         bsr.l           sgetexpd                        # operand is a DENORM
3909 _L18_6x:
3910
3911 #
3912 #       Result is now in FP0
3913 #
3914         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3915         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3916         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3917         unlk            %a6
3918         rts
3919
3920
3921 #########################################################################
3922 # MONADIC TEMPLATE                                                      #
3923 #########################################################################
3924         global          _fgetmans_
3925 _fgetmans_:
3926         link            %a6,&-LOCAL_SIZE
3927
3928         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3929         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3930         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3931
3932         fmov.l          &0x0,%fpcr              # zero FPCR
3933
3934 #
3935 #       copy, convert, and tag input argument
3936 #
3937         fmov.s          0x8(%a6),%fp0           # load sgl input
3938         fmov.x          %fp0,FP_SRC(%a6)
3939         lea             FP_SRC(%a6),%a0
3940         bsr.l           tag                     # fetch operand type
3941         mov.b           %d0,STAG(%a6)
3942         mov.b           %d0,%d1
3943
3944         andi.l          &0x00ff00ff,USER_FPSR(%a6)
3945
3946         clr.l           %d0
3947         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
3948
3949         tst.b           %d1
3950         bne.b           _L19_2s
3951         bsr.l           sgetman                 # operand is a NORM
3952         bra.b           _L19_6s
3953 _L19_2s:
3954         cmpi.b          %d1,&ZERO               # is operand a ZERO?
3955         bne.b           _L19_3s                 # no
3956         bsr.l           src_zero                        # yes
3957         bra.b           _L19_6s
3958 _L19_3s:
3959         cmpi.b          %d1,&INF                # is operand an INF?
3960         bne.b           _L19_4s                 # no
3961         bsr.l           t_operr                 # yes
3962         bra.b           _L19_6s
3963 _L19_4s:
3964         cmpi.b          %d1,&QNAN               # is operand a QNAN?
3965         bne.b           _L19_5s                 # no
3966         bsr.l           src_qnan                        # yes
3967         bra.b           _L19_6s
3968 _L19_5s:
3969         bsr.l           sgetmand                        # operand is a DENORM
3970 _L19_6s:
3971
3972 #
3973 #       Result is now in FP0
3974 #
3975         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
3976         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3977         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
3978         unlk            %a6
3979         rts
3980
3981         global          _fgetmand_
3982 _fgetmand_:
3983         link            %a6,&-LOCAL_SIZE
3984
3985         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
3986         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3987         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
3988
3989         fmov.l          &0x0,%fpcr              # zero FPCR
3990
3991 #
3992 #       copy, convert, and tag input argument
3993 #
3994         fmov.d          0x8(%a6),%fp0           # load dbl input
3995         fmov.x          %fp0,FP_SRC(%a6)
3996         lea             FP_SRC(%a6),%a0
3997         bsr.l           tag                     # fetch operand type
3998         mov.b           %d0,STAG(%a6)
3999         mov.b           %d0,%d1
4000
4001         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4002
4003         clr.l           %d0
4004         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4005
4006         mov.b           %d1,STAG(%a6)
4007         tst.b           %d1
4008         bne.b           _L19_2d
4009         bsr.l           sgetman                 # operand is a NORM
4010         bra.b           _L19_6d
4011 _L19_2d:
4012         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4013         bne.b           _L19_3d                 # no
4014         bsr.l           src_zero                        # yes
4015         bra.b           _L19_6d
4016 _L19_3d:
4017         cmpi.b          %d1,&INF                # is operand an INF?
4018         bne.b           _L19_4d                 # no
4019         bsr.l           t_operr                 # yes
4020         bra.b           _L19_6d
4021 _L19_4d:
4022         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4023         bne.b           _L19_5d                 # no
4024         bsr.l           src_qnan                        # yes
4025         bra.b           _L19_6d
4026 _L19_5d:
4027         bsr.l           sgetmand                        # operand is a DENORM
4028 _L19_6d:
4029
4030 #
4031 #       Result is now in FP0
4032 #
4033         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4034         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4035         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4036         unlk            %a6
4037         rts
4038
4039         global          _fgetmanx_
4040 _fgetmanx_:
4041         link            %a6,&-LOCAL_SIZE
4042
4043         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4044         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4045         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4046
4047         fmov.l          &0x0,%fpcr              # zero FPCR
4048
4049 #
4050 #       copy, convert, and tag input argument
4051 #
4052         lea             FP_SRC(%a6),%a0
4053         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
4054         mov.l           0x8+0x4(%a6),0x4(%a0)
4055         mov.l           0x8+0x8(%a6),0x8(%a0)
4056         bsr.l           tag                     # fetch operand type
4057         mov.b           %d0,STAG(%a6)
4058         mov.b           %d0,%d1
4059
4060         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4061
4062         clr.l           %d0
4063         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4064
4065         tst.b           %d1
4066         bne.b           _L19_2x
4067         bsr.l           sgetman                 # operand is a NORM
4068         bra.b           _L19_6x
4069 _L19_2x:
4070         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4071         bne.b           _L19_3x                 # no
4072         bsr.l           src_zero                        # yes
4073         bra.b           _L19_6x
4074 _L19_3x:
4075         cmpi.b          %d1,&INF                # is operand an INF?
4076         bne.b           _L19_4x                 # no
4077         bsr.l           t_operr                 # yes
4078         bra.b           _L19_6x
4079 _L19_4x:
4080         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4081         bne.b           _L19_5x                 # no
4082         bsr.l           src_qnan                        # yes
4083         bra.b           _L19_6x
4084 _L19_5x:
4085         bsr.l           sgetmand                        # operand is a DENORM
4086 _L19_6x:
4087
4088 #
4089 #       Result is now in FP0
4090 #
4091         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4092         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4093         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4094         unlk            %a6
4095         rts
4096
4097
4098 #########################################################################
4099 # MONADIC TEMPLATE                                                      #
4100 #########################################################################
4101         global          _fsincoss_
4102 _fsincoss_:
4103         link            %a6,&-LOCAL_SIZE
4104
4105         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4106         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4107         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4108
4109         fmov.l          &0x0,%fpcr              # zero FPCR
4110
4111 #
4112 #       copy, convert, and tag input argument
4113 #
4114         fmov.s          0x8(%a6),%fp0           # load sgl input
4115         fmov.x          %fp0,FP_SRC(%a6)
4116         lea             FP_SRC(%a6),%a0
4117         bsr.l           tag                     # fetch operand type
4118         mov.b           %d0,STAG(%a6)
4119         mov.b           %d0,%d1
4120
4121         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4122
4123         clr.l           %d0
4124         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4125
4126         tst.b           %d1
4127         bne.b           _L20_2s
4128         bsr.l           ssincos                 # operand is a NORM
4129         bra.b           _L20_6s
4130 _L20_2s:
4131         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4132         bne.b           _L20_3s                 # no
4133         bsr.l           ssincosz                        # yes
4134         bra.b           _L20_6s
4135 _L20_3s:
4136         cmpi.b          %d1,&INF                # is operand an INF?
4137         bne.b           _L20_4s                 # no
4138         bsr.l           ssincosi                        # yes
4139         bra.b           _L20_6s
4140 _L20_4s:
4141         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4142         bne.b           _L20_5s                 # no
4143         bsr.l           ssincosqnan                     # yes
4144         bra.b           _L20_6s
4145 _L20_5s:
4146         bsr.l           ssincosd                        # operand is a DENORM
4147 _L20_6s:
4148
4149 #
4150 #       Result is now in FP0
4151 #
4152         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4153         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4154         fmovm.x         &0x03,-(%sp)            # store off fp0/fp1
4155         fmovm.x         (%sp)+,&0x40            # fp0 now in fp1
4156         fmovm.x         (%sp)+,&0x80            # fp1 now in fp0
4157         unlk            %a6
4158         rts
4159
4160         global          _fsincosd_
4161 _fsincosd_:
4162         link            %a6,&-LOCAL_SIZE
4163
4164         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4165         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4166         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4167
4168         fmov.l          &0x0,%fpcr              # zero FPCR
4169
4170 #
4171 #       copy, convert, and tag input argument
4172 #
4173         fmov.d          0x8(%a6),%fp0           # load dbl input
4174         fmov.x          %fp0,FP_SRC(%a6)
4175         lea             FP_SRC(%a6),%a0
4176         bsr.l           tag                     # fetch operand type
4177         mov.b           %d0,STAG(%a6)
4178         mov.b           %d0,%d1
4179
4180         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4181
4182         clr.l           %d0
4183         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4184
4185         mov.b           %d1,STAG(%a6)
4186         tst.b           %d1
4187         bne.b           _L20_2d
4188         bsr.l           ssincos                 # operand is a NORM
4189         bra.b           _L20_6d
4190 _L20_2d:
4191         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4192         bne.b           _L20_3d                 # no
4193         bsr.l           ssincosz                        # yes
4194         bra.b           _L20_6d
4195 _L20_3d:
4196         cmpi.b          %d1,&INF                # is operand an INF?
4197         bne.b           _L20_4d                 # no
4198         bsr.l           ssincosi                        # yes
4199         bra.b           _L20_6d
4200 _L20_4d:
4201         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4202         bne.b           _L20_5d                 # no
4203         bsr.l           ssincosqnan                     # yes
4204         bra.b           _L20_6d
4205 _L20_5d:
4206         bsr.l           ssincosd                        # operand is a DENORM
4207 _L20_6d:
4208
4209 #
4210 #       Result is now in FP0
4211 #
4212         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4213         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4214         fmovm.x         &0x03,-(%sp)            # store off fp0/fp1
4215         fmovm.x         (%sp)+,&0x40            # fp0 now in fp1
4216         fmovm.x         (%sp)+,&0x80            # fp1 now in fp0
4217         unlk            %a6
4218         rts
4219
4220         global          _fsincosx_
4221 _fsincosx_:
4222         link            %a6,&-LOCAL_SIZE
4223
4224         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4225         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4226         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4227
4228         fmov.l          &0x0,%fpcr              # zero FPCR
4229
4230 #
4231 #       copy, convert, and tag input argument
4232 #
4233         lea             FP_SRC(%a6),%a0
4234         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext input
4235         mov.l           0x8+0x4(%a6),0x4(%a0)
4236         mov.l           0x8+0x8(%a6),0x8(%a0)
4237         bsr.l           tag                     # fetch operand type
4238         mov.b           %d0,STAG(%a6)
4239         mov.b           %d0,%d1
4240
4241         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4242
4243         clr.l           %d0
4244         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4245
4246         tst.b           %d1
4247         bne.b           _L20_2x
4248         bsr.l           ssincos                 # operand is a NORM
4249         bra.b           _L20_6x
4250 _L20_2x:
4251         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4252         bne.b           _L20_3x                 # no
4253         bsr.l           ssincosz                        # yes
4254         bra.b           _L20_6x
4255 _L20_3x:
4256         cmpi.b          %d1,&INF                # is operand an INF?
4257         bne.b           _L20_4x                 # no
4258         bsr.l           ssincosi                        # yes
4259         bra.b           _L20_6x
4260 _L20_4x:
4261         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4262         bne.b           _L20_5x                 # no
4263         bsr.l           ssincosqnan                     # yes
4264         bra.b           _L20_6x
4265 _L20_5x:
4266         bsr.l           ssincosd                        # operand is a DENORM
4267 _L20_6x:
4268
4269 #
4270 #       Result is now in FP0
4271 #
4272         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4273         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4274         fmovm.x         &0x03,-(%sp)            # store off fp0/fp1
4275         fmovm.x         (%sp)+,&0x40            # fp0 now in fp1
4276         fmovm.x         (%sp)+,&0x80            # fp1 now in fp0
4277         unlk            %a6
4278         rts
4279
4280
4281 #########################################################################
4282 # DYADIC TEMPLATE                                                       #
4283 #########################################################################
4284         global          _frems_
4285 _frems_:
4286         link            %a6,&-LOCAL_SIZE
4287
4288         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4289         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4290         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4291
4292         fmov.l          &0x0,%fpcr              # zero FPCR
4293
4294 #
4295 #       copy, convert, and tag input argument
4296 #
4297         fmov.s          0x8(%a6),%fp0           # load sgl dst
4298         fmov.x          %fp0,FP_DST(%a6)
4299         lea             FP_DST(%a6),%a0
4300         bsr.l           tag                     # fetch operand type
4301         mov.b           %d0,DTAG(%a6)
4302
4303         fmov.s          0xc(%a6),%fp0           # load sgl src
4304         fmov.x          %fp0,FP_SRC(%a6)
4305         lea             FP_SRC(%a6),%a0
4306         bsr.l           tag                     # fetch operand type
4307         mov.b           %d0,STAG(%a6)
4308         mov.l           %d0,%d1
4309
4310         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4311
4312         clr.l           %d0
4313         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4314
4315         lea             FP_SRC(%a6),%a0         # pass ptr to src
4316         lea             FP_DST(%a6),%a1         # pass ptr to dst
4317
4318         tst.b           %d1
4319         bne.b           _L21_2s
4320         bsr.l           srem_snorm                      # operand is a NORM
4321         bra.b           _L21_6s
4322 _L21_2s:
4323         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4324         bne.b           _L21_3s                 # no
4325         bsr.l           srem_szero                      # yes
4326         bra.b           _L21_6s
4327 _L21_3s:
4328         cmpi.b          %d1,&INF                # is operand an INF?
4329         bne.b           _L21_4s                 # no
4330         bsr.l           srem_sinf                       # yes
4331         bra.b           _L21_6s
4332 _L21_4s:
4333         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4334         bne.b           _L21_5s                 # no
4335         bsr.l           sop_sqnan                       # yes
4336         bra.b           _L21_6s
4337 _L21_5s:
4338         bsr.l           srem_sdnrm                      # operand is a DENORM
4339 _L21_6s:
4340
4341 #
4342 #       Result is now in FP0
4343 #
4344         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4345         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4346         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4347         unlk            %a6
4348         rts
4349
4350         global          _fremd_
4351 _fremd_:
4352         link            %a6,&-LOCAL_SIZE
4353
4354         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4355         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4356         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4357
4358         fmov.l          &0x0,%fpcr              # zero FPCR
4359
4360 #
4361 #       copy, convert, and tag input argument
4362 #
4363         fmov.d          0x8(%a6),%fp0           # load dbl dst
4364         fmov.x          %fp0,FP_DST(%a6)
4365         lea             FP_DST(%a6),%a0
4366         bsr.l           tag                     # fetch operand type
4367         mov.b           %d0,DTAG(%a6)
4368
4369         fmov.d          0x10(%a6),%fp0          # load dbl src
4370         fmov.x          %fp0,FP_SRC(%a6)
4371         lea             FP_SRC(%a6),%a0
4372         bsr.l           tag                     # fetch operand type
4373         mov.b           %d0,STAG(%a6)
4374         mov.l           %d0,%d1
4375
4376         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4377
4378         clr.l           %d0
4379         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4380
4381         lea             FP_SRC(%a6),%a0         # pass ptr to src
4382         lea             FP_DST(%a6),%a1         # pass ptr to dst
4383
4384         tst.b           %d1
4385         bne.b           _L21_2d
4386         bsr.l           srem_snorm                      # operand is a NORM
4387         bra.b           _L21_6d
4388 _L21_2d:
4389         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4390         bne.b           _L21_3d                 # no
4391         bsr.l           srem_szero                      # yes
4392         bra.b           _L21_6d
4393 _L21_3d:
4394         cmpi.b          %d1,&INF                # is operand an INF?
4395         bne.b           _L21_4d                 # no
4396         bsr.l           srem_sinf                       # yes
4397         bra.b           _L21_6d
4398 _L21_4d:
4399         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4400         bne.b           _L21_5d                 # no
4401         bsr.l           sop_sqnan                       # yes
4402         bra.b           _L21_6d
4403 _L21_5d:
4404         bsr.l           srem_sdnrm                      # operand is a DENORM
4405 _L21_6d:
4406
4407 #
4408 #       Result is now in FP0
4409 #
4410         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4411         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4412         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4413         unlk            %a6
4414         rts
4415
4416         global          _fremx_
4417 _fremx_:
4418         link            %a6,&-LOCAL_SIZE
4419
4420         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4421         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4422         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4423
4424         fmov.l          &0x0,%fpcr              # zero FPCR
4425
4426 #
4427 #       copy, convert, and tag input argument
4428 #
4429         lea             FP_DST(%a6),%a0
4430         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext dst
4431         mov.l           0x8+0x4(%a6),0x4(%a0)
4432         mov.l           0x8+0x8(%a6),0x8(%a0)
4433         bsr.l           tag                     # fetch operand type
4434         mov.b           %d0,DTAG(%a6)
4435
4436         lea             FP_SRC(%a6),%a0
4437         mov.l           0x14+0x0(%a6),0x0(%a0)  # load ext src
4438         mov.l           0x14+0x4(%a6),0x4(%a0)
4439         mov.l           0x14+0x8(%a6),0x8(%a0)
4440         bsr.l           tag                     # fetch operand type
4441         mov.b           %d0,STAG(%a6)
4442         mov.l           %d0,%d1
4443
4444         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4445
4446         clr.l           %d0
4447         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4448
4449         lea             FP_SRC(%a6),%a0         # pass ptr to src
4450         lea             FP_DST(%a6),%a1         # pass ptr to dst
4451
4452         tst.b           %d1
4453         bne.b           _L21_2x
4454         bsr.l           srem_snorm                      # operand is a NORM
4455         bra.b           _L21_6x
4456 _L21_2x:
4457         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4458         bne.b           _L21_3x                 # no
4459         bsr.l           srem_szero                      # yes
4460         bra.b           _L21_6x
4461 _L21_3x:
4462         cmpi.b          %d1,&INF                # is operand an INF?
4463         bne.b           _L21_4x                 # no
4464         bsr.l           srem_sinf                       # yes
4465         bra.b           _L21_6x
4466 _L21_4x:
4467         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4468         bne.b           _L21_5x                 # no
4469         bsr.l           sop_sqnan                       # yes
4470         bra.b           _L21_6x
4471 _L21_5x:
4472         bsr.l           srem_sdnrm                      # operand is a DENORM
4473 _L21_6x:
4474
4475 #
4476 #       Result is now in FP0
4477 #
4478         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4479         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4480         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4481         unlk            %a6
4482         rts
4483
4484
4485 #########################################################################
4486 # DYADIC TEMPLATE                                                       #
4487 #########################################################################
4488         global          _fmods_
4489 _fmods_:
4490         link            %a6,&-LOCAL_SIZE
4491
4492         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4493         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4494         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4495
4496         fmov.l          &0x0,%fpcr              # zero FPCR
4497
4498 #
4499 #       copy, convert, and tag input argument
4500 #
4501         fmov.s          0x8(%a6),%fp0           # load sgl dst
4502         fmov.x          %fp0,FP_DST(%a6)
4503         lea             FP_DST(%a6),%a0
4504         bsr.l           tag                     # fetch operand type
4505         mov.b           %d0,DTAG(%a6)
4506
4507         fmov.s          0xc(%a6),%fp0           # load sgl src
4508         fmov.x          %fp0,FP_SRC(%a6)
4509         lea             FP_SRC(%a6),%a0
4510         bsr.l           tag                     # fetch operand type
4511         mov.b           %d0,STAG(%a6)
4512         mov.l           %d0,%d1
4513
4514         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4515
4516         clr.l           %d0
4517         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4518
4519         lea             FP_SRC(%a6),%a0         # pass ptr to src
4520         lea             FP_DST(%a6),%a1         # pass ptr to dst
4521
4522         tst.b           %d1
4523         bne.b           _L22_2s
4524         bsr.l           smod_snorm                      # operand is a NORM
4525         bra.b           _L22_6s
4526 _L22_2s:
4527         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4528         bne.b           _L22_3s                 # no
4529         bsr.l           smod_szero                      # yes
4530         bra.b           _L22_6s
4531 _L22_3s:
4532         cmpi.b          %d1,&INF                # is operand an INF?
4533         bne.b           _L22_4s                 # no
4534         bsr.l           smod_sinf                       # yes
4535         bra.b           _L22_6s
4536 _L22_4s:
4537         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4538         bne.b           _L22_5s                 # no
4539         bsr.l           sop_sqnan                       # yes
4540         bra.b           _L22_6s
4541 _L22_5s:
4542         bsr.l           smod_sdnrm                      # operand is a DENORM
4543 _L22_6s:
4544
4545 #
4546 #       Result is now in FP0
4547 #
4548         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4549         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4550         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4551         unlk            %a6
4552         rts
4553
4554         global          _fmodd_
4555 _fmodd_:
4556         link            %a6,&-LOCAL_SIZE
4557
4558         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4559         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4560         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4561
4562         fmov.l          &0x0,%fpcr              # zero FPCR
4563
4564 #
4565 #       copy, convert, and tag input argument
4566 #
4567         fmov.d          0x8(%a6),%fp0           # load dbl dst
4568         fmov.x          %fp0,FP_DST(%a6)
4569         lea             FP_DST(%a6),%a0
4570         bsr.l           tag                     # fetch operand type
4571         mov.b           %d0,DTAG(%a6)
4572
4573         fmov.d          0x10(%a6),%fp0          # load dbl src
4574         fmov.x          %fp0,FP_SRC(%a6)
4575         lea             FP_SRC(%a6),%a0
4576         bsr.l           tag                     # fetch operand type
4577         mov.b           %d0,STAG(%a6)
4578         mov.l           %d0,%d1
4579
4580         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4581
4582         clr.l           %d0
4583         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4584
4585         lea             FP_SRC(%a6),%a0         # pass ptr to src
4586         lea             FP_DST(%a6),%a1         # pass ptr to dst
4587
4588         tst.b           %d1
4589         bne.b           _L22_2d
4590         bsr.l           smod_snorm                      # operand is a NORM
4591         bra.b           _L22_6d
4592 _L22_2d:
4593         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4594         bne.b           _L22_3d                 # no
4595         bsr.l           smod_szero                      # yes
4596         bra.b           _L22_6d
4597 _L22_3d:
4598         cmpi.b          %d1,&INF                # is operand an INF?
4599         bne.b           _L22_4d                 # no
4600         bsr.l           smod_sinf                       # yes
4601         bra.b           _L22_6d
4602 _L22_4d:
4603         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4604         bne.b           _L22_5d                 # no
4605         bsr.l           sop_sqnan                       # yes
4606         bra.b           _L22_6d
4607 _L22_5d:
4608         bsr.l           smod_sdnrm                      # operand is a DENORM
4609 _L22_6d:
4610
4611 #
4612 #       Result is now in FP0
4613 #
4614         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4615         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4616         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4617         unlk            %a6
4618         rts
4619
4620         global          _fmodx_
4621 _fmodx_:
4622         link            %a6,&-LOCAL_SIZE
4623
4624         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4625         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4626         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4627
4628         fmov.l          &0x0,%fpcr              # zero FPCR
4629
4630 #
4631 #       copy, convert, and tag input argument
4632 #
4633         lea             FP_DST(%a6),%a0
4634         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext dst
4635         mov.l           0x8+0x4(%a6),0x4(%a0)
4636         mov.l           0x8+0x8(%a6),0x8(%a0)
4637         bsr.l           tag                     # fetch operand type
4638         mov.b           %d0,DTAG(%a6)
4639
4640         lea             FP_SRC(%a6),%a0
4641         mov.l           0x14+0x0(%a6),0x0(%a0)  # load ext src
4642         mov.l           0x14+0x4(%a6),0x4(%a0)
4643         mov.l           0x14+0x8(%a6),0x8(%a0)
4644         bsr.l           tag                     # fetch operand type
4645         mov.b           %d0,STAG(%a6)
4646         mov.l           %d0,%d1
4647
4648         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4649
4650         clr.l           %d0
4651         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4652
4653         lea             FP_SRC(%a6),%a0         # pass ptr to src
4654         lea             FP_DST(%a6),%a1         # pass ptr to dst
4655
4656         tst.b           %d1
4657         bne.b           _L22_2x
4658         bsr.l           smod_snorm                      # operand is a NORM
4659         bra.b           _L22_6x
4660 _L22_2x:
4661         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4662         bne.b           _L22_3x                 # no
4663         bsr.l           smod_szero                      # yes
4664         bra.b           _L22_6x
4665 _L22_3x:
4666         cmpi.b          %d1,&INF                # is operand an INF?
4667         bne.b           _L22_4x                 # no
4668         bsr.l           smod_sinf                       # yes
4669         bra.b           _L22_6x
4670 _L22_4x:
4671         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4672         bne.b           _L22_5x                 # no
4673         bsr.l           sop_sqnan                       # yes
4674         bra.b           _L22_6x
4675 _L22_5x:
4676         bsr.l           smod_sdnrm                      # operand is a DENORM
4677 _L22_6x:
4678
4679 #
4680 #       Result is now in FP0
4681 #
4682         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4683         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4684         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4685         unlk            %a6
4686         rts
4687
4688
4689 #########################################################################
4690 # DYADIC TEMPLATE                                                       #
4691 #########################################################################
4692         global          _fscales_
4693 _fscales_:
4694         link            %a6,&-LOCAL_SIZE
4695
4696         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4697         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4698         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4699
4700         fmov.l          &0x0,%fpcr              # zero FPCR
4701
4702 #
4703 #       copy, convert, and tag input argument
4704 #
4705         fmov.s          0x8(%a6),%fp0           # load sgl dst
4706         fmov.x          %fp0,FP_DST(%a6)
4707         lea             FP_DST(%a6),%a0
4708         bsr.l           tag                     # fetch operand type
4709         mov.b           %d0,DTAG(%a6)
4710
4711         fmov.s          0xc(%a6),%fp0           # load sgl src
4712         fmov.x          %fp0,FP_SRC(%a6)
4713         lea             FP_SRC(%a6),%a0
4714         bsr.l           tag                     # fetch operand type
4715         mov.b           %d0,STAG(%a6)
4716         mov.l           %d0,%d1
4717
4718         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4719
4720         clr.l           %d0
4721         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4722
4723         lea             FP_SRC(%a6),%a0         # pass ptr to src
4724         lea             FP_DST(%a6),%a1         # pass ptr to dst
4725
4726         tst.b           %d1
4727         bne.b           _L23_2s
4728         bsr.l           sscale_snorm                    # operand is a NORM
4729         bra.b           _L23_6s
4730 _L23_2s:
4731         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4732         bne.b           _L23_3s                 # no
4733         bsr.l           sscale_szero                    # yes
4734         bra.b           _L23_6s
4735 _L23_3s:
4736         cmpi.b          %d1,&INF                # is operand an INF?
4737         bne.b           _L23_4s                 # no
4738         bsr.l           sscale_sinf                     # yes
4739         bra.b           _L23_6s
4740 _L23_4s:
4741         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4742         bne.b           _L23_5s                 # no
4743         bsr.l           sop_sqnan                       # yes
4744         bra.b           _L23_6s
4745 _L23_5s:
4746         bsr.l           sscale_sdnrm                    # operand is a DENORM
4747 _L23_6s:
4748
4749 #
4750 #       Result is now in FP0
4751 #
4752         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4753         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4754         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4755         unlk            %a6
4756         rts
4757
4758         global          _fscaled_
4759 _fscaled_:
4760         link            %a6,&-LOCAL_SIZE
4761
4762         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4763         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4764         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4765
4766         fmov.l          &0x0,%fpcr              # zero FPCR
4767
4768 #
4769 #       copy, convert, and tag input argument
4770 #
4771         fmov.d          0x8(%a6),%fp0           # load dbl dst
4772         fmov.x          %fp0,FP_DST(%a6)
4773         lea             FP_DST(%a6),%a0
4774         bsr.l           tag                     # fetch operand type
4775         mov.b           %d0,DTAG(%a6)
4776
4777         fmov.d          0x10(%a6),%fp0          # load dbl src
4778         fmov.x          %fp0,FP_SRC(%a6)
4779         lea             FP_SRC(%a6),%a0
4780         bsr.l           tag                     # fetch operand type
4781         mov.b           %d0,STAG(%a6)
4782         mov.l           %d0,%d1
4783
4784         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4785
4786         clr.l           %d0
4787         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4788
4789         lea             FP_SRC(%a6),%a0         # pass ptr to src
4790         lea             FP_DST(%a6),%a1         # pass ptr to dst
4791
4792         tst.b           %d1
4793         bne.b           _L23_2d
4794         bsr.l           sscale_snorm                    # operand is a NORM
4795         bra.b           _L23_6d
4796 _L23_2d:
4797         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4798         bne.b           _L23_3d                 # no
4799         bsr.l           sscale_szero                    # yes
4800         bra.b           _L23_6d
4801 _L23_3d:
4802         cmpi.b          %d1,&INF                # is operand an INF?
4803         bne.b           _L23_4d                 # no
4804         bsr.l           sscale_sinf                     # yes
4805         bra.b           _L23_6d
4806 _L23_4d:
4807         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4808         bne.b           _L23_5d                 # no
4809         bsr.l           sop_sqnan                       # yes
4810         bra.b           _L23_6d
4811 _L23_5d:
4812         bsr.l           sscale_sdnrm                    # operand is a DENORM
4813 _L23_6d:
4814
4815 #
4816 #       Result is now in FP0
4817 #
4818         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4819         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4820         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4821         unlk            %a6
4822         rts
4823
4824         global          _fscalex_
4825 _fscalex_:
4826         link            %a6,&-LOCAL_SIZE
4827
4828         movm.l          &0x0303,EXC_DREGS(%a6)  # save d0-d1/a0-a1
4829         fmovm.l         %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4830         fmovm.x         &0xc0,EXC_FP0(%a6)      # save fp0/fp1
4831
4832         fmov.l          &0x0,%fpcr              # zero FPCR
4833
4834 #
4835 #       copy, convert, and tag input argument
4836 #
4837         lea             FP_DST(%a6),%a0
4838         mov.l           0x8+0x0(%a6),0x0(%a0)   # load ext dst
4839         mov.l           0x8+0x4(%a6),0x4(%a0)
4840         mov.l           0x8+0x8(%a6),0x8(%a0)
4841         bsr.l           tag                     # fetch operand type
4842         mov.b           %d0,DTAG(%a6)
4843
4844         lea             FP_SRC(%a6),%a0
4845         mov.l           0x14+0x0(%a6),0x0(%a0)  # load ext src
4846         mov.l           0x14+0x4(%a6),0x4(%a0)
4847         mov.l           0x14+0x8(%a6),0x8(%a0)
4848         bsr.l           tag                     # fetch operand type
4849         mov.b           %d0,STAG(%a6)
4850         mov.l           %d0,%d1
4851
4852         andi.l          &0x00ff00ff,USER_FPSR(%a6)
4853
4854         clr.l           %d0
4855         mov.b           FPCR_MODE(%a6),%d0      # pass rnd mode,prec
4856
4857         lea             FP_SRC(%a6),%a0         # pass ptr to src
4858         lea             FP_DST(%a6),%a1         # pass ptr to dst
4859
4860         tst.b           %d1
4861         bne.b           _L23_2x
4862         bsr.l           sscale_snorm                    # operand is a NORM
4863         bra.b           _L23_6x
4864 _L23_2x:
4865         cmpi.b          %d1,&ZERO               # is operand a ZERO?
4866         bne.b           _L23_3x                 # no
4867         bsr.l           sscale_szero                    # yes
4868         bra.b           _L23_6x
4869 _L23_3x:
4870         cmpi.b          %d1,&INF                # is operand an INF?
4871         bne.b           _L23_4x                 # no
4872         bsr.l           sscale_sinf                     # yes
4873         bra.b           _L23_6x
4874 _L23_4x:
4875         cmpi.b          %d1,&QNAN               # is operand a QNAN?
4876         bne.b           _L23_5x                 # no
4877         bsr.l           sop_sqnan                       # yes
4878         bra.b           _L23_6x
4879 _L23_5x:
4880         bsr.l           sscale_sdnrm                    # operand is a DENORM
4881 _L23_6x:
4882
4883 #
4884 #       Result is now in FP0
4885 #
4886         movm.l          EXC_DREGS(%a6),&0x0303  # restore d0-d1/a0-a1
4887         fmovm.l         USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4888         fmovm.x         EXC_FP1(%a6),&0x40      # restore fp1
4889         unlk            %a6
4890         rts
4891
4892
4893 #########################################################################
4894 # ssin():     computes the sine of a normalized input                   #
4895 # ssind():    computes the sine of a denormalized input                 #
4896 # scos():     computes the cosine of a normalized input                 #
4897 # scosd():    computes the cosine of a denormalized input               #
4898 # ssincos():  computes the sine and cosine of a normalized input        #
4899 # ssincosd(): computes the sine and cosine of a denormalized input      #
4900 #                                                                       #
4901 # INPUT *************************************************************** #
4902 #       a0 = pointer to extended precision input                        #
4903 #       d0 = round precision,mode                                       #
4904 #                                                                       #
4905 # OUTPUT ************************************************************** #
4906 #       fp0 = sin(X) or cos(X)                                          #
4907 #                                                                       #
4908 #    For ssincos(X):                                                    #
4909 #       fp0 = sin(X)                                                    #
4910 #       fp1 = cos(X)                                                    #
4911 #                                                                       #
4912 # ACCURACY and MONOTONICITY ******************************************* #
4913 #       The returned result is within 1 ulp in 64 significant bit, i.e. #
4914 #       within 0.5001 ulp to 53 bits if the result is subsequently      #
4915 #       rounded to double precision. The result is provably monotonic   #
4916 #       in double precision.                                            #
4917 #                                                                       #
4918 # ALGORITHM *********************************************************** #
4919 #                                                                       #
4920 #       SIN and COS:                                                    #
4921 #       1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1.  #
4922 #                                                                       #
4923 #       2. If |X| >= 15Pi or |X| < 2**(-40), go to 7.                   #
4924 #                                                                       #
4925 #       3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
4926 #               k = N mod 4, so in particular, k = 0,1,2,or 3.          #
4927 #               Overwrite k by k := k + AdjN.                           #
4928 #                                                                       #
4929 #       4. If k is even, go to 6.                                       #
4930 #                                                                       #
4931 #       5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j.                 #
4932 #               Return sgn*cos(r) where cos(r) is approximated by an    #
4933 #               even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)),  #
4934 #               s = r*r.                                                #
4935 #               Exit.                                                   #
4936 #                                                                       #
4937 #       6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r)  #
4938 #               where sin(r) is approximated by an odd polynomial in r  #
4939 #               r + r*s*(A1+s*(A2+ ... + s*A7)),        s = r*r.        #
4940 #               Exit.                                                   #
4941 #                                                                       #
4942 #       7. If |X| > 1, go to 9.                                         #
4943 #                                                                       #
4944 #       8. (|X|<2**(-40)) If SIN is invoked, return X;                  #
4945 #               otherwise return 1.                                     #
4946 #                                                                       #
4947 #       9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,           #
4948 #               go back to 3.                                           #
4949 #                                                                       #
4950 #       SINCOS:                                                         #
4951 #       1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.                   #
4952 #                                                                       #
4953 #       2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
4954 #               k = N mod 4, so in particular, k = 0,1,2,or 3.          #
4955 #                                                                       #
4956 #       3. If k is even, go to 5.                                       #
4957 #                                                                       #
4958 #       4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie.  #
4959 #               j1 exclusive or with the l.s.b. of k.                   #
4960 #               sgn1 := (-1)**j1, sgn2 := (-1)**j2.                     #
4961 #               SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where   #
4962 #               sin(r) and cos(r) are computed as odd and even          #
4963 #               polynomials in r, respectively. Exit                    #
4964 #                                                                       #
4965 #       5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1.                 #
4966 #               SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where   #
4967 #               sin(r) and cos(r) are computed as odd and even          #
4968 #               polynomials in r, respectively. Exit                    #
4969 #                                                                       #
4970 #       6. If |X| > 1, go to 8.                                         #
4971 #                                                                       #
4972 #       7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit.              #
4973 #                                                                       #
4974 #       8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,           #
4975 #               go back to 2.                                           #
4976 #                                                                       #
4977 #########################################################################
4978
4979 SINA7:  long            0xBD6AAA77,0xCCC994F5
4980 SINA6:  long            0x3DE61209,0x7AAE8DA1
4981 SINA5:  long            0xBE5AE645,0x2A118AE4
4982 SINA4:  long            0x3EC71DE3,0xA5341531
4983 SINA3:  long            0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
4984 SINA2:  long            0x3FF80000,0x88888888,0x888859AF,0x00000000
4985 SINA1:  long            0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
4986
4987 COSB8:  long            0x3D2AC4D0,0xD6011EE3
4988 COSB7:  long            0xBDA9396F,0x9F45AC19
4989 COSB6:  long            0x3E21EED9,0x0612C972
4990 COSB5:  long            0xBE927E4F,0xB79D9FCF
4991 COSB4:  long            0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
4992 COSB3:  long            0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
4993 COSB2:  long            0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
4994 COSB1:  long            0xBF000000
4995
4996         set             INARG,FP_SCR0
4997
4998         set             X,FP_SCR0
4999 #       set             XDCARE,X+2
5000         set             XFRAC,X+4
5001
5002         set             RPRIME,FP_SCR0
5003         set             SPRIME,FP_SCR1
5004
5005         set             POSNEG1,L_SCR1
5006         set             TWOTO63,L_SCR1
5007
5008         set             ENDFLAG,L_SCR2
5009         set             INT,L_SCR2
5010
5011         set             ADJN,L_SCR3
5012
5013 ############################################
5014         global          ssin
5015 ssin:
5016         mov.l           &0,ADJN(%a6)            # yes; SET ADJN TO 0
5017         bra.b           SINBGN
5018
5019 ############################################
5020         global          scos
5021 scos:
5022         mov.l           &1,ADJN(%a6)            # yes; SET ADJN TO 1
5023
5024 ############################################
5025 SINBGN:
5026 #--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
5027
5028         fmov.x          (%a0),%fp0              # LOAD INPUT
5029         fmov.x          %fp0,X(%a6)             # save input at X
5030
5031 # "COMPACTIFY" X
5032         mov.l           (%a0),%d1               # put exp in hi word
5033         mov.w           4(%a0),%d1              # fetch hi(man)
5034         and.l           &0x7FFFFFFF,%d1         # strip sign
5035
5036         cmpi.l          %d1,&0x3FD78000         # is |X| >= 2**(-40)?
5037         bge.b           SOK1                    # no
5038         bra.w           SINSM                   # yes; input is very small
5039
5040 SOK1:
5041         cmp.l           %d1,&0x4004BC7E         # is |X| < 15 PI?
5042         blt.b           SINMAIN                 # no
5043         bra.w           SREDUCEX                # yes; input is very large
5044
5045 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5046 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5047 SINMAIN:
5048         fmov.x          %fp0,%fp1
5049         fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
5050
5051         lea             PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
5052
5053         fmov.l          %fp1,INT(%a6)           # CONVERT TO INTEGER
5054
5055         mov.l           INT(%a6),%d1            # make a copy of N
5056         asl.l           &4,%d1                  # N *= 16
5057         add.l           %d1,%a1                 # tbl_addr = a1 + (N*16)
5058
5059 # A1 IS THE ADDRESS OF N*PIBY2
5060 # ...WHICH IS IN TWO PIECES Y1 & Y2
5061         fsub.x          (%a1)+,%fp0             # X-Y1
5062         fsub.s          (%a1),%fp0              # fp0 = R = (X-Y1)-Y2
5063
5064 SINCONT:
5065 #--continuation from REDUCEX
5066
5067 #--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
5068         mov.l           INT(%a6),%d1
5069         add.l           ADJN(%a6),%d1           # SEE IF D0 IS ODD OR EVEN
5070         ror.l           &1,%d1                  # D0 WAS ODD IFF D0 IS NEGATIVE
5071         cmp.l           %d1,&0
5072         blt.w           COSPOLY
5073
5074 #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5075 #--THEN WE RETURN       SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
5076 #--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
5077 #--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
5078 #--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
5079 #--WHERE T=S*S.
5080 #--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
5081 #--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
5082 SINPOLY:
5083         fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
5084
5085         fmov.x          %fp0,X(%a6)             # X IS R
5086         fmul.x          %fp0,%fp0               # FP0 IS S
5087
5088         fmov.d          SINA7(%pc),%fp3
5089         fmov.d          SINA6(%pc),%fp2
5090
5091         fmov.x          %fp0,%fp1
5092         fmul.x          %fp1,%fp1               # FP1 IS T
5093
5094         ror.l           &1,%d1
5095         and.l           &0x80000000,%d1
5096 # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5097         eor.l           %d1,X(%a6)              # X IS NOW R'= SGN*R
5098
5099         fmul.x          %fp1,%fp3               # TA7
5100         fmul.x          %fp1,%fp2               # TA6
5101
5102         fadd.d          SINA5(%pc),%fp3         # A5+TA7
5103         fadd.d          SINA4(%pc),%fp2         # A4+TA6
5104
5105         fmul.x          %fp1,%fp3               # T(A5+TA7)
5106         fmul.x          %fp1,%fp2               # T(A4+TA6)
5107
5108         fadd.d          SINA3(%pc),%fp3         # A3+T(A5+TA7)
5109         fadd.x          SINA2(%pc),%fp2         # A2+T(A4+TA6)
5110
5111         fmul.x          %fp3,%fp1               # T(A3+T(A5+TA7))
5112
5113         fmul.x          %fp0,%fp2               # S(A2+T(A4+TA6))
5114         fadd.x          SINA1(%pc),%fp1         # A1+T(A3+T(A5+TA7))
5115         fmul.x          X(%a6),%fp0             # R'*S
5116
5117         fadd.x          %fp2,%fp1               # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
5118
5119         fmul.x          %fp1,%fp0               # SIN(R')-R'
5120
5121         fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
5122
5123         fmov.l          %d0,%fpcr               # restore users round mode,prec
5124         fadd.x          X(%a6),%fp0             # last inst - possible exception set
5125         bra             t_inx2
5126
5127 #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5128 #--THEN WE RETURN       SGN*COS(R). SGN*COS(R) IS COMPUTED BY
5129 #--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
5130 #--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
5131 #--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
5132 #--WHERE T=S*S.
5133 #--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
5134 #--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
5135 #--AND IS THEREFORE STORED AS SINGLE PRECISION.
5136 COSPOLY:
5137         fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
5138
5139         fmul.x          %fp0,%fp0               # FP0 IS S
5140
5141         fmov.d          COSB8(%pc),%fp2
5142         fmov.d          COSB7(%pc),%fp3
5143
5144         fmov.x          %fp0,%fp1
5145         fmul.x          %fp1,%fp1               # FP1 IS T
5146
5147         fmov.x          %fp0,X(%a6)             # X IS S
5148         ror.l           &1,%d1
5149         and.l           &0x80000000,%d1
5150 # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5151
5152         fmul.x          %fp1,%fp2               # TB8
5153
5154         eor.l           %d1,X(%a6)              # X IS NOW S'= SGN*S
5155         and.l           &0x80000000,%d1
5156
5157         fmul.x          %fp1,%fp3               # TB7
5158
5159         or.l            &0x3F800000,%d1         # D0 IS SGN IN SINGLE
5160         mov.l           %d1,POSNEG1(%a6)
5161
5162         fadd.d          COSB6(%pc),%fp2         # B6+TB8
5163         fadd.d          COSB5(%pc),%fp3         # B5+TB7
5164
5165         fmul.x          %fp1,%fp2               # T(B6+TB8)
5166         fmul.x          %fp1,%fp3               # T(B5+TB7)
5167
5168         fadd.d          COSB4(%pc),%fp2         # B4+T(B6+TB8)
5169         fadd.x          COSB3(%pc),%fp3         # B3+T(B5+TB7)
5170
5171         fmul.x          %fp1,%fp2               # T(B4+T(B6+TB8))
5172         fmul.x          %fp3,%fp1               # T(B3+T(B5+TB7))
5173
5174         fadd.x          COSB2(%pc),%fp2         # B2+T(B4+T(B6+TB8))
5175         fadd.s          COSB1(%pc),%fp1         # B1+T(B3+T(B5+TB7))
5176
5177         fmul.x          %fp2,%fp0               # S(B2+T(B4+T(B6+TB8)))
5178
5179         fadd.x          %fp1,%fp0
5180
5181         fmul.x          X(%a6),%fp0
5182
5183         fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
5184
5185         fmov.l          %d0,%fpcr               # restore users round mode,prec
5186         fadd.s          POSNEG1(%a6),%fp0       # last inst - possible exception set
5187         bra             t_inx2
5188
5189 ##############################################
5190
5191 # SINe: Big OR Small?
5192 #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5193 #--IF |X| < 2**(-40), RETURN X OR 1.
5194 SINBORS:
5195         cmp.l           %d1,&0x3FFF8000
5196         bgt.l           SREDUCEX
5197
5198 SINSM:
5199         mov.l           ADJN(%a6),%d1
5200         cmp.l           %d1,&0
5201         bgt.b           COSTINY
5202
5203 # here, the operation may underflow iff the precision is sgl or dbl.
5204 # extended denorms are handled through another entry point.
5205 SINTINY:
5206 #       mov.w           &0x0000,XDCARE(%a6)     # JUST IN CASE
5207
5208         fmov.l          %d0,%fpcr               # restore users round mode,prec
5209         mov.b           &FMOV_OP,%d1            # last inst is MOVE
5210         fmov.x          X(%a6),%fp0             # last inst - possible exception set
5211         bra             t_catch
5212
5213 COSTINY:
5214         fmov.s          &0x3F800000,%fp0        # fp0 = 1.0
5215         fmov.l          %d0,%fpcr               # restore users round mode,prec
5216         fadd.s          &0x80800000,%fp0        # last inst - possible exception set
5217         bra             t_pinx2
5218
5219 ################################################
5220         global          ssind
5221 #--SIN(X) = X FOR DENORMALIZED X
5222 ssind:
5223         bra             t_extdnrm
5224
5225 ############################################
5226         global          scosd
5227 #--COS(X) = 1 FOR DENORMALIZED X
5228 scosd:
5229         fmov.s          &0x3F800000,%fp0        # fp0 = 1.0
5230         bra             t_pinx2
5231
5232 ##################################################
5233
5234         global          ssincos
5235 ssincos:
5236 #--SET ADJN TO 4
5237         mov.l           &4,ADJN(%a6)
5238
5239         fmov.x          (%a0),%fp0              # LOAD INPUT
5240         fmov.x          %fp0,X(%a6)
5241
5242         mov.l           (%a0),%d1
5243         mov.w           4(%a0),%d1
5244         and.l           &0x7FFFFFFF,%d1         # COMPACTIFY X
5245
5246         cmp.l           %d1,&0x3FD78000         # |X| >= 2**(-40)?
5247         bge.b           SCOK1
5248         bra.w           SCSM
5249
5250 SCOK1:
5251         cmp.l           %d1,&0x4004BC7E         # |X| < 15 PI?
5252         blt.b           SCMAIN
5253         bra.w           SREDUCEX
5254
5255
5256 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5257 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5258 SCMAIN:
5259         fmov.x          %fp0,%fp1
5260
5261         fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
5262
5263         lea             PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
5264
5265         fmov.l          %fp1,INT(%a6)           # CONVERT TO INTEGER
5266
5267         mov.l           INT(%a6),%d1
5268         asl.l           &4,%d1
5269         add.l           %d1,%a1                 # ADDRESS OF N*PIBY2, IN Y1, Y2
5270
5271         fsub.x          (%a1)+,%fp0             # X-Y1
5272         fsub.s          (%a1),%fp0              # FP0 IS R = (X-Y1)-Y2
5273
5274 SCCONT:
5275 #--continuation point from REDUCEX
5276
5277         mov.l           INT(%a6),%d1
5278         ror.l           &1,%d1
5279         cmp.l           %d1,&0                  # D0 < 0 IFF N IS ODD
5280         bge.w           NEVEN
5281
5282 SNODD:
5283 #--REGISTERS SAVED SO FAR: D0, A0, FP2.
5284         fmovm.x         &0x04,-(%sp)            # save fp2
5285
5286         fmov.x          %fp0,RPRIME(%a6)
5287         fmul.x          %fp0,%fp0               # FP0 IS S = R*R
5288         fmov.d          SINA7(%pc),%fp1         # A7
5289         fmov.d          COSB8(%pc),%fp2         # B8
5290         fmul.x          %fp0,%fp1               # SA7
5291         fmul.x          %fp0,%fp2               # SB8
5292
5293         mov.l           %d2,-(%sp)
5294         mov.l           %d1,%d2
5295         ror.l           &1,%d2
5296         and.l           &0x80000000,%d2
5297         eor.l           %d1,%d2
5298         and.l           &0x80000000,%d2
5299
5300         fadd.d          SINA6(%pc),%fp1         # A6+SA7
5301         fadd.d          COSB7(%pc),%fp2         # B7+SB8
5302
5303         fmul.x          %fp0,%fp1               # S(A6+SA7)
5304         eor.l           %d2,RPRIME(%a6)
5305         mov.l           (%sp)+,%d2
5306         fmul.x          %fp0,%fp2               # S(B7+SB8)
5307         ror.l           &1,%d1
5308         and.l           &0x80000000,%d1
5309         mov.l           &0x3F800000,POSNEG1(%a6)
5310         eor.l           %d1,POSNEG1(%a6)
5311
5312         fadd.d          SINA5(%pc),%fp1         # A5+S(A6+SA7)
5313         fadd.d          COSB6(%pc),%fp2         # B6+S(B7+SB8)
5314
5315         fmul.x          %fp0,%fp1               # S(A5+S(A6+SA7))
5316         fmul.x          %fp0,%fp2               # S(B6+S(B7+SB8))
5317         fmov.x          %fp0,SPRIME(%a6)
5318
5319         fadd.d          SINA4(%pc),%fp1         # A4+S(A5+S(A6+SA7))
5320         eor.l           %d1,SPRIME(%a6)
5321         fadd.d          COSB5(%pc),%fp2         # B5+S(B6+S(B7+SB8))
5322
5323         fmul.x          %fp0,%fp1               # S(A4+...)
5324         fmul.x          %fp0,%fp2               # S(B5+...)
5325
5326         fadd.d          SINA3(%pc),%fp1         # A3+S(A4+...)
5327         fadd.d          COSB4(%pc),%fp2         # B4+S(B5+...)
5328
5329         fmul.x          %fp0,%fp1               # S(A3+...)
5330         fmul.x          %fp0,%fp2               # S(B4+...)
5331
5332         fadd.x          SINA2(%pc),%fp1         # A2+S(A3+...)
5333         fadd.x          COSB3(%pc),%fp2         # B3+S(B4+...)
5334
5335         fmul.x          %fp0,%fp1               # S(A2+...)
5336         fmul.x          %fp0,%fp2               # S(B3+...)
5337
5338         fadd.x          SINA1(%pc),%fp1         # A1+S(A2+...)
5339         fadd.x          COSB2(%pc),%fp2         # B2+S(B3+...)
5340
5341         fmul.x          %fp0,%fp1               # S(A1+...)
5342         fmul.x          %fp2,%fp0               # S(B2+...)
5343
5344         fmul.x          RPRIME(%a6),%fp1        # R'S(A1+...)
5345         fadd.s          COSB1(%pc),%fp0         # B1+S(B2...)
5346         fmul.x          SPRIME(%a6),%fp0        # S'(B1+S(B2+...))
5347
5348         fmovm.x         (%sp)+,&0x20            # restore fp2
5349
5350         fmov.l          %d0,%fpcr
5351         fadd.x          RPRIME(%a6),%fp1        # COS(X)
5352         bsr             sto_cos                 # store cosine result
5353         fadd.s          POSNEG1(%a6),%fp0       # SIN(X)
5354         bra             t_inx2
5355
5356 NEVEN:
5357 #--REGISTERS SAVED SO FAR: FP2.
5358         fmovm.x         &0x04,-(%sp)            # save fp2
5359
5360         fmov.x          %fp0,RPRIME(%a6)
5361         fmul.x          %fp0,%fp0               # FP0 IS S = R*R
5362
5363         fmov.d          COSB8(%pc),%fp1         # B8
5364         fmov.d          SINA7(%pc),%fp2         # A7
5365
5366         fmul.x          %fp0,%fp1               # SB8
5367         fmov.x          %fp0,SPRIME(%a6)
5368         fmul.x          %fp0,%fp2               # SA7
5369
5370         ror.l           &1,%d1
5371         and.l           &0x80000000,%d1
5372
5373         fadd.d          COSB7(%pc),%fp1         # B7+SB8
5374         fadd.d          SINA6(%pc),%fp2         # A6+SA7
5375
5376         eor.l           %d1,RPRIME(%a6)
5377         eor.l           %d1,SPRIME(%a6)
5378
5379         fmul.x          %fp0,%fp1               # S(B7+SB8)
5380
5381         or.l            &0x3F800000,%d1
5382         mov.l           %d1,POSNEG1(%a6)
5383
5384         fmul.x          %fp0,%fp2               # S(A6+SA7)
5385
5386         fadd.d          COSB6(%pc),%fp1         # B6+S(B7+SB8)
5387         fadd.d          SINA5(%pc),%fp2         # A5+S(A6+SA7)
5388
5389         fmul.x          %fp0,%fp1               # S(B6+S(B7+SB8))
5390         fmul.x          %fp0,%fp2               # S(A5+S(A6+SA7))
5391
5392         fadd.d          COSB5(%pc),%fp1         # B5+S(B6+S(B7+SB8))
5393         fadd.d          SINA4(%pc),%fp2         # A4+S(A5+S(A6+SA7))
5394
5395         fmul.x          %fp0,%fp1               # S(B5+...)
5396         fmul.x          %fp0,%fp2               # S(A4+...)
5397
5398         fadd.d          COSB4(%pc),%fp1         # B4+S(B5+...)
5399         fadd.d          SINA3(%pc),%fp2         # A3+S(A4+...)
5400
5401         fmul.x          %fp0,%fp1               # S(B4+...)
5402         fmul.x          %fp0,%fp2               # S(A3+...)
5403
5404         fadd.x          COSB3(%pc),%fp1         # B3+S(B4+...)
5405         fadd.x          SINA2(%pc),%fp2         # A2+S(A3+...)
5406
5407         fmul.x          %fp0,%fp1               # S(B3+...)
5408         fmul.x          %fp0,%fp2               # S(A2+...)
5409
5410         fadd.x          COSB2(%pc),%fp1         # B2+S(B3+...)
5411         fadd.x          SINA1(%pc),%fp2         # A1+S(A2+...)
5412
5413         fmul.x          %fp0,%fp1               # S(B2+...)
5414         fmul.x          %fp2,%fp0               # s(a1+...)
5415
5416
5417         fadd.s          COSB1(%pc),%fp1         # B1+S(B2...)
5418         fmul.x          RPRIME(%a6),%fp0        # R'S(A1+...)
5419         fmul.x          SPRIME(%a6),%fp1        # S'(B1+S(B2+...))
5420
5421         fmovm.x         (%sp)+,&0x20            # restore fp2
5422
5423         fmov.l          %d0,%fpcr
5424         fadd.s          POSNEG1(%a6),%fp1       # COS(X)
5425         bsr             sto_cos                 # store cosine result
5426         fadd.x          RPRIME(%a6),%fp0        # SIN(X)
5427         bra             t_inx2
5428
5429 ################################################
5430
5431 SCBORS:
5432         cmp.l           %d1,&0x3FFF8000
5433         bgt.w           SREDUCEX
5434
5435 ################################################
5436
5437 SCSM:
5438 #       mov.w           &0x0000,XDCARE(%a6)
5439         fmov.s          &0x3F800000,%fp1
5440
5441         fmov.l          %d0,%fpcr
5442         fsub.s          &0x00800000,%fp1
5443         bsr             sto_cos                 # store cosine result
5444         fmov.l          %fpcr,%d0               # d0 must have fpcr,too
5445         mov.b           &FMOV_OP,%d1            # last inst is MOVE
5446         fmov.x          X(%a6),%fp0
5447         bra             t_catch
5448
5449 ##############################################
5450
5451         global          ssincosd
5452 #--SIN AND COS OF X FOR DENORMALIZED X
5453 ssincosd:
5454         mov.l           %d0,-(%sp)              # save d0
5455         fmov.s          &0x3F800000,%fp1
5456         bsr             sto_cos                 # store cosine result
5457         mov.l           (%sp)+,%d0              # restore d0
5458         bra             t_extdnrm
5459
5460 ############################################
5461
5462 #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5463 #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5464 #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5465 SREDUCEX:
5466         fmovm.x         &0x3c,-(%sp)            # save {fp2-fp5}
5467         mov.l           %d2,-(%sp)              # save d2
5468         fmov.s          &0x00000000,%fp1        # fp1 = 0
5469
5470 #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5471 #--there is a danger of unwanted overflow in first LOOP iteration.  In this
5472 #--case, reduce argument by one remainder step to make subsequent reduction
5473 #--safe.
5474         cmp.l           %d1,&0x7ffeffff         # is arg dangerously large?
5475         bne.b           SLOOP                   # no
5476
5477 # yes; create 2**16383*PI/2
5478         mov.w           &0x7ffe,FP_SCR0_EX(%a6)
5479         mov.l           &0xc90fdaa2,FP_SCR0_HI(%a6)
5480         clr.l           FP_SCR0_LO(%a6)
5481
5482 # create low half of 2**16383*PI/2 at FP_SCR1
5483         mov.w           &0x7fdc,FP_SCR1_EX(%a6)
5484         mov.l           &0x85a308d3,FP_SCR1_HI(%a6)
5485         clr.l           FP_SCR1_LO(%a6)
5486
5487         ftest.x         %fp0                    # test sign of argument
5488         fblt.w          sred_neg
5489
5490         or.b            &0x80,FP_SCR0_EX(%a6)   # positive arg
5491         or.b            &0x80,FP_SCR1_EX(%a6)
5492 sred_neg:
5493         fadd.x          FP_SCR0(%a6),%fp0       # high part of reduction is exact
5494         fmov.x          %fp0,%fp1               # save high result in fp1
5495         fadd.x          FP_SCR1(%a6),%fp0       # low part of reduction
5496         fsub.x          %fp0,%fp1               # determine low component of result
5497         fadd.x          FP_SCR1(%a6),%fp1       # fp0/fp1 are reduced argument.
5498
5499 #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5500 #--integer quotient will be stored in N
5501 #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5502 SLOOP:
5503         fmov.x          %fp0,INARG(%a6)         # +-2**K * F, 1 <= F < 2
5504         mov.w           INARG(%a6),%d1
5505         mov.l           %d1,%a1                 # save a copy of D0
5506         and.l           &0x00007FFF,%d1
5507         sub.l           &0x00003FFF,%d1         # d0 = K
5508         cmp.l           %d1,&28
5509         ble.b           SLASTLOOP
5510 SCONTLOOP:
5511         sub.l           &27,%d1                 # d0 = L := K-27
5512         mov.b           &0,ENDFLAG(%a6)
5513         bra.b           SWORK
5514 SLASTLOOP:
5515         clr.l           %d1                     # d0 = L := 0
5516         mov.b           &1,ENDFLAG(%a6)
5517
5518 SWORK:
5519 #--FIND THE REMAINDER OF (R,r) W.R.T.   2**L * (PI/2). L IS SO CHOSEN
5520 #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5521
5522 #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5523 #--2**L * (PIby2_1), 2**L * (PIby2_2)
5524
5525         mov.l           &0x00003FFE,%d2         # BIASED EXP OF 2/PI
5526         sub.l           %d1,%d2                 # BIASED EXP OF 2**(-L)*(2/PI)
5527
5528         mov.l           &0xA2F9836E,FP_SCR0_HI(%a6)
5529         mov.l           &0x4E44152A,FP_SCR0_LO(%a6)
5530         mov.w           %d2,FP_SCR0_EX(%a6)     # FP_SCR0 = 2**(-L)*(2/PI)
5531
5532         fmov.x          %fp0,%fp2
5533         fmul.x          FP_SCR0(%a6),%fp2       # fp2 = X * 2**(-L)*(2/PI)
5534
5535 #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5536 #--FLOATING POINT FORMAT, THE TWO FMOVE'S       FMOVE.L FP <--> N
5537 #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5538 #--(SIGN(INARG)*2**63   +       FP2) - SIGN(INARG)*2**63 WILL GIVE
5539 #--US THE DESIRED VALUE IN FLOATING POINT.
5540         mov.l           %a1,%d2
5541         swap            %d2
5542         and.l           &0x80000000,%d2
5543         or.l            &0x5F000000,%d2         # d2 = SIGN(INARG)*2**63 IN SGL
5544         mov.l           %d2,TWOTO63(%a6)
5545         fadd.s          TWOTO63(%a6),%fp2       # THE FRACTIONAL PART OF FP1 IS ROUNDED
5546         fsub.s          TWOTO63(%a6),%fp2       # fp2 = N
5547 #       fint.x          %fp2
5548
5549 #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5550         mov.l           %d1,%d2                 # d2 = L
5551
5552         add.l           &0x00003FFF,%d2         # BIASED EXP OF 2**L * (PI/2)
5553         mov.w           %d2,FP_SCR0_EX(%a6)
5554         mov.l           &0xC90FDAA2,FP_SCR0_HI(%a6)
5555         clr.l           FP_SCR0_LO(%a6)         # FP_SCR0 = 2**(L) * Piby2_1
5556
5557         add.l           &0x00003FDD,%d1
5558         mov.w           %d1,FP_SCR1_EX(%a6)
5559         mov.l           &0x85A308D3,FP_SCR1_HI(%a6)
5560         clr.l           FP_SCR1_LO(%a6)         # FP_SCR1 = 2**(L) * Piby2_2
5561
5562         mov.b           ENDFLAG(%a6),%d1
5563
5564 #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5565 #--P2 = 2**(L) * Piby2_2
5566         fmov.x          %fp2,%fp4               # fp4 = N
5567         fmul.x          FP_SCR0(%a6),%fp4       # fp4 = W = N*P1
5568         fmov.x          %fp2,%fp5               # fp5 = N
5569         fmul.x          FP_SCR1(%a6),%fp5       # fp5 = w = N*P2
5570         fmov.x          %fp4,%fp3               # fp3 = W = N*P1
5571
5572 #--we want P+p = W+w  but  |p| <= half ulp of P
5573 #--Then, we need to compute  A := R-P   and  a := r-p
5574         fadd.x          %fp5,%fp3               # fp3 = P
5575         fsub.x          %fp3,%fp4               # fp4 = W-P
5576
5577         fsub.x          %fp3,%fp0               # fp0 = A := R - P
5578         fadd.x          %fp5,%fp4               # fp4 = p = (W-P)+w
5579
5580         fmov.x          %fp0,%fp3               # fp3 = A
5581         fsub.x          %fp4,%fp1               # fp1 = a := r - p
5582
5583 #--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
5584 #--|r| <= half ulp of R.
5585         fadd.x          %fp1,%fp0               # fp0 = R := A+a
5586 #--No need to calculate r if this is the last loop
5587         cmp.b           %d1,&0
5588         bgt.w           SRESTORE
5589
5590 #--Need to calculate r
5591         fsub.x          %fp0,%fp3               # fp3 = A-R
5592         fadd.x          %fp3,%fp1               # fp1 = r := (A-R)+a
5593         bra.w           SLOOP
5594
5595 SRESTORE:
5596         fmov.l          %fp2,INT(%a6)
5597         mov.l           (%sp)+,%d2              # restore d2
5598         fmovm.x         (%sp)+,&0x3c            # restore {fp2-fp5}
5599
5600         mov.l           ADJN(%a6),%d1
5601         cmp.l           %d1,&4
5602
5603         blt.w           SINCONT
5604         bra.w           SCCONT
5605
5606 #########################################################################
5607 # stan():  computes the tangent of a normalized input                   #
5608 # stand(): computes the tangent of a denormalized input                 #
5609 #                                                                       #
5610 # INPUT *************************************************************** #
5611 #       a0 = pointer to extended precision input                        #
5612 #       d0 = round precision,mode                                       #
5613 #                                                                       #
5614 # OUTPUT ************************************************************** #
5615 #       fp0 = tan(X)                                                    #
5616 #                                                                       #
5617 # ACCURACY and MONOTONICITY ******************************************* #
5618 #       The returned result is within 3 ulp in 64 significant bit, i.e. #
5619 #       within 0.5001 ulp to 53 bits if the result is subsequently      #
5620 #       rounded to double precision. The result is provably monotonic   #
5621 #       in double precision.                                            #
5622 #                                                                       #
5623 # ALGORITHM *********************************************************** #
5624 #                                                                       #
5625 #       1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.                   #
5626 #                                                                       #
5627 #       2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let        #
5628 #               k = N mod 2, so in particular, k = 0 or 1.              #
5629 #                                                                       #
5630 #       3. If k is odd, go to 5.                                        #
5631 #                                                                       #
5632 #       4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a  #
5633 #               rational function U/V where                             #
5634 #               U = r + r*s*(P1 + s*(P2 + s*P3)), and                   #
5635 #               V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))),  s = r*r.      #
5636 #               Exit.                                                   #
5637 #                                                                       #
5638 #       4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
5639 #               a rational function U/V where                           #
5640 #               U = r + r*s*(P1 + s*(P2 + s*P3)), and                   #
5641 #               V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r,       #
5642 #               -Cot(r) = -V/U. Exit.                                   #
5643 #                                                                       #
5644 #       6. If |X| > 1, go to 8.                                         #
5645 #                                                                       #
5646 #       7. (|X|<2**(-40)) Tan(X) = X. Exit.                             #
5647 #                                                                       #
5648 #       8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back   #
5649 #               to 2.                                                   #
5650 #                                                                       #
5651 #########################################################################
5652
5653 TANQ4:
5654         long            0x3EA0B759,0xF50F8688
5655 TANP3:
5656         long            0xBEF2BAA5,0xA8924F04
5657
5658 TANQ3:
5659         long            0xBF346F59,0xB39BA65F,0x00000000,0x00000000
5660
5661 TANP2:
5662         long            0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
5663
5664 TANQ2:
5665         long            0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
5666
5667 TANP1:
5668         long            0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
5669
5670 TANQ1:
5671         long            0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
5672
5673 INVTWOPI:
5674         long            0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
5675
5676 TWOPI1:
5677         long            0x40010000,0xC90FDAA2,0x00000000,0x00000000
5678 TWOPI2:
5679         long            0x3FDF0000,0x85A308D4,0x00000000,0x00000000
5680
5681 #--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
5682 #--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
5683 #--MOST 69 BITS LONG.
5684 #       global          PITBL
5685 PITBL:
5686         long            0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
5687         long            0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
5688         long            0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
5689         long            0xC0040000,0xB6365E22,0xEE46F000,0x21480000
5690         long            0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
5691         long            0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
5692         long            0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
5693         long            0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
5694         long            0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
5695         long            0xC0040000,0x90836524,0x88034B96,0x20B00000
5696         long            0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
5697         long            0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
5698         long            0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
5699         long            0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
5700         long            0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
5701         long            0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
5702         long            0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
5703         long            0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
5704         long            0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
5705         long            0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
5706         long            0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
5707         long            0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
5708         long            0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
5709         long            0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
5710         long            0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
5711         long            0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
5712         long            0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
5713         long            0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
5714         long            0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
5715         long            0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
5716         long            0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
5717         long            0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
5718         long            0x00000000,0x00000000,0x00000000,0x00000000
5719         long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
5720         long            0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
5721         long            0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
5722         long            0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
5723         long            0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
5724         long            0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
5725         long            0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
5726         long            0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
5727         long            0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
5728         long            0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
5729         long            0x40030000,0x8A3AE64F,0x76F80584,0x21080000
5730         long            0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
5731         long            0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
5732         long            0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
5733         long            0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
5734         long            0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
5735         long            0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
5736         long            0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
5737         long            0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
5738         long            0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
5739         long            0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
5740         long            0x40040000,0x8A3AE64F,0x76F80584,0x21880000
5741         long            0x40040000,0x90836524,0x88034B96,0xA0B00000
5742         long            0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
5743         long            0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
5744         long            0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
5745         long            0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
5746         long            0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
5747         long            0x40040000,0xB6365E22,0xEE46F000,0xA1480000
5748         long            0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
5749         long            0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
5750         long            0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
5751
5752         set             INARG,FP_SCR0
5753
5754         set             TWOTO63,L_SCR1
5755         set             INT,L_SCR1
5756         set             ENDFLAG,L_SCR2
5757
5758         global          stan
5759 stan:
5760         fmov.x          (%a0),%fp0              # LOAD INPUT
5761
5762         mov.l           (%a0),%d1
5763         mov.w           4(%a0),%d1
5764         and.l           &0x7FFFFFFF,%d1
5765
5766         cmp.l           %d1,&0x3FD78000         # |X| >= 2**(-40)?
5767         bge.b           TANOK1
5768         bra.w           TANSM
5769 TANOK1:
5770         cmp.l           %d1,&0x4004BC7E         # |X| < 15 PI?
5771         blt.b           TANMAIN
5772         bra.w           REDUCEX
5773
5774 TANMAIN:
5775 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5776 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5777         fmov.x          %fp0,%fp1
5778         fmul.d          TWOBYPI(%pc),%fp1       # X*2/PI
5779
5780         lea.l           PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
5781
5782         fmov.l          %fp1,%d1                # CONVERT TO INTEGER
5783
5784         asl.l           &4,%d1
5785         add.l           %d1,%a1                 # ADDRESS N*PIBY2 IN Y1, Y2
5786
5787         fsub.x          (%a1)+,%fp0             # X-Y1
5788
5789         fsub.s          (%a1),%fp0              # FP0 IS R = (X-Y1)-Y2
5790
5791         ror.l           &5,%d1
5792         and.l           &0x80000000,%d1         # D0 WAS ODD IFF D0 < 0
5793
5794 TANCONT:
5795         fmovm.x         &0x0c,-(%sp)            # save fp2,fp3
5796
5797         cmp.l           %d1,&0
5798         blt.w           NODD
5799
5800         fmov.x          %fp0,%fp1
5801         fmul.x          %fp1,%fp1               # S = R*R
5802
5803         fmov.d          TANQ4(%pc),%fp3
5804         fmov.d          TANP3(%pc),%fp2
5805
5806         fmul.x          %fp1,%fp3               # SQ4
5807         fmul.x          %fp1,%fp2               # SP3
5808
5809         fadd.d          TANQ3(%pc),%fp3         # Q3+SQ4
5810         fadd.x          TANP2(%pc),%fp2         # P2+SP3
5811
5812         fmul.x          %fp1,%fp3               # S(Q3+SQ4)
5813         fmul.x          %fp1,%fp2               # S(P2+SP3)
5814
5815         fadd.x          TANQ2(%pc),%fp3         # Q2+S(Q3+SQ4)
5816         fadd.x          TANP1(%pc),%fp2         # P1+S(P2+SP3)
5817
5818         fmul.x          %fp1,%fp3               # S(Q2+S(Q3+SQ4))
5819         fmul.x          %fp1,%fp2               # S(P1+S(P2+SP3))
5820
5821         fadd.x          TANQ1(%pc),%fp3         # Q1+S(Q2+S(Q3+SQ4))
5822         fmul.x          %fp0,%fp2               # RS(P1+S(P2+SP3))
5823
5824         fmul.x          %fp3,%fp1               # S(Q1+S(Q2+S(Q3+SQ4)))
5825
5826         fadd.x          %fp2,%fp0               # R+RS(P1+S(P2+SP3))
5827
5828         fadd.s          &0x3F800000,%fp1        # 1+S(Q1+...)
5829
5830         fmovm.x         (%sp)+,&0x30            # restore fp2,fp3
5831
5832         fmov.l          %d0,%fpcr               # restore users round mode,prec
5833         fdiv.x          %fp1,%fp0               # last inst - possible exception set
5834         bra             t_inx2
5835
5836 NODD:
5837         fmov.x          %fp0,%fp1
5838         fmul.x          %fp0,%fp0               # S = R*R
5839
5840         fmov.d          TANQ4(%pc),%fp3
5841         fmov.d          TANP3(%pc),%fp2
5842
5843         fmul.x          %fp0,%fp3               # SQ4
5844         fmul.x          %fp0,%fp2               # SP3
5845
5846         fadd.d          TANQ3(%pc),%fp3         # Q3+SQ4
5847         fadd.x          TANP2(%pc),%fp2         # P2+SP3
5848
5849         fmul.x          %fp0,%fp3               # S(Q3+SQ4)
5850         fmul.x          %fp0,%fp2               # S(P2+SP3)
5851
5852         fadd.x          TANQ2(%pc),%fp3         # Q2+S(Q3+SQ4)
5853         fadd.x          TANP1(%pc),%fp2         # P1+S(P2+SP3)
5854
5855         fmul.x          %fp0,%fp3               # S(Q2+S(Q3+SQ4))
5856         fmul.x          %fp0,%fp2               # S(P1+S(P2+SP3))
5857
5858         fadd.x          TANQ1(%pc),%fp3         # Q1+S(Q2+S(Q3+SQ4))
5859         fmul.x          %fp1,%fp2               # RS(P1+S(P2+SP3))
5860
5861         fmul.x          %fp3,%fp0               # S(Q1+S(Q2+S(Q3+SQ4)))
5862
5863         fadd.x          %fp2,%fp1               # R+RS(P1+S(P2+SP3))
5864         fadd.s          &0x3F800000,%fp0        # 1+S(Q1+...)
5865
5866         fmovm.x         (%sp)+,&0x30            # restore fp2,fp3
5867
5868         fmov.x          %fp1,-(%sp)
5869         eor.l           &0x80000000,(%sp)
5870
5871         fmov.l          %d0,%fpcr               # restore users round mode,prec
5872         fdiv.x          (%sp)+,%fp0             # last inst - possible exception set
5873         bra             t_inx2
5874
5875 TANBORS:
5876 #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5877 #--IF |X| < 2**(-40), RETURN X OR 1.
5878         cmp.l           %d1,&0x3FFF8000
5879         bgt.b           REDUCEX
5880
5881 TANSM:
5882         fmov.x          %fp0,-(%sp)
5883         fmov.l          %d0,%fpcr               # restore users round mode,prec
5884         mov.b           &FMOV_OP,%d1            # last inst is MOVE
5885         fmov.x          (%sp)+,%fp0             # last inst - posibble exception set
5886         bra             t_catch
5887
5888         global          stand
5889 #--TAN(X) = X FOR DENORMALIZED X
5890 stand:
5891         bra             t_extdnrm
5892
5893 #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5894 #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5895 #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5896 REDUCEX:
5897         fmovm.x         &0x3c,-(%sp)            # save {fp2-fp5}
5898         mov.l           %d2,-(%sp)              # save d2
5899         fmov.s          &0x00000000,%fp1        # fp1 = 0
5900
5901 #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5902 #--there is a danger of unwanted overflow in first LOOP iteration.  In this
5903 #--case, reduce argument by one remainder step to make subsequent reduction
5904 #--safe.
5905         cmp.l           %d1,&0x7ffeffff         # is arg dangerously large?
5906         bne.b           LOOP                    # no
5907
5908 # yes; create 2**16383*PI/2
5909         mov.w           &0x7ffe,FP_SCR0_EX(%a6)
5910         mov.l           &0xc90fdaa2,FP_SCR0_HI(%a6)
5911         clr.l           FP_SCR0_LO(%a6)
5912
5913 # create low half of 2**16383*PI/2 at FP_SCR1
5914         mov.w           &0x7fdc,FP_SCR1_EX(%a6)
5915         mov.l           &0x85a308d3,FP_SCR1_HI(%a6)
5916         clr.l           FP_SCR1_LO(%a6)
5917
5918         ftest.x         %fp0                    # test sign of argument
5919         fblt.w          red_neg
5920
5921         or.b            &0x80,FP_SCR0_EX(%a6)   # positive arg
5922         or.b            &0x80,FP_SCR1_EX(%a6)
5923 red_neg:
5924         fadd.x          FP_SCR0(%a6),%fp0       # high part of reduction is exact
5925         fmov.x          %fp0,%fp1               # save high result in fp1
5926         fadd.x          FP_SCR1(%a6),%fp0       # low part of reduction
5927         fsub.x          %fp0,%fp1               # determine low component of result
5928         fadd.x          FP_SCR1(%a6),%fp1       # fp0/fp1 are reduced argument.
5929
5930 #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5931 #--integer quotient will be stored in N
5932 #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5933 LOOP:
5934         fmov.x          %fp0,INARG(%a6)         # +-2**K * F, 1 <= F < 2
5935         mov.w           INARG(%a6),%d1
5936         mov.l           %d1,%a1                 # save a copy of D0
5937         and.l           &0x00007FFF,%d1
5938         sub.l           &0x00003FFF,%d1         # d0 = K
5939         cmp.l           %d1,&28
5940         ble.b           LASTLOOP
5941 CONTLOOP:
5942         sub.l           &27,%d1                 # d0 = L := K-27
5943         mov.b           &0,ENDFLAG(%a6)
5944         bra.b           WORK
5945 LASTLOOP:
5946         clr.l           %d1                     # d0 = L := 0
5947         mov.b           &1,ENDFLAG(%a6)
5948
5949 WORK:
5950 #--FIND THE REMAINDER OF (R,r) W.R.T.   2**L * (PI/2). L IS SO CHOSEN
5951 #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5952
5953 #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5954 #--2**L * (PIby2_1), 2**L * (PIby2_2)
5955
5956         mov.l           &0x00003FFE,%d2         # BIASED EXP OF 2/PI
5957         sub.l           %d1,%d2                 # BIASED EXP OF 2**(-L)*(2/PI)
5958
5959         mov.l           &0xA2F9836E,FP_SCR0_HI(%a6)
5960         mov.l           &0x4E44152A,FP_SCR0_LO(%a6)
5961         mov.w           %d2,FP_SCR0_EX(%a6)     # FP_SCR0 = 2**(-L)*(2/PI)
5962
5963         fmov.x          %fp0,%fp2
5964         fmul.x          FP_SCR0(%a6),%fp2       # fp2 = X * 2**(-L)*(2/PI)
5965
5966 #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5967 #--FLOATING POINT FORMAT, THE TWO FMOVE'S       FMOVE.L FP <--> N
5968 #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5969 #--(SIGN(INARG)*2**63   +       FP2) - SIGN(INARG)*2**63 WILL GIVE
5970 #--US THE DESIRED VALUE IN FLOATING POINT.
5971         mov.l           %a1,%d2
5972         swap            %d2
5973         and.l           &0x80000000,%d2
5974         or.l            &0x5F000000,%d2         # d2 = SIGN(INARG)*2**63 IN SGL
5975         mov.l           %d2,TWOTO63(%a6)
5976         fadd.s          TWOTO63(%a6),%fp2       # THE FRACTIONAL PART OF FP1 IS ROUNDED
5977         fsub.s          TWOTO63(%a6),%fp2       # fp2 = N
5978 #       fintrz.x        %fp2,%fp2
5979
5980 #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5981         mov.l           %d1,%d2                 # d2 = L
5982
5983         add.l           &0x00003FFF,%d2         # BIASED EXP OF 2**L * (PI/2)
5984         mov.w           %d2,FP_SCR0_EX(%a6)
5985         mov.l           &0xC90FDAA2,FP_SCR0_HI(%a6)
5986         clr.l           FP_SCR0_LO(%a6)         # FP_SCR0 = 2**(L) * Piby2_1
5987
5988         add.l           &0x00003FDD,%d1
5989         mov.w           %d1,FP_SCR1_EX(%a6)
5990         mov.l           &0x85A308D3,FP_SCR1_HI(%a6)
5991         clr.l           FP_SCR1_LO(%a6)         # FP_SCR1 = 2**(L) * Piby2_2
5992
5993         mov.b           ENDFLAG(%a6),%d1
5994
5995 #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5996 #--P2 = 2**(L) * Piby2_2
5997         fmov.x          %fp2,%fp4               # fp4 = N
5998         fmul.x          FP_SCR0(%a6),%fp4       # fp4 = W = N*P1
5999         fmov.x          %fp2,%fp5               # fp5 = N
6000         fmul.x          FP_SCR1(%a6),%fp5       # fp5 = w = N*P2
6001         fmov.x          %fp4,%fp3               # fp3 = W = N*P1
6002
6003 #--we want P+p = W+w  but  |p| <= half ulp of P
6004 #--Then, we need to compute  A := R-P   and  a := r-p
6005         fadd.x          %fp5,%fp3               # fp3 = P
6006         fsub.x          %fp3,%fp4               # fp4 = W-P
6007
6008         fsub.x          %fp3,%fp0               # fp0 = A := R - P
6009         fadd.x          %fp5,%fp4               # fp4 = p = (W-P)+w
6010
6011         fmov.x          %fp0,%fp3               # fp3 = A
6012         fsub.x          %fp4,%fp1               # fp1 = a := r - p
6013
6014 #--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
6015 #--|r| <= half ulp of R.
6016         fadd.x          %fp1,%fp0               # fp0 = R := A+a
6017 #--No need to calculate r if this is the last loop
6018         cmp.b           %d1,&0
6019         bgt.w           RESTORE
6020
6021 #--Need to calculate r
6022         fsub.x          %fp0,%fp3               # fp3 = A-R
6023         fadd.x          %fp3,%fp1               # fp1 = r := (A-R)+a
6024         bra.w           LOOP
6025
6026 RESTORE:
6027         fmov.l          %fp2,INT(%a6)
6028         mov.l           (%sp)+,%d2              # restore d2
6029         fmovm.x         (%sp)+,&0x3c            # restore {fp2-fp5}
6030
6031         mov.l           INT(%a6),%d1
6032         ror.l           &1,%d1
6033
6034         bra.w           TANCONT
6035
6036 #########################################################################
6037 # satan():  computes the arctangent of a normalized number              #
6038 # satand(): computes the arctangent of a denormalized number            #
6039 #                                                                       #
6040 # INPUT *************************************************************** #
6041 #       a0 = pointer to extended precision input                        #
6042 #       d0 = round precision,mode                                       #
6043 #                                                                       #
6044 # OUTPUT ************************************************************** #
6045 #       fp0 = arctan(X)                                                 #
6046 #                                                                       #
6047 # ACCURACY and MONOTONICITY ******************************************* #
6048 #       The returned result is within 2 ulps in 64 significant bit,     #
6049 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6050 #       rounded to double precision. The result is provably monotonic   #
6051 #       in double precision.                                            #
6052 #                                                                       #
6053 # ALGORITHM *********************************************************** #
6054 #       Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5.               #
6055 #                                                                       #
6056 #       Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x.                    #
6057 #               Note that k = -4, -3,..., or 3.                         #
6058 #               Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5       #
6059 #               significant bits of X with a bit-1 attached at the 6-th #
6060 #               bit position. Define u to be u = (X-F) / (1 + X*F).     #
6061 #                                                                       #
6062 #       Step 3. Approximate arctan(u) by a polynomial poly.             #
6063 #                                                                       #
6064 #       Step 4. Return arctan(F) + poly, arctan(F) is fetched from a    #
6065 #               table of values calculated beforehand. Exit.            #
6066 #                                                                       #
6067 #       Step 5. If |X| >= 16, go to Step 7.                             #
6068 #                                                                       #
6069 #       Step 6. Approximate arctan(X) by an odd polynomial in X. Exit.  #
6070 #                                                                       #
6071 #       Step 7. Define X' = -1/X. Approximate arctan(X') by an odd      #
6072 #               polynomial in X'.                                       #
6073 #               Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit.            #
6074 #                                                                       #
6075 #########################################################################
6076
6077 ATANA3: long            0xBFF6687E,0x314987D8
6078 ATANA2: long            0x4002AC69,0x34A26DB3
6079 ATANA1: long            0xBFC2476F,0x4E1DA28E
6080
6081 ATANB6: long            0x3FB34444,0x7F876989
6082 ATANB5: long            0xBFB744EE,0x7FAF45DB
6083 ATANB4: long            0x3FBC71C6,0x46940220
6084 ATANB3: long            0xBFC24924,0x921872F9
6085 ATANB2: long            0x3FC99999,0x99998FA9
6086 ATANB1: long            0xBFD55555,0x55555555
6087
6088 ATANC5: long            0xBFB70BF3,0x98539E6A
6089 ATANC4: long            0x3FBC7187,0x962D1D7D
6090 ATANC3: long            0xBFC24924,0x827107B8
6091 ATANC2: long            0x3FC99999,0x9996263E
6092 ATANC1: long            0xBFD55555,0x55555536
6093
6094 PPIBY2: long            0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
6095 NPIBY2: long            0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
6096
6097 PTINY:  long            0x00010000,0x80000000,0x00000000,0x00000000
6098 NTINY:  long            0x80010000,0x80000000,0x00000000,0x00000000
6099
6100 ATANTBL:
6101         long            0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
6102         long            0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
6103         long            0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
6104         long            0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
6105         long            0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
6106         long            0x3FFB0000,0xAB98E943,0x62765619,0x00000000
6107         long            0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
6108         long            0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
6109         long            0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
6110         long            0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
6111         long            0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
6112         long            0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
6113         long            0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
6114         long            0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
6115         long            0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
6116         long            0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
6117         long            0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
6118         long            0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
6119         long            0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
6120         long            0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
6121         long            0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
6122         long            0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
6123         long            0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
6124         long            0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
6125         long            0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
6126         long            0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
6127         long            0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
6128         long            0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
6129         long            0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
6130         long            0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
6131         long            0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
6132         long            0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
6133         long            0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
6134         long            0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
6135         long            0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
6136         long            0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
6137         long            0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
6138         long            0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
6139         long            0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
6140         long            0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
6141         long            0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
6142         long            0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
6143         long            0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
6144         long            0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
6145         long            0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
6146         long            0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
6147         long            0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
6148         long            0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
6149         long            0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
6150         long            0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
6151         long            0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
6152         long            0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
6153         long            0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
6154         long            0x3FFE0000,0x97731420,0x365E538C,0x00000000
6155         long            0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
6156         long            0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
6157         long            0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
6158         long            0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
6159         long            0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
6160         long            0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
6161         long            0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
6162         long            0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
6163         long            0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
6164         long            0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
6165         long            0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
6166         long            0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
6167         long            0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
6168         long            0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
6169         long            0x3FFE0000,0xE8771129,0xC4353259,0x00000000
6170         long            0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
6171         long            0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
6172         long            0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
6173         long            0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
6174         long            0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
6175         long            0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
6176         long            0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
6177         long            0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
6178         long            0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
6179         long            0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
6180         long            0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
6181         long            0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
6182         long            0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
6183         long            0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
6184         long            0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
6185         long            0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
6186         long            0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
6187         long            0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
6188         long            0x3FFF0000,0x9F100575,0x006CC571,0x00000000
6189         long            0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
6190         long            0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
6191         long            0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
6192         long            0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
6193         long            0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
6194         long            0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
6195         long            0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
6196         long            0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
6197         long            0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
6198         long            0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
6199         long            0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
6200         long            0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
6201         long            0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
6202         long            0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
6203         long            0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
6204         long            0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
6205         long            0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
6206         long            0x3FFF0000,0xB525529D,0x562246BD,0x00000000
6207         long            0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
6208         long            0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
6209         long            0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
6210         long            0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
6211         long            0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
6212         long            0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
6213         long            0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
6214         long            0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
6215         long            0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
6216         long            0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
6217         long            0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
6218         long            0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
6219         long            0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
6220         long            0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
6221         long            0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
6222         long            0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
6223         long            0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
6224         long            0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
6225         long            0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
6226         long            0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
6227         long            0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
6228         long            0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
6229
6230         set             X,FP_SCR0
6231         set             XDCARE,X+2
6232         set             XFRAC,X+4
6233         set             XFRACLO,X+8
6234
6235         set             ATANF,FP_SCR1
6236         set             ATANFHI,ATANF+4
6237         set             ATANFLO,ATANF+8
6238
6239         global          satan
6240 #--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
6241 satan:
6242         fmov.x          (%a0),%fp0              # LOAD INPUT
6243
6244         mov.l           (%a0),%d1
6245         mov.w           4(%a0),%d1
6246         fmov.x          %fp0,X(%a6)
6247         and.l           &0x7FFFFFFF,%d1
6248
6249         cmp.l           %d1,&0x3FFB8000         # |X| >= 1/16?
6250         bge.b           ATANOK1
6251         bra.w           ATANSM
6252
6253 ATANOK1:
6254         cmp.l           %d1,&0x4002FFFF         # |X| < 16 ?
6255         ble.b           ATANMAIN
6256         bra.w           ATANBIG
6257
6258 #--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
6259 #--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
6260 #--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
6261 #--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
6262 #--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
6263 #--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
6264 #--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
6265 #--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
6266 #--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
6267 #--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
6268 #--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
6269 #--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
6270 #--WILL INVOLVE A VERY LONG POLYNOMIAL.
6271
6272 #--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
6273 #--WE CHOSE F TO BE +-2^K * 1.BBBB1
6274 #--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
6275 #--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
6276 #--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
6277 #-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
6278
6279 ATANMAIN:
6280
6281         and.l           &0xF8000000,XFRAC(%a6)  # FIRST 5 BITS
6282         or.l            &0x04000000,XFRAC(%a6)  # SET 6-TH BIT TO 1
6283         mov.l           &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
6284
6285         fmov.x          %fp0,%fp1               # FP1 IS X
6286         fmul.x          X(%a6),%fp1             # FP1 IS X*F, NOTE THAT X*F > 0
6287         fsub.x          X(%a6),%fp0             # FP0 IS X-F
6288         fadd.s          &0x3F800000,%fp1        # FP1 IS 1 + X*F
6289         fdiv.x          %fp1,%fp0               # FP0 IS U = (X-F)/(1+X*F)
6290
6291 #--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
6292 #--CREATE ATAN(F) AND STORE IT IN ATANF, AND
6293 #--SAVE REGISTERS FP2.
6294
6295         mov.l           %d2,-(%sp)              # SAVE d2 TEMPORARILY
6296         mov.l           %d1,%d2                 # THE EXP AND 16 BITS OF X
6297         and.l           &0x00007800,%d1         # 4 VARYING BITS OF F'S FRACTION
6298         and.l           &0x7FFF0000,%d2         # EXPONENT OF F
6299         sub.l           &0x3FFB0000,%d2         # K+4
6300         asr.l           &1,%d2
6301         add.l           %d2,%d1                 # THE 7 BITS IDENTIFYING F
6302         asr.l           &7,%d1                  # INDEX INTO TBL OF ATAN(|F|)
6303         lea             ATANTBL(%pc),%a1
6304         add.l           %d1,%a1                 # ADDRESS OF ATAN(|F|)
6305         mov.l           (%a1)+,ATANF(%a6)
6306         mov.l           (%a1)+,ATANFHI(%a6)
6307         mov.l           (%a1)+,ATANFLO(%a6)     # ATANF IS NOW ATAN(|F|)
6308         mov.l           X(%a6),%d1              # LOAD SIGN AND EXPO. AGAIN
6309         and.l           &0x80000000,%d1         # SIGN(F)
6310         or.l            %d1,ATANF(%a6)          # ATANF IS NOW SIGN(F)*ATAN(|F|)
6311         mov.l           (%sp)+,%d2              # RESTORE d2
6312
6313 #--THAT'S ALL I HAVE TO DO FOR NOW,
6314 #--BUT ALAS, THE DIVIDE IS STILL CRANKING!
6315
6316 #--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
6317 #--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
6318 #--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
6319 #--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
6320 #--WHAT WE HAVE HERE IS MERELY  A1 = A3, A2 = A1/A3, A3 = A2/A3.
6321 #--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
6322 #--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
6323
6324         fmovm.x         &0x04,-(%sp)            # save fp2
6325
6326         fmov.x          %fp0,%fp1
6327         fmul.x          %fp1,%fp1
6328         fmov.d          ATANA3(%pc),%fp2
6329         fadd.x          %fp1,%fp2               # A3+V
6330         fmul.x          %fp1,%fp2               # V*(A3+V)
6331         fmul.x          %fp0,%fp1               # U*V
6332         fadd.d          ATANA2(%pc),%fp2        # A2+V*(A3+V)
6333         fmul.d          ATANA1(%pc),%fp1        # A1*U*V
6334         fmul.x          %fp2,%fp1               # A1*U*V*(A2+V*(A3+V))
6335         fadd.x          %fp1,%fp0               # ATAN(U), FP1 RELEASED
6336
6337         fmovm.x         (%sp)+,&0x20            # restore fp2
6338
6339         fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6340         fadd.x          ATANF(%a6),%fp0         # ATAN(X)
6341         bra             t_inx2
6342
6343 ATANBORS:
6344 #--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
6345 #--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
6346         cmp.l           %d1,&0x3FFF8000
6347         bgt.w           ATANBIG                 # I.E. |X| >= 16
6348
6349 ATANSM:
6350 #--|X| <= 1/16
6351 #--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
6352 #--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
6353 #--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
6354 #--WHERE Y = X*X, AND Z = Y*Y.
6355
6356         cmp.l           %d1,&0x3FD78000
6357         blt.w           ATANTINY
6358
6359 #--COMPUTE POLYNOMIAL
6360         fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
6361
6362         fmul.x          %fp0,%fp0               # FPO IS Y = X*X
6363
6364         fmov.x          %fp0,%fp1
6365         fmul.x          %fp1,%fp1               # FP1 IS Z = Y*Y
6366
6367         fmov.d          ATANB6(%pc),%fp2
6368         fmov.d          ATANB5(%pc),%fp3
6369
6370         fmul.x          %fp1,%fp2               # Z*B6
6371         fmul.x          %fp1,%fp3               # Z*B5
6372
6373         fadd.d          ATANB4(%pc),%fp2        # B4+Z*B6
6374         fadd.d          ATANB3(%pc),%fp3        # B3+Z*B5
6375
6376         fmul.x          %fp1,%fp2               # Z*(B4+Z*B6)
6377         fmul.x          %fp3,%fp1               # Z*(B3+Z*B5)
6378
6379         fadd.d          ATANB2(%pc),%fp2        # B2+Z*(B4+Z*B6)
6380         fadd.d          ATANB1(%pc),%fp1        # B1+Z*(B3+Z*B5)
6381
6382         fmul.x          %fp0,%fp2               # Y*(B2+Z*(B4+Z*B6))
6383         fmul.x          X(%a6),%fp0             # X*Y
6384
6385         fadd.x          %fp2,%fp1               # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
6386
6387         fmul.x          %fp1,%fp0               # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
6388
6389         fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
6390
6391         fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6392         fadd.x          X(%a6),%fp0
6393         bra             t_inx2
6394
6395 ATANTINY:
6396 #--|X| < 2^(-40), ATAN(X) = X
6397
6398         fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6399         mov.b           &FMOV_OP,%d1            # last inst is MOVE
6400         fmov.x          X(%a6),%fp0             # last inst - possible exception set
6401
6402         bra             t_catch
6403
6404 ATANBIG:
6405 #--IF |X| > 2^(100), RETURN     SIGN(X)*(PI/2 - TINY). OTHERWISE,
6406 #--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
6407         cmp.l           %d1,&0x40638000
6408         bgt.w           ATANHUGE
6409
6410 #--APPROXIMATE ATAN(-1/X) BY
6411 #--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
6412 #--THIS CAN BE RE-WRITTEN AS
6413 #--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
6414
6415         fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
6416
6417         fmov.s          &0xBF800000,%fp1        # LOAD -1
6418         fdiv.x          %fp0,%fp1               # FP1 IS -1/X
6419
6420 #--DIVIDE IS STILL CRANKING
6421
6422         fmov.x          %fp1,%fp0               # FP0 IS X'
6423         fmul.x          %fp0,%fp0               # FP0 IS Y = X'*X'
6424         fmov.x          %fp1,X(%a6)             # X IS REALLY X'
6425
6426         fmov.x          %fp0,%fp1
6427         fmul.x          %fp1,%fp1               # FP1 IS Z = Y*Y
6428
6429         fmov.d          ATANC5(%pc),%fp3
6430         fmov.d          ATANC4(%pc),%fp2
6431
6432         fmul.x          %fp1,%fp3               # Z*C5
6433         fmul.x          %fp1,%fp2               # Z*B4
6434
6435         fadd.d          ATANC3(%pc),%fp3        # C3+Z*C5
6436         fadd.d          ATANC2(%pc),%fp2        # C2+Z*C4
6437
6438         fmul.x          %fp3,%fp1               # Z*(C3+Z*C5), FP3 RELEASED
6439         fmul.x          %fp0,%fp2               # Y*(C2+Z*C4)
6440
6441         fadd.d          ATANC1(%pc),%fp1        # C1+Z*(C3+Z*C5)
6442         fmul.x          X(%a6),%fp0             # X'*Y
6443
6444         fadd.x          %fp2,%fp1               # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
6445
6446         fmul.x          %fp1,%fp0               # X'*Y*([B1+Z*(B3+Z*B5)]
6447 #                                       ...     +[Y*(B2+Z*(B4+Z*B6))])
6448         fadd.x          X(%a6),%fp0
6449
6450         fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
6451
6452         fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6453         tst.b           (%a0)
6454         bpl.b           pos_big
6455
6456 neg_big:
6457         fadd.x          NPIBY2(%pc),%fp0
6458         bra             t_minx2
6459
6460 pos_big:
6461         fadd.x          PPIBY2(%pc),%fp0
6462         bra             t_pinx2
6463
6464 ATANHUGE:
6465 #--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
6466         tst.b           (%a0)
6467         bpl.b           pos_huge
6468
6469 neg_huge:
6470         fmov.x          NPIBY2(%pc),%fp0
6471         fmov.l          %d0,%fpcr
6472         fadd.x          PTINY(%pc),%fp0
6473         bra             t_minx2
6474
6475 pos_huge:
6476         fmov.x          PPIBY2(%pc),%fp0
6477         fmov.l          %d0,%fpcr
6478         fadd.x          NTINY(%pc),%fp0
6479         bra             t_pinx2
6480
6481         global          satand
6482 #--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
6483 satand:
6484         bra             t_extdnrm
6485
6486 #########################################################################
6487 # sasin():  computes the inverse sine of a normalized input             #
6488 # sasind(): computes the inverse sine of a denormalized input           #
6489 #                                                                       #
6490 # INPUT *************************************************************** #
6491 #       a0 = pointer to extended precision input                        #
6492 #       d0 = round precision,mode                                       #
6493 #                                                                       #
6494 # OUTPUT ************************************************************** #
6495 #       fp0 = arcsin(X)                                                 #
6496 #                                                                       #
6497 # ACCURACY and MONOTONICITY ******************************************* #
6498 #       The returned result is within 3 ulps in 64 significant bit,     #
6499 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6500 #       rounded to double precision. The result is provably monotonic   #
6501 #       in double precision.                                            #
6502 #                                                                       #
6503 # ALGORITHM *********************************************************** #
6504 #                                                                       #
6505 #       ASIN                                                            #
6506 #       1. If |X| >= 1, go to 3.                                        #
6507 #                                                                       #
6508 #       2. (|X| < 1) Calculate asin(X) by                               #
6509 #               z := sqrt( [1-X][1+X] )                                 #
6510 #               asin(X) = atan( x / z ).                                #
6511 #               Exit.                                                   #
6512 #                                                                       #
6513 #       3. If |X| > 1, go to 5.                                         #
6514 #                                                                       #
6515 #       4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
6516 #                                                                       #
6517 #       5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
6518 #               Exit.                                                   #
6519 #                                                                       #
6520 #########################################################################
6521
6522         global          sasin
6523 sasin:
6524         fmov.x          (%a0),%fp0              # LOAD INPUT
6525
6526         mov.l           (%a0),%d1
6527         mov.w           4(%a0),%d1
6528         and.l           &0x7FFFFFFF,%d1
6529         cmp.l           %d1,&0x3FFF8000
6530         bge.b           ASINBIG
6531
6532 # This catch is added here for the '060 QSP. Originally, the call to
6533 # satan() would handle this case by causing the exception which would
6534 # not be caught until gen_except(). Now, with the exceptions being
6535 # detected inside of satan(), the exception would have been handled there
6536 # instead of inside sasin() as expected.
6537         cmp.l           %d1,&0x3FD78000
6538         blt.w           ASINTINY
6539
6540 #--THIS IS THE USUAL CASE, |X| < 1
6541 #--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
6542
6543 ASINMAIN:
6544         fmov.s          &0x3F800000,%fp1
6545         fsub.x          %fp0,%fp1               # 1-X
6546         fmovm.x         &0x4,-(%sp)             #  {fp2}
6547         fmov.s          &0x3F800000,%fp2
6548         fadd.x          %fp0,%fp2               # 1+X
6549         fmul.x          %fp2,%fp1               # (1+X)(1-X)
6550         fmovm.x         (%sp)+,&0x20            #  {fp2}
6551         fsqrt.x         %fp1                    # SQRT([1-X][1+X])
6552         fdiv.x          %fp1,%fp0               # X/SQRT([1-X][1+X])
6553         fmovm.x         &0x01,-(%sp)            # save X/SQRT(...)
6554         lea             (%sp),%a0               # pass ptr to X/SQRT(...)
6555         bsr             satan
6556         add.l           &0xc,%sp                # clear X/SQRT(...) from stack
6557         bra             t_inx2
6558
6559 ASINBIG:
6560         fabs.x          %fp0                    # |X|
6561         fcmp.s          %fp0,&0x3F800000
6562         fbgt            t_operr                 # cause an operr exception
6563
6564 #--|X| = 1, ASIN(X) = +- PI/2.
6565 ASINONE:
6566         fmov.x          PIBY2(%pc),%fp0
6567         mov.l           (%a0),%d1
6568         and.l           &0x80000000,%d1         # SIGN BIT OF X
6569         or.l            &0x3F800000,%d1         # +-1 IN SGL FORMAT
6570         mov.l           %d1,-(%sp)              # push SIGN(X) IN SGL-FMT
6571         fmov.l          %d0,%fpcr
6572         fmul.s          (%sp)+,%fp0
6573         bra             t_inx2
6574
6575 #--|X| < 2^(-40), ATAN(X) = X
6576 ASINTINY:
6577         fmov.l          %d0,%fpcr               # restore users rnd mode,prec
6578         mov.b           &FMOV_OP,%d1            # last inst is MOVE
6579         fmov.x          (%a0),%fp0              # last inst - possible exception
6580         bra             t_catch
6581
6582         global          sasind
6583 #--ASIN(X) = X FOR DENORMALIZED X
6584 sasind:
6585         bra             t_extdnrm
6586
6587 #########################################################################
6588 # sacos():  computes the inverse cosine of a normalized input           #
6589 # sacosd(): computes the inverse cosine of a denormalized input         #
6590 #                                                                       #
6591 # INPUT *************************************************************** #
6592 #       a0 = pointer to extended precision input                        #
6593 #       d0 = round precision,mode                                       #
6594 #                                                                       #
6595 # OUTPUT ************************************************************** #
6596 #       fp0 = arccos(X)                                                 #
6597 #                                                                       #
6598 # ACCURACY and MONOTONICITY ******************************************* #
6599 #       The returned result is within 3 ulps in 64 significant bit,     #
6600 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6601 #       rounded to double precision. The result is provably monotonic   #
6602 #       in double precision.                                            #
6603 #                                                                       #
6604 # ALGORITHM *********************************************************** #
6605 #                                                                       #
6606 #       ACOS                                                            #
6607 #       1. If |X| >= 1, go to 3.                                        #
6608 #                                                                       #
6609 #       2. (|X| < 1) Calculate acos(X) by                               #
6610 #               z := (1-X) / (1+X)                                      #
6611 #               acos(X) = 2 * atan( sqrt(z) ).                          #
6612 #               Exit.                                                   #
6613 #                                                                       #
6614 #       3. If |X| > 1, go to 5.                                         #
6615 #                                                                       #
6616 #       4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit.    #
6617 #                                                                       #
6618 #       5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
6619 #               Exit.                                                   #
6620 #                                                                       #
6621 #########################################################################
6622
6623         global          sacos
6624 sacos:
6625         fmov.x          (%a0),%fp0              # LOAD INPUT
6626
6627         mov.l           (%a0),%d1               # pack exp w/ upper 16 fraction
6628         mov.w           4(%a0),%d1
6629         and.l           &0x7FFFFFFF,%d1
6630         cmp.l           %d1,&0x3FFF8000
6631         bge.b           ACOSBIG
6632
6633 #--THIS IS THE USUAL CASE, |X| < 1
6634 #--ACOS(X) = 2 * ATAN(  SQRT( (1-X)/(1+X) ) )
6635
6636 ACOSMAIN:
6637         fmov.s          &0x3F800000,%fp1
6638         fadd.x          %fp0,%fp1               # 1+X
6639         fneg.x          %fp0                    # -X
6640         fadd.s          &0x3F800000,%fp0        # 1-X
6641         fdiv.x          %fp1,%fp0               # (1-X)/(1+X)
6642         fsqrt.x         %fp0                    # SQRT((1-X)/(1+X))
6643         mov.l           %d0,-(%sp)              # save original users fpcr
6644         clr.l           %d0
6645         fmovm.x         &0x01,-(%sp)            # save SQRT(...) to stack
6646         lea             (%sp),%a0               # pass ptr to sqrt
6647         bsr             satan                   # ATAN(SQRT([1-X]/[1+X]))
6648         add.l           &0xc,%sp                # clear SQRT(...) from stack
6649
6650         fmov.l          (%sp)+,%fpcr            # restore users round prec,mode
6651         fadd.x          %fp0,%fp0               # 2 * ATAN( STUFF )
6652         bra             t_pinx2
6653
6654 ACOSBIG:
6655         fabs.x          %fp0
6656         fcmp.s          %fp0,&0x3F800000
6657         fbgt            t_operr                 # cause an operr exception
6658
6659 #--|X| = 1, ACOS(X) = 0 OR PI
6660         tst.b           (%a0)                   # is X positive or negative?
6661         bpl.b           ACOSP1
6662
6663 #--X = -1
6664 #Returns PI and inexact exception
6665 ACOSM1:
6666         fmov.x          PI(%pc),%fp0            # load PI
6667         fmov.l          %d0,%fpcr               # load round mode,prec
6668         fadd.s          &0x00800000,%fp0        # add a small value
6669         bra             t_pinx2
6670
6671 ACOSP1:
6672         bra             ld_pzero                # answer is positive zero
6673
6674         global          sacosd
6675 #--ACOS(X) = PI/2 FOR DENORMALIZED X
6676 sacosd:
6677         fmov.l          %d0,%fpcr               # load user's rnd mode/prec
6678         fmov.x          PIBY2(%pc),%fp0
6679         bra             t_pinx2
6680
6681 #########################################################################
6682 # setox():    computes the exponential for a normalized input           #
6683 # setoxd():   computes the exponential for a denormalized input         #
6684 # setoxm1():  computes the exponential minus 1 for a normalized input   #
6685 # setoxm1d(): computes the exponential minus 1 for a denormalized input #
6686 #                                                                       #
6687 # INPUT *************************************************************** #
6688 #       a0 = pointer to extended precision input                        #
6689 #       d0 = round precision,mode                                       #
6690 #                                                                       #
6691 # OUTPUT ************************************************************** #
6692 #       fp0 = exp(X) or exp(X)-1                                        #
6693 #                                                                       #
6694 # ACCURACY and MONOTONICITY ******************************************* #
6695 #       The returned result is within 0.85 ulps in 64 significant bit,  #
6696 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6697 #       rounded to double precision. The result is provably monotonic   #
6698 #       in double precision.                                            #
6699 #                                                                       #
6700 # ALGORITHM and IMPLEMENTATION **************************************** #
6701 #                                                                       #
6702 #       setoxd                                                          #
6703 #       ------                                                          #
6704 #       Step 1. Set ans := 1.0                                          #
6705 #                                                                       #
6706 #       Step 2. Return  ans := ans + sign(X)*2^(-126). Exit.            #
6707 #       Notes:  This will always generate one exception -- inexact.     #
6708 #                                                                       #
6709 #                                                                       #
6710 #       setox                                                           #
6711 #       -----                                                           #
6712 #                                                                       #
6713 #       Step 1. Filter out extreme cases of input argument.             #
6714 #               1.1     If |X| >= 2^(-65), go to Step 1.3.              #
6715 #               1.2     Go to Step 7.                                   #
6716 #               1.3     If |X| < 16380 log(2), go to Step 2.            #
6717 #               1.4     Go to Step 8.                                   #
6718 #       Notes:  The usual case should take the branches 1.1 -> 1.3 -> 2.#
6719 #               To avoid the use of floating-point comparisons, a       #
6720 #               compact representation of |X| is used. This format is a #
6721 #               32-bit integer, the upper (more significant) 16 bits    #
6722 #               are the sign and biased exponent field of |X|; the      #
6723 #               lower 16 bits are the 16 most significant fraction      #
6724 #               (including the explicit bit) bits of |X|. Consequently, #
6725 #               the comparisons in Steps 1.1 and 1.3 can be performed   #
6726 #               by integer comparison. Note also that the constant      #
6727 #               16380 log(2) used in Step 1.3 is also in the compact    #
6728 #               form. Thus taking the branch to Step 2 guarantees       #
6729 #               |X| < 16380 log(2). There is no harm to have a small    #
6730 #               number of cases where |X| is less than, but close to,   #
6731 #               16380 log(2) and the branch to Step 9 is taken.         #
6732 #                                                                       #
6733 #       Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).      #
6734 #               2.1     Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
6735 #                       was taken)                                      #
6736 #               2.2     N := round-to-nearest-integer( X * 64/log2 ).   #
6737 #               2.3     Calculate       J = N mod 64; so J = 0,1,2,..., #
6738 #                       or 63.                                          #
6739 #               2.4     Calculate       M = (N - J)/64; so N = 64M + J. #
6740 #               2.5     Calculate the address of the stored value of    #
6741 #                       2^(J/64).                                       #
6742 #               2.6     Create the value Scale = 2^M.                   #
6743 #       Notes:  The calculation in 2.2 is really performed by           #
6744 #                       Z := X * constant                               #
6745 #                       N := round-to-nearest-integer(Z)                #
6746 #               where                                                   #
6747 #                       constant := single-precision( 64/log 2 ).       #
6748 #                                                                       #
6749 #               Using a single-precision constant avoids memory         #
6750 #               access. Another effect of using a single-precision      #
6751 #               "constant" is that the calculated value Z is            #
6752 #                                                                       #
6753 #                       Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24).      #
6754 #                                                                       #
6755 #               This error has to be considered later in Steps 3 and 4. #
6756 #                                                                       #
6757 #       Step 3. Calculate X - N*log2/64.                                #
6758 #               3.1     R := X + N*L1,                                  #
6759 #                               where L1 := single-precision(-log2/64). #
6760 #               3.2     R := R + N*L2,                                  #
6761 #                               L2 := extended-precision(-log2/64 - L1).#
6762 #       Notes:  a) The way L1 and L2 are chosen ensures L1+L2           #
6763 #               approximate the value -log2/64 to 88 bits of accuracy.  #
6764 #               b) N*L1 is exact because N is no longer than 22 bits    #
6765 #               and L1 is no longer than 24 bits.                       #
6766 #               c) The calculation X+N*L1 is also exact due to          #
6767 #               cancellation. Thus, R is practically X+N(L1+L2) to full #
6768 #               64 bits.                                                #
6769 #               d) It is important to estimate how large can |R| be     #
6770 #               after Step 3.2.                                         #
6771 #                                                                       #
6772 #               N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24)     #
6773 #               X*64/log2 (1+eps)       =       N + f,  |f| <= 0.5      #
6774 #               X*64/log2 - N   =       f - eps*X 64/log2               #
6775 #               X - N*log2/64   =       f*log2/64 - eps*X               #
6776 #                                                                       #
6777 #                                                                       #
6778 #               Now |X| <= 16446 log2, thus                             #
6779 #                                                                       #
6780 #                       |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
6781 #                                       <= 0.57 log2/64.                #
6782 #                This bound will be used in Step 4.                     #
6783 #                                                                       #
6784 #       Step 4. Approximate exp(R)-1 by a polynomial                    #
6785 #               p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))      #
6786 #       Notes:  a) In order to reduce memory access, the coefficients   #
6787 #               are made as "short" as possible: A1 (which is 1/2), A4  #
6788 #               and A5 are single precision; A2 and A3 are double       #
6789 #               precision.                                              #
6790 #               b) Even with the restrictions above,                    #
6791 #                  |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062.  #
6792 #               Note that 0.0062 is slightly bigger than 0.57 log2/64.  #
6793 #               c) To fully utilize the pipeline, p is separated into   #
6794 #               two independent pieces of roughly equal complexities    #
6795 #                       p = [ R + R*S*(A2 + S*A4) ]     +               #
6796 #                               [ S*(A1 + S*(A3 + S*A5)) ]              #
6797 #               where S = R*R.                                          #
6798 #                                                                       #
6799 #       Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by             #
6800 #                               ans := T + ( T*p + t)                   #
6801 #               where T and t are the stored values for 2^(J/64).       #
6802 #       Notes:  2^(J/64) is stored as T and t where T+t approximates    #
6803 #               2^(J/64) to roughly 85 bits; T is in extended precision #
6804 #               and t is in single precision. Note also that T is       #
6805 #               rounded to 62 bits so that the last two bits of T are   #
6806 #               zero. The reason for such a special form is that T-1,   #
6807 #               T-2, and T-8 will all be exact --- a property that will #
6808 #               give much more accurate computation of the function     #
6809 #               EXPM1.                                                  #
6810 #                                                                       #
6811 #       Step 6. Reconstruction of exp(X)                                #
6812 #                       exp(X) = 2^M * 2^(J/64) * exp(R).               #
6813 #               6.1     If AdjFlag = 0, go to 6.3                       #
6814 #               6.2     ans := ans * AdjScale                           #
6815 #               6.3     Restore the user FPCR                           #
6816 #               6.4     Return ans := ans * Scale. Exit.                #
6817 #       Notes:  If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R,       #
6818 #               |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will    #
6819 #               neither overflow nor underflow. If AdjFlag = 1, that    #
6820 #               means that                                              #
6821 #                       X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
6822 #               Hence, exp(X) may overflow or underflow or neither.     #
6823 #               When that is the case, AdjScale = 2^(M1) where M1 is    #
6824 #               approximately M. Thus 6.2 will never cause              #
6825 #               over/underflow. Possible exception in 6.4 is overflow   #
6826 #               or underflow. The inexact exception is not generated in #
6827 #               6.4. Although one can argue that the inexact flag       #
6828 #               should always be raised, to simulate that exception     #
6829 #               cost to much than the flag is worth in practical uses.  #
6830 #                                                                       #
6831 #       Step 7. Return 1 + X.                                           #
6832 #               7.1     ans := X                                        #
6833 #               7.2     Restore user FPCR.                              #
6834 #               7.3     Return ans := 1 + ans. Exit                     #
6835 #       Notes:  For non-zero X, the inexact exception will always be    #
6836 #               raised by 7.3. That is the only exception raised by 7.3.#
6837 #               Note also that we use the FMOVEM instruction to move X  #
6838 #               in Step 7.1 to avoid unnecessary trapping. (Although    #
6839 #               the FMOVEM may not seem relevant since X is normalized, #
6840 #               the precaution will be useful in the library version of #
6841 #               this code where the separate entry for denormalized     #
6842 #               inputs will be done away with.)                         #
6843 #                                                                       #
6844 #       Step 8. Handle exp(X) where |X| >= 16380log2.                   #
6845 #               8.1     If |X| > 16480 log2, go to Step 9.              #
6846 #               (mimic 2.2 - 2.6)                                       #
6847 #               8.2     N := round-to-integer( X * 64/log2 )            #
6848 #               8.3     Calculate J = N mod 64, J = 0,1,...,63          #
6849 #               8.4     K := (N-J)/64, M1 := truncate(K/2), M = K-M1,   #
6850 #                       AdjFlag := 1.                                   #
6851 #               8.5     Calculate the address of the stored value       #
6852 #                       2^(J/64).                                       #
6853 #               8.6     Create the values Scale = 2^M, AdjScale = 2^M1. #
6854 #               8.7     Go to Step 3.                                   #
6855 #       Notes:  Refer to notes for 2.2 - 2.6.                           #
6856 #                                                                       #
6857 #       Step 9. Handle exp(X), |X| > 16480 log2.                        #
6858 #               9.1     If X < 0, go to 9.3                             #
6859 #               9.2     ans := Huge, go to 9.4                          #
6860 #               9.3     ans := Tiny.                                    #
6861 #               9.4     Restore user FPCR.                              #
6862 #               9.5     Return ans := ans * ans. Exit.                  #
6863 #       Notes:  Exp(X) will surely overflow or underflow, depending on  #
6864 #               X's sign. "Huge" and "Tiny" are respectively large/tiny #
6865 #               extended-precision numbers whose square over/underflow  #
6866 #               with an inexact result. Thus, 9.5 always raises the     #
6867 #               inexact together with either overflow or underflow.     #
6868 #                                                                       #
6869 #       setoxm1d                                                        #
6870 #       --------                                                        #
6871 #                                                                       #
6872 #       Step 1. Set ans := 0                                            #
6873 #                                                                       #
6874 #       Step 2. Return  ans := X + ans. Exit.                           #
6875 #       Notes:  This will return X with the appropriate rounding        #
6876 #                precision prescribed by the user FPCR.                 #
6877 #                                                                       #
6878 #       setoxm1                                                         #
6879 #       -------                                                         #
6880 #                                                                       #
6881 #       Step 1. Check |X|                                               #
6882 #               1.1     If |X| >= 1/4, go to Step 1.3.                  #
6883 #               1.2     Go to Step 7.                                   #
6884 #               1.3     If |X| < 70 log(2), go to Step 2.               #
6885 #               1.4     Go to Step 10.                                  #
6886 #       Notes:  The usual case should take the branches 1.1 -> 1.3 -> 2.#
6887 #               However, it is conceivable |X| can be small very often  #
6888 #               because EXPM1 is intended to evaluate exp(X)-1          #
6889 #               accurately when |X| is small. For further details on    #
6890 #               the comparisons, see the notes on Step 1 of setox.      #
6891 #                                                                       #
6892 #       Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ).      #
6893 #               2.1     N := round-to-nearest-integer( X * 64/log2 ).   #
6894 #               2.2     Calculate       J = N mod 64; so J = 0,1,2,..., #
6895 #                       or 63.                                          #
6896 #               2.3     Calculate       M = (N - J)/64; so N = 64M + J. #
6897 #               2.4     Calculate the address of the stored value of    #
6898 #                       2^(J/64).                                       #
6899 #               2.5     Create the values Sc = 2^M and                  #
6900 #                       OnebySc := -2^(-M).                             #
6901 #       Notes:  See the notes on Step 2 of setox.                       #
6902 #                                                                       #
6903 #       Step 3. Calculate X - N*log2/64.                                #
6904 #               3.1     R := X + N*L1,                                  #
6905 #                               where L1 := single-precision(-log2/64). #
6906 #               3.2     R := R + N*L2,                                  #
6907 #                               L2 := extended-precision(-log2/64 - L1).#
6908 #       Notes:  Applying the analysis of Step 3 of setox in this case   #
6909 #               shows that |R| <= 0.0055 (note that |X| <= 70 log2 in   #
6910 #               this case).                                             #
6911 #                                                                       #
6912 #       Step 4. Approximate exp(R)-1 by a polynomial                    #
6913 #                       p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
6914 #       Notes:  a) In order to reduce memory access, the coefficients   #
6915 #               are made as "short" as possible: A1 (which is 1/2), A5  #
6916 #               and A6 are single precision; A2, A3 and A4 are double   #
6917 #               precision.                                              #
6918 #               b) Even with the restriction above,                     #
6919 #                       |p - (exp(R)-1)| <      |R| * 2^(-72.7)         #
6920 #               for all |R| <= 0.0055.                                  #
6921 #               c) To fully utilize the pipeline, p is separated into   #
6922 #               two independent pieces of roughly equal complexity      #
6923 #                       p = [ R*S*(A2 + S*(A4 + S*A6)) ]        +       #
6924 #                               [ R + S*(A1 + S*(A3 + S*A5)) ]          #
6925 #               where S = R*R.                                          #
6926 #                                                                       #
6927 #       Step 5. Compute 2^(J/64)*p by                                   #
6928 #                               p := T*p                                #
6929 #               where T and t are the stored values for 2^(J/64).       #
6930 #       Notes:  2^(J/64) is stored as T and t where T+t approximates    #
6931 #               2^(J/64) to roughly 85 bits; T is in extended precision #
6932 #               and t is in single precision. Note also that T is       #
6933 #               rounded to 62 bits so that the last two bits of T are   #
6934 #               zero. The reason for such a special form is that T-1,   #
6935 #               T-2, and T-8 will all be exact --- a property that will #
6936 #               be exploited in Step 6 below. The total relative error  #
6937 #               in p is no bigger than 2^(-67.7) compared to the final  #
6938 #               result.                                                 #
6939 #                                                                       #
6940 #       Step 6. Reconstruction of exp(X)-1                              #
6941 #                       exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ).     #
6942 #               6.1     If M <= 63, go to Step 6.3.                     #
6943 #               6.2     ans := T + (p + (t + OnebySc)). Go to 6.6       #
6944 #               6.3     If M >= -3, go to 6.5.                          #
6945 #               6.4     ans := (T + (p + t)) + OnebySc. Go to 6.6       #
6946 #               6.5     ans := (T + OnebySc) + (p + t).                 #
6947 #               6.6     Restore user FPCR.                              #
6948 #               6.7     Return ans := Sc * ans. Exit.                   #
6949 #       Notes:  The various arrangements of the expressions give        #
6950 #               accurate evaluations.                                   #
6951 #                                                                       #
6952 #       Step 7. exp(X)-1 for |X| < 1/4.                                 #
6953 #               7.1     If |X| >= 2^(-65), go to Step 9.                #
6954 #               7.2     Go to Step 8.                                   #
6955 #                                                                       #
6956 #       Step 8. Calculate exp(X)-1, |X| < 2^(-65).                      #
6957 #               8.1     If |X| < 2^(-16312), goto 8.3                   #
6958 #               8.2     Restore FPCR; return ans := X - 2^(-16382).     #
6959 #                       Exit.                                           #
6960 #               8.3     X := X * 2^(140).                               #
6961 #               8.4     Restore FPCR; ans := ans - 2^(-16382).          #
6962 #                Return ans := ans*2^(140). Exit                        #
6963 #       Notes:  The idea is to return "X - tiny" under the user         #
6964 #               precision and rounding modes. To avoid unnecessary      #
6965 #               inefficiency, we stay away from denormalized numbers    #
6966 #               the best we can. For |X| >= 2^(-16312), the             #
6967 #               straightforward 8.2 generates the inexact exception as  #
6968 #               the case warrants.                                      #
6969 #                                                                       #
6970 #       Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial          #
6971 #                       p = X + X*X*(B1 + X*(B2 + ... + X*B12))         #
6972 #       Notes:  a) In order to reduce memory access, the coefficients   #
6973 #               are made as "short" as possible: B1 (which is 1/2), B9  #
6974 #               to B12 are single precision; B3 to B8 are double        #
6975 #               precision; and B2 is double extended.                   #
6976 #               b) Even with the restriction above,                     #
6977 #                       |p - (exp(X)-1)| < |X| 2^(-70.6)                #
6978 #               for all |X| <= 0.251.                                   #
6979 #               Note that 0.251 is slightly bigger than 1/4.            #
6980 #               c) To fully preserve accuracy, the polynomial is        #
6981 #               computed as                                             #
6982 #                       X + ( S*B1 +    Q ) where S = X*X and           #
6983 #                       Q       =       X*S*(B2 + X*(B3 + ... + X*B12)) #
6984 #               d) To fully utilize the pipeline, Q is separated into   #
6985 #               two independent pieces of roughly equal complexity      #
6986 #                       Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] +       #
6987 #                               [ S*S*(B3 + S*(B5 + ... + S*B11)) ]     #
6988 #                                                                       #
6989 #       Step 10. Calculate exp(X)-1 for |X| >= 70 log 2.                #
6990 #               10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all       #
6991 #               practical purposes. Therefore, go to Step 1 of setox.   #
6992 #               10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
6993 #               purposes.                                               #
6994 #               ans := -1                                               #
6995 #               Restore user FPCR                                       #
6996 #               Return ans := ans + 2^(-126). Exit.                     #
6997 #       Notes:  10.2 will always create an inexact and return -1 + tiny #
6998 #               in the user rounding precision and mode.                #
6999 #                                                                       #
7000 #########################################################################
7001
7002 L2:     long            0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
7003
7004 EEXPA3: long            0x3FA55555,0x55554CC1
7005 EEXPA2: long            0x3FC55555,0x55554A54
7006
7007 EM1A4:  long            0x3F811111,0x11174385
7008 EM1A3:  long            0x3FA55555,0x55554F5A
7009
7010 EM1A2:  long            0x3FC55555,0x55555555,0x00000000,0x00000000
7011
7012 EM1B8:  long            0x3EC71DE3,0xA5774682
7013 EM1B7:  long            0x3EFA01A0,0x19D7CB68
7014
7015 EM1B6:  long            0x3F2A01A0,0x1A019DF3
7016 EM1B5:  long            0x3F56C16C,0x16C170E2
7017
7018 EM1B4:  long            0x3F811111,0x11111111
7019 EM1B3:  long            0x3FA55555,0x55555555
7020
7021 EM1B2:  long            0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
7022         long            0x00000000
7023
7024 TWO140: long            0x48B00000,0x00000000
7025 TWON140:
7026         long            0x37300000,0x00000000
7027
7028 EEXPTBL:
7029         long            0x3FFF0000,0x80000000,0x00000000,0x00000000
7030         long            0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
7031         long            0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
7032         long            0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
7033         long            0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
7034         long            0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
7035         long            0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
7036         long            0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
7037         long            0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
7038         long            0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
7039         long            0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
7040         long            0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
7041         long            0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
7042         long            0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
7043         long            0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
7044         long            0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
7045         long            0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
7046         long            0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
7047         long            0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
7048         long            0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
7049         long            0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
7050         long            0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
7051         long            0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
7052         long            0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
7053         long            0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
7054         long            0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
7055         long            0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
7056         long            0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
7057         long            0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
7058         long            0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
7059         long            0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
7060         long            0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
7061         long            0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
7062         long            0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
7063         long            0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
7064         long            0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
7065         long            0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
7066         long            0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
7067         long            0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
7068         long            0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
7069         long            0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
7070         long            0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
7071         long            0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
7072         long            0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
7073         long            0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
7074         long            0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
7075         long            0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
7076         long            0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
7077         long            0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
7078         long            0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
7079         long            0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
7080         long            0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
7081         long            0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
7082         long            0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
7083         long            0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
7084         long            0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
7085         long            0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
7086         long            0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
7087         long            0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
7088         long            0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
7089         long            0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
7090         long            0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
7091         long            0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
7092         long            0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
7093
7094         set             ADJFLAG,L_SCR2
7095         set             SCALE,FP_SCR0
7096         set             ADJSCALE,FP_SCR1
7097         set             SC,FP_SCR0
7098         set             ONEBYSC,FP_SCR1
7099
7100         global          setox
7101 setox:
7102 #--entry point for EXP(X), here X is finite, non-zero, and not NaN's
7103
7104 #--Step 1.
7105         mov.l           (%a0),%d1               # load part of input X
7106         and.l           &0x7FFF0000,%d1         # biased expo. of X
7107         cmp.l           %d1,&0x3FBE0000         # 2^(-65)
7108         bge.b           EXPC1                   # normal case
7109         bra             EXPSM
7110
7111 EXPC1:
7112 #--The case |X| >= 2^(-65)
7113         mov.w           4(%a0),%d1              # expo. and partial sig. of |X|
7114         cmp.l           %d1,&0x400CB167         # 16380 log2 trunc. 16 bits
7115         blt.b           EXPMAIN                 # normal case
7116         bra             EEXPBIG
7117
7118 EXPMAIN:
7119 #--Step 2.
7120 #--This is the normal branch:   2^(-65) <= |X| < 16380 log2.
7121         fmov.x          (%a0),%fp0              # load input from (a0)
7122
7123         fmov.x          %fp0,%fp1
7124         fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
7125         fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7126         mov.l           &0,ADJFLAG(%a6)
7127         fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
7128         lea             EEXPTBL(%pc),%a1
7129         fmov.l          %d1,%fp0                # convert to floating-format
7130
7131         mov.l           %d1,L_SCR1(%a6)         # save N temporarily
7132         and.l           &0x3F,%d1               # D0 is J = N mod 64
7133         lsl.l           &4,%d1
7134         add.l           %d1,%a1                 # address of 2^(J/64)
7135         mov.l           L_SCR1(%a6),%d1
7136         asr.l           &6,%d1                  # D0 is M
7137         add.w           &0x3FFF,%d1             # biased expo. of 2^(M)
7138         mov.w           L2(%pc),L_SCR1(%a6)     # prefetch L2, no need in CB
7139
7140 EXPCONT1:
7141 #--Step 3.
7142 #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7143 #--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
7144         fmov.x          %fp0,%fp2
7145         fmul.s          &0xBC317218,%fp0        # N * L1, L1 = lead(-log2/64)
7146         fmul.x          L2(%pc),%fp2            # N * L2, L1+L2 = -log2/64
7147         fadd.x          %fp1,%fp0               # X + N*L1
7148         fadd.x          %fp2,%fp0               # fp0 is R, reduced arg.
7149
7150 #--Step 4.
7151 #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7152 #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
7153 #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7154 #--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
7155
7156         fmov.x          %fp0,%fp1
7157         fmul.x          %fp1,%fp1               # fp1 IS S = R*R
7158
7159         fmov.s          &0x3AB60B70,%fp2        # fp2 IS A5
7160
7161         fmul.x          %fp1,%fp2               # fp2 IS S*A5
7162         fmov.x          %fp1,%fp3
7163         fmul.s          &0x3C088895,%fp3        # fp3 IS S*A4
7164
7165         fadd.d          EEXPA3(%pc),%fp2        # fp2 IS A3+S*A5
7166         fadd.d          EEXPA2(%pc),%fp3        # fp3 IS A2+S*A4
7167
7168         fmul.x          %fp1,%fp2               # fp2 IS S*(A3+S*A5)
7169         mov.w           %d1,SCALE(%a6)          # SCALE is 2^(M) in extended
7170         mov.l           &0x80000000,SCALE+4(%a6)
7171         clr.l           SCALE+8(%a6)
7172
7173         fmul.x          %fp1,%fp3               # fp3 IS S*(A2+S*A4)
7174
7175         fadd.s          &0x3F000000,%fp2        # fp2 IS A1+S*(A3+S*A5)
7176         fmul.x          %fp0,%fp3               # fp3 IS R*S*(A2+S*A4)
7177
7178         fmul.x          %fp1,%fp2               # fp2 IS S*(A1+S*(A3+S*A5))
7179         fadd.x          %fp3,%fp0               # fp0 IS R+R*S*(A2+S*A4),
7180
7181         fmov.x          (%a1)+,%fp1             # fp1 is lead. pt. of 2^(J/64)
7182         fadd.x          %fp2,%fp0               # fp0 is EXP(R) - 1
7183
7184 #--Step 5
7185 #--final reconstruction process
7186 #--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
7187
7188         fmul.x          %fp1,%fp0               # 2^(J/64)*(Exp(R)-1)
7189         fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
7190         fadd.s          (%a1),%fp0              # accurate 2^(J/64)
7191
7192         fadd.x          %fp1,%fp0               # 2^(J/64) + 2^(J/64)*...
7193         mov.l           ADJFLAG(%a6),%d1
7194
7195 #--Step 6
7196         tst.l           %d1
7197         beq.b           NORMAL
7198 ADJUST:
7199         fmul.x          ADJSCALE(%a6),%fp0
7200 NORMAL:
7201         fmov.l          %d0,%fpcr               # restore user FPCR
7202         mov.b           &FMUL_OP,%d1            # last inst is MUL
7203         fmul.x          SCALE(%a6),%fp0         # multiply 2^(M)
7204         bra             t_catch
7205
7206 EXPSM:
7207 #--Step 7
7208         fmovm.x         (%a0),&0x80             # load X
7209         fmov.l          %d0,%fpcr
7210         fadd.s          &0x3F800000,%fp0        # 1+X in user mode
7211         bra             t_pinx2
7212
7213 EEXPBIG:
7214 #--Step 8
7215         cmp.l           %d1,&0x400CB27C         # 16480 log2
7216         bgt.b           EXP2BIG
7217 #--Steps 8.2 -- 8.6
7218         fmov.x          (%a0),%fp0              # load input from (a0)
7219
7220         fmov.x          %fp0,%fp1
7221         fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
7222         fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7223         mov.l           &1,ADJFLAG(%a6)
7224         fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
7225         lea             EEXPTBL(%pc),%a1
7226         fmov.l          %d1,%fp0                # convert to floating-format
7227         mov.l           %d1,L_SCR1(%a6)         # save N temporarily
7228         and.l           &0x3F,%d1               # D0 is J = N mod 64
7229         lsl.l           &4,%d1
7230         add.l           %d1,%a1                 # address of 2^(J/64)
7231         mov.l           L_SCR1(%a6),%d1
7232         asr.l           &6,%d1                  # D0 is K
7233         mov.l           %d1,L_SCR1(%a6)         # save K temporarily
7234         asr.l           &1,%d1                  # D0 is M1
7235         sub.l           %d1,L_SCR1(%a6)         # a1 is M
7236         add.w           &0x3FFF,%d1             # biased expo. of 2^(M1)
7237         mov.w           %d1,ADJSCALE(%a6)       # ADJSCALE := 2^(M1)
7238         mov.l           &0x80000000,ADJSCALE+4(%a6)
7239         clr.l           ADJSCALE+8(%a6)
7240         mov.l           L_SCR1(%a6),%d1         # D0 is M
7241         add.w           &0x3FFF,%d1             # biased expo. of 2^(M)
7242         bra.w           EXPCONT1                # go back to Step 3
7243
7244 EXP2BIG:
7245 #--Step 9
7246         tst.b           (%a0)                   # is X positive or negative?
7247         bmi             t_unfl2
7248         bra             t_ovfl2
7249
7250         global          setoxd
7251 setoxd:
7252 #--entry point for EXP(X), X is denormalized
7253         mov.l           (%a0),-(%sp)
7254         andi.l          &0x80000000,(%sp)
7255         ori.l           &0x00800000,(%sp)       # sign(X)*2^(-126)
7256
7257         fmov.s          &0x3F800000,%fp0
7258
7259         fmov.l          %d0,%fpcr
7260         fadd.s          (%sp)+,%fp0
7261         bra             t_pinx2
7262
7263         global          setoxm1
7264 setoxm1:
7265 #--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
7266
7267 #--Step 1.
7268 #--Step 1.1
7269         mov.l           (%a0),%d1               # load part of input X
7270         and.l           &0x7FFF0000,%d1         # biased expo. of X
7271         cmp.l           %d1,&0x3FFD0000         # 1/4
7272         bge.b           EM1CON1                 # |X| >= 1/4
7273         bra             EM1SM
7274
7275 EM1CON1:
7276 #--Step 1.3
7277 #--The case |X| >= 1/4
7278         mov.w           4(%a0),%d1              # expo. and partial sig. of |X|
7279         cmp.l           %d1,&0x4004C215         # 70log2 rounded up to 16 bits
7280         ble.b           EM1MAIN                 # 1/4 <= |X| <= 70log2
7281         bra             EM1BIG
7282
7283 EM1MAIN:
7284 #--Step 2.
7285 #--This is the case:    1/4 <= |X| <= 70 log2.
7286         fmov.x          (%a0),%fp0              # load input from (a0)
7287
7288         fmov.x          %fp0,%fp1
7289         fmul.s          &0x42B8AA3B,%fp0        # 64/log2 * X
7290         fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7291         fmov.l          %fp0,%d1                # N = int( X * 64/log2 )
7292         lea             EEXPTBL(%pc),%a1
7293         fmov.l          %d1,%fp0                # convert to floating-format
7294
7295         mov.l           %d1,L_SCR1(%a6)         # save N temporarily
7296         and.l           &0x3F,%d1               # D0 is J = N mod 64
7297         lsl.l           &4,%d1
7298         add.l           %d1,%a1                 # address of 2^(J/64)
7299         mov.l           L_SCR1(%a6),%d1
7300         asr.l           &6,%d1                  # D0 is M
7301         mov.l           %d1,L_SCR1(%a6)         # save a copy of M
7302
7303 #--Step 3.
7304 #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7305 #--a0 points to 2^(J/64), D0 and a1 both contain M
7306         fmov.x          %fp0,%fp2
7307         fmul.s          &0xBC317218,%fp0        # N * L1, L1 = lead(-log2/64)
7308         fmul.x          L2(%pc),%fp2            # N * L2, L1+L2 = -log2/64
7309         fadd.x          %fp1,%fp0               # X + N*L1
7310         fadd.x          %fp2,%fp0               # fp0 is R, reduced arg.
7311         add.w           &0x3FFF,%d1             # D0 is biased expo. of 2^M
7312
7313 #--Step 4.
7314 #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7315 #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
7316 #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7317 #--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
7318
7319         fmov.x          %fp0,%fp1
7320         fmul.x          %fp1,%fp1               # fp1 IS S = R*R
7321
7322         fmov.s          &0x3950097B,%fp2        # fp2 IS a6
7323
7324         fmul.x          %fp1,%fp2               # fp2 IS S*A6
7325         fmov.x          %fp1,%fp3
7326         fmul.s          &0x3AB60B6A,%fp3        # fp3 IS S*A5
7327
7328         fadd.d          EM1A4(%pc),%fp2         # fp2 IS A4+S*A6
7329         fadd.d          EM1A3(%pc),%fp3         # fp3 IS A3+S*A5
7330         mov.w           %d1,SC(%a6)             # SC is 2^(M) in extended
7331         mov.l           &0x80000000,SC+4(%a6)
7332         clr.l           SC+8(%a6)
7333
7334         fmul.x          %fp1,%fp2               # fp2 IS S*(A4+S*A6)
7335         mov.l           L_SCR1(%a6),%d1         # D0 is M
7336         neg.w           %d1                     # D0 is -M
7337         fmul.x          %fp1,%fp3               # fp3 IS S*(A3+S*A5)
7338         add.w           &0x3FFF,%d1             # biased expo. of 2^(-M)
7339         fadd.d          EM1A2(%pc),%fp2         # fp2 IS A2+S*(A4+S*A6)
7340         fadd.s          &0x3F000000,%fp3        # fp3 IS A1+S*(A3+S*A5)
7341
7342         fmul.x          %fp1,%fp2               # fp2 IS S*(A2+S*(A4+S*A6))
7343         or.w            &0x8000,%d1             # signed/expo. of -2^(-M)
7344         mov.w           %d1,ONEBYSC(%a6)        # OnebySc is -2^(-M)
7345         mov.l           &0x80000000,ONEBYSC+4(%a6)
7346         clr.l           ONEBYSC+8(%a6)
7347         fmul.x          %fp3,%fp1               # fp1 IS S*(A1+S*(A3+S*A5))
7348
7349         fmul.x          %fp0,%fp2               # fp2 IS R*S*(A2+S*(A4+S*A6))
7350         fadd.x          %fp1,%fp0               # fp0 IS R+S*(A1+S*(A3+S*A5))
7351
7352         fadd.x          %fp2,%fp0               # fp0 IS EXP(R)-1
7353
7354         fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
7355
7356 #--Step 5
7357 #--Compute 2^(J/64)*p
7358
7359         fmul.x          (%a1),%fp0              # 2^(J/64)*(Exp(R)-1)
7360
7361 #--Step 6
7362 #--Step 6.1
7363         mov.l           L_SCR1(%a6),%d1         # retrieve M
7364         cmp.l           %d1,&63
7365         ble.b           MLE63
7366 #--Step 6.2     M >= 64
7367         fmov.s          12(%a1),%fp1            # fp1 is t
7368         fadd.x          ONEBYSC(%a6),%fp1       # fp1 is t+OnebySc
7369         fadd.x          %fp1,%fp0               # p+(t+OnebySc), fp1 released
7370         fadd.x          (%a1),%fp0              # T+(p+(t+OnebySc))
7371         bra             EM1SCALE
7372 MLE63:
7373 #--Step 6.3     M <= 63
7374         cmp.l           %d1,&-3
7375         bge.b           MGEN3
7376 MLTN3:
7377 #--Step 6.4     M <= -4
7378         fadd.s          12(%a1),%fp0            # p+t
7379         fadd.x          (%a1),%fp0              # T+(p+t)
7380         fadd.x          ONEBYSC(%a6),%fp0       # OnebySc + (T+(p+t))
7381         bra             EM1SCALE
7382 MGEN3:
7383 #--Step 6.5     -3 <= M <= 63
7384         fmov.x          (%a1)+,%fp1             # fp1 is T
7385         fadd.s          (%a1),%fp0              # fp0 is p+t
7386         fadd.x          ONEBYSC(%a6),%fp1       # fp1 is T+OnebySc
7387         fadd.x          %fp1,%fp0               # (T+OnebySc)+(p+t)
7388
7389 EM1SCALE:
7390 #--Step 6.6
7391         fmov.l          %d0,%fpcr
7392         fmul.x          SC(%a6),%fp0
7393         bra             t_inx2
7394
7395 EM1SM:
7396 #--Step 7       |X| < 1/4.
7397         cmp.l           %d1,&0x3FBE0000         # 2^(-65)
7398         bge.b           EM1POLY
7399
7400 EM1TINY:
7401 #--Step 8       |X| < 2^(-65)
7402         cmp.l           %d1,&0x00330000         # 2^(-16312)
7403         blt.b           EM12TINY
7404 #--Step 8.2
7405         mov.l           &0x80010000,SC(%a6)     # SC is -2^(-16382)
7406         mov.l           &0x80000000,SC+4(%a6)
7407         clr.l           SC+8(%a6)
7408         fmov.x          (%a0),%fp0
7409         fmov.l          %d0,%fpcr
7410         mov.b           &FADD_OP,%d1            # last inst is ADD
7411         fadd.x          SC(%a6),%fp0
7412         bra             t_catch
7413
7414 EM12TINY:
7415 #--Step 8.3
7416         fmov.x          (%a0),%fp0
7417         fmul.d          TWO140(%pc),%fp0
7418         mov.l           &0x80010000,SC(%a6)
7419         mov.l           &0x80000000,SC+4(%a6)
7420         clr.l           SC+8(%a6)
7421         fadd.x          SC(%a6),%fp0
7422         fmov.l          %d0,%fpcr
7423         mov.b           &FMUL_OP,%d1            # last inst is MUL
7424         fmul.d          TWON140(%pc),%fp0
7425         bra             t_catch
7426
7427 EM1POLY:
7428 #--Step 9       exp(X)-1 by a simple polynomial
7429         fmov.x          (%a0),%fp0              # fp0 is X
7430         fmul.x          %fp0,%fp0               # fp0 is S := X*X
7431         fmovm.x         &0xc,-(%sp)             # save fp2 {%fp2/%fp3}
7432         fmov.s          &0x2F30CAA8,%fp1        # fp1 is B12
7433         fmul.x          %fp0,%fp1               # fp1 is S*B12
7434         fmov.s          &0x310F8290,%fp2        # fp2 is B11
7435         fadd.s          &0x32D73220,%fp1        # fp1 is B10+S*B12
7436
7437         fmul.x          %fp0,%fp2               # fp2 is S*B11
7438         fmul.x          %fp0,%fp1               # fp1 is S*(B10 + ...
7439
7440         fadd.s          &0x3493F281,%fp2        # fp2 is B9+S*...
7441         fadd.d          EM1B8(%pc),%fp1         # fp1 is B8+S*...
7442
7443         fmul.x          %fp0,%fp2               # fp2 is S*(B9+...
7444         fmul.x          %fp0,%fp1               # fp1 is S*(B8+...
7445
7446         fadd.d          EM1B7(%pc),%fp2         # fp2 is B7+S*...
7447         fadd.d          EM1B6(%pc),%fp1         # fp1 is B6+S*...
7448
7449         fmul.x          %fp0,%fp2               # fp2 is S*(B7+...
7450         fmul.x          %fp0,%fp1               # fp1 is S*(B6+...
7451
7452         fadd.d          EM1B5(%pc),%fp2         # fp2 is B5+S*...
7453         fadd.d          EM1B4(%pc),%fp1         # fp1 is B4+S*...
7454
7455         fmul.x          %fp0,%fp2               # fp2 is S*(B5+...
7456         fmul.x          %fp0,%fp1               # fp1 is S*(B4+...
7457
7458         fadd.d          EM1B3(%pc),%fp2         # fp2 is B3+S*...
7459         fadd.x          EM1B2(%pc),%fp1         # fp1 is B2+S*...
7460
7461         fmul.x          %fp0,%fp2               # fp2 is S*(B3+...
7462         fmul.x          %fp0,%fp1               # fp1 is S*(B2+...
7463
7464         fmul.x          %fp0,%fp2               # fp2 is S*S*(B3+...)
7465         fmul.x          (%a0),%fp1              # fp1 is X*S*(B2...
7466
7467         fmul.s          &0x3F000000,%fp0        # fp0 is S*B1
7468         fadd.x          %fp2,%fp1               # fp1 is Q
7469
7470         fmovm.x         (%sp)+,&0x30            # fp2 restored {%fp2/%fp3}
7471
7472         fadd.x          %fp1,%fp0               # fp0 is S*B1+Q
7473
7474         fmov.l          %d0,%fpcr
7475         fadd.x          (%a0),%fp0
7476         bra             t_inx2
7477
7478 EM1BIG:
7479 #--Step 10      |X| > 70 log2
7480         mov.l           (%a0),%d1
7481         cmp.l           %d1,&0
7482         bgt.w           EXPC1
7483 #--Step 10.2
7484         fmov.s          &0xBF800000,%fp0        # fp0 is -1
7485         fmov.l          %d0,%fpcr
7486         fadd.s          &0x00800000,%fp0        # -1 + 2^(-126)
7487         bra             t_minx2
7488
7489         global          setoxm1d
7490 setoxm1d:
7491 #--entry point for EXPM1(X), here X is denormalized
7492 #--Step 0.
7493         bra             t_extdnrm
7494
7495 #########################################################################
7496 # sgetexp():  returns the exponent portion of the input argument.       #
7497 #             The exponent bias is removed and the exponent value is    #
7498 #             returned as an extended precision number in fp0.          #
7499 # sgetexpd(): handles denormalized numbers.                             #
7500 #                                                                       #
7501 # sgetman():  extracts the mantissa of the input argument. The          #
7502 #             mantissa is converted to an extended precision number w/  #
7503 #             an exponent of $3fff and is returned in fp0. The range of #
7504 #             the result is [1.0 - 2.0).                                #
7505 # sgetmand(): handles denormalized numbers.                             #
7506 #                                                                       #
7507 # INPUT *************************************************************** #
7508 #       a0  = pointer to extended precision input                       #
7509 #                                                                       #
7510 # OUTPUT ************************************************************** #
7511 #       fp0 = exponent(X) or mantissa(X)                                #
7512 #                                                                       #
7513 #########################################################################
7514
7515         global          sgetexp
7516 sgetexp:
7517         mov.w           SRC_EX(%a0),%d0         # get the exponent
7518         bclr            &0xf,%d0                # clear the sign bit
7519         subi.w          &0x3fff,%d0             # subtract off the bias
7520         fmov.w          %d0,%fp0                # return exp in fp0
7521         blt.b           sgetexpn                # it's negative
7522         rts
7523
7524 sgetexpn:
7525         mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7526         rts
7527
7528         global          sgetexpd
7529 sgetexpd:
7530         bsr.l           norm                    # normalize
7531         neg.w           %d0                     # new exp = -(shft amt)
7532         subi.w          &0x3fff,%d0             # subtract off the bias
7533         fmov.w          %d0,%fp0                # return exp in fp0
7534         mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7535         rts
7536
7537         global          sgetman
7538 sgetman:
7539         mov.w           SRC_EX(%a0),%d0         # get the exp
7540         ori.w           &0x7fff,%d0             # clear old exp
7541         bclr            &0xe,%d0                # make it the new exp +-3fff
7542
7543 # here, we build the result in a tmp location so as not to disturb the input
7544         mov.l           SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
7545         mov.l           SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
7546         mov.w           %d0,FP_SCR0_EX(%a6)     # insert new exponent
7547         fmov.x          FP_SCR0(%a6),%fp0       # put new value back in fp0
7548         bmi.b           sgetmann                # it's negative
7549         rts
7550
7551 sgetmann:
7552         mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7553         rts
7554
7555 #
7556 # For denormalized numbers, shift the mantissa until the j-bit = 1,
7557 # then load the exponent with +/1 $3fff.
7558 #
7559         global          sgetmand
7560 sgetmand:
7561         bsr.l           norm                    # normalize exponent
7562         bra.b           sgetman
7563
7564 #########################################################################
7565 # scosh():  computes the hyperbolic cosine of a normalized input        #
7566 # scoshd(): computes the hyperbolic cosine of a denormalized input      #
7567 #                                                                       #
7568 # INPUT *************************************************************** #
7569 #       a0 = pointer to extended precision input                        #
7570 #       d0 = round precision,mode                                       #
7571 #                                                                       #
7572 # OUTPUT ************************************************************** #
7573 #       fp0 = cosh(X)                                                   #
7574 #                                                                       #
7575 # ACCURACY and MONOTONICITY ******************************************* #
7576 #       The returned result is within 3 ulps in 64 significant bit,     #
7577 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7578 #       rounded to double precision. The result is provably monotonic   #
7579 #       in double precision.                                            #
7580 #                                                                       #
7581 # ALGORITHM *********************************************************** #
7582 #                                                                       #
7583 #       COSH                                                            #
7584 #       1. If |X| > 16380 log2, go to 3.                                #
7585 #                                                                       #
7586 #       2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae      #
7587 #               y = |X|, z = exp(Y), and                                #
7588 #               cosh(X) = (1/2)*( z + 1/z ).                            #
7589 #               Exit.                                                   #
7590 #                                                                       #
7591 #       3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5.            #
7592 #                                                                       #
7593 #       4. (16380 log2 < |X| <= 16480 log2)                             #
7594 #               cosh(X) = sign(X) * exp(|X|)/2.                         #
7595 #               However, invoking exp(|X|) may cause premature          #
7596 #               overflow. Thus, we calculate sinh(X) as follows:        #
7597 #               Y       := |X|                                          #
7598 #               Fact    :=      2**(16380)                              #
7599 #               Y'      := Y - 16381 log2                               #
7600 #               cosh(X) := Fact * exp(Y').                              #
7601 #               Exit.                                                   #
7602 #                                                                       #
7603 #       5. (|X| > 16480 log2) sinh(X) must overflow. Return             #
7604 #               Huge*Huge to generate overflow and an infinity with     #
7605 #               the appropriate sign. Huge is the largest finite number #
7606 #               in extended format. Exit.                               #
7607 #                                                                       #
7608 #########################################################################
7609
7610 TWO16380:
7611         long            0x7FFB0000,0x80000000,0x00000000,0x00000000
7612
7613         global          scosh
7614 scosh:
7615         fmov.x          (%a0),%fp0              # LOAD INPUT
7616
7617         mov.l           (%a0),%d1
7618         mov.w           4(%a0),%d1
7619         and.l           &0x7FFFFFFF,%d1
7620         cmp.l           %d1,&0x400CB167
7621         bgt.b           COSHBIG
7622
7623 #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7624 #--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
7625
7626         fabs.x          %fp0                    # |X|
7627
7628         mov.l           %d0,-(%sp)
7629         clr.l           %d0
7630         fmovm.x         &0x01,-(%sp)            # save |X| to stack
7631         lea             (%sp),%a0               # pass ptr to |X|
7632         bsr             setox                   # FP0 IS EXP(|X|)
7633         add.l           &0xc,%sp                # erase |X| from stack
7634         fmul.s          &0x3F000000,%fp0        # (1/2)EXP(|X|)
7635         mov.l           (%sp)+,%d0
7636
7637         fmov.s          &0x3E800000,%fp1        # (1/4)
7638         fdiv.x          %fp0,%fp1               # 1/(2 EXP(|X|))
7639
7640         fmov.l          %d0,%fpcr
7641         mov.b           &FADD_OP,%d1            # last inst is ADD
7642         fadd.x          %fp1,%fp0
7643         bra             t_catch
7644
7645 COSHBIG:
7646         cmp.l           %d1,&0x400CB2B3
7647         bgt.b           COSHHUGE
7648
7649         fabs.x          %fp0
7650         fsub.d          T1(%pc),%fp0            # (|X|-16381LOG2_LEAD)
7651         fsub.d          T2(%pc),%fp0            # |X| - 16381 LOG2, ACCURATE
7652
7653         mov.l           %d0,-(%sp)
7654         clr.l           %d0
7655         fmovm.x         &0x01,-(%sp)            # save fp0 to stack
7656         lea             (%sp),%a0               # pass ptr to fp0
7657         bsr             setox
7658         add.l           &0xc,%sp                # clear fp0 from stack
7659         mov.l           (%sp)+,%d0
7660
7661         fmov.l          %d0,%fpcr
7662         mov.b           &FMUL_OP,%d1            # last inst is MUL
7663         fmul.x          TWO16380(%pc),%fp0
7664         bra             t_catch
7665
7666 COSHHUGE:
7667         bra             t_ovfl2
7668
7669         global          scoshd
7670 #--COSH(X) = 1 FOR DENORMALIZED X
7671 scoshd:
7672         fmov.s          &0x3F800000,%fp0
7673
7674         fmov.l          %d0,%fpcr
7675         fadd.s          &0x00800000,%fp0
7676         bra             t_pinx2
7677
7678 #########################################################################
7679 # ssinh():  computes the hyperbolic sine of a normalized input          #
7680 # ssinhd(): computes the hyperbolic sine of a denormalized input        #
7681 #                                                                       #
7682 # INPUT *************************************************************** #
7683 #       a0 = pointer to extended precision input                        #
7684 #       d0 = round precision,mode                                       #
7685 #                                                                       #
7686 # OUTPUT ************************************************************** #
7687 #       fp0 = sinh(X)                                                   #
7688 #                                                                       #
7689 # ACCURACY and MONOTONICITY ******************************************* #
7690 #       The returned result is within 3 ulps in 64 significant bit,     #
7691 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7692 #       rounded to double precision. The result is provably monotonic   #
7693 #       in double precision.                                            #
7694 #                                                                       #
7695 # ALGORITHM *********************************************************** #
7696 #                                                                       #
7697 #       SINH                                                            #
7698 #       1. If |X| > 16380 log2, go to 3.                                #
7699 #                                                                       #
7700 #       2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula       #
7701 #               y = |X|, sgn = sign(X), and z = expm1(Y),               #
7702 #               sinh(X) = sgn*(1/2)*( z + z/(1+z) ).                    #
7703 #          Exit.                                                        #
7704 #                                                                       #
7705 #       3. If |X| > 16480 log2, go to 5.                                #
7706 #                                                                       #
7707 #       4. (16380 log2 < |X| <= 16480 log2)                             #
7708 #               sinh(X) = sign(X) * exp(|X|)/2.                         #
7709 #          However, invoking exp(|X|) may cause premature overflow.     #
7710 #          Thus, we calculate sinh(X) as follows:                       #
7711 #             Y       := |X|                                            #
7712 #             sgn     := sign(X)                                        #
7713 #             sgnFact := sgn * 2**(16380)                               #
7714 #             Y'      := Y - 16381 log2                                 #
7715 #             sinh(X) := sgnFact * exp(Y').                             #
7716 #          Exit.                                                        #
7717 #                                                                       #
7718 #       5. (|X| > 16480 log2) sinh(X) must overflow. Return             #
7719 #          sign(X)*Huge*Huge to generate overflow and an infinity with  #
7720 #          the appropriate sign. Huge is the largest finite number in   #
7721 #          extended format. Exit.                                       #
7722 #                                                                       #
7723 #########################################################################
7724
7725         global          ssinh
7726 ssinh:
7727         fmov.x          (%a0),%fp0              # LOAD INPUT
7728
7729         mov.l           (%a0),%d1
7730         mov.w           4(%a0),%d1
7731         mov.l           %d1,%a1                 # save (compacted) operand
7732         and.l           &0x7FFFFFFF,%d1
7733         cmp.l           %d1,&0x400CB167
7734         bgt.b           SINHBIG
7735
7736 #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7737 #--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
7738
7739         fabs.x          %fp0                    # Y = |X|
7740
7741         movm.l          &0x8040,-(%sp)          # {a1/d0}
7742         fmovm.x         &0x01,-(%sp)            # save Y on stack
7743         lea             (%sp),%a0               # pass ptr to Y
7744         clr.l           %d0
7745         bsr             setoxm1                 # FP0 IS Z = EXPM1(Y)
7746         add.l           &0xc,%sp                # clear Y from stack
7747         fmov.l          &0,%fpcr
7748         movm.l          (%sp)+,&0x0201          # {a1/d0}
7749
7750         fmov.x          %fp0,%fp1
7751         fadd.s          &0x3F800000,%fp1        # 1+Z
7752         fmov.x          %fp0,-(%sp)
7753         fdiv.x          %fp1,%fp0               # Z/(1+Z)
7754         mov.l           %a1,%d1
7755         and.l           &0x80000000,%d1
7756         or.l            &0x3F000000,%d1
7757         fadd.x          (%sp)+,%fp0
7758         mov.l           %d1,-(%sp)
7759
7760         fmov.l          %d0,%fpcr
7761         mov.b           &FMUL_OP,%d1            # last inst is MUL
7762         fmul.s          (%sp)+,%fp0             # last fp inst - possible exceptions set
7763         bra             t_catch
7764
7765 SINHBIG:
7766         cmp.l           %d1,&0x400CB2B3
7767         bgt             t_ovfl
7768         fabs.x          %fp0
7769         fsub.d          T1(%pc),%fp0            # (|X|-16381LOG2_LEAD)
7770         mov.l           &0,-(%sp)
7771         mov.l           &0x80000000,-(%sp)
7772         mov.l           %a1,%d1
7773         and.l           &0x80000000,%d1
7774         or.l            &0x7FFB0000,%d1
7775         mov.l           %d1,-(%sp)              # EXTENDED FMT
7776         fsub.d          T2(%pc),%fp0            # |X| - 16381 LOG2, ACCURATE
7777
7778         mov.l           %d0,-(%sp)
7779         clr.l           %d0
7780         fmovm.x         &0x01,-(%sp)            # save fp0 on stack
7781         lea             (%sp),%a0               # pass ptr to fp0
7782         bsr             setox
7783         add.l           &0xc,%sp                # clear fp0 from stack
7784
7785         mov.l           (%sp)+,%d0
7786         fmov.l          %d0,%fpcr
7787         mov.b           &FMUL_OP,%d1            # last inst is MUL
7788         fmul.x          (%sp)+,%fp0             # possible exception
7789         bra             t_catch
7790
7791         global          ssinhd
7792 #--SINH(X) = X FOR DENORMALIZED X
7793 ssinhd:
7794         bra             t_extdnrm
7795
7796 #########################################################################
7797 # stanh():  computes the hyperbolic tangent of a normalized input       #
7798 # stanhd(): computes the hyperbolic tangent of a denormalized input     #
7799 #                                                                       #
7800 # INPUT *************************************************************** #
7801 #       a0 = pointer to extended precision input                        #
7802 #       d0 = round precision,mode                                       #
7803 #                                                                       #
7804 # OUTPUT ************************************************************** #
7805 #       fp0 = tanh(X)                                                   #
7806 #                                                                       #
7807 # ACCURACY and MONOTONICITY ******************************************* #
7808 #       The returned result is within 3 ulps in 64 significant bit,     #
7809 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7810 #       rounded to double precision. The result is provably monotonic   #
7811 #       in double precision.                                            #
7812 #                                                                       #
7813 # ALGORITHM *********************************************************** #
7814 #                                                                       #
7815 #       TANH                                                            #
7816 #       1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3.            #
7817 #                                                                       #
7818 #       2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by           #
7819 #               sgn := sign(X), y := 2|X|, z := expm1(Y), and           #
7820 #               tanh(X) = sgn*( z/(2+z) ).                              #
7821 #               Exit.                                                   #
7822 #                                                                       #
7823 #       3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1,          #
7824 #               go to 7.                                                #
7825 #                                                                       #
7826 #       4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6.              #
7827 #                                                                       #
7828 #       5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by           #
7829 #               sgn := sign(X), y := 2|X|, z := exp(Y),                 #
7830 #               tanh(X) = sgn - [ sgn*2/(1+z) ].                        #
7831 #               Exit.                                                   #
7832 #                                                                       #
7833 #       6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we  #
7834 #               calculate Tanh(X) by                                    #
7835 #               sgn := sign(X), Tiny := 2**(-126),                      #
7836 #               tanh(X) := sgn - sgn*Tiny.                              #
7837 #               Exit.                                                   #
7838 #                                                                       #
7839 #       7. (|X| < 2**(-40)). Tanh(X) = X.       Exit.                   #
7840 #                                                                       #
7841 #########################################################################
7842
7843         set             X,FP_SCR0
7844         set             XFRAC,X+4
7845
7846         set             SGN,L_SCR3
7847
7848         set             V,FP_SCR0
7849
7850         global          stanh
7851 stanh:
7852         fmov.x          (%a0),%fp0              # LOAD INPUT
7853
7854         fmov.x          %fp0,X(%a6)
7855         mov.l           (%a0),%d1
7856         mov.w           4(%a0),%d1
7857         mov.l           %d1,X(%a6)
7858         and.l           &0x7FFFFFFF,%d1
7859         cmp.l           %d1, &0x3fd78000        # is |X| < 2^(-40)?
7860         blt.w           TANHBORS                # yes
7861         cmp.l           %d1, &0x3fffddce        # is |X| > (5/2)LOG2?
7862         bgt.w           TANHBORS                # yes
7863
7864 #--THIS IS THE USUAL CASE
7865 #--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
7866
7867         mov.l           X(%a6),%d1
7868         mov.l           %d1,SGN(%a6)
7869         and.l           &0x7FFF0000,%d1
7870         add.l           &0x00010000,%d1         # EXPONENT OF 2|X|
7871         mov.l           %d1,X(%a6)
7872         and.l           &0x80000000,SGN(%a6)
7873         fmov.x          X(%a6),%fp0             # FP0 IS Y = 2|X|
7874
7875         mov.l           %d0,-(%sp)
7876         clr.l           %d0
7877         fmovm.x         &0x1,-(%sp)             # save Y on stack
7878         lea             (%sp),%a0               # pass ptr to Y
7879         bsr             setoxm1                 # FP0 IS Z = EXPM1(Y)
7880         add.l           &0xc,%sp                # clear Y from stack
7881         mov.l           (%sp)+,%d0
7882
7883         fmov.x          %fp0,%fp1
7884         fadd.s          &0x40000000,%fp1        # Z+2
7885         mov.l           SGN(%a6),%d1
7886         fmov.x          %fp1,V(%a6)
7887         eor.l           %d1,V(%a6)
7888
7889         fmov.l          %d0,%fpcr               # restore users round prec,mode
7890         fdiv.x          V(%a6),%fp0
7891         bra             t_inx2
7892
7893 TANHBORS:
7894         cmp.l           %d1,&0x3FFF8000
7895         blt.w           TANHSM
7896
7897         cmp.l           %d1,&0x40048AA1
7898         bgt.w           TANHHUGE
7899
7900 #-- (5/2) LOG2 < |X| < 50 LOG2,
7901 #--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
7902 #--TANH(X) = SGN -      SGN*2/[EXP(Y)+1].
7903
7904         mov.l           X(%a6),%d1
7905         mov.l           %d1,SGN(%a6)
7906         and.l           &0x7FFF0000,%d1
7907         add.l           &0x00010000,%d1         # EXPO OF 2|X|
7908         mov.l           %d1,X(%a6)              # Y = 2|X|
7909         and.l           &0x80000000,SGN(%a6)
7910         mov.l           SGN(%a6),%d1
7911         fmov.x          X(%a6),%fp0             # Y = 2|X|
7912
7913         mov.l           %d0,-(%sp)
7914         clr.l           %d0
7915         fmovm.x         &0x01,-(%sp)            # save Y on stack
7916         lea             (%sp),%a0               # pass ptr to Y
7917         bsr             setox                   # FP0 IS EXP(Y)
7918         add.l           &0xc,%sp                # clear Y from stack
7919         mov.l           (%sp)+,%d0
7920         mov.l           SGN(%a6),%d1
7921         fadd.s          &0x3F800000,%fp0        # EXP(Y)+1
7922
7923         eor.l           &0xC0000000,%d1         # -SIGN(X)*2
7924         fmov.s          %d1,%fp1                # -SIGN(X)*2 IN SGL FMT
7925         fdiv.x          %fp0,%fp1               # -SIGN(X)2 / [EXP(Y)+1 ]
7926
7927         mov.l           SGN(%a6),%d1
7928         or.l            &0x3F800000,%d1         # SGN
7929         fmov.s          %d1,%fp0                # SGN IN SGL FMT
7930
7931         fmov.l          %d0,%fpcr               # restore users round prec,mode
7932         mov.b           &FADD_OP,%d1            # last inst is ADD
7933         fadd.x          %fp1,%fp0
7934         bra             t_inx2
7935
7936 TANHSM:
7937         fmov.l          %d0,%fpcr               # restore users round prec,mode
7938         mov.b           &FMOV_OP,%d1            # last inst is MOVE
7939         fmov.x          X(%a6),%fp0             # last inst - possible exception set
7940         bra             t_catch
7941
7942 #---RETURN SGN(X) - SGN(X)EPS
7943 TANHHUGE:
7944         mov.l           X(%a6),%d1
7945         and.l           &0x80000000,%d1
7946         or.l            &0x3F800000,%d1
7947         fmov.s          %d1,%fp0
7948         and.l           &0x80000000,%d1
7949         eor.l           &0x80800000,%d1         # -SIGN(X)*EPS
7950
7951         fmov.l          %d0,%fpcr               # restore users round prec,mode
7952         fadd.s          %d1,%fp0
7953         bra             t_inx2
7954
7955         global          stanhd
7956 #--TANH(X) = X FOR DENORMALIZED X
7957 stanhd:
7958         bra             t_extdnrm
7959
7960 #########################################################################
7961 # slogn():    computes the natural logarithm of a normalized input      #
7962 # slognd():   computes the natural logarithm of a denormalized input    #
7963 # slognp1():  computes the log(1+X) of a normalized input               #
7964 # slognp1d(): computes the log(1+X) of a denormalized input             #
7965 #                                                                       #
7966 # INPUT *************************************************************** #
7967 #       a0 = pointer to extended precision input                        #
7968 #       d0 = round precision,mode                                       #
7969 #                                                                       #
7970 # OUTPUT ************************************************************** #
7971 #       fp0 = log(X) or log(1+X)                                        #
7972 #                                                                       #
7973 # ACCURACY and MONOTONICITY ******************************************* #
7974 #       The returned result is within 2 ulps in 64 significant bit,     #
7975 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7976 #       rounded to double precision. The result is provably monotonic   #
7977 #       in double precision.                                            #
7978 #                                                                       #
7979 # ALGORITHM *********************************************************** #
7980 #       LOGN:                                                           #
7981 #       Step 1. If |X-1| < 1/16, approximate log(X) by an odd           #
7982 #               polynomial in u, where u = 2(X-1)/(X+1). Otherwise,     #
7983 #               move on to Step 2.                                      #
7984 #                                                                       #
7985 #       Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
7986 #               seven significant bits of Y plus 2**(-7), i.e.          #
7987 #               F = 1.xxxxxx1 in base 2 where the six "x" match those   #
7988 #               of Y. Note that |Y-F| <= 2**(-7).                       #
7989 #                                                                       #
7990 #       Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a           #
7991 #               polynomial in u, log(1+u) = poly.                       #
7992 #                                                                       #
7993 #       Step 4. Reconstruct                                             #
7994 #               log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
7995 #               by k*log(2) + (log(F) + poly). The values of log(F) are #
7996 #               calculated beforehand and stored in the program.        #
7997 #                                                                       #
7998 #       lognp1:                                                         #
7999 #       Step 1: If |X| < 1/16, approximate log(1+X) by an odd           #
8000 #               polynomial in u where u = 2X/(2+X). Otherwise, move on  #
8001 #               to Step 2.                                              #
8002 #                                                                       #
8003 #       Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done  #
8004 #               in Step 2 of the algorithm for LOGN and compute         #
8005 #               log(1+X) as k*log(2) + log(F) + poly where poly         #
8006 #               approximates log(1+u), u = (Y-F)/F.                     #
8007 #                                                                       #
8008 #       Implementation Notes:                                           #
8009 #       Note 1. There are 64 different possible values for F, thus 64   #
8010 #               log(F)'s need to be tabulated. Moreover, the values of  #
8011 #               1/F are also tabulated so that the division in (Y-F)/F  #
8012 #               can be performed by a multiplication.                   #
8013 #                                                                       #
8014 #       Note 2. In Step 2 of lognp1, in order to preserved accuracy,    #
8015 #               the value Y-F has to be calculated carefully when       #
8016 #               1/2 <= X < 3/2.                                         #
8017 #                                                                       #
8018 #       Note 3. To fully exploit the pipeline, polynomials are usually  #
8019 #               separated into two parts evaluated independently before #
8020 #               being added up.                                         #
8021 #                                                                       #
8022 #########################################################################
8023 LOGOF2:
8024         long            0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8025
8026 one:
8027         long            0x3F800000
8028 zero:
8029         long            0x00000000
8030 infty:
8031         long            0x7F800000
8032 negone:
8033         long            0xBF800000
8034
8035 LOGA6:
8036         long            0x3FC2499A,0xB5E4040B
8037 LOGA5:
8038         long            0xBFC555B5,0x848CB7DB
8039
8040 LOGA4:
8041         long            0x3FC99999,0x987D8730
8042 LOGA3:
8043         long            0xBFCFFFFF,0xFF6F7E97
8044
8045 LOGA2:
8046         long            0x3FD55555,0x555555A4
8047 LOGA1:
8048         long            0xBFE00000,0x00000008
8049
8050 LOGB5:
8051         long            0x3F175496,0xADD7DAD6
8052 LOGB4:
8053         long            0x3F3C71C2,0xFE80C7E0
8054
8055 LOGB3:
8056         long            0x3F624924,0x928BCCFF
8057 LOGB2:
8058         long            0x3F899999,0x999995EC
8059
8060 LOGB1:
8061         long            0x3FB55555,0x55555555
8062 TWO:
8063         long            0x40000000,0x00000000
8064
8065 LTHOLD:
8066         long            0x3f990000,0x80000000,0x00000000,0x00000000
8067
8068 LOGTBL:
8069         long            0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
8070         long            0x3FF70000,0xFF015358,0x833C47E2,0x00000000
8071         long            0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
8072         long            0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
8073         long            0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
8074         long            0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
8075         long            0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
8076         long            0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
8077         long            0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
8078         long            0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
8079         long            0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
8080         long            0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
8081         long            0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
8082         long            0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
8083         long            0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
8084         long            0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
8085         long            0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
8086         long            0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
8087         long            0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
8088         long            0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
8089         long            0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
8090         long            0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
8091         long            0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
8092         long            0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
8093         long            0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
8094         long            0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
8095         long            0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
8096         long            0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
8097         long            0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
8098         long            0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
8099         long            0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
8100         long            0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
8101         long            0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
8102         long            0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
8103         long            0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
8104         long            0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
8105         long            0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
8106         long            0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
8107         long            0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
8108         long            0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
8109         long            0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
8110         long            0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
8111         long            0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
8112         long            0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
8113         long            0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
8114         long            0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
8115         long            0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
8116         long            0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
8117         long            0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
8118         long            0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
8119         long            0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
8120         long            0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
8121         long            0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
8122         long            0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
8123         long            0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
8124         long            0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
8125         long            0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
8126         long            0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
8127         long            0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
8128         long            0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
8129         long            0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
8130         long            0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
8131         long            0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
8132         long            0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
8133         long            0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
8134         long            0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
8135         long            0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
8136         long            0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
8137         long            0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
8138         long            0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
8139         long            0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
8140         long            0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
8141         long            0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
8142         long            0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
8143         long            0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
8144         long            0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
8145         long            0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
8146         long            0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
8147         long            0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
8148         long            0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
8149         long            0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
8150         long            0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
8151         long            0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
8152         long            0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
8153         long            0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
8154         long            0x3FFE0000,0x825EFCED,0x49369330,0x00000000
8155         long            0x3FFE0000,0x9868C809,0x868C8098,0x00000000
8156         long            0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
8157         long            0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
8158         long            0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
8159         long            0x3FFE0000,0x95A02568,0x095A0257,0x00000000
8160         long            0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
8161         long            0x3FFE0000,0x94458094,0x45809446,0x00000000
8162         long            0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
8163         long            0x3FFE0000,0x92F11384,0x0497889C,0x00000000
8164         long            0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
8165         long            0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
8166         long            0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
8167         long            0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
8168         long            0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
8169         long            0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
8170         long            0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
8171         long            0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
8172         long            0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
8173         long            0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
8174         long            0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
8175         long            0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
8176         long            0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
8177         long            0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
8178         long            0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
8179         long            0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
8180         long            0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
8181         long            0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
8182         long            0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
8183         long            0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
8184         long            0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
8185         long            0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
8186         long            0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
8187         long            0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
8188         long            0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
8189         long            0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
8190         long            0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
8191         long            0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
8192         long            0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
8193         long            0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
8194         long            0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
8195         long            0x3FFE0000,0x80808080,0x80808081,0x00000000
8196         long            0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
8197
8198         set             ADJK,L_SCR1
8199
8200         set             X,FP_SCR0
8201         set             XDCARE,X+2
8202         set             XFRAC,X+4
8203
8204         set             F,FP_SCR1
8205         set             FFRAC,F+4
8206
8207         set             KLOG2,FP_SCR0
8208
8209         set             SAVEU,FP_SCR0
8210
8211         global          slogn
8212 #--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
8213 slogn:
8214         fmov.x          (%a0),%fp0              # LOAD INPUT
8215         mov.l           &0x00000000,ADJK(%a6)
8216
8217 LOGBGN:
8218 #--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
8219 #--A FINITE, NON-ZERO, NORMALIZED NUMBER.
8220
8221         mov.l           (%a0),%d1
8222         mov.w           4(%a0),%d1
8223
8224         mov.l           (%a0),X(%a6)
8225         mov.l           4(%a0),X+4(%a6)
8226         mov.l           8(%a0),X+8(%a6)
8227
8228         cmp.l           %d1,&0                  # CHECK IF X IS NEGATIVE
8229         blt.w           LOGNEG                  # LOG OF NEGATIVE ARGUMENT IS INVALID
8230 # X IS POSITIVE, CHECK IF X IS NEAR 1
8231         cmp.l           %d1,&0x3ffef07d         # IS X < 15/16?
8232         blt.b           LOGMAIN                 # YES
8233         cmp.l           %d1,&0x3fff8841         # IS X > 17/16?
8234         ble.w           LOGNEAR1                # NO
8235
8236 LOGMAIN:
8237 #--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
8238
8239 #--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
8240 #--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
8241 #--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
8242 #--                      = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
8243 #--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
8244 #--LOG(1+U) CAN BE VERY EFFICIENT.
8245 #--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
8246 #--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
8247
8248 #--GET K, Y, F, AND ADDRESS OF 1/F.
8249         asr.l           &8,%d1
8250         asr.l           &8,%d1                  # SHIFTED 16 BITS, BIASED EXPO. OF X
8251         sub.l           &0x3FFF,%d1             # THIS IS K
8252         add.l           ADJK(%a6),%d1           # ADJUST K, ORIGINAL INPUT MAY BE  DENORM.
8253         lea             LOGTBL(%pc),%a0         # BASE ADDRESS OF 1/F AND LOG(F)
8254         fmov.l          %d1,%fp1                # CONVERT K TO FLOATING-POINT FORMAT
8255
8256 #--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
8257         mov.l           &0x3FFF0000,X(%a6)      # X IS NOW Y, I.E. 2^(-K)*X
8258         mov.l           XFRAC(%a6),FFRAC(%a6)
8259         and.l           &0xFE000000,FFRAC(%a6)  # FIRST 7 BITS OF Y
8260         or.l            &0x01000000,FFRAC(%a6)  # GET F: ATTACH A 1 AT THE EIGHTH BIT
8261         mov.l           FFRAC(%a6),%d1  # READY TO GET ADDRESS OF 1/F
8262         and.l           &0x7E000000,%d1
8263         asr.l           &8,%d1
8264         asr.l           &8,%d1
8265         asr.l           &4,%d1                  # SHIFTED 20, D0 IS THE DISPLACEMENT
8266         add.l           %d1,%a0                 # A0 IS THE ADDRESS FOR 1/F
8267
8268         fmov.x          X(%a6),%fp0
8269         mov.l           &0x3fff0000,F(%a6)
8270         clr.l           F+8(%a6)
8271         fsub.x          F(%a6),%fp0             # Y-F
8272         fmovm.x         &0xc,-(%sp)             # SAVE FP2-3 WHILE FP0 IS NOT READY
8273 #--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
8274 #--REGISTERS SAVED: FPCR, FP1, FP2
8275
8276 LP1CONT1:
8277 #--AN RE-ENTRY POINT FOR LOGNP1
8278         fmul.x          (%a0),%fp0              # FP0 IS U = (Y-F)/F
8279         fmul.x          LOGOF2(%pc),%fp1        # GET K*LOG2 WHILE FP0 IS NOT READY
8280         fmov.x          %fp0,%fp2
8281         fmul.x          %fp2,%fp2               # FP2 IS V=U*U
8282         fmov.x          %fp1,KLOG2(%a6)         # PUT K*LOG2 IN MEMEORY, FREE FP1
8283
8284 #--LOG(1+U) IS APPROXIMATED BY
8285 #--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
8286 #--[U + V*(A1+V*(A3+V*A5))]  +  [U*V*(A2+V*(A4+V*A6))]
8287
8288         fmov.x          %fp2,%fp3
8289         fmov.x          %fp2,%fp1
8290
8291         fmul.d          LOGA6(%pc),%fp1         # V*A6
8292         fmul.d          LOGA5(%pc),%fp2         # V*A5
8293
8294         fadd.d          LOGA4(%pc),%fp1         # A4+V*A6
8295         fadd.d          LOGA3(%pc),%fp2         # A3+V*A5
8296
8297         fmul.x          %fp3,%fp1               # V*(A4+V*A6)
8298         fmul.x          %fp3,%fp2               # V*(A3+V*A5)
8299
8300         fadd.d          LOGA2(%pc),%fp1         # A2+V*(A4+V*A6)
8301         fadd.d          LOGA1(%pc),%fp2         # A1+V*(A3+V*A5)
8302
8303         fmul.x          %fp3,%fp1               # V*(A2+V*(A4+V*A6))
8304         add.l           &16,%a0                 # ADDRESS OF LOG(F)
8305         fmul.x          %fp3,%fp2               # V*(A1+V*(A3+V*A5))
8306
8307         fmul.x          %fp0,%fp1               # U*V*(A2+V*(A4+V*A6))
8308         fadd.x          %fp2,%fp0               # U+V*(A1+V*(A3+V*A5))
8309
8310         fadd.x          (%a0),%fp1              # LOG(F)+U*V*(A2+V*(A4+V*A6))
8311         fmovm.x         (%sp)+,&0x30            # RESTORE FP2-3
8312         fadd.x          %fp1,%fp0               # FP0 IS LOG(F) + LOG(1+U)
8313
8314         fmov.l          %d0,%fpcr
8315         fadd.x          KLOG2(%a6),%fp0         # FINAL ADD
8316         bra             t_inx2
8317
8318
8319 LOGNEAR1:
8320
8321 # if the input is exactly equal to one, then exit through ld_pzero.
8322 # if these 2 lines weren't here, the correct answer would be returned
8323 # but the INEX2 bit would be set.
8324         fcmp.b          %fp0,&0x1               # is it equal to one?
8325         fbeq.l          ld_pzero                # yes
8326
8327 #--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
8328         fmov.x          %fp0,%fp1
8329         fsub.s          one(%pc),%fp1           # FP1 IS X-1
8330         fadd.s          one(%pc),%fp0           # FP0 IS X+1
8331         fadd.x          %fp1,%fp1               # FP1 IS 2(X-1)
8332 #--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
8333 #--IN U, U = 2(X-1)/(X+1) = FP1/FP0
8334
8335 LP1CONT2:
8336 #--THIS IS AN RE-ENTRY POINT FOR LOGNP1
8337         fdiv.x          %fp0,%fp1               # FP1 IS U
8338         fmovm.x         &0xc,-(%sp)             # SAVE FP2-3
8339 #--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
8340 #--LET V=U*U, W=V*V, CALCULATE
8341 #--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
8342 #--U + U*V*(  [B1 + W*(B3 + W*B5)]  +  [V*(B2 + W*B4)]  )
8343         fmov.x          %fp1,%fp0
8344         fmul.x          %fp0,%fp0               # FP0 IS V
8345         fmov.x          %fp1,SAVEU(%a6)         # STORE U IN MEMORY, FREE FP1
8346         fmov.x          %fp0,%fp1
8347         fmul.x          %fp1,%fp1               # FP1 IS W
8348
8349         fmov.d          LOGB5(%pc),%fp3
8350         fmov.d          LOGB4(%pc),%fp2
8351
8352         fmul.x          %fp1,%fp3               # W*B5
8353         fmul.x          %fp1,%fp2               # W*B4
8354
8355         fadd.d          LOGB3(%pc),%fp3         # B3+W*B5
8356         fadd.d          LOGB2(%pc),%fp2         # B2+W*B4
8357
8358         fmul.x          %fp3,%fp1               # W*(B3+W*B5), FP3 RELEASED
8359
8360         fmul.x          %fp0,%fp2               # V*(B2+W*B4)
8361
8362         fadd.d          LOGB1(%pc),%fp1         # B1+W*(B3+W*B5)
8363         fmul.x          SAVEU(%a6),%fp0         # FP0 IS U*V
8364
8365         fadd.x          %fp2,%fp1               # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
8366         fmovm.x         (%sp)+,&0x30            # FP2-3 RESTORED
8367
8368         fmul.x          %fp1,%fp0               # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
8369
8370         fmov.l          %d0,%fpcr
8371         fadd.x          SAVEU(%a6),%fp0
8372         bra             t_inx2
8373
8374 #--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
8375 LOGNEG:
8376         bra             t_operr
8377
8378         global          slognd
8379 slognd:
8380 #--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
8381
8382         mov.l           &-100,ADJK(%a6)         # INPUT = 2^(ADJK) * FP0
8383
8384 #----normalize the input value by left shifting k bits (k to be determined
8385 #----below), adjusting exponent and storing -k to  ADJK
8386 #----the value TWOTO100 is no longer needed.
8387 #----Note that this code assumes the denormalized input is NON-ZERO.
8388
8389         movm.l          &0x3f00,-(%sp)          # save some registers  {d2-d7}
8390         mov.l           (%a0),%d3               # D3 is exponent of smallest norm. #
8391         mov.l           4(%a0),%d4
8392         mov.l           8(%a0),%d5              # (D4,D5) is (Hi_X,Lo_X)
8393         clr.l           %d2                     # D2 used for holding K
8394
8395         tst.l           %d4
8396         bne.b           Hi_not0
8397
8398 Hi_0:
8399         mov.l           %d5,%d4
8400         clr.l           %d5
8401         mov.l           &32,%d2
8402         clr.l           %d6
8403         bfffo           %d4{&0:&32},%d6
8404         lsl.l           %d6,%d4
8405         add.l           %d6,%d2                 # (D3,D4,D5) is normalized
8406
8407         mov.l           %d3,X(%a6)
8408         mov.l           %d4,XFRAC(%a6)
8409         mov.l           %d5,XFRAC+4(%a6)
8410         neg.l           %d2
8411         mov.l           %d2,ADJK(%a6)
8412         fmov.x          X(%a6),%fp0
8413         movm.l          (%sp)+,&0xfc            # restore registers {d2-d7}
8414         lea             X(%a6),%a0
8415         bra.w           LOGBGN                  # begin regular log(X)
8416
8417 Hi_not0:
8418         clr.l           %d6
8419         bfffo           %d4{&0:&32},%d6         # find first 1
8420         mov.l           %d6,%d2                 # get k
8421         lsl.l           %d6,%d4
8422         mov.l           %d5,%d7                 # a copy of D5
8423         lsl.l           %d6,%d5
8424         neg.l           %d6
8425         add.l           &32,%d6
8426         lsr.l           %d6,%d7
8427         or.l            %d7,%d4                 # (D3,D4,D5) normalized
8428
8429         mov.l           %d3,X(%a6)
8430         mov.l           %d4,XFRAC(%a6)
8431         mov.l           %d5,XFRAC+4(%a6)
8432         neg.l           %d2
8433         mov.l           %d2,ADJK(%a6)
8434         fmov.x          X(%a6),%fp0
8435         movm.l          (%sp)+,&0xfc            # restore registers {d2-d7}
8436         lea             X(%a6),%a0
8437         bra.w           LOGBGN                  # begin regular log(X)
8438
8439         global          slognp1
8440 #--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
8441 slognp1:
8442         fmov.x          (%a0),%fp0              # LOAD INPUT
8443         fabs.x          %fp0                    # test magnitude
8444         fcmp.x          %fp0,LTHOLD(%pc)        # compare with min threshold
8445         fbgt.w          LP1REAL                 # if greater, continue
8446         fmov.l          %d0,%fpcr
8447         mov.b           &FMOV_OP,%d1            # last inst is MOVE
8448         fmov.x          (%a0),%fp0              # return signed argument
8449         bra             t_catch
8450
8451 LP1REAL:
8452         fmov.x          (%a0),%fp0              # LOAD INPUT
8453         mov.l           &0x00000000,ADJK(%a6)
8454         fmov.x          %fp0,%fp1               # FP1 IS INPUT Z
8455         fadd.s          one(%pc),%fp0           # X := ROUND(1+Z)
8456         fmov.x          %fp0,X(%a6)
8457         mov.w           XFRAC(%a6),XDCARE(%a6)
8458         mov.l           X(%a6),%d1
8459         cmp.l           %d1,&0
8460         ble.w           LP1NEG0                 # LOG OF ZERO OR -VE
8461         cmp.l           %d1,&0x3ffe8000         # IS BOUNDS [1/2,3/2]?
8462         blt.w           LOGMAIN
8463         cmp.l           %d1,&0x3fffc000
8464         bgt.w           LOGMAIN
8465 #--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
8466 #--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
8467 #--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
8468
8469 LP1NEAR1:
8470 #--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
8471         cmp.l           %d1,&0x3ffef07d
8472         blt.w           LP1CARE
8473         cmp.l           %d1,&0x3fff8841
8474         bgt.w           LP1CARE
8475
8476 LP1ONE16:
8477 #--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
8478 #--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
8479         fadd.x          %fp1,%fp1               # FP1 IS 2Z
8480         fadd.s          one(%pc),%fp0           # FP0 IS 1+X
8481 #--U = FP1/FP0
8482         bra.w           LP1CONT2
8483
8484 LP1CARE:
8485 #--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
8486 #--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
8487 #--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
8488 #--THERE ARE ONLY TWO CASES.
8489 #--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
8490 #--CASE 2: 1+Z > 1, THEN K = 0  AND Y-F = (1-F) + Z
8491 #--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
8492 #--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
8493
8494         mov.l           XFRAC(%a6),FFRAC(%a6)
8495         and.l           &0xFE000000,FFRAC(%a6)
8496         or.l            &0x01000000,FFRAC(%a6)  # F OBTAINED
8497         cmp.l           %d1,&0x3FFF8000         # SEE IF 1+Z > 1
8498         bge.b           KISZERO
8499
8500 KISNEG1:
8501         fmov.s          TWO(%pc),%fp0
8502         mov.l           &0x3fff0000,F(%a6)
8503         clr.l           F+8(%a6)
8504         fsub.x          F(%a6),%fp0             # 2-F
8505         mov.l           FFRAC(%a6),%d1
8506         and.l           &0x7E000000,%d1
8507         asr.l           &8,%d1
8508         asr.l           &8,%d1
8509         asr.l           &4,%d1                  # D0 CONTAINS DISPLACEMENT FOR 1/F
8510         fadd.x          %fp1,%fp1               # GET 2Z
8511         fmovm.x         &0xc,-(%sp)             # SAVE FP2  {%fp2/%fp3}
8512         fadd.x          %fp1,%fp0               # FP0 IS Y-F = (2-F)+2Z
8513         lea             LOGTBL(%pc),%a0         # A0 IS ADDRESS OF 1/F
8514         add.l           %d1,%a0
8515         fmov.s          negone(%pc),%fp1        # FP1 IS K = -1
8516         bra.w           LP1CONT1
8517
8518 KISZERO:
8519         fmov.s          one(%pc),%fp0
8520         mov.l           &0x3fff0000,F(%a6)
8521         clr.l           F+8(%a6)
8522         fsub.x          F(%a6),%fp0             # 1-F
8523         mov.l           FFRAC(%a6),%d1
8524         and.l           &0x7E000000,%d1
8525         asr.l           &8,%d1
8526         asr.l           &8,%d1
8527         asr.l           &4,%d1
8528         fadd.x          %fp1,%fp0               # FP0 IS Y-F
8529         fmovm.x         &0xc,-(%sp)             # FP2 SAVED {%fp2/%fp3}
8530         lea             LOGTBL(%pc),%a0
8531         add.l           %d1,%a0                 # A0 IS ADDRESS OF 1/F
8532         fmov.s          zero(%pc),%fp1          # FP1 IS K = 0
8533         bra.w           LP1CONT1
8534
8535 LP1NEG0:
8536 #--FPCR SAVED. D0 IS X IN COMPACT FORM.
8537         cmp.l           %d1,&0
8538         blt.b           LP1NEG
8539 LP1ZERO:
8540         fmov.s          negone(%pc),%fp0
8541
8542         fmov.l          %d0,%fpcr
8543         bra             t_dz
8544
8545 LP1NEG:
8546         fmov.s          zero(%pc),%fp0
8547
8548         fmov.l          %d0,%fpcr
8549         bra             t_operr
8550
8551         global          slognp1d
8552 #--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
8553 # Simply return the denorm
8554 slognp1d:
8555         bra             t_extdnrm
8556
8557 #########################################################################
8558 # satanh():  computes the inverse hyperbolic tangent of a norm input    #
8559 # satanhd(): computes the inverse hyperbolic tangent of a denorm input  #
8560 #                                                                       #
8561 # INPUT *************************************************************** #
8562 #       a0 = pointer to extended precision input                        #
8563 #       d0 = round precision,mode                                       #
8564 #                                                                       #
8565 # OUTPUT ************************************************************** #
8566 #       fp0 = arctanh(X)                                                #
8567 #                                                                       #
8568 # ACCURACY and MONOTONICITY ******************************************* #
8569 #       The returned result is within 3 ulps in 64 significant bit,     #
8570 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8571 #       rounded to double precision. The result is provably monotonic   #
8572 #       in double precision.                                            #
8573 #                                                                       #
8574 # ALGORITHM *********************************************************** #
8575 #                                                                       #
8576 #       ATANH                                                           #
8577 #       1. If |X| >= 1, go to 3.                                        #
8578 #                                                                       #
8579 #       2. (|X| < 1) Calculate atanh(X) by                              #
8580 #               sgn := sign(X)                                          #
8581 #               y := |X|                                                #
8582 #               z := 2y/(1-y)                                           #
8583 #               atanh(X) := sgn * (1/2) * logp1(z)                      #
8584 #               Exit.                                                   #
8585 #                                                                       #
8586 #       3. If |X| > 1, go to 5.                                         #
8587 #                                                                       #
8588 #       4. (|X| = 1) Generate infinity with an appropriate sign and     #
8589 #               divide-by-zero by                                       #
8590 #               sgn := sign(X)                                          #
8591 #               atan(X) := sgn / (+0).                                  #
8592 #               Exit.                                                   #
8593 #                                                                       #
8594 #       5. (|X| > 1) Generate an invalid operation by 0 * infinity.     #
8595 #               Exit.                                                   #
8596 #                                                                       #
8597 #########################################################################
8598
8599         global          satanh
8600 satanh:
8601         mov.l           (%a0),%d1
8602         mov.w           4(%a0),%d1
8603         and.l           &0x7FFFFFFF,%d1
8604         cmp.l           %d1,&0x3FFF8000
8605         bge.b           ATANHBIG
8606
8607 #--THIS IS THE USUAL CASE, |X| < 1
8608 #--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
8609
8610         fabs.x          (%a0),%fp0              # Y = |X|
8611         fmov.x          %fp0,%fp1
8612         fneg.x          %fp1                    # -Y
8613         fadd.x          %fp0,%fp0               # 2Y
8614         fadd.s          &0x3F800000,%fp1        # 1-Y
8615         fdiv.x          %fp1,%fp0               # 2Y/(1-Y)
8616         mov.l           (%a0),%d1
8617         and.l           &0x80000000,%d1
8618         or.l            &0x3F000000,%d1         # SIGN(X)*HALF
8619         mov.l           %d1,-(%sp)
8620
8621         mov.l           %d0,-(%sp)              # save rnd prec,mode
8622         clr.l           %d0                     # pass ext prec,RN
8623         fmovm.x         &0x01,-(%sp)            # save Z on stack
8624         lea             (%sp),%a0               # pass ptr to Z
8625         bsr             slognp1                 # LOG1P(Z)
8626         add.l           &0xc,%sp                # clear Z from stack
8627
8628         mov.l           (%sp)+,%d0              # fetch old prec,mode
8629         fmov.l          %d0,%fpcr               # load it
8630         mov.b           &FMUL_OP,%d1            # last inst is MUL
8631         fmul.s          (%sp)+,%fp0
8632         bra             t_catch
8633
8634 ATANHBIG:
8635         fabs.x          (%a0),%fp0              # |X|
8636         fcmp.s          %fp0,&0x3F800000
8637         fbgt            t_operr
8638         bra             t_dz
8639
8640         global          satanhd
8641 #--ATANH(X) = X FOR DENORMALIZED X
8642 satanhd:
8643         bra             t_extdnrm
8644
8645 #########################################################################
8646 # slog10():  computes the base-10 logarithm of a normalized input       #
8647 # slog10d(): computes the base-10 logarithm of a denormalized input     #
8648 # slog2():   computes the base-2 logarithm of a normalized input        #
8649 # slog2d():  computes the base-2 logarithm of a denormalized input      #
8650 #                                                                       #
8651 # INPUT *************************************************************** #
8652 #       a0 = pointer to extended precision input                        #
8653 #       d0 = round precision,mode                                       #
8654 #                                                                       #
8655 # OUTPUT ************************************************************** #
8656 #       fp0 = log_10(X) or log_2(X)                                     #
8657 #                                                                       #
8658 # ACCURACY and MONOTONICITY ******************************************* #
8659 #       The returned result is within 1.7 ulps in 64 significant bit,   #
8660 #       i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
8661 #       rounded to double precision. The result is provably monotonic   #
8662 #       in double precision.                                            #
8663 #                                                                       #
8664 # ALGORITHM *********************************************************** #
8665 #                                                                       #
8666 #       slog10d:                                                        #
8667 #                                                                       #
8668 #       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8669 #               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8670 #       Notes:  Default means round-to-nearest mode, no floating-point  #
8671 #               traps, and precision control = double extended.         #
8672 #                                                                       #
8673 #       Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8674 #       Notes:  Even if X is denormalized, log(X) is always normalized. #
8675 #                                                                       #
8676 #       Step 2.  Compute log_10(X) = log(X) * (1/log(10)).              #
8677 #            2.1 Restore the user FPCR                                  #
8678 #            2.2 Return ans := Y * INV_L10.                             #
8679 #                                                                       #
8680 #       slog10:                                                         #
8681 #                                                                       #
8682 #       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8683 #               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8684 #       Notes:  Default means round-to-nearest mode, no floating-point  #
8685 #               traps, and precision control = double extended.         #
8686 #                                                                       #
8687 #       Step 1. Call sLogN to obtain Y = log(X), the natural log of X.  #
8688 #                                                                       #
8689 #       Step 2.   Compute log_10(X) = log(X) * (1/log(10)).             #
8690 #            2.1  Restore the user FPCR                                 #
8691 #            2.2  Return ans := Y * INV_L10.                            #
8692 #                                                                       #
8693 #       sLog2d:                                                         #
8694 #                                                                       #
8695 #       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8696 #               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8697 #       Notes:  Default means round-to-nearest mode, no floating-point  #
8698 #               traps, and precision control = double extended.         #
8699 #                                                                       #
8700 #       Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8701 #       Notes:  Even if X is denormalized, log(X) is always normalized. #
8702 #                                                                       #
8703 #       Step 2.   Compute log_10(X) = log(X) * (1/log(2)).              #
8704 #            2.1  Restore the user FPCR                                 #
8705 #            2.2  Return ans := Y * INV_L2.                             #
8706 #                                                                       #
8707 #       sLog2:                                                          #
8708 #                                                                       #
8709 #       Step 0. If X < 0, create a NaN and raise the invalid operation  #
8710 #               flag. Otherwise, save FPCR in D1; set FpCR to default.  #
8711 #       Notes:  Default means round-to-nearest mode, no floating-point  #
8712 #               traps, and precision control = double extended.         #
8713 #                                                                       #
8714 #       Step 1. If X is not an integer power of two, i.e., X != 2^k,    #
8715 #               go to Step 3.                                           #
8716 #                                                                       #
8717 #       Step 2.   Return k.                                             #
8718 #            2.1  Get integer k, X = 2^k.                               #
8719 #            2.2  Restore the user FPCR.                                #
8720 #            2.3  Return ans := convert-to-double-extended(k).          #
8721 #                                                                       #
8722 #       Step 3. Call sLogN to obtain Y = log(X), the natural log of X.  #
8723 #                                                                       #
8724 #       Step 4.   Compute log_2(X) = log(X) * (1/log(2)).               #
8725 #            4.1  Restore the user FPCR                                 #
8726 #            4.2  Return ans := Y * INV_L2.                             #
8727 #                                                                       #
8728 #########################################################################
8729
8730 INV_L10:
8731         long            0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
8732
8733 INV_L2:
8734         long            0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
8735
8736         global          slog10
8737 #--entry point for Log10(X), X is normalized
8738 slog10:
8739         fmov.b          &0x1,%fp0
8740         fcmp.x          %fp0,(%a0)              # if operand == 1,
8741         fbeq.l          ld_pzero                # return an EXACT zero
8742
8743         mov.l           (%a0),%d1
8744         blt.w           invalid
8745         mov.l           %d0,-(%sp)
8746         clr.l           %d0
8747         bsr             slogn                   # log(X), X normal.
8748         fmov.l          (%sp)+,%fpcr
8749         fmul.x          INV_L10(%pc),%fp0
8750         bra             t_inx2
8751
8752         global          slog10d
8753 #--entry point for Log10(X), X is denormalized
8754 slog10d:
8755         mov.l           (%a0),%d1
8756         blt.w           invalid
8757         mov.l           %d0,-(%sp)
8758         clr.l           %d0
8759         bsr             slognd                  # log(X), X denorm.
8760         fmov.l          (%sp)+,%fpcr
8761         fmul.x          INV_L10(%pc),%fp0
8762         bra             t_minx2
8763
8764         global          slog2
8765 #--entry point for Log2(X), X is normalized
8766 slog2:
8767         mov.l           (%a0),%d1
8768         blt.w           invalid
8769
8770         mov.l           8(%a0),%d1
8771         bne.b           continue                # X is not 2^k
8772
8773         mov.l           4(%a0),%d1
8774         and.l           &0x7FFFFFFF,%d1
8775         bne.b           continue
8776
8777 #--X = 2^k.
8778         mov.w           (%a0),%d1
8779         and.l           &0x00007FFF,%d1
8780         sub.l           &0x3FFF,%d1
8781         beq.l           ld_pzero
8782         fmov.l          %d0,%fpcr
8783         fmov.l          %d1,%fp0
8784         bra             t_inx2
8785
8786 continue:
8787         mov.l           %d0,-(%sp)
8788         clr.l           %d0
8789         bsr             slogn                   # log(X), X normal.
8790         fmov.l          (%sp)+,%fpcr
8791         fmul.x          INV_L2(%pc),%fp0
8792         bra             t_inx2
8793
8794 invalid:
8795         bra             t_operr
8796
8797         global          slog2d
8798 #--entry point for Log2(X), X is denormalized
8799 slog2d:
8800         mov.l           (%a0),%d1
8801         blt.w           invalid
8802         mov.l           %d0,-(%sp)
8803         clr.l           %d0
8804         bsr             slognd                  # log(X), X denorm.
8805         fmov.l          (%sp)+,%fpcr
8806         fmul.x          INV_L2(%pc),%fp0
8807         bra             t_minx2
8808
8809 #########################################################################
8810 # stwotox():  computes 2**X for a normalized input                      #
8811 # stwotoxd(): computes 2**X for a denormalized input                    #
8812 # stentox():  computes 10**X for a normalized input                     #
8813 # stentoxd(): computes 10**X for a denormalized input                   #
8814 #                                                                       #
8815 # INPUT *************************************************************** #
8816 #       a0 = pointer to extended precision input                        #
8817 #       d0 = round precision,mode                                       #
8818 #                                                                       #
8819 # OUTPUT ************************************************************** #
8820 #       fp0 = 2**X or 10**X                                             #
8821 #                                                                       #
8822 # ACCURACY and MONOTONICITY ******************************************* #
8823 #       The returned result is within 2 ulps in 64 significant bit,     #
8824 #       i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8825 #       rounded to double precision. The result is provably monotonic   #
8826 #       in double precision.                                            #
8827 #                                                                       #
8828 # ALGORITHM *********************************************************** #
8829 #                                                                       #
8830 #       twotox                                                          #
8831 #       1. If |X| > 16480, go to ExpBig.                                #
8832 #                                                                       #
8833 #       2. If |X| < 2**(-70), go to ExpSm.                              #
8834 #                                                                       #
8835 #       3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore  #
8836 #               decompose N as                                          #
8837 #                N = 64(M + M') + j,  j = 0,1,2,...,63.                 #
8838 #                                                                       #
8839 #       4. Overwrite r := r * log2. Then                                #
8840 #               2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).           #
8841 #               Go to expr to compute that expression.                  #
8842 #                                                                       #
8843 #       tentox                                                          #
8844 #       1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig.   #
8845 #                                                                       #
8846 #       2. If |X| < 2**(-70), go to ExpSm.                              #
8847 #                                                                       #
8848 #       3. Set y := X*log_2(10)*64 (base 2 log of 10). Set              #
8849 #               N := round-to-int(y). Decompose N as                    #
8850 #                N = 64(M + M') + j,  j = 0,1,2,...,63.                 #
8851 #                                                                       #
8852 #       4. Define r as                                                  #
8853 #               r := ((X - N*L1)-N*L2) * L10                            #
8854 #               where L1, L2 are the leading and trailing parts of      #
8855 #               log_10(2)/64 and L10 is the natural log of 10. Then     #
8856 #               10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).          #
8857 #               Go to expr to compute that expression.                  #
8858 #                                                                       #
8859 #       expr                                                            #
8860 #       1. Fetch 2**(j/64) from table as Fact1 and Fact2.               #
8861 #                                                                       #
8862 #       2. Overwrite Fact1 and Fact2 by                                 #
8863 #               Fact1 := 2**(M) * Fact1                                 #
8864 #               Fact2 := 2**(M) * Fact2                                 #
8865 #               Thus Fact1 + Fact2 = 2**(M) * 2**(j/64).                #
8866 #                                                                       #
8867 #       3. Calculate P where 1 + P approximates exp(r):                 #
8868 #               P = r + r*r*(A1+r*(A2+...+r*A5)).                       #
8869 #                                                                       #
8870 #       4. Let AdjFact := 2**(M'). Return                               #
8871 #               AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ).              #
8872 #               Exit.                                                   #
8873 #                                                                       #
8874 #       ExpBig                                                          #
8875 #       1. Generate overflow by Huge * Huge if X > 0; otherwise,        #
8876 #               generate underflow by Tiny * Tiny.                      #
8877 #                                                                       #
8878 #       ExpSm                                                           #
8879 #       1. Return 1 + X.                                                #
8880 #                                                                       #
8881 #########################################################################
8882
8883 L2TEN64:
8884         long            0x406A934F,0x0979A371   # 64LOG10/LOG2
8885 L10TWO1:
8886         long            0x3F734413,0x509F8000   # LOG2/64LOG10
8887
8888 L10TWO2:
8889         long            0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
8890
8891 LOG10:  long            0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
8892
8893 LOG2:   long            0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8894
8895 EXPA5:  long            0x3F56C16D,0x6F7BD0B2
8896 EXPA4:  long            0x3F811112,0x302C712C
8897 EXPA3:  long            0x3FA55555,0x55554CC1
8898 EXPA2:  long            0x3FC55555,0x55554A54
8899 EXPA1:  long            0x3FE00000,0x00000000,0x00000000,0x00000000
8900
8901 TEXPTBL:
8902         long            0x3FFF0000,0x80000000,0x00000000,0x3F738000
8903         long            0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
8904         long            0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
8905         long            0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
8906         long            0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
8907         long            0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
8908         long            0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
8909         long            0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
8910         long            0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
8911         long            0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
8912         long            0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
8913         long            0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
8914         long            0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
8915         long            0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
8916         long            0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
8917         long            0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
8918         long            0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
8919         long            0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
8920         long            0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
8921         long            0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
8922         long            0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
8923         long            0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
8924         long            0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
8925         long            0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
8926         long            0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
8927         long            0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
8928         long            0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
8929         long            0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
8930         long            0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
8931         long            0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
8932         long            0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
8933         long            0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
8934         long            0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
8935         long            0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
8936         long            0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
8937         long            0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
8938         long            0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
8939         long            0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
8940         long            0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
8941         long            0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
8942         long            0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
8943         long            0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
8944         long            0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
8945         long            0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
8946         long            0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
8947         long            0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
8948         long            0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
8949         long            0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
8950         long            0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
8951         long            0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
8952         long            0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
8953         long            0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
8954         long            0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
8955         long            0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
8956         long            0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
8957         long            0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
8958         long            0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
8959         long            0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
8960         long            0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
8961         long            0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
8962         long            0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
8963         long            0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
8964         long            0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
8965         long            0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
8966
8967         set             INT,L_SCR1
8968
8969         set             X,FP_SCR0
8970         set             XDCARE,X+2
8971         set             XFRAC,X+4
8972
8973         set             ADJFACT,FP_SCR0
8974
8975         set             FACT1,FP_SCR0
8976         set             FACT1HI,FACT1+4
8977         set             FACT1LOW,FACT1+8
8978
8979         set             FACT2,FP_SCR1
8980         set             FACT2HI,FACT2+4
8981         set             FACT2LOW,FACT2+8
8982
8983         global          stwotox
8984 #--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
8985 stwotox:
8986         fmovm.x         (%a0),&0x80             # LOAD INPUT
8987
8988         mov.l           (%a0),%d1
8989         mov.w           4(%a0),%d1
8990         fmov.x          %fp0,X(%a6)
8991         and.l           &0x7FFFFFFF,%d1
8992
8993         cmp.l           %d1,&0x3FB98000         # |X| >= 2**(-70)?
8994         bge.b           TWOOK1
8995         bra.w           EXPBORS
8996
8997 TWOOK1:
8998         cmp.l           %d1,&0x400D80C0         # |X| > 16480?
8999         ble.b           TWOMAIN
9000         bra.w           EXPBORS
9001
9002 TWOMAIN:
9003 #--USUAL CASE, 2^(-70) <= |X| <= 16480
9004
9005         fmov.x          %fp0,%fp1
9006         fmul.s          &0x42800000,%fp1        # 64 * X
9007         fmov.l          %fp1,INT(%a6)           # N = ROUND-TO-INT(64 X)
9008         mov.l           %d2,-(%sp)
9009         lea             TEXPTBL(%pc),%a1        # LOAD ADDRESS OF TABLE OF 2^(J/64)
9010         fmov.l          INT(%a6),%fp1           # N --> FLOATING FMT
9011         mov.l           INT(%a6),%d1
9012         mov.l           %d1,%d2
9013         and.l           &0x3F,%d1               # D0 IS J
9014         asl.l           &4,%d1                  # DISPLACEMENT FOR 2^(J/64)
9015         add.l           %d1,%a1                 # ADDRESS FOR 2^(J/64)
9016         asr.l           &6,%d2                  # d2 IS L, N = 64L + J
9017         mov.l           %d2,%d1
9018         asr.l           &1,%d1                  # D0 IS M
9019         sub.l           %d1,%d2                 # d2 IS M', N = 64(M+M') + J
9020         add.l           &0x3FFF,%d2
9021
9022 #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9023 #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9024 #--ADJFACT = 2^(M').
9025 #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9026
9027         fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
9028
9029         fmul.s          &0x3C800000,%fp1        # (1/64)*N
9030         mov.l           (%a1)+,FACT1(%a6)
9031         mov.l           (%a1)+,FACT1HI(%a6)
9032         mov.l           (%a1)+,FACT1LOW(%a6)
9033         mov.w           (%a1)+,FACT2(%a6)
9034
9035         fsub.x          %fp1,%fp0               # X - (1/64)*INT(64 X)
9036
9037         mov.w           (%a1)+,FACT2HI(%a6)
9038         clr.w           FACT2HI+2(%a6)
9039         clr.l           FACT2LOW(%a6)
9040         add.w           %d1,FACT1(%a6)
9041         fmul.x          LOG2(%pc),%fp0          # FP0 IS R
9042         add.w           %d1,FACT2(%a6)
9043
9044         bra.w           expr
9045
9046 EXPBORS:
9047 #--FPCR, D0 SAVED
9048         cmp.l           %d1,&0x3FFF8000
9049         bgt.b           TEXPBIG
9050
9051 #--|X| IS SMALL, RETURN 1 + X
9052
9053         fmov.l          %d0,%fpcr               # restore users round prec,mode
9054         fadd.s          &0x3F800000,%fp0        # RETURN 1 + X
9055         bra             t_pinx2
9056
9057 TEXPBIG:
9058 #--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
9059 #--REGISTERS SAVE SO FAR ARE FPCR AND  D0
9060         mov.l           X(%a6),%d1
9061         cmp.l           %d1,&0
9062         blt.b           EXPNEG
9063
9064         bra             t_ovfl2                 # t_ovfl expects positive value
9065
9066 EXPNEG:
9067         bra             t_unfl2                 # t_unfl expects positive value
9068
9069         global          stwotoxd
9070 stwotoxd:
9071 #--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
9072
9073         fmov.l          %d0,%fpcr               # set user's rounding mode/precision
9074         fmov.s          &0x3F800000,%fp0        # RETURN 1 + X
9075         mov.l           (%a0),%d1
9076         or.l            &0x00800001,%d1
9077         fadd.s          %d1,%fp0
9078         bra             t_pinx2
9079
9080         global          stentox
9081 #--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9082 stentox:
9083         fmovm.x         (%a0),&0x80             # LOAD INPUT
9084
9085         mov.l           (%a0),%d1
9086         mov.w           4(%a0),%d1
9087         fmov.x          %fp0,X(%a6)
9088         and.l           &0x7FFFFFFF,%d1
9089
9090         cmp.l           %d1,&0x3FB98000         # |X| >= 2**(-70)?
9091         bge.b           TENOK1
9092         bra.w           EXPBORS
9093
9094 TENOK1:
9095         cmp.l           %d1,&0x400B9B07         # |X| <= 16480*log2/log10 ?
9096         ble.b           TENMAIN
9097         bra.w           EXPBORS
9098
9099 TENMAIN:
9100 #--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
9101
9102         fmov.x          %fp0,%fp1
9103         fmul.d          L2TEN64(%pc),%fp1       # X*64*LOG10/LOG2
9104         fmov.l          %fp1,INT(%a6)           # N=INT(X*64*LOG10/LOG2)
9105         mov.l           %d2,-(%sp)
9106         lea             TEXPTBL(%pc),%a1        # LOAD ADDRESS OF TABLE OF 2^(J/64)
9107         fmov.l          INT(%a6),%fp1           # N --> FLOATING FMT
9108         mov.l           INT(%a6),%d1
9109         mov.l           %d1,%d2
9110         and.l           &0x3F,%d1               # D0 IS J
9111         asl.l           &4,%d1                  # DISPLACEMENT FOR 2^(J/64)
9112         add.l           %d1,%a1                 # ADDRESS FOR 2^(J/64)
9113         asr.l           &6,%d2                  # d2 IS L, N = 64L + J
9114         mov.l           %d2,%d1
9115         asr.l           &1,%d1                  # D0 IS M
9116         sub.l           %d1,%d2                 # d2 IS M', N = 64(M+M') + J
9117         add.l           &0x3FFF,%d2
9118
9119 #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9120 #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9121 #--ADJFACT = 2^(M').
9122 #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9123         fmovm.x         &0x0c,-(%sp)            # save fp2/fp3
9124
9125         fmov.x          %fp1,%fp2
9126
9127         fmul.d          L10TWO1(%pc),%fp1       # N*(LOG2/64LOG10)_LEAD
9128         mov.l           (%a1)+,FACT1(%a6)
9129
9130         fmul.x          L10TWO2(%pc),%fp2       # N*(LOG2/64LOG10)_TRAIL
9131
9132         mov.l           (%a1)+,FACT1HI(%a6)
9133         mov.l           (%a1)+,FACT1LOW(%a6)
9134         fsub.x          %fp1,%fp0               # X - N L_LEAD
9135         mov.w           (%a1)+,FACT2(%a6)
9136
9137         fsub.x          %fp2,%fp0               # X - N L_TRAIL
9138
9139         mov.w           (%a1)+,FACT2HI(%a6)
9140         clr.w           FACT2HI+2(%a6)
9141         clr.l           FACT2LOW(%a6)
9142
9143         fmul.x          LOG10(%pc),%fp0         # FP0 IS R
9144         add.w           %d1,FACT1(%a6)
9145         add.w           %d1,FACT2(%a6)
9146
9147 expr:
9148 #--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
9149 #--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
9150 #--FP0 IS R. THE FOLLOWING CODE COMPUTES
9151 #--     2**(M'+M) * 2**(J/64) * EXP(R)
9152
9153         fmov.x          %fp0,%fp1
9154         fmul.x          %fp1,%fp1               # FP1 IS S = R*R
9155
9156         fmov.d          EXPA5(%pc),%fp2         # FP2 IS A5
9157         fmov.d          EXPA4(%pc),%fp3         # FP3 IS A4
9158
9159         fmul.x          %fp1,%fp2               # FP2 IS S*A5
9160         fmul.x          %fp1,%fp3               # FP3 IS S*A4
9161
9162         fadd.d          EXPA3(%pc),%fp2         # FP2 IS A3+S*A5
9163         fadd.d          EXPA2(%pc),%fp3         # FP3 IS A2+S*A4
9164
9165         fmul.x          %fp1,%fp2               # FP2 IS S*(A3+S*A5)
9166         fmul.x          %fp1,%fp3               # FP3 IS S*(A2+S*A4)
9167
9168         fadd.d          EXPA1(%pc),%fp2         # FP2 IS A1+S*(A3+S*A5)
9169         fmul.x          %fp0,%fp3               # FP3 IS R*S*(A2+S*A4)
9170
9171         fmul.x          %fp1,%fp2               # FP2 IS S*(A1+S*(A3+S*A5))
9172         fadd.x          %fp3,%fp0               # FP0 IS R+R*S*(A2+S*A4)
9173         fadd.x          %fp2,%fp0               # FP0 IS EXP(R) - 1
9174
9175         fmovm.x         (%sp)+,&0x30            # restore fp2/fp3
9176
9177 #--FINAL RECONSTRUCTION PROCESS
9178 #--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1)  -  (1 OR 0)
9179
9180         fmul.x          FACT1(%a6),%fp0
9181         fadd.x          FACT2(%a6),%fp0
9182         fadd.x          FACT1(%a6),%fp0
9183
9184         fmov.l          %d0,%fpcr               # restore users round prec,mode
9185         mov.w           %d2,ADJFACT(%a6)        # INSERT EXPONENT
9186         mov.l           (%sp)+,%d2
9187         mov.l           &0x80000000,ADJFACT+4(%a6)
9188         clr.l           ADJFACT+8(%a6)
9189         mov.b           &FMUL_OP,%d1            # last inst is MUL
9190         fmul.x          ADJFACT(%a6),%fp0       # FINAL ADJUSTMENT
9191         bra             t_catch
9192
9193         global          stentoxd
9194 stentoxd:
9195 #--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
9196
9197         fmov.l          %d0,%fpcr               # set user's rounding mode/precision
9198         fmov.s          &0x3F800000,%fp0        # RETURN 1 + X
9199         mov.l           (%a0),%d1
9200         or.l            &0x00800001,%d1
9201         fadd.s          %d1,%fp0
9202         bra             t_pinx2
9203
9204 #########################################################################
9205 # sscale(): computes the destination operand scaled by the source       #
9206 #           operand. If the absoulute value of the source operand is    #
9207 #           >= 2^14, an overflow or underflow is returned.              #
9208 #                                                                       #
9209 # INPUT *************************************************************** #
9210 #       a0  = pointer to double-extended source operand X               #
9211 #       a1  = pointer to double-extended destination operand Y          #
9212 #                                                                       #
9213 # OUTPUT ************************************************************** #
9214 #       fp0 =  scale(X,Y)                                               #
9215 #                                                                       #
9216 #########################################################################
9217
9218 set     SIGN,           L_SCR1
9219
9220         global          sscale
9221 sscale:
9222         mov.l           %d0,-(%sp)              # store off ctrl bits for now
9223
9224         mov.w           DST_EX(%a1),%d1         # get dst exponent
9225         smi.b           SIGN(%a6)               # use SIGN to hold dst sign
9226         andi.l          &0x00007fff,%d1         # strip sign from dst exp
9227
9228         mov.w           SRC_EX(%a0),%d0         # check src bounds
9229         andi.w          &0x7fff,%d0             # clr src sign bit
9230         cmpi.w          %d0,&0x3fff             # is src ~ ZERO?
9231         blt.w           src_small               # yes
9232         cmpi.w          %d0,&0x400c             # no; is src too big?
9233         bgt.w           src_out                 # yes
9234
9235 #
9236 # Source is within 2^14 range.
9237 #
9238 src_ok:
9239         fintrz.x        SRC(%a0),%fp0           # calc int of src
9240         fmov.l          %fp0,%d0                # int src to d0
9241 # don't want any accrued bits from the fintrz showing up later since
9242 # we may need to read the fpsr for the last fp op in t_catch2().
9243         fmov.l          &0x0,%fpsr
9244
9245         tst.b           DST_HI(%a1)             # is dst denormalized?
9246         bmi.b           sok_norm
9247
9248 # the dst is a DENORM. normalize the DENORM and add the adjustment to
9249 # the src value. then, jump to the norm part of the routine.
9250 sok_dnrm:
9251         mov.l           %d0,-(%sp)              # save src for now
9252
9253         mov.w           DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
9254         mov.l           DST_HI(%a1),FP_SCR0_HI(%a6)
9255         mov.l           DST_LO(%a1),FP_SCR0_LO(%a6)
9256
9257         lea             FP_SCR0(%a6),%a0        # pass ptr to DENORM
9258         bsr.l           norm                    # normalize the DENORM
9259         neg.l           %d0
9260         add.l           (%sp)+,%d0              # add adjustment to src
9261
9262         fmovm.x         FP_SCR0(%a6),&0x80      # load normalized DENORM
9263
9264         cmpi.w          %d0,&-0x3fff            # is the shft amt really low?
9265         bge.b           sok_norm2               # thank goodness no
9266
9267 # the multiply factor that we're trying to create should be a denorm
9268 # for the multiply to work. therefore, we're going to actually do a
9269 # multiply with a denorm which will cause an unimplemented data type
9270 # exception to be put into the machine which will be caught and corrected
9271 # later. we don't do this with the DENORMs above because this method
9272 # is slower. but, don't fret, I don't see it being used much either.
9273         fmov.l          (%sp)+,%fpcr            # restore user fpcr
9274         mov.l           &0x80000000,%d1         # load normalized mantissa
9275         subi.l          &-0x3fff,%d0            # how many should we shift?
9276         neg.l           %d0                     # make it positive
9277         cmpi.b          %d0,&0x20               # is it > 32?
9278         bge.b           sok_dnrm_32             # yes
9279         lsr.l           %d0,%d1                 # no; bit stays in upper lw
9280         clr.l           -(%sp)                  # insert zero low mantissa
9281         mov.l           %d1,-(%sp)              # insert new high mantissa
9282         clr.l           -(%sp)                  # make zero exponent
9283         bra.b           sok_norm_cont
9284 sok_dnrm_32:
9285         subi.b          &0x20,%d0               # get shift count
9286         lsr.l           %d0,%d1                 # make low mantissa longword
9287         mov.l           %d1,-(%sp)              # insert new low mantissa
9288         clr.l           -(%sp)                  # insert zero high mantissa
9289         clr.l           -(%sp)                  # make zero exponent
9290         bra.b           sok_norm_cont
9291
9292 # the src will force the dst to a DENORM value or worse. so, let's
9293 # create an fp multiply that will create the result.
9294 sok_norm:
9295         fmovm.x         DST(%a1),&0x80          # load fp0 with normalized src
9296 sok_norm2:
9297         fmov.l          (%sp)+,%fpcr            # restore user fpcr
9298
9299         addi.w          &0x3fff,%d0             # turn src amt into exp value
9300         swap            %d0                     # put exponent in high word
9301         clr.l           -(%sp)                  # insert new exponent
9302         mov.l           &0x80000000,-(%sp)      # insert new high mantissa
9303         mov.l           %d0,-(%sp)              # insert new lo mantissa
9304
9305 sok_norm_cont:
9306         fmov.l          %fpcr,%d0               # d0 needs fpcr for t_catch2
9307         mov.b           &FMUL_OP,%d1            # last inst is MUL
9308         fmul.x          (%sp)+,%fp0             # do the multiply
9309         bra             t_catch2                # catch any exceptions
9310
9311 #
9312 # Source is outside of 2^14 range.  Test the sign and branch
9313 # to the appropriate exception handler.
9314 #
9315 src_out:
9316         mov.l           (%sp)+,%d0              # restore ctrl bits
9317         exg             %a0,%a1                 # swap src,dst ptrs
9318         tst.b           SRC_EX(%a1)             # is src negative?
9319         bmi             t_unfl                  # yes; underflow
9320         bra             t_ovfl_sc               # no; overflow
9321
9322 #
9323 # The source input is below 1, so we check for denormalized numbers
9324 # and set unfl.
9325 #
9326 src_small:
9327         tst.b           DST_HI(%a1)             # is dst denormalized?
9328         bpl.b           ssmall_done             # yes
9329
9330         mov.l           (%sp)+,%d0
9331         fmov.l          %d0,%fpcr               # no; load control bits
9332         mov.b           &FMOV_OP,%d1            # last inst is MOVE
9333         fmov.x          DST(%a1),%fp0           # simply return dest
9334         bra             t_catch2
9335 ssmall_done:
9336         mov.l           (%sp)+,%d0              # load control bits into d1
9337         mov.l           %a1,%a0                 # pass ptr to dst
9338         bra             t_resdnrm
9339
9340 #########################################################################
9341 # smod(): computes the fp MOD of the input values X,Y.                  #
9342 # srem(): computes the fp (IEEE) REM of the input values X,Y.           #
9343 #                                                                       #
9344 # INPUT *************************************************************** #
9345 #       a0 = pointer to extended precision input X                      #
9346 #       a1 = pointer to extended precision input Y                      #
9347 #       d0 = round precision,mode                                       #
9348 #                                                                       #
9349 #       The input operands X and Y can be either normalized or          #
9350 #       denormalized.                                                   #
9351 #                                                                       #
9352 # OUTPUT ************************************************************** #
9353 #      fp0 = FREM(X,Y) or FMOD(X,Y)                                     #
9354 #                                                                       #
9355 # ALGORITHM *********************************************************** #
9356 #                                                                       #
9357 #       Step 1.  Save and strip signs of X and Y: signX := sign(X),     #
9358 #                signY := sign(Y), X := |X|, Y := |Y|,                  #
9359 #                signQ := signX EOR signY. Record whether MOD or REM    #
9360 #                is requested.                                          #
9361 #                                                                       #
9362 #       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.              #
9363 #                If (L < 0) then                                        #
9364 #                   R := X, go to Step 4.                               #
9365 #                else                                                   #
9366 #                   R := 2^(-L)X, j := L.                               #
9367 #                endif                                                  #
9368 #                                                                       #
9369 #       Step 3.  Perform MOD(X,Y)                                       #
9370 #            3.1 If R = Y, go to Step 9.                                #
9371 #            3.2 If R > Y, then { R := R - Y, Q := Q + 1}               #
9372 #            3.3 If j = 0, go to Step 4.                                #
9373 #            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to        #
9374 #                Step 3.1.                                              #
9375 #                                                                       #
9376 #       Step 4.  At this point, R = X - QY = MOD(X,Y). Set              #
9377 #                Last_Subtract := false (used in Step 7 below). If      #
9378 #                MOD is requested, go to Step 6.                        #
9379 #                                                                       #
9380 #       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested.               #
9381 #            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to        #
9382 #                Step 6.                                                #
9383 #            5.2 If R > Y/2, then { set Last_Subtract := true,          #
9384 #                Q := Q + 1, Y := signY*Y }. Go to Step 6.              #
9385 #            5.3 This is the tricky case of R = Y/2. If Q is odd,       #
9386 #                then { Q := Q + 1, signX := -signX }.                  #
9387 #                                                                       #
9388 #       Step 6.  R := signX*R.                                          #
9389 #                                                                       #
9390 #       Step 7.  If Last_Subtract = true, R := R - Y.                   #
9391 #                                                                       #
9392 #       Step 8.  Return signQ, last 7 bits of Q, and R as required.     #
9393 #                                                                       #
9394 #       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus,           #
9395 #                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),                #
9396 #                R := 0. Return signQ, last 7 bits of Q, and R.         #
9397 #                                                                       #
9398 #########################################################################
9399
9400         set             Mod_Flag,L_SCR3
9401         set             Sc_Flag,L_SCR3+1
9402
9403         set             SignY,L_SCR2
9404         set             SignX,L_SCR2+2
9405         set             SignQ,L_SCR3+2
9406
9407         set             Y,FP_SCR0
9408         set             Y_Hi,Y+4
9409         set             Y_Lo,Y+8
9410
9411         set             R,FP_SCR1
9412         set             R_Hi,R+4
9413         set             R_Lo,R+8
9414
9415 Scale:
9416         long            0x00010000,0x80000000,0x00000000,0x00000000
9417
9418         global          smod
9419 smod:
9420         clr.b           FPSR_QBYTE(%a6)
9421         mov.l           %d0,-(%sp)              # save ctrl bits
9422         clr.b           Mod_Flag(%a6)
9423         bra.b           Mod_Rem
9424
9425         global          srem
9426 srem:
9427         clr.b           FPSR_QBYTE(%a6)
9428         mov.l           %d0,-(%sp)              # save ctrl bits
9429         mov.b           &0x1,Mod_Flag(%a6)
9430
9431 Mod_Rem:
9432 #..Save sign of X and Y
9433         movm.l          &0x3f00,-(%sp)          # save data registers
9434         mov.w           SRC_EX(%a0),%d3
9435         mov.w           %d3,SignY(%a6)
9436         and.l           &0x00007FFF,%d3         # Y := |Y|
9437
9438 #
9439         mov.l           SRC_HI(%a0),%d4
9440         mov.l           SRC_LO(%a0),%d5         # (D3,D4,D5) is |Y|
9441
9442         tst.l           %d3
9443         bne.b           Y_Normal
9444
9445         mov.l           &0x00003FFE,%d3         # $3FFD + 1
9446         tst.l           %d4
9447         bne.b           HiY_not0
9448
9449 HiY_0:
9450         mov.l           %d5,%d4
9451         clr.l           %d5
9452         sub.l           &32,%d3
9453         clr.l           %d6
9454         bfffo           %d4{&0:&32},%d6
9455         lsl.l           %d6,%d4
9456         sub.l           %d6,%d3                 # (D3,D4,D5) is normalized
9457 #                                               ...with bias $7FFD
9458         bra.b           Chk_X
9459
9460 HiY_not0:
9461         clr.l           %d6
9462         bfffo           %d4{&0:&32},%d6
9463         sub.l           %d6,%d3
9464         lsl.l           %d6,%d4
9465         mov.l           %d5,%d7                 # a copy of D5
9466         lsl.l           %d6,%d5
9467         neg.l           %d6
9468         add.l           &32,%d6
9469         lsr.l           %d6,%d7
9470         or.l            %d7,%d4                 # (D3,D4,D5) normalized
9471 #                                       ...with bias $7FFD
9472         bra.b           Chk_X
9473
9474 Y_Normal:
9475         add.l           &0x00003FFE,%d3         # (D3,D4,D5) normalized
9476 #                                       ...with bias $7FFD
9477
9478 Chk_X:
9479         mov.w           DST_EX(%a1),%d0
9480         mov.w           %d0,SignX(%a6)
9481         mov.w           SignY(%a6),%d1
9482         eor.l           %d0,%d1
9483         and.l           &0x00008000,%d1
9484         mov.w           %d1,SignQ(%a6)          # sign(Q) obtained
9485         and.l           &0x00007FFF,%d0
9486         mov.l           DST_HI(%a1),%d1
9487         mov.l           DST_LO(%a1),%d2         # (D0,D1,D2) is |X|
9488         tst.l           %d0
9489         bne.b           X_Normal
9490         mov.l           &0x00003FFE,%d0
9491         tst.l           %d1
9492         bne.b           HiX_not0
9493
9494 HiX_0:
9495         mov.l           %d2,%d1
9496         clr.l           %d2
9497         sub.l           &32,%d0
9498         clr.l           %d6
9499         bfffo           %d1{&0:&32},%d6
9500         lsl.l           %d6,%d1
9501         sub.l           %d6,%d0                 # (D0,D1,D2) is normalized
9502 #                                       ...with bias $7FFD
9503         bra.b           Init
9504
9505 HiX_not0:
9506         clr.l           %d6
9507         bfffo           %d1{&0:&32},%d6
9508         sub.l           %d6,%d0
9509         lsl.l           %d6,%d1
9510         mov.l           %d2,%d7                 # a copy of D2
9511         lsl.l           %d6,%d2
9512         neg.l           %d6
9513         add.l           &32,%d6
9514         lsr.l           %d6,%d7
9515         or.l            %d7,%d1                 # (D0,D1,D2) normalized
9516 #                                       ...with bias $7FFD
9517         bra.b           Init
9518
9519 X_Normal:
9520         add.l           &0x00003FFE,%d0         # (D0,D1,D2) normalized
9521 #                                       ...with bias $7FFD
9522
9523 Init:
9524 #
9525         mov.l           %d3,L_SCR1(%a6)         # save biased exp(Y)
9526         mov.l           %d0,-(%sp)              # save biased exp(X)
9527         sub.l           %d3,%d0                 # L := expo(X)-expo(Y)
9528
9529         clr.l           %d6                     # D6 := carry <- 0
9530         clr.l           %d3                     # D3 is Q
9531         mov.l           &0,%a1                  # A1 is k; j+k=L, Q=0
9532
9533 #..(Carry,D1,D2) is R
9534         tst.l           %d0
9535         bge.b           Mod_Loop_pre
9536
9537 #..expo(X) < expo(Y). Thus X = mod(X,Y)
9538 #
9539         mov.l           (%sp)+,%d0              # restore d0
9540         bra.w           Get_Mod
9541
9542 Mod_Loop_pre:
9543         addq.l          &0x4,%sp                # erase exp(X)
9544 #..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L
9545 Mod_Loop:
9546         tst.l           %d6                     # test carry bit
9547         bgt.b           R_GT_Y
9548
9549 #..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
9550         cmp.l           %d1,%d4                 # compare hi(R) and hi(Y)
9551         bne.b           R_NE_Y
9552         cmp.l           %d2,%d5                 # compare lo(R) and lo(Y)
9553         bne.b           R_NE_Y
9554
9555 #..At this point, R = Y
9556         bra.w           Rem_is_0
9557
9558 R_NE_Y:
9559 #..use the borrow of the previous compare
9560         bcs.b           R_LT_Y                  # borrow is set iff R < Y
9561
9562 R_GT_Y:
9563 #..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
9564 #..and Y < (D1,D2) < 2Y. Either way, perform R - Y
9565         sub.l           %d5,%d2                 # lo(R) - lo(Y)
9566         subx.l          %d4,%d1                 # hi(R) - hi(Y)
9567         clr.l           %d6                     # clear carry
9568         addq.l          &1,%d3                  # Q := Q + 1
9569
9570 R_LT_Y:
9571 #..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
9572         tst.l           %d0                     # see if j = 0.
9573         beq.b           PostLoop
9574
9575         add.l           %d3,%d3                 # Q := 2Q
9576         add.l           %d2,%d2                 # lo(R) = 2lo(R)
9577         roxl.l          &1,%d1                  # hi(R) = 2hi(R) + carry
9578         scs             %d6                     # set Carry if 2(R) overflows
9579         addq.l          &1,%a1                  # k := k+1
9580         subq.l          &1,%d0                  # j := j - 1
9581 #..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
9582
9583         bra.b           Mod_Loop
9584
9585 PostLoop:
9586 #..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
9587
9588 #..normalize R.
9589         mov.l           L_SCR1(%a6),%d0         # new biased expo of R
9590         tst.l           %d1
9591         bne.b           HiR_not0
9592
9593 HiR_0:
9594         mov.l           %d2,%d1
9595         clr.l           %d2
9596         sub.l           &32,%d0
9597         clr.l           %d6
9598         bfffo           %d1{&0:&32},%d6
9599         lsl.l           %d6,%d1
9600         sub.l           %d6,%d0                 # (D0,D1,D2) is normalized
9601 #                                       ...with bias $7FFD
9602         bra.b           Get_Mod
9603
9604 HiR_not0:
9605         clr.l           %d6
9606         bfffo           %d1{&0:&32},%d6
9607         bmi.b           Get_Mod                 # already normalized
9608         sub.l           %d6,%d0
9609         lsl.l           %d6,%d1
9610         mov.l           %d2,%d7                 # a copy of D2
9611         lsl.l           %d6,%d2
9612         neg.l           %d6
9613         add.l           &32,%d6
9614         lsr.l           %d6,%d7
9615         or.l            %d7,%d1                 # (D0,D1,D2) normalized
9616
9617 #
9618 Get_Mod:
9619         cmp.l           %d0,&0x000041FE
9620         bge.b           No_Scale
9621 Do_Scale:
9622         mov.w           %d0,R(%a6)
9623         mov.l           %d1,R_Hi(%a6)
9624         mov.l           %d2,R_Lo(%a6)
9625         mov.l           L_SCR1(%a6),%d6
9626         mov.w           %d6,Y(%a6)
9627         mov.l           %d4,Y_Hi(%a6)
9628         mov.l           %d5,Y_Lo(%a6)
9629         fmov.x          R(%a6),%fp0             # no exception
9630         mov.b           &1,Sc_Flag(%a6)
9631         bra.b           ModOrRem
9632 No_Scale:
9633         mov.l           %d1,R_Hi(%a6)
9634         mov.l           %d2,R_Lo(%a6)
9635         sub.l           &0x3FFE,%d0
9636         mov.w           %d0,R(%a6)
9637         mov.l           L_SCR1(%a6),%d6
9638         sub.l           &0x3FFE,%d6
9639         mov.l           %d6,L_SCR1(%a6)
9640         fmov.x          R(%a6),%fp0
9641         mov.w           %d6,Y(%a6)
9642         mov.l           %d4,Y_Hi(%a6)
9643         mov.l           %d5,Y_Lo(%a6)
9644         clr.b           Sc_Flag(%a6)
9645
9646 #
9647 ModOrRem:
9648         tst.b           Mod_Flag(%a6)
9649         beq.b           Fix_Sign
9650
9651         mov.l           L_SCR1(%a6),%d6         # new biased expo(Y)
9652         subq.l          &1,%d6                  # biased expo(Y/2)
9653         cmp.l           %d0,%d6
9654         blt.b           Fix_Sign
9655         bgt.b           Last_Sub
9656
9657         cmp.l           %d1,%d4
9658         bne.b           Not_EQ
9659         cmp.l           %d2,%d5
9660         bne.b           Not_EQ
9661         bra.w           Tie_Case
9662
9663 Not_EQ:
9664         bcs.b           Fix_Sign
9665
9666 Last_Sub:
9667 #
9668         fsub.x          Y(%a6),%fp0             # no exceptions
9669         addq.l          &1,%d3                  # Q := Q + 1
9670
9671 #
9672 Fix_Sign:
9673 #..Get sign of X
9674         mov.w           SignX(%a6),%d6
9675         bge.b           Get_Q
9676         fneg.x          %fp0
9677
9678 #..Get Q
9679 #
9680 Get_Q:
9681         clr.l           %d6
9682         mov.w           SignQ(%a6),%d6          # D6 is sign(Q)
9683         mov.l           &8,%d7
9684         lsr.l           %d7,%d6
9685         and.l           &0x0000007F,%d3         # 7 bits of Q
9686         or.l            %d6,%d3                 # sign and bits of Q
9687 #       swap            %d3
9688 #       fmov.l          %fpsr,%d6
9689 #       and.l           &0xFF00FFFF,%d6
9690 #       or.l            %d3,%d6
9691 #       fmov.l          %d6,%fpsr               # put Q in fpsr
9692         mov.b           %d3,FPSR_QBYTE(%a6)     # put Q in fpsr
9693
9694 #
9695 Restore:
9696         movm.l          (%sp)+,&0xfc            #  {%d2-%d7}
9697         mov.l           (%sp)+,%d0
9698         fmov.l          %d0,%fpcr
9699         tst.b           Sc_Flag(%a6)
9700         beq.b           Finish
9701         mov.b           &FMUL_OP,%d1            # last inst is MUL
9702         fmul.x          Scale(%pc),%fp0         # may cause underflow
9703         bra             t_catch2
9704 # the '040 package did this apparently to see if the dst operand for the
9705 # preceding fmul was a denorm. but, it better not have been since the
9706 # algorithm just got done playing with fp0 and expected no exceptions
9707 # as a result. trust me...
9708 #       bra             t_avoid_unsupp          # check for denorm as a
9709 #                                               ;result of the scaling
9710
9711 Finish:
9712         mov.b           &FMOV_OP,%d1            # last inst is MOVE
9713         fmov.x          %fp0,%fp0               # capture exceptions & round
9714         bra             t_catch2
9715
9716 Rem_is_0:
9717 #..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
9718         addq.l          &1,%d3
9719         cmp.l           %d0,&8                  # D0 is j
9720         bge.b           Q_Big
9721
9722         lsl.l           %d0,%d3
9723         bra.b           Set_R_0
9724
9725 Q_Big:
9726         clr.l           %d3
9727
9728 Set_R_0:
9729         fmov.s          &0x00000000,%fp0
9730         clr.b           Sc_Flag(%a6)
9731         bra.w           Fix_Sign
9732
9733 Tie_Case:
9734 #..Check parity of Q
9735         mov.l           %d3,%d6
9736         and.l           &0x00000001,%d6
9737         tst.l           %d6
9738         beq.w           Fix_Sign                # Q is even
9739
9740 #..Q is odd, Q := Q + 1, signX := -signX
9741         addq.l          &1,%d3
9742         mov.w           SignX(%a6),%d6
9743         eor.l           &0x00008000,%d6
9744         mov.w           %d6,SignX(%a6)
9745         bra.w           Fix_Sign
9746
9747 #########################################################################
9748 # XDEF **************************************************************** #
9749 #       tag(): return the optype of the input ext fp number             #
9750 #                                                                       #
9751 #       This routine is used by the 060FPLSP.                           #
9752 #                                                                       #
9753 # XREF **************************************************************** #
9754 #       None                                                            #
9755 #                                                                       #
9756 # INPUT *************************************************************** #
9757 #       a0 = pointer to extended precision operand                      #
9758 #                                                                       #
9759 # OUTPUT ************************************************************** #
9760 #       d0 = value of type tag                                          #
9761 #               one of: NORM, INF, QNAN, SNAN, DENORM, ZERO             #
9762 #                                                                       #
9763 # ALGORITHM *********************************************************** #
9764 #       Simply test the exponent, j-bit, and mantissa values to         #
9765 # determine the type of operand.                                        #
9766 #       If it's an unnormalized zero, alter the operand and force it    #
9767 # to be a normal zero.                                                  #
9768 #                                                                       #
9769 #########################################################################
9770
9771         global          tag
9772 tag:
9773         mov.w           FTEMP_EX(%a0), %d0      # extract exponent
9774         andi.w          &0x7fff, %d0            # strip off sign
9775         cmpi.w          %d0, &0x7fff            # is (EXP == MAX)?
9776         beq.b           inf_or_nan_x
9777 not_inf_or_nan_x:
9778         btst            &0x7,FTEMP_HI(%a0)
9779         beq.b           not_norm_x
9780 is_norm_x:
9781         mov.b           &NORM, %d0
9782         rts
9783 not_norm_x:
9784         tst.w           %d0                     # is exponent = 0?
9785         bne.b           is_unnorm_x
9786 not_unnorm_x:
9787         tst.l           FTEMP_HI(%a0)
9788         bne.b           is_denorm_x
9789         tst.l           FTEMP_LO(%a0)
9790         bne.b           is_denorm_x
9791 is_zero_x:
9792         mov.b           &ZERO, %d0
9793         rts
9794 is_denorm_x:
9795         mov.b           &DENORM, %d0
9796         rts
9797 is_unnorm_x:
9798         bsr.l           unnorm_fix              # convert to norm,denorm,or zero
9799         rts
9800 is_unnorm_reg_x:
9801         mov.b           &UNNORM, %d0
9802         rts
9803 inf_or_nan_x:
9804         tst.l           FTEMP_LO(%a0)
9805         bne.b           is_nan_x
9806         mov.l           FTEMP_HI(%a0), %d0
9807         and.l           &0x7fffffff, %d0        # msb is a don't care!
9808         bne.b           is_nan_x
9809 is_inf_x:
9810         mov.b           &INF, %d0
9811         rts
9812 is_nan_x:
9813         mov.b           &QNAN, %d0
9814         rts
9815
9816 #############################################################
9817
9818 qnan:   long            0x7fff0000, 0xffffffff, 0xffffffff
9819
9820 #########################################################################
9821 # XDEF **************************************************************** #
9822 #       t_dz(): Handle 060FPLSP dz exception for "flogn" emulation.     #
9823 #       t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation.   #
9824 #                                                                       #
9825 #       These rouitnes are used by the 060FPLSP package.                #
9826 #                                                                       #
9827 # XREF **************************************************************** #
9828 #       None                                                            #
9829 #                                                                       #
9830 # INPUT *************************************************************** #
9831 #       a0 = pointer to extended precision source operand.              #
9832 #                                                                       #
9833 # OUTPUT ************************************************************** #
9834 #       fp0 = default DZ result.                                        #
9835 #                                                                       #
9836 # ALGORITHM *********************************************************** #
9837 #       Transcendental emulation for the 060FPLSP has detected that     #
9838 # a DZ exception should occur for the instruction. If DZ is disabled,   #
9839 # return the default result.                                            #
9840 #       If DZ is enabled, the dst operand should be returned unscathed  #
9841 # in fp0 while fp1 is used to create a DZ exception so that the         #
9842 # operating system can log that such an event occurred.                 #
9843 #                                                                       #
9844 #########################################################################
9845
9846         global          t_dz
9847 t_dz:
9848         tst.b           SRC_EX(%a0)             # check sign for neg or pos
9849         bpl.b           dz_pinf                 # branch if pos sign
9850
9851         global          t_dz2
9852 t_dz2:
9853         ori.l           &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
9854
9855         btst            &dz_bit,FPCR_ENABLE(%a6)
9856         bne.b           dz_minf_ena
9857
9858 # dz is disabled. return a -INF.
9859         fmov.s          &0xff800000,%fp0        # return -INF
9860         rts
9861
9862 # dz is enabled. create a dz exception so the user can record it
9863 # but use fp1 instead. return the dst operand unscathed in fp0.
9864 dz_minf_ena:
9865         fmovm.x         EXC_FP0(%a6),&0x80      # return fp0 unscathed
9866         fmov.l          USER_FPCR(%a6),%fpcr
9867         fmov.s          &0xbf800000,%fp1        # load -1
9868         fdiv.s          &0x00000000,%fp1        # -1 / 0
9869         rts
9870
9871 dz_pinf:
9872         ori.l           &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
9873
9874         btst            &dz_bit,FPCR_ENABLE(%a6)
9875         bne.b           dz_pinf_ena
9876
9877 # dz is disabled. return a +INF.
9878         fmov.s          &0x7f800000,%fp0        # return +INF
9879         rts
9880
9881 # dz is enabled. create a dz exception so the user can record it
9882 # but use fp1 instead. return the dst operand unscathed in fp0.
9883 dz_pinf_ena:
9884         fmovm.x         EXC_FP0(%a6),&0x80      # return fp0 unscathed
9885         fmov.l          USER_FPCR(%a6),%fpcr
9886         fmov.s          &0x3f800000,%fp1        # load +1
9887         fdiv.s          &0x00000000,%fp1        # +1 / 0
9888         rts
9889
9890 #########################################################################
9891 # XDEF **************************************************************** #
9892 #       t_operr(): Handle 060FPLSP OPERR exception during emulation.    #
9893 #                                                                       #
9894 #       This routine is used by the 060FPLSP package.                   #
9895 #                                                                       #
9896 # XREF **************************************************************** #
9897 #       None.                                                           #
9898 #                                                                       #
9899 # INPUT *************************************************************** #
9900 #       fp1 = source operand                                            #
9901 #                                                                       #
9902 # OUTPUT ************************************************************** #
9903 #       fp0 = default result                                            #
9904 #       fp1 = unchanged                                                 #
9905 #                                                                       #
9906 # ALGORITHM *********************************************************** #
9907 #       An operand error should occur as the result of transcendental   #
9908 # emulation in the 060FPLSP. If OPERR is disabled, just return a NAN    #
9909 # in fp0. If OPERR is enabled, return the dst operand unscathed in fp0  #
9910 # and the source operand in fp1. Use fp2 to create an OPERR exception   #
9911 # so that the operating system can log the event.                       #
9912 #                                                                       #
9913 #########################################################################
9914
9915         global          t_operr
9916 t_operr:
9917         ori.l           &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
9918
9919         btst            &operr_bit,FPCR_ENABLE(%a6)
9920         bne.b           operr_ena
9921
9922 # operr is disabled. return a QNAN in fp0
9923         fmovm.x         qnan(%pc),&0x80         # return QNAN
9924         rts
9925
9926 # operr is enabled. create an operr exception so the user can record it
9927 # but use fp2 instead. return the dst operand unscathed in fp0.
9928 operr_ena:
9929         fmovm.x         EXC_FP0(%a6),&0x80      # return fp0 unscathed
9930         fmov.l          USER_FPCR(%a6),%fpcr
9931         fmovm.x         &0x04,-(%sp)            # save fp2
9932         fmov.s          &0x7f800000,%fp2        # load +INF
9933         fmul.s          &0x00000000,%fp2        # +INF x 0
9934         fmovm.x         (%sp)+,&0x20            # restore fp2
9935         rts
9936
9937 pls_huge:
9938         long            0x7ffe0000,0xffffffff,0xffffffff
9939 mns_huge:
9940         long            0xfffe0000,0xffffffff,0xffffffff
9941 pls_tiny:
9942         long            0x00000000,0x80000000,0x00000000
9943 mns_tiny:
9944         long            0x80000000,0x80000000,0x00000000
9945
9946 #########################################################################
9947 # XDEF **************************************************************** #
9948 #       t_unfl(): Handle 060FPLSP underflow exception during emulation. #
9949 #       t_unfl2(): Handle 060FPLSP underflow exception during           #
9950 #                  emulation. result always positive.                   #
9951 #                                                                       #
9952 #       This routine is used by the 060FPLSP package.                   #
9953 #                                                                       #
9954 # XREF **************************************************************** #
9955 #       None.                                                           #
9956 #                                                                       #
9957 # INPUT *************************************************************** #
9958 #       a0 = pointer to extended precision source operand               #
9959 #                                                                       #
9960 # OUTPUT ************************************************************** #
9961 #       fp0 = default underflow result                                  #
9962 #                                                                       #
9963 # ALGORITHM *********************************************************** #
9964 #       An underflow should occur as the result of transcendental       #
9965 # emulation in the 060FPLSP. Create an underflow by using "fmul"        #
9966 # and two very small numbers of appropriate sign so the operating       #
9967 # system can log the event.                                             #
9968 #                                                                       #
9969 #########################################################################
9970
9971         global          t_unfl
9972 t_unfl:
9973         tst.b           SRC_EX(%a0)
9974         bpl.b           unf_pos
9975
9976         global          t_unfl2
9977 t_unfl2:
9978         ori.l           &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
9979
9980         fmov.l          USER_FPCR(%a6),%fpcr
9981         fmovm.x         mns_tiny(%pc),&0x80
9982         fmul.x          pls_tiny(%pc),%fp0
9983
9984         fmov.l          %fpsr,%d0
9985         rol.l           &0x8,%d0
9986         mov.b           %d0,FPSR_CC(%a6)
9987         rts
9988 unf_pos:
9989         ori.w           &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
9990
9991         fmov.l          USER_FPCR(%a6),%fpcr
9992         fmovm.x         pls_tiny(%pc),&0x80
9993         fmul.x          %fp0,%fp0
9994
9995         fmov.l          %fpsr,%d0
9996         rol.l           &0x8,%d0
9997         mov.b           %d0,FPSR_CC(%a6)
9998         rts
9999
10000 #########################################################################
10001 # XDEF **************************************************************** #
10002 #       t_ovfl(): Handle 060FPLSP overflow exception during emulation.  #
10003 #                 (monadic)                                             #
10004 #       t_ovfl2(): Handle 060FPLSP overflow exception during            #
10005 #                  emulation. result always positive. (dyadic)          #
10006 #       t_ovfl_sc(): Handle 060FPLSP overflow exception during          #
10007 #                    emulation for "fscale".                            #
10008 #                                                                       #
10009 #       This routine is used by the 060FPLSP package.                   #
10010 #                                                                       #
10011 # XREF **************************************************************** #
10012 #       None.                                                           #
10013 #                                                                       #
10014 # INPUT *************************************************************** #
10015 #       a0 = pointer to extended precision source operand               #
10016 #                                                                       #
10017 # OUTPUT ************************************************************** #
10018 #       fp0 = default underflow result                                  #
10019 #                                                                       #
10020 # ALGORITHM *********************************************************** #
10021 #       An overflow should occur as the result of transcendental        #
10022 # emulation in the 060FPLSP. Create an overflow by using "fmul"         #
10023 # and two very lareg numbers of appropriate sign so the operating       #
10024 # system can log the event.                                             #
10025 #       For t_ovfl_sc() we take special care not to lose the INEX2 bit. #
10026 #                                                                       #
10027 #########################################################################
10028
10029         global          t_ovfl_sc
10030 t_ovfl_sc:
10031         ori.l           &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
10032
10033         mov.b           %d0,%d1                 # fetch rnd prec,mode
10034         andi.b          &0xc0,%d1               # extract prec
10035         beq.w           ovfl_work
10036
10037 # dst op is a DENORM. we have to normalize the mantissa to see if the
10038 # result would be inexact for the given precision. make a copy of the
10039 # dst so we don't screw up the version passed to us.
10040         mov.w           LOCAL_EX(%a0),FP_SCR0_EX(%a6)
10041         mov.l           LOCAL_HI(%a0),FP_SCR0_HI(%a6)
10042         mov.l           LOCAL_LO(%a0),FP_SCR0_LO(%a6)
10043         lea             FP_SCR0(%a6),%a0        # pass ptr to FP_SCR0
10044         movm.l          &0xc080,-(%sp)          # save d0-d1/a0
10045         bsr.l           norm                    # normalize mantissa
10046         movm.l          (%sp)+,&0x0103          # restore d0-d1/a0
10047
10048         cmpi.b          %d1,&0x40               # is precision sgl?
10049         bne.b           ovfl_sc_dbl             # no; dbl
10050 ovfl_sc_sgl:
10051         tst.l           LOCAL_LO(%a0)           # is lo lw of sgl set?
10052         bne.b           ovfl_sc_inx             # yes
10053         tst.b           3+LOCAL_HI(%a0)         # is lo byte of hi lw set?
10054         bne.b           ovfl_sc_inx             # yes
10055         bra.w           ovfl_work               # don't set INEX2
10056 ovfl_sc_dbl:
10057         mov.l           LOCAL_LO(%a0),%d1       # are any of lo 11 bits of
10058         andi.l          &0x7ff,%d1              # dbl mantissa set?
10059         beq.w           ovfl_work               # no; don't set INEX2
10060 ovfl_sc_inx:
10061         ori.l           &inex2_mask,USER_FPSR(%a6) # set INEX2
10062         bra.b           ovfl_work               # continue
10063
10064         global          t_ovfl
10065 t_ovfl:
10066         ori.w           &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10067 ovfl_work:
10068         tst.b           SRC_EX(%a0)
10069         bpl.b           ovfl_p
10070 ovfl_m:
10071         fmov.l          USER_FPCR(%a6),%fpcr
10072         fmovm.x         mns_huge(%pc),&0x80
10073         fmul.x          pls_huge(%pc),%fp0
10074
10075         fmov.l          %fpsr,%d0
10076         rol.l           &0x8,%d0
10077         ori.b           &neg_mask,%d0
10078         mov.b           %d0,FPSR_CC(%a6)
10079         rts
10080 ovfl_p:
10081         fmov.l          USER_FPCR(%a6),%fpcr
10082         fmovm.x         pls_huge(%pc),&0x80
10083         fmul.x          pls_huge(%pc),%fp0
10084
10085         fmov.l          %fpsr,%d0
10086         rol.l           &0x8,%d0
10087         mov.b           %d0,FPSR_CC(%a6)
10088         rts
10089
10090         global          t_ovfl2
10091 t_ovfl2:
10092         ori.w           &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10093         fmov.l          USER_FPCR(%a6),%fpcr
10094         fmovm.x         pls_huge(%pc),&0x80
10095         fmul.x          pls_huge(%pc),%fp0
10096
10097         fmov.l          %fpsr,%d0
10098         rol.l           &0x8,%d0
10099         mov.b           %d0,FPSR_CC(%a6)
10100         rts
10101
10102 #########################################################################
10103 # XDEF **************************************************************** #
10104 #       t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during  #
10105 #                  emulation.                                           #
10106 #       t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10107 #                   emulation.                                          #
10108 #                                                                       #
10109 #       These routines are used by the 060FPLSP package.                #
10110 #                                                                       #
10111 # XREF **************************************************************** #
10112 #       None.                                                           #
10113 #                                                                       #
10114 # INPUT *************************************************************** #
10115 #       fp0 = default underflow or overflow result                      #
10116 #                                                                       #
10117 # OUTPUT ************************************************************** #
10118 #       fp0 = default result                                            #
10119 #                                                                       #
10120 # ALGORITHM *********************************************************** #
10121 #       If an overflow or underflow occurred during the last            #
10122 # instruction of transcendental 060FPLSP emulation, then it has already #
10123 # occurred and has been logged. Now we need to see if an inexact        #
10124 # exception should occur.                                               #
10125 #                                                                       #
10126 #########################################################################
10127
10128         global          t_catch2
10129 t_catch2:
10130         fmov.l          %fpsr,%d0
10131         or.l            %d0,USER_FPSR(%a6)
10132         bra.b           inx2_work
10133
10134         global          t_catch
10135 t_catch:
10136         fmov.l          %fpsr,%d0
10137         or.l            %d0,USER_FPSR(%a6)
10138
10139 #########################################################################
10140 # XDEF **************************************************************** #
10141 #       t_inx2(): Handle inexact 060FPLSP exception during emulation.   #
10142 #       t_pinx2(): Handle inexact 060FPLSP exception for "+" results.   #
10143 #       t_minx2(): Handle inexact 060FPLSP exception for "-" results.   #
10144 #                                                                       #
10145 # XREF **************************************************************** #
10146 #       None.                                                           #
10147 #                                                                       #
10148 # INPUT *************************************************************** #
10149 #       fp0 = default result                                            #
10150 #                                                                       #
10151 # OUTPUT ************************************************************** #
10152 #       fp0 = default result                                            #
10153 #                                                                       #
10154 # ALGORITHM *********************************************************** #
10155 #       The last instruction of transcendental emulation for the        #
10156 # 060FPLSP should be inexact. So, if inexact is enabled, then we create #
10157 # the event here by adding a large and very small number together       #
10158 # so that the operating system can log the event.                       #
10159 #       Must check, too, if the result was zero, in which case we just  #
10160 # set the FPSR bits and return.                                         #
10161 #                                                                       #
10162 #########################################################################
10163
10164         global          t_inx2
10165 t_inx2:
10166         fblt.w          t_minx2
10167         fbeq.w          inx2_zero
10168
10169         global          t_pinx2
10170 t_pinx2:
10171         ori.w           &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
10172         bra.b           inx2_work
10173
10174         global          t_minx2
10175 t_minx2:
10176         ori.l           &inx2a_mask+neg_mask,USER_FPSR(%a6)
10177
10178 inx2_work:
10179         btst            &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
10180         bne.b           inx2_work_ena           # yes
10181         rts
10182 inx2_work_ena:
10183         fmov.l          USER_FPCR(%a6),%fpcr    # insert user's exceptions
10184         fmov.s          &0x3f800000,%fp1        # load +1
10185         fadd.x          pls_tiny(%pc),%fp1      # cause exception
10186         rts
10187
10188 inx2_zero:
10189         mov.b           &z_bmask,FPSR_CC(%a6)
10190         ori.w           &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
10191         rts
10192
10193 #########################################################################
10194 # XDEF **************************************************************** #
10195 #       t_extdnrm(): Handle DENORM inputs in 060FPLSP.                  #
10196 #       t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale".     #
10197 #                                                                       #
10198 #       This routine is used by the 060FPLSP package.                   #
10199 #                                                                       #
10200 # XREF **************************************************************** #
10201 #       None.                                                           #
10202 #                                                                       #
10203 # INPUT *************************************************************** #
10204 #       a0 = pointer to extended precision input operand                #
10205 #                                                                       #
10206 # OUTPUT ************************************************************** #
10207 #       fp0 = default result                                            #
10208 #                                                                       #
10209 # ALGORITHM *********************************************************** #
10210 #       For all functions that have a denormalized input and that       #
10211 # f(x)=x, this is the entry point.                                      #
10212 #       DENORM value is moved using "fmove" which triggers an exception #
10213 # if enabled so the operating system can log the event.                 #
10214 #                                                                       #
10215 #########################################################################
10216
10217         global          t_extdnrm
10218 t_extdnrm:
10219         fmov.l          USER_FPCR(%a6),%fpcr
10220         fmov.x          SRC_EX(%a0),%fp0
10221         fmov.l          %fpsr,%d0
10222         ori.l           &unfinx_mask,%d0
10223         or.l            %d0,USER_FPSR(%a6)
10224         rts
10225
10226         global          t_resdnrm
10227 t_resdnrm:
10228         fmov.l          USER_FPCR(%a6),%fpcr
10229         fmov.x          SRC_EX(%a0),%fp0
10230         fmov.l          %fpsr,%d0
10231         or.l            %d0,USER_FPSR(%a6)
10232         rts
10233
10234 ##########################################
10235
10236 #
10237 # sto_cos:
10238 #       This is used by fsincos library emulation. The correct
10239 # values are already in fp0 and fp1 so we do nothing here.
10240 #
10241         global          sto_cos
10242 sto_cos:
10243         rts
10244
10245 ##########################################
10246
10247 #
10248 #       dst_qnan --- force result when destination is a NaN
10249 #
10250         global          dst_qnan
10251 dst_qnan:
10252         fmov.x          DST(%a1),%fp0
10253         tst.b           DST_EX(%a1)
10254         bmi.b           dst_qnan_m
10255 dst_qnan_p:
10256         mov.b           &nan_bmask,FPSR_CC(%a6)
10257         rts
10258 dst_qnan_m:
10259         mov.b           &nan_bmask+neg_bmask,FPSR_CC(%a6)
10260         rts
10261
10262 #
10263 #       src_qnan --- force result when source is a NaN
10264 #
10265         global          src_qnan
10266 src_qnan:
10267         fmov.x          SRC(%a0),%fp0
10268         tst.b           SRC_EX(%a0)
10269         bmi.b           src_qnan_m
10270 src_qnan_p:
10271         mov.b           &nan_bmask,FPSR_CC(%a6)
10272         rts
10273 src_qnan_m:
10274         mov.b           &nan_bmask+neg_bmask,FPSR_CC(%a6)
10275         rts
10276
10277 ##########################################
10278
10279 #
10280 #       Native instruction support
10281 #
10282 #       Some systems may need entry points even for 68060 native
10283 #       instructions.  These routines are provided for
10284 #       convenience.
10285 #
10286         global          _fadds_
10287 _fadds_:
10288         fmov.l          %fpcr,-(%sp)            # save fpcr
10289         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10290         fmov.s          0x8(%sp),%fp0           # load sgl dst
10291         fmov.l          (%sp)+,%fpcr            # restore fpcr
10292         fadd.s          0x8(%sp),%fp0           # fadd w/ sgl src
10293         rts
10294
10295         global          _faddd_
10296 _faddd_:
10297         fmov.l          %fpcr,-(%sp)            # save fpcr
10298         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10299         fmov.d          0x8(%sp),%fp0           # load dbl dst
10300         fmov.l          (%sp)+,%fpcr            # restore fpcr
10301         fadd.d          0xc(%sp),%fp0           # fadd w/ dbl src
10302         rts
10303
10304         global          _faddx_
10305 _faddx_:
10306         fmovm.x         0x4(%sp),&0x80          # load ext dst
10307         fadd.x          0x10(%sp),%fp0          # fadd w/ ext src
10308         rts
10309
10310         global          _fsubs_
10311 _fsubs_:
10312         fmov.l          %fpcr,-(%sp)            # save fpcr
10313         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10314         fmov.s          0x8(%sp),%fp0           # load sgl dst
10315         fmov.l          (%sp)+,%fpcr            # restore fpcr
10316         fsub.s          0x8(%sp),%fp0           # fsub w/ sgl src
10317         rts
10318
10319         global          _fsubd_
10320 _fsubd_:
10321         fmov.l          %fpcr,-(%sp)            # save fpcr
10322         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10323         fmov.d          0x8(%sp),%fp0           # load dbl dst
10324         fmov.l          (%sp)+,%fpcr            # restore fpcr
10325         fsub.d          0xc(%sp),%fp0           # fsub w/ dbl src
10326         rts
10327
10328         global          _fsubx_
10329 _fsubx_:
10330         fmovm.x         0x4(%sp),&0x80          # load ext dst
10331         fsub.x          0x10(%sp),%fp0          # fsub w/ ext src
10332         rts
10333
10334         global          _fmuls_
10335 _fmuls_:
10336         fmov.l          %fpcr,-(%sp)            # save fpcr
10337         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10338         fmov.s          0x8(%sp),%fp0           # load sgl dst
10339         fmov.l          (%sp)+,%fpcr            # restore fpcr
10340         fmul.s          0x8(%sp),%fp0           # fmul w/ sgl src
10341         rts
10342
10343         global          _fmuld_
10344 _fmuld_:
10345         fmov.l          %fpcr,-(%sp)            # save fpcr
10346         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10347         fmov.d          0x8(%sp),%fp0           # load dbl dst
10348         fmov.l          (%sp)+,%fpcr            # restore fpcr
10349         fmul.d          0xc(%sp),%fp0           # fmul w/ dbl src
10350         rts
10351
10352         global          _fmulx_
10353 _fmulx_:
10354         fmovm.x         0x4(%sp),&0x80          # load ext dst
10355         fmul.x          0x10(%sp),%fp0          # fmul w/ ext src
10356         rts
10357
10358         global          _fdivs_
10359 _fdivs_:
10360         fmov.l          %fpcr,-(%sp)            # save fpcr
10361         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10362         fmov.s          0x8(%sp),%fp0           # load sgl dst
10363         fmov.l          (%sp)+,%fpcr            # restore fpcr
10364         fdiv.s          0x8(%sp),%fp0           # fdiv w/ sgl src
10365         rts
10366
10367         global          _fdivd_
10368 _fdivd_:
10369         fmov.l          %fpcr,-(%sp)            # save fpcr
10370         fmov.l          &0x00000000,%fpcr       # clear fpcr for load
10371         fmov.d          0x8(%sp),%fp0           # load dbl dst
10372         fmov.l          (%sp)+,%fpcr            # restore fpcr
10373         fdiv.d          0xc(%sp),%fp0           # fdiv w/ dbl src
10374         rts
10375
10376         global          _fdivx_
10377 _fdivx_:
10378         fmovm.x         0x4(%sp),&0x80          # load ext dst
10379         fdiv.x          0x10(%sp),%fp0          # fdiv w/ ext src
10380         rts
10381
10382         global          _fabss_
10383 _fabss_:
10384         fabs.s          0x4(%sp),%fp0           # fabs w/ sgl src
10385         rts
10386
10387         global          _fabsd_
10388 _fabsd_:
10389         fabs.d          0x4(%sp),%fp0           # fabs w/ dbl src
10390         rts
10391
10392         global          _fabsx_
10393 _fabsx_:
10394         fabs.x          0x4(%sp),%fp0           # fabs w/ ext src
10395         rts
10396
10397         global          _fnegs_
10398 _fnegs_:
10399         fneg.s          0x4(%sp),%fp0           # fneg w/ sgl src
10400         rts
10401
10402         global          _fnegd_
10403 _fnegd_:
10404         fneg.d          0x4(%sp),%fp0           # fneg w/ dbl src
10405         rts
10406
10407         global          _fnegx_
10408 _fnegx_:
10409         fneg.x          0x4(%sp),%fp0           # fneg w/ ext src
10410         rts
10411
10412         global          _fsqrts_
10413 _fsqrts_:
10414         fsqrt.s         0x4(%sp),%fp0           # fsqrt w/ sgl src
10415         rts
10416
10417         global          _fsqrtd_
10418 _fsqrtd_:
10419         fsqrt.d         0x4(%sp),%fp0           # fsqrt w/ dbl src
10420         rts
10421
10422         global          _fsqrtx_
10423 _fsqrtx_:
10424         fsqrt.x         0x4(%sp),%fp0           # fsqrt w/ ext src
10425         rts
10426
10427         global          _fints_
10428 _fints_:
10429         fint.s          0x4(%sp),%fp0           # fint w/ sgl src
10430         rts
10431
10432         global          _fintd_
10433 _fintd_:
10434         fint.d          0x4(%sp),%fp0           # fint w/ dbl src
10435         rts
10436
10437         global          _fintx_
10438 _fintx_:
10439         fint.x          0x4(%sp),%fp0           # fint w/ ext src
10440         rts
10441
10442         global          _fintrzs_
10443 _fintrzs_:
10444         fintrz.s        0x4(%sp),%fp0           # fintrz w/ sgl src
10445         rts
10446
10447         global          _fintrzd_
10448 _fintrzd_:
10449         fintrz.d        0x4(%sp),%fp0           # fintrx w/ dbl src
10450         rts
10451
10452         global          _fintrzx_
10453 _fintrzx_:
10454         fintrz.x        0x4(%sp),%fp0           # fintrz w/ ext src
10455         rts
10456
10457 ########################################################################
10458
10459 #########################################################################
10460 # src_zero(): Return signed zero according to sign of src operand.      #
10461 #########################################################################
10462         global          src_zero
10463 src_zero:
10464         tst.b           SRC_EX(%a0)             # get sign of src operand
10465         bmi.b           ld_mzero                # if neg, load neg zero
10466
10467 #
10468 # ld_pzero(): return a positive zero.
10469 #
10470         global          ld_pzero
10471 ld_pzero:
10472         fmov.s          &0x00000000,%fp0        # load +0
10473         mov.b           &z_bmask,FPSR_CC(%a6)   # set 'Z' ccode bit
10474         rts
10475
10476 # ld_mzero(): return a negative zero.
10477         global          ld_mzero
10478 ld_mzero:
10479         fmov.s          &0x80000000,%fp0        # load -0
10480         mov.b           &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
10481         rts
10482
10483 #########################################################################
10484 # dst_zero(): Return signed zero according to sign of dst operand.      #
10485 #########################################################################
10486         global          dst_zero
10487 dst_zero:
10488         tst.b           DST_EX(%a1)             # get sign of dst operand
10489         bmi.b           ld_mzero                # if neg, load neg zero
10490         bra.b           ld_pzero                # load positive zero
10491
10492 #########################################################################
10493 # src_inf(): Return signed inf according to sign of src operand.        #
10494 #########################################################################
10495         global          src_inf
10496 src_inf:
10497         tst.b           SRC_EX(%a0)             # get sign of src operand
10498         bmi.b           ld_minf                 # if negative branch
10499
10500 #
10501 # ld_pinf(): return a positive infinity.
10502 #
10503         global          ld_pinf
10504 ld_pinf:
10505         fmov.s          &0x7f800000,%fp0        # load +INF
10506         mov.b           &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
10507         rts
10508
10509 #
10510 # ld_minf():return a negative infinity.
10511 #
10512         global          ld_minf
10513 ld_minf:
10514         fmov.s          &0xff800000,%fp0        # load -INF
10515         mov.b           &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
10516         rts
10517
10518 #########################################################################
10519 # dst_inf(): Return signed inf according to sign of dst operand.        #
10520 #########################################################################
10521         global          dst_inf
10522 dst_inf:
10523         tst.b           DST_EX(%a1)             # get sign of dst operand
10524         bmi.b           ld_minf                 # if negative branch
10525         bra.b           ld_pinf
10526
10527         global          szr_inf
10528 #################################################################
10529 # szr_inf(): Return +ZERO for a negative src operand or         #
10530 #                   +INF for a positive src operand.            #
10531 #            Routine used for fetox, ftwotox, and ftentox.      #
10532 #################################################################
10533 szr_inf:
10534         tst.b           SRC_EX(%a0)             # check sign of source
10535         bmi.b           ld_pzero
10536         bra.b           ld_pinf
10537
10538 #########################################################################
10539 # sopr_inf(): Return +INF for a positive src operand or                 #
10540 #             jump to operand error routine for a negative src operand. #
10541 #             Routine used for flogn, flognp1, flog10, and flog2.       #
10542 #########################################################################
10543         global          sopr_inf
10544 sopr_inf:
10545         tst.b           SRC_EX(%a0)             # check sign of source
10546         bmi.w           t_operr
10547         bra.b           ld_pinf
10548
10549 #################################################################
10550 # setoxm1i(): Return minus one for a negative src operand or    #
10551 #             positive infinity for a positive src operand.     #
10552 #             Routine used for fetoxm1.                         #
10553 #################################################################
10554         global          setoxm1i
10555 setoxm1i:
10556         tst.b           SRC_EX(%a0)             # check sign of source
10557         bmi.b           ld_mone
10558         bra.b           ld_pinf
10559
10560 #########################################################################
10561 # src_one(): Return signed one according to sign of src operand.        #
10562 #########################################################################
10563         global          src_one
10564 src_one:
10565         tst.b           SRC_EX(%a0)             # check sign of source
10566         bmi.b           ld_mone
10567
10568 #
10569 # ld_pone(): return positive one.
10570 #
10571         global          ld_pone
10572 ld_pone:
10573         fmov.s          &0x3f800000,%fp0        # load +1
10574         clr.b           FPSR_CC(%a6)
10575         rts
10576
10577 #
10578 # ld_mone(): return negative one.
10579 #
10580         global          ld_mone
10581 ld_mone:
10582         fmov.s          &0xbf800000,%fp0        # load -1
10583         mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
10584         rts
10585
10586 ppiby2: long            0x3fff0000, 0xc90fdaa2, 0x2168c235
10587 mpiby2: long            0xbfff0000, 0xc90fdaa2, 0x2168c235
10588
10589 #################################################################
10590 # spi_2(): Return signed PI/2 according to sign of src operand. #
10591 #################################################################
10592         global          spi_2
10593 spi_2:
10594         tst.b           SRC_EX(%a0)             # check sign of source
10595         bmi.b           ld_mpi2
10596
10597 #
10598 # ld_ppi2(): return positive PI/2.
10599 #
10600         global          ld_ppi2
10601 ld_ppi2:
10602         fmov.l          %d0,%fpcr
10603         fmov.x          ppiby2(%pc),%fp0        # load +pi/2
10604         bra.w           t_pinx2                 # set INEX2
10605
10606 #
10607 # ld_mpi2(): return negative PI/2.
10608 #
10609         global          ld_mpi2
10610 ld_mpi2:
10611         fmov.l          %d0,%fpcr
10612         fmov.x          mpiby2(%pc),%fp0        # load -pi/2
10613         bra.w           t_minx2                 # set INEX2
10614
10615 ####################################################
10616 # The following routines give support for fsincos. #
10617 ####################################################
10618
10619 #
10620 # ssincosz(): When the src operand is ZERO, store a one in the
10621 #             cosine register and return a ZERO in fp0 w/ the same sign
10622 #             as the src operand.
10623 #
10624         global          ssincosz
10625 ssincosz:
10626         fmov.s          &0x3f800000,%fp1
10627         tst.b           SRC_EX(%a0)             # test sign
10628         bpl.b           sincoszp
10629         fmov.s          &0x80000000,%fp0        # return sin result in fp0
10630         mov.b           &z_bmask+neg_bmask,FPSR_CC(%a6)
10631         rts
10632 sincoszp:
10633         fmov.s          &0x00000000,%fp0        # return sin result in fp0
10634         mov.b           &z_bmask,FPSR_CC(%a6)
10635         rts
10636
10637 #
10638 # ssincosi(): When the src operand is INF, store a QNAN in the cosine
10639 #             register and jump to the operand error routine for negative
10640 #             src operands.
10641 #
10642         global          ssincosi
10643 ssincosi:
10644         fmov.x          qnan(%pc),%fp1          # load NAN
10645         bra.w           t_operr
10646
10647 #
10648 # ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
10649 #                register and branch to the src QNAN routine.
10650 #
10651         global          ssincosqnan
10652 ssincosqnan:
10653         fmov.x          LOCAL_EX(%a0),%fp1
10654         bra.w           src_qnan
10655
10656 ########################################################################
10657
10658         global          smod_sdnrm
10659         global          smod_snorm
10660 smod_sdnrm:
10661 smod_snorm:
10662         mov.b           DTAG(%a6),%d1
10663         beq.l           smod
10664         cmpi.b          %d1,&ZERO
10665         beq.w           smod_zro
10666         cmpi.b          %d1,&INF
10667         beq.l           t_operr
10668         cmpi.b          %d1,&DENORM
10669         beq.l           smod
10670         bra.l           dst_qnan
10671
10672         global          smod_szero
10673 smod_szero:
10674         mov.b           DTAG(%a6),%d1
10675         beq.l           t_operr
10676         cmpi.b          %d1,&ZERO
10677         beq.l           t_operr
10678         cmpi.b          %d1,&INF
10679         beq.l           t_operr
10680         cmpi.b          %d1,&DENORM
10681         beq.l           t_operr
10682         bra.l           dst_qnan
10683
10684         global          smod_sinf
10685 smod_sinf:
10686         mov.b           DTAG(%a6),%d1
10687         beq.l           smod_fpn
10688         cmpi.b          %d1,&ZERO
10689         beq.l           smod_zro
10690         cmpi.b          %d1,&INF
10691         beq.l           t_operr
10692         cmpi.b          %d1,&DENORM
10693         beq.l           smod_fpn
10694         bra.l           dst_qnan
10695
10696 smod_zro:
10697 srem_zro:
10698         mov.b           SRC_EX(%a0),%d1         # get src sign
10699         mov.b           DST_EX(%a1),%d0         # get dst sign
10700         eor.b           %d0,%d1                 # get qbyte sign
10701         andi.b          &0x80,%d1
10702         mov.b           %d1,FPSR_QBYTE(%a6)
10703         tst.b           %d0
10704         bpl.w           ld_pzero
10705         bra.w           ld_mzero
10706
10707 smod_fpn:
10708 srem_fpn:
10709         clr.b           FPSR_QBYTE(%a6)
10710         mov.l           %d0,-(%sp)
10711         mov.b           SRC_EX(%a0),%d1         # get src sign
10712         mov.b           DST_EX(%a1),%d0         # get dst sign
10713         eor.b           %d0,%d1                 # get qbyte sign
10714         andi.b          &0x80,%d1
10715         mov.b           %d1,FPSR_QBYTE(%a6)
10716         cmpi.b          DTAG(%a6),&DENORM
10717         bne.b           smod_nrm
10718         lea             DST(%a1),%a0
10719         mov.l           (%sp)+,%d0
10720         bra             t_resdnrm
10721 smod_nrm:
10722         fmov.l          (%sp)+,%fpcr
10723         fmov.x          DST(%a1),%fp0
10724         tst.b           DST_EX(%a1)
10725         bmi.b           smod_nrm_neg
10726         rts
10727
10728 smod_nrm_neg:
10729         mov.b           &neg_bmask,FPSR_CC(%a6) # set 'N' code
10730         rts
10731
10732 #########################################################################
10733         global          srem_snorm
10734         global          srem_sdnrm
10735 srem_sdnrm:
10736 srem_snorm:
10737         mov.b           DTAG(%a6),%d1
10738         beq.l           srem
10739         cmpi.b          %d1,&ZERO
10740         beq.w           srem_zro
10741         cmpi.b          %d1,&INF
10742         beq.l           t_operr
10743         cmpi.b          %d1,&DENORM
10744         beq.l           srem
10745         bra.l           dst_qnan
10746
10747         global          srem_szero
10748 srem_szero:
10749         mov.b           DTAG(%a6),%d1
10750         beq.l           t_operr
10751         cmpi.b          %d1,&ZERO
10752         beq.l           t_operr
10753         cmpi.b          %d1,&INF
10754         beq.l           t_operr
10755         cmpi.b          %d1,&DENORM
10756         beq.l           t_operr
10757         bra.l           dst_qnan
10758
10759         global          srem_sinf
10760 srem_sinf:
10761         mov.b           DTAG(%a6),%d1
10762         beq.w           srem_fpn
10763         cmpi.b          %d1,&ZERO
10764         beq.w           srem_zro
10765         cmpi.b          %d1,&INF
10766         beq.l           t_operr
10767         cmpi.b          %d1,&DENORM
10768         beq.l           srem_fpn
10769         bra.l           dst_qnan
10770
10771 #########################################################################
10772
10773         global          sscale_snorm
10774         global          sscale_sdnrm
10775 sscale_snorm:
10776 sscale_sdnrm:
10777         mov.b           DTAG(%a6),%d1
10778         beq.l           sscale
10779         cmpi.b          %d1,&ZERO
10780         beq.l           dst_zero
10781         cmpi.b          %d1,&INF
10782         beq.l           dst_inf
10783         cmpi.b          %d1,&DENORM
10784         beq.l           sscale
10785         bra.l           dst_qnan
10786
10787         global          sscale_szero
10788 sscale_szero:
10789         mov.b           DTAG(%a6),%d1
10790         beq.l           sscale
10791         cmpi.b          %d1,&ZERO
10792         beq.l           dst_zero
10793         cmpi.b          %d1,&INF
10794         beq.l           dst_inf
10795         cmpi.b          %d1,&DENORM
10796         beq.l           sscale
10797         bra.l           dst_qnan
10798
10799         global          sscale_sinf
10800 sscale_sinf:
10801         mov.b           DTAG(%a6),%d1
10802         beq.l           t_operr
10803         cmpi.b          %d1,&QNAN
10804         beq.l           dst_qnan
10805         bra.l           t_operr
10806
10807 ########################################################################
10808
10809         global          sop_sqnan
10810 sop_sqnan:
10811         mov.b           DTAG(%a6),%d1
10812         cmpi.b          %d1,&QNAN
10813         beq.l           dst_qnan
10814         bra.l           src_qnan
10815
10816 #########################################################################
10817 # norm(): normalize the mantissa of an extended precision input. the    #
10818 #         input operand should not be normalized already.               #
10819 #                                                                       #
10820 # XDEF **************************************************************** #
10821 #       norm()                                                          #
10822 #                                                                       #
10823 # XREF **************************************************************** #
10824 #       none                                                            #
10825 #                                                                       #
10826 # INPUT *************************************************************** #
10827 #       a0 = pointer fp extended precision operand to normalize         #
10828 #                                                                       #
10829 # OUTPUT ************************************************************** #
10830 #       d0 = number of bit positions the mantissa was shifted           #
10831 #       a0 = the input operand's mantissa is normalized; the exponent   #
10832 #            is unchanged.                                              #
10833 #                                                                       #
10834 #########################################################################
10835         global          norm
10836 norm:
10837         mov.l           %d2, -(%sp)             # create some temp regs
10838         mov.l           %d3, -(%sp)
10839
10840         mov.l           FTEMP_HI(%a0), %d0      # load hi(mantissa)
10841         mov.l           FTEMP_LO(%a0), %d1      # load lo(mantissa)
10842
10843         bfffo           %d0{&0:&32}, %d2        # how many places to shift?
10844         beq.b           norm_lo                 # hi(man) is all zeroes!
10845
10846 norm_hi:
10847         lsl.l           %d2, %d0                # left shift hi(man)
10848         bfextu          %d1{&0:%d2}, %d3        # extract lo bits
10849
10850         or.l            %d3, %d0                # create hi(man)
10851         lsl.l           %d2, %d1                # create lo(man)
10852
10853         mov.l           %d0, FTEMP_HI(%a0)      # store new hi(man)
10854         mov.l           %d1, FTEMP_LO(%a0)      # store new lo(man)
10855
10856         mov.l           %d2, %d0                # return shift amount
10857
10858         mov.l           (%sp)+, %d3             # restore temp regs
10859         mov.l           (%sp)+, %d2
10860
10861         rts
10862
10863 norm_lo:
10864         bfffo           %d1{&0:&32}, %d2        # how many places to shift?
10865         lsl.l           %d2, %d1                # shift lo(man)
10866         add.l           &32, %d2                # add 32 to shft amount
10867
10868         mov.l           %d1, FTEMP_HI(%a0)      # store hi(man)
10869         clr.l           FTEMP_LO(%a0)           # lo(man) is now zero
10870
10871         mov.l           %d2, %d0                # return shift amount
10872
10873         mov.l           (%sp)+, %d3             # restore temp regs
10874         mov.l           (%sp)+, %d2
10875
10876         rts
10877
10878 #########################################################################
10879 # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO     #
10880 #               - returns corresponding optype tag                      #
10881 #                                                                       #
10882 # XDEF **************************************************************** #
10883 #       unnorm_fix()                                                    #
10884 #                                                                       #
10885 # XREF **************************************************************** #
10886 #       norm() - normalize the mantissa                                 #
10887 #                                                                       #
10888 # INPUT *************************************************************** #
10889 #       a0 = pointer to unnormalized extended precision number          #
10890 #                                                                       #
10891 # OUTPUT ************************************************************** #
10892 #       d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO  #
10893 #       a0 = input operand has been converted to a norm, denorm, or     #
10894 #            zero; both the exponent and mantissa are changed.          #
10895 #                                                                       #
10896 #########################################################################
10897
10898         global          unnorm_fix
10899 unnorm_fix:
10900         bfffo           FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
10901         bne.b           unnorm_shift            # hi(man) is not all zeroes
10902
10903 #
10904 # hi(man) is all zeroes so see if any bits in lo(man) are set
10905 #
10906 unnorm_chk_lo:
10907         bfffo           FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
10908         beq.w           unnorm_zero             # yes
10909
10910         add.w           &32, %d0                # no; fix shift distance
10911
10912 #
10913 # d0 = # shifts needed for complete normalization
10914 #
10915 unnorm_shift:
10916         clr.l           %d1                     # clear top word
10917         mov.w           FTEMP_EX(%a0), %d1      # extract exponent
10918         and.w           &0x7fff, %d1            # strip off sgn
10919
10920         cmp.w           %d0, %d1                # will denorm push exp < 0?
10921         bgt.b           unnorm_nrm_zero         # yes; denorm only until exp = 0
10922
10923 #
10924 # exponent would not go < 0. therefore, number stays normalized
10925 #
10926         sub.w           %d0, %d1                # shift exponent value
10927         mov.w           FTEMP_EX(%a0), %d0      # load old exponent
10928         and.w           &0x8000, %d0            # save old sign
10929         or.w            %d0, %d1                # {sgn,new exp}
10930         mov.w           %d1, FTEMP_EX(%a0)      # insert new exponent
10931
10932         bsr.l           norm                    # normalize UNNORM
10933
10934         mov.b           &NORM, %d0              # return new optype tag
10935         rts
10936
10937 #
10938 # exponent would go < 0, so only denormalize until exp = 0
10939 #
10940 unnorm_nrm_zero:
10941         cmp.b           %d1, &32                # is exp <= 32?
10942         bgt.b           unnorm_nrm_zero_lrg     # no; go handle large exponent
10943
10944         bfextu          FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
10945         mov.l           %d0, FTEMP_HI(%a0)      # save new hi(man)
10946
10947         mov.l           FTEMP_LO(%a0), %d0      # fetch old lo(man)
10948         lsl.l           %d1, %d0                # extract new lo(man)
10949         mov.l           %d0, FTEMP_LO(%a0)      # save new lo(man)
10950
10951         and.w           &0x8000, FTEMP_EX(%a0)  # set exp = 0
10952
10953         mov.b           &DENORM, %d0            # return new optype tag
10954         rts
10955
10956 #
10957 # only mantissa bits set are in lo(man)
10958 #
10959 unnorm_nrm_zero_lrg:
10960         sub.w           &32, %d1                # adjust shft amt by 32
10961
10962         mov.l           FTEMP_LO(%a0), %d0      # fetch old lo(man)
10963         lsl.l           %d1, %d0                # left shift lo(man)
10964
10965         mov.l           %d0, FTEMP_HI(%a0)      # store new hi(man)
10966         clr.l           FTEMP_LO(%a0)           # lo(man) = 0
10967
10968         and.w           &0x8000, FTEMP_EX(%a0)  # set exp = 0
10969
10970         mov.b           &DENORM, %d0            # return new optype tag
10971         rts
10972
10973 #
10974 # whole mantissa is zero so this UNNORM is actually a zero
10975 #
10976 unnorm_zero:
10977         and.w           &0x8000, FTEMP_EX(%a0)  # force exponent to zero
10978
10979         mov.b           &ZERO, %d0              # fix optype tag
10980         rts