fplsp.s revision 1.1 1 #
2 # $NetBSD: fplsp.s,v 1.1 2000/04/14 20:24:37 is Exp $
3 #
4
5 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 # MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
7 # M68000 Hi-Performance Microprocessor Division
8 # M68060 Software Package Production Release
9 #
10 # M68060 Software Package Copyright (C) 1993, 1994, 1995, 1996 Motorola Inc.
11 # All rights reserved.
12 #
13 # THE SOFTWARE is provided on an "AS IS" basis and without warranty.
14 # To the maximum extent permitted by applicable law,
15 # MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
16 # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
17 # FOR A PARTICULAR PURPOSE and any warranty against infringement with
18 # regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
19 # and any accompanying written materials.
20 #
21 # To the maximum extent permitted by applicable law,
22 # IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
23 # (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
24 # BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
25 # ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
26 #
27 # Motorola assumes no responsibility for the maintenance and support
28 # of the SOFTWARE.
29 #
30 # You are hereby granted a copyright license to use, modify, and distribute the
31 # SOFTWARE so long as this entire notice is retained without alteration
32 # in any modified and/or redistributed versions, and that such modified
33 # versions are clearly identified as such.
34 # No licenses are granted by implication, estoppel or otherwise under any
35 # patents or trademarks of Motorola, Inc.
36 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37
38 #
39 # lfptop.s:
40 # This file is appended to the top of the 060ILSP package
41 # and contains the entry points into the package. The user, in
42 # effect, branches to one of the branch table entries located here.
43 #
44
45 bra.l _facoss_
46 short 0x0000
47 bra.l _facosd_
48 short 0x0000
49 bra.l _facosx_
50 short 0x0000
51
52 bra.l _fasins_
53 short 0x0000
54 bra.l _fasind_
55 short 0x0000
56 bra.l _fasinx_
57 short 0x0000
58
59 bra.l _fatans_
60 short 0x0000
61 bra.l _fatand_
62 short 0x0000
63 bra.l _fatanx_
64 short 0x0000
65
66 bra.l _fatanhs_
67 short 0x0000
68 bra.l _fatanhd_
69 short 0x0000
70 bra.l _fatanhx_
71 short 0x0000
72
73 bra.l _fcoss_
74 short 0x0000
75 bra.l _fcosd_
76 short 0x0000
77 bra.l _fcosx_
78 short 0x0000
79
80 bra.l _fcoshs_
81 short 0x0000
82 bra.l _fcoshd_
83 short 0x0000
84 bra.l _fcoshx_
85 short 0x0000
86
87 bra.l _fetoxs_
88 short 0x0000
89 bra.l _fetoxd_
90 short 0x0000
91 bra.l _fetoxx_
92 short 0x0000
93
94 bra.l _fetoxm1s_
95 short 0x0000
96 bra.l _fetoxm1d_
97 short 0x0000
98 bra.l _fetoxm1x_
99 short 0x0000
100
101 bra.l _fgetexps_
102 short 0x0000
103 bra.l _fgetexpd_
104 short 0x0000
105 bra.l _fgetexpx_
106 short 0x0000
107
108 bra.l _fgetmans_
109 short 0x0000
110 bra.l _fgetmand_
111 short 0x0000
112 bra.l _fgetmanx_
113 short 0x0000
114
115 bra.l _flog10s_
116 short 0x0000
117 bra.l _flog10d_
118 short 0x0000
119 bra.l _flog10x_
120 short 0x0000
121
122 bra.l _flog2s_
123 short 0x0000
124 bra.l _flog2d_
125 short 0x0000
126 bra.l _flog2x_
127 short 0x0000
128
129 bra.l _flogns_
130 short 0x0000
131 bra.l _flognd_
132 short 0x0000
133 bra.l _flognx_
134 short 0x0000
135
136 bra.l _flognp1s_
137 short 0x0000
138 bra.l _flognp1d_
139 short 0x0000
140 bra.l _flognp1x_
141 short 0x0000
142
143 bra.l _fmods_
144 short 0x0000
145 bra.l _fmodd_
146 short 0x0000
147 bra.l _fmodx_
148 short 0x0000
149
150 bra.l _frems_
151 short 0x0000
152 bra.l _fremd_
153 short 0x0000
154 bra.l _fremx_
155 short 0x0000
156
157 bra.l _fscales_
158 short 0x0000
159 bra.l _fscaled_
160 short 0x0000
161 bra.l _fscalex_
162 short 0x0000
163
164 bra.l _fsins_
165 short 0x0000
166 bra.l _fsind_
167 short 0x0000
168 bra.l _fsinx_
169 short 0x0000
170
171 bra.l _fsincoss_
172 short 0x0000
173 bra.l _fsincosd_
174 short 0x0000
175 bra.l _fsincosx_
176 short 0x0000
177
178 bra.l _fsinhs_
179 short 0x0000
180 bra.l _fsinhd_
181 short 0x0000
182 bra.l _fsinhx_
183 short 0x0000
184
185 bra.l _ftans_
186 short 0x0000
187 bra.l _ftand_
188 short 0x0000
189 bra.l _ftanx_
190 short 0x0000
191
192 bra.l _ftanhs_
193 short 0x0000
194 bra.l _ftanhd_
195 short 0x0000
196 bra.l _ftanhx_
197 short 0x0000
198
199 bra.l _ftentoxs_
200 short 0x0000
201 bra.l _ftentoxd_
202 short 0x0000
203 bra.l _ftentoxx_
204 short 0x0000
205
206 bra.l _ftwotoxs_
207 short 0x0000
208 bra.l _ftwotoxd_
209 short 0x0000
210 bra.l _ftwotoxx_
211 short 0x0000
212
213 bra.l _fabss_
214 short 0x0000
215 bra.l _fabsd_
216 short 0x0000
217 bra.l _fabsx_
218 short 0x0000
219
220 bra.l _fadds_
221 short 0x0000
222 bra.l _faddd_
223 short 0x0000
224 bra.l _faddx_
225 short 0x0000
226
227 bra.l _fdivs_
228 short 0x0000
229 bra.l _fdivd_
230 short 0x0000
231 bra.l _fdivx_
232 short 0x0000
233
234 bra.l _fints_
235 short 0x0000
236 bra.l _fintd_
237 short 0x0000
238 bra.l _fintx_
239 short 0x0000
240
241 bra.l _fintrzs_
242 short 0x0000
243 bra.l _fintrzd_
244 short 0x0000
245 bra.l _fintrzx_
246 short 0x0000
247
248 bra.l _fmuls_
249 short 0x0000
250 bra.l _fmuld_
251 short 0x0000
252 bra.l _fmulx_
253 short 0x0000
254
255 bra.l _fnegs_
256 short 0x0000
257 bra.l _fnegd_
258 short 0x0000
259 bra.l _fnegx_
260 short 0x0000
261
262 bra.l _fsqrts_
263 short 0x0000
264 bra.l _fsqrtd_
265 short 0x0000
266 bra.l _fsqrtx_
267 short 0x0000
268
269 bra.l _fsubs_
270 short 0x0000
271 bra.l _fsubd_
272 short 0x0000
273 bra.l _fsubx_
274 short 0x0000
275
276 # leave room for future possible additions
277 align 0x400
278
279 #
280 # This file contains a set of define statements for constants
281 # in order to promote readability within the corecode itself.
282 #
283
284 set LOCAL_SIZE, 192 # stack frame size(bytes)
285 set LV, -LOCAL_SIZE # stack offset
286
287 set EXC_SR, 0x4 # stack status register
288 set EXC_PC, 0x6 # stack pc
289 set EXC_VOFF, 0xa # stacked vector offset
290 set EXC_EA, 0xc # stacked <ea>
291
292 set EXC_FP, 0x0 # frame pointer
293
294 set EXC_AREGS, -68 # offset of all address regs
295 set EXC_DREGS, -100 # offset of all data regs
296 set EXC_FPREGS, -36 # offset of all fp regs
297
298 set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
299 set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
300 set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
301 set EXC_A5, EXC_AREGS+(5*4)
302 set EXC_A4, EXC_AREGS+(4*4)
303 set EXC_A3, EXC_AREGS+(3*4)
304 set EXC_A2, EXC_AREGS+(2*4)
305 set EXC_A1, EXC_AREGS+(1*4)
306 set EXC_A0, EXC_AREGS+(0*4)
307 set EXC_D7, EXC_DREGS+(7*4)
308 set EXC_D6, EXC_DREGS+(6*4)
309 set EXC_D5, EXC_DREGS+(5*4)
310 set EXC_D4, EXC_DREGS+(4*4)
311 set EXC_D3, EXC_DREGS+(3*4)
312 set EXC_D2, EXC_DREGS+(2*4)
313 set EXC_D1, EXC_DREGS+(1*4)
314 set EXC_D0, EXC_DREGS+(0*4)
315
316 set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
317 set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
318 set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
319
320 set FP_SCR1, LV+80 # fp scratch 1
321 set FP_SCR1_EX, FP_SCR1+0
322 set FP_SCR1_SGN, FP_SCR1+2
323 set FP_SCR1_HI, FP_SCR1+4
324 set FP_SCR1_LO, FP_SCR1+8
325
326 set FP_SCR0, LV+68 # fp scratch 0
327 set FP_SCR0_EX, FP_SCR0+0
328 set FP_SCR0_SGN, FP_SCR0+2
329 set FP_SCR0_HI, FP_SCR0+4
330 set FP_SCR0_LO, FP_SCR0+8
331
332 set FP_DST, LV+56 # fp destination operand
333 set FP_DST_EX, FP_DST+0
334 set FP_DST_SGN, FP_DST+2
335 set FP_DST_HI, FP_DST+4
336 set FP_DST_LO, FP_DST+8
337
338 set FP_SRC, LV+44 # fp source operand
339 set FP_SRC_EX, FP_SRC+0
340 set FP_SRC_SGN, FP_SRC+2
341 set FP_SRC_HI, FP_SRC+4
342 set FP_SRC_LO, FP_SRC+8
343
344 set USER_FPIAR, LV+40 # FP instr address register
345
346 set USER_FPSR, LV+36 # FP status register
347 set FPSR_CC, USER_FPSR+0 # FPSR condition codes
348 set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
349 set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
350 set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
351
352 set USER_FPCR, LV+32 # FP control register
353 set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
354 set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
355
356 set L_SCR3, LV+28 # integer scratch 3
357 set L_SCR2, LV+24 # integer scratch 2
358 set L_SCR1, LV+20 # integer scratch 1
359
360 set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
361
362 set EXC_TEMP2, LV+24 # temporary space
363 set EXC_TEMP, LV+16 # temporary space
364
365 set DTAG, LV+15 # destination operand type
366 set STAG, LV+14 # source operand type
367
368 set SPCOND_FLG, LV+10 # flag: special case (see below)
369
370 set EXC_CC, LV+8 # saved condition codes
371 set EXC_EXTWPTR, LV+4 # saved current PC (active)
372 set EXC_EXTWORD, LV+2 # saved extension word
373 set EXC_CMDREG, LV+2 # saved extension word
374 set EXC_OPWORD, LV+0 # saved operation word
375
376 ################################
377
378 # Helpful macros
379
380 set FTEMP, 0 # offsets within an
381 set FTEMP_EX, 0 # extended precision
382 set FTEMP_SGN, 2 # value saved in memory.
383 set FTEMP_HI, 4
384 set FTEMP_LO, 8
385 set FTEMP_GRS, 12
386
387 set LOCAL, 0 # offsets within an
388 set LOCAL_EX, 0 # extended precision
389 set LOCAL_SGN, 2 # value saved in memory.
390 set LOCAL_HI, 4
391 set LOCAL_LO, 8
392 set LOCAL_GRS, 12
393
394 set DST, 0 # offsets within an
395 set DST_EX, 0 # extended precision
396 set DST_HI, 4 # value saved in memory.
397 set DST_LO, 8
398
399 set SRC, 0 # offsets within an
400 set SRC_EX, 0 # extended precision
401 set SRC_HI, 4 # value saved in memory.
402 set SRC_LO, 8
403
404 set SGL_LO, 0x3f81 # min sgl prec exponent
405 set SGL_HI, 0x407e # max sgl prec exponent
406 set DBL_LO, 0x3c01 # min dbl prec exponent
407 set DBL_HI, 0x43fe # max dbl prec exponent
408 set EXT_LO, 0x0 # min ext prec exponent
409 set EXT_HI, 0x7ffe # max ext prec exponent
410
411 set EXT_BIAS, 0x3fff # extended precision bias
412 set SGL_BIAS, 0x007f # single precision bias
413 set DBL_BIAS, 0x03ff # double precision bias
414
415 set NORM, 0x00 # operand type for STAG/DTAG
416 set ZERO, 0x01 # operand type for STAG/DTAG
417 set INF, 0x02 # operand type for STAG/DTAG
418 set QNAN, 0x03 # operand type for STAG/DTAG
419 set DENORM, 0x04 # operand type for STAG/DTAG
420 set SNAN, 0x05 # operand type for STAG/DTAG
421 set UNNORM, 0x06 # operand type for STAG/DTAG
422
423 ##################
424 # FPSR/FPCR bits #
425 ##################
426 set neg_bit, 0x3 # negative result
427 set z_bit, 0x2 # zero result
428 set inf_bit, 0x1 # infinite result
429 set nan_bit, 0x0 # NAN result
430
431 set q_sn_bit, 0x7 # sign bit of quotient byte
432
433 set bsun_bit, 7 # branch on unordered
434 set snan_bit, 6 # signalling NAN
435 set operr_bit, 5 # operand error
436 set ovfl_bit, 4 # overflow
437 set unfl_bit, 3 # underflow
438 set dz_bit, 2 # divide by zero
439 set inex2_bit, 1 # inexact result 2
440 set inex1_bit, 0 # inexact result 1
441
442 set aiop_bit, 7 # accrued inexact operation bit
443 set aovfl_bit, 6 # accrued overflow bit
444 set aunfl_bit, 5 # accrued underflow bit
445 set adz_bit, 4 # accrued dz bit
446 set ainex_bit, 3 # accrued inexact bit
447
448 #############################
449 # FPSR individual bit masks #
450 #############################
451 set neg_mask, 0x08000000 # negative bit mask (lw)
452 set inf_mask, 0x02000000 # infinity bit mask (lw)
453 set z_mask, 0x04000000 # zero bit mask (lw)
454 set nan_mask, 0x01000000 # nan bit mask (lw)
455
456 set neg_bmask, 0x08 # negative bit mask (byte)
457 set inf_bmask, 0x02 # infinity bit mask (byte)
458 set z_bmask, 0x04 # zero bit mask (byte)
459 set nan_bmask, 0x01 # nan bit mask (byte)
460
461 set bsun_mask, 0x00008000 # bsun exception mask
462 set snan_mask, 0x00004000 # snan exception mask
463 set operr_mask, 0x00002000 # operr exception mask
464 set ovfl_mask, 0x00001000 # overflow exception mask
465 set unfl_mask, 0x00000800 # underflow exception mask
466 set dz_mask, 0x00000400 # dz exception mask
467 set inex2_mask, 0x00000200 # inex2 exception mask
468 set inex1_mask, 0x00000100 # inex1 exception mask
469
470 set aiop_mask, 0x00000080 # accrued illegal operation
471 set aovfl_mask, 0x00000040 # accrued overflow
472 set aunfl_mask, 0x00000020 # accrued underflow
473 set adz_mask, 0x00000010 # accrued divide by zero
474 set ainex_mask, 0x00000008 # accrued inexact
475
476 ######################################
477 # FPSR combinations used in the FPSP #
478 ######################################
479 set dzinf_mask, inf_mask+dz_mask+adz_mask
480 set opnan_mask, nan_mask+operr_mask+aiop_mask
481 set nzi_mask, 0x01ffffff #clears N, Z, and I
482 set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
483 set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
484 set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
485 set inx1a_mask, inex1_mask+ainex_mask
486 set inx2a_mask, inex2_mask+ainex_mask
487 set snaniop_mask, nan_mask+snan_mask+aiop_mask
488 set snaniop2_mask, snan_mask+aiop_mask
489 set naniop_mask, nan_mask+aiop_mask
490 set neginf_mask, neg_mask+inf_mask
491 set infaiop_mask, inf_mask+aiop_mask
492 set negz_mask, neg_mask+z_mask
493 set opaop_mask, operr_mask+aiop_mask
494 set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
495 set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
496
497 #########
498 # misc. #
499 #########
500 set rnd_stky_bit, 29 # stky bit pos in longword
501
502 set sign_bit, 0x7 # sign bit
503 set signan_bit, 0x6 # signalling nan bit
504
505 set sgl_thresh, 0x3f81 # minimum sgl exponent
506 set dbl_thresh, 0x3c01 # minimum dbl exponent
507
508 set x_mode, 0x0 # extended precision
509 set s_mode, 0x4 # single precision
510 set d_mode, 0x8 # double precision
511
512 set rn_mode, 0x0 # round-to-nearest
513 set rz_mode, 0x1 # round-to-zero
514 set rm_mode, 0x2 # round-tp-minus-infinity
515 set rp_mode, 0x3 # round-to-plus-infinity
516
517 set mantissalen, 64 # length of mantissa in bits
518
519 set BYTE, 1 # len(byte) == 1 byte
520 set WORD, 2 # len(word) == 2 bytes
521 set LONG, 4 # len(longword) == 2 bytes
522
523 set BSUN_VEC, 0xc0 # bsun vector offset
524 set INEX_VEC, 0xc4 # inexact vector offset
525 set DZ_VEC, 0xc8 # dz vector offset
526 set UNFL_VEC, 0xcc # unfl vector offset
527 set OPERR_VEC, 0xd0 # operr vector offset
528 set OVFL_VEC, 0xd4 # ovfl vector offset
529 set SNAN_VEC, 0xd8 # snan vector offset
530
531 ###########################
532 # SPecial CONDition FLaGs #
533 ###########################
534 set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
535 set fbsun_flg, 0x02 # flag bit: bsun exception
536 set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
537 set mda7_flg, 0x08 # flag bit: -(a7) <ea>
538 set fmovm_flg, 0x40 # flag bit: fmovm instruction
539 set immed_flg, 0x80 # flag bit: &<data> <ea>
540
541 set ftrapcc_bit, 0x0
542 set fbsun_bit, 0x1
543 set mia7_bit, 0x2
544 set mda7_bit, 0x3
545 set immed_bit, 0x7
546
547 ##################################
548 # TRANSCENDENTAL "LAST-OP" FLAGS #
549 ##################################
550 set FMUL_OP, 0x0 # fmul instr performed last
551 set FDIV_OP, 0x1 # fdiv performed last
552 set FADD_OP, 0x2 # fadd performed last
553 set FMOV_OP, 0x3 # fmov performed last
554
555 #############
556 # CONSTANTS #
557 #############
558 T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
559 T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
560
561 PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
562 PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
563
564 TWOBYPI:
565 long 0x3FE45F30,0x6DC9C883
566
567 #########################################################################
568 # MONADIC TEMPLATE #
569 #########################################################################
570 global _fsins_
571 _fsins_:
572 link %a6,&-LOCAL_SIZE
573
574 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
575 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
576 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
577
578 fmov.l &0x0,%fpcr # zero FPCR
579
580 #
581 # copy, convert, and tag input argument
582 #
583 fmov.s 0x8(%a6),%fp0 # load sgl input
584 fmov.x %fp0,FP_SRC(%a6)
585 lea FP_SRC(%a6),%a0
586 bsr.l tag # fetch operand type
587 mov.b %d0,STAG(%a6)
588 mov.b %d0,%d1
589
590 andi.l &0x00ff00ff,USER_FPSR(%a6)
591
592 clr.l %d0
593 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
594
595 tst.b %d1
596 bne.b _L0_2s
597 bsr.l ssin # operand is a NORM
598 bra.b _L0_6s
599 _L0_2s:
600 cmpi.b %d1,&ZERO # is operand a ZERO?
601 bne.b _L0_3s # no
602 bsr.l src_zero # yes
603 bra.b _L0_6s
604 _L0_3s:
605 cmpi.b %d1,&INF # is operand an INF?
606 bne.b _L0_4s # no
607 bsr.l t_operr # yes
608 bra.b _L0_6s
609 _L0_4s:
610 cmpi.b %d1,&QNAN # is operand a QNAN?
611 bne.b _L0_5s # no
612 bsr.l src_qnan # yes
613 bra.b _L0_6s
614 _L0_5s:
615 bsr.l ssind # operand is a DENORM
616 _L0_6s:
617
618 #
619 # Result is now in FP0
620 #
621 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
622 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
623 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
624 unlk %a6
625 rts
626
627 global _fsind_
628 _fsind_:
629 link %a6,&-LOCAL_SIZE
630
631 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
632 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
633 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
634
635 fmov.l &0x0,%fpcr # zero FPCR
636
637 #
638 # copy, convert, and tag input argument
639 #
640 fmov.d 0x8(%a6),%fp0 # load dbl input
641 fmov.x %fp0,FP_SRC(%a6)
642 lea FP_SRC(%a6),%a0
643 bsr.l tag # fetch operand type
644 mov.b %d0,STAG(%a6)
645 mov.b %d0,%d1
646
647 andi.l &0x00ff00ff,USER_FPSR(%a6)
648
649 clr.l %d0
650 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
651
652 mov.b %d1,STAG(%a6)
653 tst.b %d1
654 bne.b _L0_2d
655 bsr.l ssin # operand is a NORM
656 bra.b _L0_6d
657 _L0_2d:
658 cmpi.b %d1,&ZERO # is operand a ZERO?
659 bne.b _L0_3d # no
660 bsr.l src_zero # yes
661 bra.b _L0_6d
662 _L0_3d:
663 cmpi.b %d1,&INF # is operand an INF?
664 bne.b _L0_4d # no
665 bsr.l t_operr # yes
666 bra.b _L0_6d
667 _L0_4d:
668 cmpi.b %d1,&QNAN # is operand a QNAN?
669 bne.b _L0_5d # no
670 bsr.l src_qnan # yes
671 bra.b _L0_6d
672 _L0_5d:
673 bsr.l ssind # operand is a DENORM
674 _L0_6d:
675
676 #
677 # Result is now in FP0
678 #
679 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
680 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
681 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
682 unlk %a6
683 rts
684
685 global _fsinx_
686 _fsinx_:
687 link %a6,&-LOCAL_SIZE
688
689 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
690 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
691 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
692
693 fmov.l &0x0,%fpcr # zero FPCR
694
695 #
696 # copy, convert, and tag input argument
697 #
698 lea FP_SRC(%a6),%a0
699 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
700 mov.l 0x8+0x4(%a6),0x4(%a0)
701 mov.l 0x8+0x8(%a6),0x8(%a0)
702 bsr.l tag # fetch operand type
703 mov.b %d0,STAG(%a6)
704 mov.b %d0,%d1
705
706 andi.l &0x00ff00ff,USER_FPSR(%a6)
707
708 clr.l %d0
709 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
710
711 tst.b %d1
712 bne.b _L0_2x
713 bsr.l ssin # operand is a NORM
714 bra.b _L0_6x
715 _L0_2x:
716 cmpi.b %d1,&ZERO # is operand a ZERO?
717 bne.b _L0_3x # no
718 bsr.l src_zero # yes
719 bra.b _L0_6x
720 _L0_3x:
721 cmpi.b %d1,&INF # is operand an INF?
722 bne.b _L0_4x # no
723 bsr.l t_operr # yes
724 bra.b _L0_6x
725 _L0_4x:
726 cmpi.b %d1,&QNAN # is operand a QNAN?
727 bne.b _L0_5x # no
728 bsr.l src_qnan # yes
729 bra.b _L0_6x
730 _L0_5x:
731 bsr.l ssind # operand is a DENORM
732 _L0_6x:
733
734 #
735 # Result is now in FP0
736 #
737 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
738 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
739 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
740 unlk %a6
741 rts
742
743
744 #########################################################################
745 # MONADIC TEMPLATE #
746 #########################################################################
747 global _fcoss_
748 _fcoss_:
749 link %a6,&-LOCAL_SIZE
750
751 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
752 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
753 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
754
755 fmov.l &0x0,%fpcr # zero FPCR
756
757 #
758 # copy, convert, and tag input argument
759 #
760 fmov.s 0x8(%a6),%fp0 # load sgl input
761 fmov.x %fp0,FP_SRC(%a6)
762 lea FP_SRC(%a6),%a0
763 bsr.l tag # fetch operand type
764 mov.b %d0,STAG(%a6)
765 mov.b %d0,%d1
766
767 andi.l &0x00ff00ff,USER_FPSR(%a6)
768
769 clr.l %d0
770 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
771
772 tst.b %d1
773 bne.b _L1_2s
774 bsr.l scos # operand is a NORM
775 bra.b _L1_6s
776 _L1_2s:
777 cmpi.b %d1,&ZERO # is operand a ZERO?
778 bne.b _L1_3s # no
779 bsr.l ld_pone # yes
780 bra.b _L1_6s
781 _L1_3s:
782 cmpi.b %d1,&INF # is operand an INF?
783 bne.b _L1_4s # no
784 bsr.l t_operr # yes
785 bra.b _L1_6s
786 _L1_4s:
787 cmpi.b %d1,&QNAN # is operand a QNAN?
788 bne.b _L1_5s # no
789 bsr.l src_qnan # yes
790 bra.b _L1_6s
791 _L1_5s:
792 bsr.l scosd # operand is a DENORM
793 _L1_6s:
794
795 #
796 # Result is now in FP0
797 #
798 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
799 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
800 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
801 unlk %a6
802 rts
803
804 global _fcosd_
805 _fcosd_:
806 link %a6,&-LOCAL_SIZE
807
808 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
809 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
810 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
811
812 fmov.l &0x0,%fpcr # zero FPCR
813
814 #
815 # copy, convert, and tag input argument
816 #
817 fmov.d 0x8(%a6),%fp0 # load dbl input
818 fmov.x %fp0,FP_SRC(%a6)
819 lea FP_SRC(%a6),%a0
820 bsr.l tag # fetch operand type
821 mov.b %d0,STAG(%a6)
822 mov.b %d0,%d1
823
824 andi.l &0x00ff00ff,USER_FPSR(%a6)
825
826 clr.l %d0
827 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
828
829 mov.b %d1,STAG(%a6)
830 tst.b %d1
831 bne.b _L1_2d
832 bsr.l scos # operand is a NORM
833 bra.b _L1_6d
834 _L1_2d:
835 cmpi.b %d1,&ZERO # is operand a ZERO?
836 bne.b _L1_3d # no
837 bsr.l ld_pone # yes
838 bra.b _L1_6d
839 _L1_3d:
840 cmpi.b %d1,&INF # is operand an INF?
841 bne.b _L1_4d # no
842 bsr.l t_operr # yes
843 bra.b _L1_6d
844 _L1_4d:
845 cmpi.b %d1,&QNAN # is operand a QNAN?
846 bne.b _L1_5d # no
847 bsr.l src_qnan # yes
848 bra.b _L1_6d
849 _L1_5d:
850 bsr.l scosd # operand is a DENORM
851 _L1_6d:
852
853 #
854 # Result is now in FP0
855 #
856 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
857 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
858 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
859 unlk %a6
860 rts
861
862 global _fcosx_
863 _fcosx_:
864 link %a6,&-LOCAL_SIZE
865
866 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
867 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
868 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
869
870 fmov.l &0x0,%fpcr # zero FPCR
871
872 #
873 # copy, convert, and tag input argument
874 #
875 lea FP_SRC(%a6),%a0
876 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
877 mov.l 0x8+0x4(%a6),0x4(%a0)
878 mov.l 0x8+0x8(%a6),0x8(%a0)
879 bsr.l tag # fetch operand type
880 mov.b %d0,STAG(%a6)
881 mov.b %d0,%d1
882
883 andi.l &0x00ff00ff,USER_FPSR(%a6)
884
885 clr.l %d0
886 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
887
888 tst.b %d1
889 bne.b _L1_2x
890 bsr.l scos # operand is a NORM
891 bra.b _L1_6x
892 _L1_2x:
893 cmpi.b %d1,&ZERO # is operand a ZERO?
894 bne.b _L1_3x # no
895 bsr.l ld_pone # yes
896 bra.b _L1_6x
897 _L1_3x:
898 cmpi.b %d1,&INF # is operand an INF?
899 bne.b _L1_4x # no
900 bsr.l t_operr # yes
901 bra.b _L1_6x
902 _L1_4x:
903 cmpi.b %d1,&QNAN # is operand a QNAN?
904 bne.b _L1_5x # no
905 bsr.l src_qnan # yes
906 bra.b _L1_6x
907 _L1_5x:
908 bsr.l scosd # operand is a DENORM
909 _L1_6x:
910
911 #
912 # Result is now in FP0
913 #
914 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
915 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
916 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
917 unlk %a6
918 rts
919
920
921 #########################################################################
922 # MONADIC TEMPLATE #
923 #########################################################################
924 global _fsinhs_
925 _fsinhs_:
926 link %a6,&-LOCAL_SIZE
927
928 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
929 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
930 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
931
932 fmov.l &0x0,%fpcr # zero FPCR
933
934 #
935 # copy, convert, and tag input argument
936 #
937 fmov.s 0x8(%a6),%fp0 # load sgl input
938 fmov.x %fp0,FP_SRC(%a6)
939 lea FP_SRC(%a6),%a0
940 bsr.l tag # fetch operand type
941 mov.b %d0,STAG(%a6)
942 mov.b %d0,%d1
943
944 andi.l &0x00ff00ff,USER_FPSR(%a6)
945
946 clr.l %d0
947 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
948
949 tst.b %d1
950 bne.b _L2_2s
951 bsr.l ssinh # operand is a NORM
952 bra.b _L2_6s
953 _L2_2s:
954 cmpi.b %d1,&ZERO # is operand a ZERO?
955 bne.b _L2_3s # no
956 bsr.l src_zero # yes
957 bra.b _L2_6s
958 _L2_3s:
959 cmpi.b %d1,&INF # is operand an INF?
960 bne.b _L2_4s # no
961 bsr.l src_inf # yes
962 bra.b _L2_6s
963 _L2_4s:
964 cmpi.b %d1,&QNAN # is operand a QNAN?
965 bne.b _L2_5s # no
966 bsr.l src_qnan # yes
967 bra.b _L2_6s
968 _L2_5s:
969 bsr.l ssinhd # operand is a DENORM
970 _L2_6s:
971
972 #
973 # Result is now in FP0
974 #
975 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
976 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
977 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
978 unlk %a6
979 rts
980
981 global _fsinhd_
982 _fsinhd_:
983 link %a6,&-LOCAL_SIZE
984
985 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
986 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
987 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
988
989 fmov.l &0x0,%fpcr # zero FPCR
990
991 #
992 # copy, convert, and tag input argument
993 #
994 fmov.d 0x8(%a6),%fp0 # load dbl input
995 fmov.x %fp0,FP_SRC(%a6)
996 lea FP_SRC(%a6),%a0
997 bsr.l tag # fetch operand type
998 mov.b %d0,STAG(%a6)
999 mov.b %d0,%d1
1000
1001 andi.l &0x00ff00ff,USER_FPSR(%a6)
1002
1003 clr.l %d0
1004 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1005
1006 mov.b %d1,STAG(%a6)
1007 tst.b %d1
1008 bne.b _L2_2d
1009 bsr.l ssinh # operand is a NORM
1010 bra.b _L2_6d
1011 _L2_2d:
1012 cmpi.b %d1,&ZERO # is operand a ZERO?
1013 bne.b _L2_3d # no
1014 bsr.l src_zero # yes
1015 bra.b _L2_6d
1016 _L2_3d:
1017 cmpi.b %d1,&INF # is operand an INF?
1018 bne.b _L2_4d # no
1019 bsr.l src_inf # yes
1020 bra.b _L2_6d
1021 _L2_4d:
1022 cmpi.b %d1,&QNAN # is operand a QNAN?
1023 bne.b _L2_5d # no
1024 bsr.l src_qnan # yes
1025 bra.b _L2_6d
1026 _L2_5d:
1027 bsr.l ssinhd # operand is a DENORM
1028 _L2_6d:
1029
1030 #
1031 # Result is now in FP0
1032 #
1033 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1034 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1035 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1036 unlk %a6
1037 rts
1038
1039 global _fsinhx_
1040 _fsinhx_:
1041 link %a6,&-LOCAL_SIZE
1042
1043 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1044 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1045 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1046
1047 fmov.l &0x0,%fpcr # zero FPCR
1048
1049 #
1050 # copy, convert, and tag input argument
1051 #
1052 lea FP_SRC(%a6),%a0
1053 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1054 mov.l 0x8+0x4(%a6),0x4(%a0)
1055 mov.l 0x8+0x8(%a6),0x8(%a0)
1056 bsr.l tag # fetch operand type
1057 mov.b %d0,STAG(%a6)
1058 mov.b %d0,%d1
1059
1060 andi.l &0x00ff00ff,USER_FPSR(%a6)
1061
1062 clr.l %d0
1063 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1064
1065 tst.b %d1
1066 bne.b _L2_2x
1067 bsr.l ssinh # operand is a NORM
1068 bra.b _L2_6x
1069 _L2_2x:
1070 cmpi.b %d1,&ZERO # is operand a ZERO?
1071 bne.b _L2_3x # no
1072 bsr.l src_zero # yes
1073 bra.b _L2_6x
1074 _L2_3x:
1075 cmpi.b %d1,&INF # is operand an INF?
1076 bne.b _L2_4x # no
1077 bsr.l src_inf # yes
1078 bra.b _L2_6x
1079 _L2_4x:
1080 cmpi.b %d1,&QNAN # is operand a QNAN?
1081 bne.b _L2_5x # no
1082 bsr.l src_qnan # yes
1083 bra.b _L2_6x
1084 _L2_5x:
1085 bsr.l ssinhd # operand is a DENORM
1086 _L2_6x:
1087
1088 #
1089 # Result is now in FP0
1090 #
1091 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1092 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1093 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1094 unlk %a6
1095 rts
1096
1097
1098 #########################################################################
1099 # MONADIC TEMPLATE #
1100 #########################################################################
1101 global _flognp1s_
1102 _flognp1s_:
1103 link %a6,&-LOCAL_SIZE
1104
1105 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1106 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1107 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1108
1109 fmov.l &0x0,%fpcr # zero FPCR
1110
1111 #
1112 # copy, convert, and tag input argument
1113 #
1114 fmov.s 0x8(%a6),%fp0 # load sgl input
1115 fmov.x %fp0,FP_SRC(%a6)
1116 lea FP_SRC(%a6),%a0
1117 bsr.l tag # fetch operand type
1118 mov.b %d0,STAG(%a6)
1119 mov.b %d0,%d1
1120
1121 andi.l &0x00ff00ff,USER_FPSR(%a6)
1122
1123 clr.l %d0
1124 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1125
1126 tst.b %d1
1127 bne.b _L3_2s
1128 bsr.l slognp1 # operand is a NORM
1129 bra.b _L3_6s
1130 _L3_2s:
1131 cmpi.b %d1,&ZERO # is operand a ZERO?
1132 bne.b _L3_3s # no
1133 bsr.l src_zero # yes
1134 bra.b _L3_6s
1135 _L3_3s:
1136 cmpi.b %d1,&INF # is operand an INF?
1137 bne.b _L3_4s # no
1138 bsr.l sopr_inf # yes
1139 bra.b _L3_6s
1140 _L3_4s:
1141 cmpi.b %d1,&QNAN # is operand a QNAN?
1142 bne.b _L3_5s # no
1143 bsr.l src_qnan # yes
1144 bra.b _L3_6s
1145 _L3_5s:
1146 bsr.l slognp1d # operand is a DENORM
1147 _L3_6s:
1148
1149 #
1150 # Result is now in FP0
1151 #
1152 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1153 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1154 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1155 unlk %a6
1156 rts
1157
1158 global _flognp1d_
1159 _flognp1d_:
1160 link %a6,&-LOCAL_SIZE
1161
1162 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1163 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1164 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1165
1166 fmov.l &0x0,%fpcr # zero FPCR
1167
1168 #
1169 # copy, convert, and tag input argument
1170 #
1171 fmov.d 0x8(%a6),%fp0 # load dbl input
1172 fmov.x %fp0,FP_SRC(%a6)
1173 lea FP_SRC(%a6),%a0
1174 bsr.l tag # fetch operand type
1175 mov.b %d0,STAG(%a6)
1176 mov.b %d0,%d1
1177
1178 andi.l &0x00ff00ff,USER_FPSR(%a6)
1179
1180 clr.l %d0
1181 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1182
1183 mov.b %d1,STAG(%a6)
1184 tst.b %d1
1185 bne.b _L3_2d
1186 bsr.l slognp1 # operand is a NORM
1187 bra.b _L3_6d
1188 _L3_2d:
1189 cmpi.b %d1,&ZERO # is operand a ZERO?
1190 bne.b _L3_3d # no
1191 bsr.l src_zero # yes
1192 bra.b _L3_6d
1193 _L3_3d:
1194 cmpi.b %d1,&INF # is operand an INF?
1195 bne.b _L3_4d # no
1196 bsr.l sopr_inf # yes
1197 bra.b _L3_6d
1198 _L3_4d:
1199 cmpi.b %d1,&QNAN # is operand a QNAN?
1200 bne.b _L3_5d # no
1201 bsr.l src_qnan # yes
1202 bra.b _L3_6d
1203 _L3_5d:
1204 bsr.l slognp1d # operand is a DENORM
1205 _L3_6d:
1206
1207 #
1208 # Result is now in FP0
1209 #
1210 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1211 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1212 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1213 unlk %a6
1214 rts
1215
1216 global _flognp1x_
1217 _flognp1x_:
1218 link %a6,&-LOCAL_SIZE
1219
1220 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1221 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1222 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1223
1224 fmov.l &0x0,%fpcr # zero FPCR
1225
1226 #
1227 # copy, convert, and tag input argument
1228 #
1229 lea FP_SRC(%a6),%a0
1230 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1231 mov.l 0x8+0x4(%a6),0x4(%a0)
1232 mov.l 0x8+0x8(%a6),0x8(%a0)
1233 bsr.l tag # fetch operand type
1234 mov.b %d0,STAG(%a6)
1235 mov.b %d0,%d1
1236
1237 andi.l &0x00ff00ff,USER_FPSR(%a6)
1238
1239 clr.l %d0
1240 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1241
1242 tst.b %d1
1243 bne.b _L3_2x
1244 bsr.l slognp1 # operand is a NORM
1245 bra.b _L3_6x
1246 _L3_2x:
1247 cmpi.b %d1,&ZERO # is operand a ZERO?
1248 bne.b _L3_3x # no
1249 bsr.l src_zero # yes
1250 bra.b _L3_6x
1251 _L3_3x:
1252 cmpi.b %d1,&INF # is operand an INF?
1253 bne.b _L3_4x # no
1254 bsr.l sopr_inf # yes
1255 bra.b _L3_6x
1256 _L3_4x:
1257 cmpi.b %d1,&QNAN # is operand a QNAN?
1258 bne.b _L3_5x # no
1259 bsr.l src_qnan # yes
1260 bra.b _L3_6x
1261 _L3_5x:
1262 bsr.l slognp1d # operand is a DENORM
1263 _L3_6x:
1264
1265 #
1266 # Result is now in FP0
1267 #
1268 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1269 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1270 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1271 unlk %a6
1272 rts
1273
1274
1275 #########################################################################
1276 # MONADIC TEMPLATE #
1277 #########################################################################
1278 global _fetoxm1s_
1279 _fetoxm1s_:
1280 link %a6,&-LOCAL_SIZE
1281
1282 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1283 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1284 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1285
1286 fmov.l &0x0,%fpcr # zero FPCR
1287
1288 #
1289 # copy, convert, and tag input argument
1290 #
1291 fmov.s 0x8(%a6),%fp0 # load sgl input
1292 fmov.x %fp0,FP_SRC(%a6)
1293 lea FP_SRC(%a6),%a0
1294 bsr.l tag # fetch operand type
1295 mov.b %d0,STAG(%a6)
1296 mov.b %d0,%d1
1297
1298 andi.l &0x00ff00ff,USER_FPSR(%a6)
1299
1300 clr.l %d0
1301 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1302
1303 tst.b %d1
1304 bne.b _L4_2s
1305 bsr.l setoxm1 # operand is a NORM
1306 bra.b _L4_6s
1307 _L4_2s:
1308 cmpi.b %d1,&ZERO # is operand a ZERO?
1309 bne.b _L4_3s # no
1310 bsr.l src_zero # yes
1311 bra.b _L4_6s
1312 _L4_3s:
1313 cmpi.b %d1,&INF # is operand an INF?
1314 bne.b _L4_4s # no
1315 bsr.l setoxm1i # yes
1316 bra.b _L4_6s
1317 _L4_4s:
1318 cmpi.b %d1,&QNAN # is operand a QNAN?
1319 bne.b _L4_5s # no
1320 bsr.l src_qnan # yes
1321 bra.b _L4_6s
1322 _L4_5s:
1323 bsr.l setoxm1d # operand is a DENORM
1324 _L4_6s:
1325
1326 #
1327 # Result is now in FP0
1328 #
1329 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1330 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1331 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1332 unlk %a6
1333 rts
1334
1335 global _fetoxm1d_
1336 _fetoxm1d_:
1337 link %a6,&-LOCAL_SIZE
1338
1339 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1340 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1341 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1342
1343 fmov.l &0x0,%fpcr # zero FPCR
1344
1345 #
1346 # copy, convert, and tag input argument
1347 #
1348 fmov.d 0x8(%a6),%fp0 # load dbl input
1349 fmov.x %fp0,FP_SRC(%a6)
1350 lea FP_SRC(%a6),%a0
1351 bsr.l tag # fetch operand type
1352 mov.b %d0,STAG(%a6)
1353 mov.b %d0,%d1
1354
1355 andi.l &0x00ff00ff,USER_FPSR(%a6)
1356
1357 clr.l %d0
1358 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1359
1360 mov.b %d1,STAG(%a6)
1361 tst.b %d1
1362 bne.b _L4_2d
1363 bsr.l setoxm1 # operand is a NORM
1364 bra.b _L4_6d
1365 _L4_2d:
1366 cmpi.b %d1,&ZERO # is operand a ZERO?
1367 bne.b _L4_3d # no
1368 bsr.l src_zero # yes
1369 bra.b _L4_6d
1370 _L4_3d:
1371 cmpi.b %d1,&INF # is operand an INF?
1372 bne.b _L4_4d # no
1373 bsr.l setoxm1i # yes
1374 bra.b _L4_6d
1375 _L4_4d:
1376 cmpi.b %d1,&QNAN # is operand a QNAN?
1377 bne.b _L4_5d # no
1378 bsr.l src_qnan # yes
1379 bra.b _L4_6d
1380 _L4_5d:
1381 bsr.l setoxm1d # operand is a DENORM
1382 _L4_6d:
1383
1384 #
1385 # Result is now in FP0
1386 #
1387 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1388 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1389 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1390 unlk %a6
1391 rts
1392
1393 global _fetoxm1x_
1394 _fetoxm1x_:
1395 link %a6,&-LOCAL_SIZE
1396
1397 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1398 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1399 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1400
1401 fmov.l &0x0,%fpcr # zero FPCR
1402
1403 #
1404 # copy, convert, and tag input argument
1405 #
1406 lea FP_SRC(%a6),%a0
1407 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1408 mov.l 0x8+0x4(%a6),0x4(%a0)
1409 mov.l 0x8+0x8(%a6),0x8(%a0)
1410 bsr.l tag # fetch operand type
1411 mov.b %d0,STAG(%a6)
1412 mov.b %d0,%d1
1413
1414 andi.l &0x00ff00ff,USER_FPSR(%a6)
1415
1416 clr.l %d0
1417 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1418
1419 tst.b %d1
1420 bne.b _L4_2x
1421 bsr.l setoxm1 # operand is a NORM
1422 bra.b _L4_6x
1423 _L4_2x:
1424 cmpi.b %d1,&ZERO # is operand a ZERO?
1425 bne.b _L4_3x # no
1426 bsr.l src_zero # yes
1427 bra.b _L4_6x
1428 _L4_3x:
1429 cmpi.b %d1,&INF # is operand an INF?
1430 bne.b _L4_4x # no
1431 bsr.l setoxm1i # yes
1432 bra.b _L4_6x
1433 _L4_4x:
1434 cmpi.b %d1,&QNAN # is operand a QNAN?
1435 bne.b _L4_5x # no
1436 bsr.l src_qnan # yes
1437 bra.b _L4_6x
1438 _L4_5x:
1439 bsr.l setoxm1d # operand is a DENORM
1440 _L4_6x:
1441
1442 #
1443 # Result is now in FP0
1444 #
1445 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1446 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1447 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1448 unlk %a6
1449 rts
1450
1451
1452 #########################################################################
1453 # MONADIC TEMPLATE #
1454 #########################################################################
1455 global _ftanhs_
1456 _ftanhs_:
1457 link %a6,&-LOCAL_SIZE
1458
1459 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1460 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1461 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1462
1463 fmov.l &0x0,%fpcr # zero FPCR
1464
1465 #
1466 # copy, convert, and tag input argument
1467 #
1468 fmov.s 0x8(%a6),%fp0 # load sgl input
1469 fmov.x %fp0,FP_SRC(%a6)
1470 lea FP_SRC(%a6),%a0
1471 bsr.l tag # fetch operand type
1472 mov.b %d0,STAG(%a6)
1473 mov.b %d0,%d1
1474
1475 andi.l &0x00ff00ff,USER_FPSR(%a6)
1476
1477 clr.l %d0
1478 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1479
1480 tst.b %d1
1481 bne.b _L5_2s
1482 bsr.l stanh # operand is a NORM
1483 bra.b _L5_6s
1484 _L5_2s:
1485 cmpi.b %d1,&ZERO # is operand a ZERO?
1486 bne.b _L5_3s # no
1487 bsr.l src_zero # yes
1488 bra.b _L5_6s
1489 _L5_3s:
1490 cmpi.b %d1,&INF # is operand an INF?
1491 bne.b _L5_4s # no
1492 bsr.l src_one # yes
1493 bra.b _L5_6s
1494 _L5_4s:
1495 cmpi.b %d1,&QNAN # is operand a QNAN?
1496 bne.b _L5_5s # no
1497 bsr.l src_qnan # yes
1498 bra.b _L5_6s
1499 _L5_5s:
1500 bsr.l stanhd # operand is a DENORM
1501 _L5_6s:
1502
1503 #
1504 # Result is now in FP0
1505 #
1506 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1507 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1508 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1509 unlk %a6
1510 rts
1511
1512 global _ftanhd_
1513 _ftanhd_:
1514 link %a6,&-LOCAL_SIZE
1515
1516 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1517 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1518 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1519
1520 fmov.l &0x0,%fpcr # zero FPCR
1521
1522 #
1523 # copy, convert, and tag input argument
1524 #
1525 fmov.d 0x8(%a6),%fp0 # load dbl input
1526 fmov.x %fp0,FP_SRC(%a6)
1527 lea FP_SRC(%a6),%a0
1528 bsr.l tag # fetch operand type
1529 mov.b %d0,STAG(%a6)
1530 mov.b %d0,%d1
1531
1532 andi.l &0x00ff00ff,USER_FPSR(%a6)
1533
1534 clr.l %d0
1535 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1536
1537 mov.b %d1,STAG(%a6)
1538 tst.b %d1
1539 bne.b _L5_2d
1540 bsr.l stanh # operand is a NORM
1541 bra.b _L5_6d
1542 _L5_2d:
1543 cmpi.b %d1,&ZERO # is operand a ZERO?
1544 bne.b _L5_3d # no
1545 bsr.l src_zero # yes
1546 bra.b _L5_6d
1547 _L5_3d:
1548 cmpi.b %d1,&INF # is operand an INF?
1549 bne.b _L5_4d # no
1550 bsr.l src_one # yes
1551 bra.b _L5_6d
1552 _L5_4d:
1553 cmpi.b %d1,&QNAN # is operand a QNAN?
1554 bne.b _L5_5d # no
1555 bsr.l src_qnan # yes
1556 bra.b _L5_6d
1557 _L5_5d:
1558 bsr.l stanhd # operand is a DENORM
1559 _L5_6d:
1560
1561 #
1562 # Result is now in FP0
1563 #
1564 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1565 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1566 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1567 unlk %a6
1568 rts
1569
1570 global _ftanhx_
1571 _ftanhx_:
1572 link %a6,&-LOCAL_SIZE
1573
1574 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1575 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1576 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1577
1578 fmov.l &0x0,%fpcr # zero FPCR
1579
1580 #
1581 # copy, convert, and tag input argument
1582 #
1583 lea FP_SRC(%a6),%a0
1584 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1585 mov.l 0x8+0x4(%a6),0x4(%a0)
1586 mov.l 0x8+0x8(%a6),0x8(%a0)
1587 bsr.l tag # fetch operand type
1588 mov.b %d0,STAG(%a6)
1589 mov.b %d0,%d1
1590
1591 andi.l &0x00ff00ff,USER_FPSR(%a6)
1592
1593 clr.l %d0
1594 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1595
1596 tst.b %d1
1597 bne.b _L5_2x
1598 bsr.l stanh # operand is a NORM
1599 bra.b _L5_6x
1600 _L5_2x:
1601 cmpi.b %d1,&ZERO # is operand a ZERO?
1602 bne.b _L5_3x # no
1603 bsr.l src_zero # yes
1604 bra.b _L5_6x
1605 _L5_3x:
1606 cmpi.b %d1,&INF # is operand an INF?
1607 bne.b _L5_4x # no
1608 bsr.l src_one # yes
1609 bra.b _L5_6x
1610 _L5_4x:
1611 cmpi.b %d1,&QNAN # is operand a QNAN?
1612 bne.b _L5_5x # no
1613 bsr.l src_qnan # yes
1614 bra.b _L5_6x
1615 _L5_5x:
1616 bsr.l stanhd # operand is a DENORM
1617 _L5_6x:
1618
1619 #
1620 # Result is now in FP0
1621 #
1622 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1623 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1624 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1625 unlk %a6
1626 rts
1627
1628
1629 #########################################################################
1630 # MONADIC TEMPLATE #
1631 #########################################################################
1632 global _fatans_
1633 _fatans_:
1634 link %a6,&-LOCAL_SIZE
1635
1636 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1637 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1638 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1639
1640 fmov.l &0x0,%fpcr # zero FPCR
1641
1642 #
1643 # copy, convert, and tag input argument
1644 #
1645 fmov.s 0x8(%a6),%fp0 # load sgl input
1646 fmov.x %fp0,FP_SRC(%a6)
1647 lea FP_SRC(%a6),%a0
1648 bsr.l tag # fetch operand type
1649 mov.b %d0,STAG(%a6)
1650 mov.b %d0,%d1
1651
1652 andi.l &0x00ff00ff,USER_FPSR(%a6)
1653
1654 clr.l %d0
1655 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1656
1657 tst.b %d1
1658 bne.b _L6_2s
1659 bsr.l satan # operand is a NORM
1660 bra.b _L6_6s
1661 _L6_2s:
1662 cmpi.b %d1,&ZERO # is operand a ZERO?
1663 bne.b _L6_3s # no
1664 bsr.l src_zero # yes
1665 bra.b _L6_6s
1666 _L6_3s:
1667 cmpi.b %d1,&INF # is operand an INF?
1668 bne.b _L6_4s # no
1669 bsr.l spi_2 # yes
1670 bra.b _L6_6s
1671 _L6_4s:
1672 cmpi.b %d1,&QNAN # is operand a QNAN?
1673 bne.b _L6_5s # no
1674 bsr.l src_qnan # yes
1675 bra.b _L6_6s
1676 _L6_5s:
1677 bsr.l satand # operand is a DENORM
1678 _L6_6s:
1679
1680 #
1681 # Result is now in FP0
1682 #
1683 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1684 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1685 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1686 unlk %a6
1687 rts
1688
1689 global _fatand_
1690 _fatand_:
1691 link %a6,&-LOCAL_SIZE
1692
1693 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1694 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1695 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1696
1697 fmov.l &0x0,%fpcr # zero FPCR
1698
1699 #
1700 # copy, convert, and tag input argument
1701 #
1702 fmov.d 0x8(%a6),%fp0 # load dbl input
1703 fmov.x %fp0,FP_SRC(%a6)
1704 lea FP_SRC(%a6),%a0
1705 bsr.l tag # fetch operand type
1706 mov.b %d0,STAG(%a6)
1707 mov.b %d0,%d1
1708
1709 andi.l &0x00ff00ff,USER_FPSR(%a6)
1710
1711 clr.l %d0
1712 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1713
1714 mov.b %d1,STAG(%a6)
1715 tst.b %d1
1716 bne.b _L6_2d
1717 bsr.l satan # operand is a NORM
1718 bra.b _L6_6d
1719 _L6_2d:
1720 cmpi.b %d1,&ZERO # is operand a ZERO?
1721 bne.b _L6_3d # no
1722 bsr.l src_zero # yes
1723 bra.b _L6_6d
1724 _L6_3d:
1725 cmpi.b %d1,&INF # is operand an INF?
1726 bne.b _L6_4d # no
1727 bsr.l spi_2 # yes
1728 bra.b _L6_6d
1729 _L6_4d:
1730 cmpi.b %d1,&QNAN # is operand a QNAN?
1731 bne.b _L6_5d # no
1732 bsr.l src_qnan # yes
1733 bra.b _L6_6d
1734 _L6_5d:
1735 bsr.l satand # operand is a DENORM
1736 _L6_6d:
1737
1738 #
1739 # Result is now in FP0
1740 #
1741 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1742 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1743 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1744 unlk %a6
1745 rts
1746
1747 global _fatanx_
1748 _fatanx_:
1749 link %a6,&-LOCAL_SIZE
1750
1751 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1752 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1753 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1754
1755 fmov.l &0x0,%fpcr # zero FPCR
1756
1757 #
1758 # copy, convert, and tag input argument
1759 #
1760 lea FP_SRC(%a6),%a0
1761 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1762 mov.l 0x8+0x4(%a6),0x4(%a0)
1763 mov.l 0x8+0x8(%a6),0x8(%a0)
1764 bsr.l tag # fetch operand type
1765 mov.b %d0,STAG(%a6)
1766 mov.b %d0,%d1
1767
1768 andi.l &0x00ff00ff,USER_FPSR(%a6)
1769
1770 clr.l %d0
1771 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1772
1773 tst.b %d1
1774 bne.b _L6_2x
1775 bsr.l satan # operand is a NORM
1776 bra.b _L6_6x
1777 _L6_2x:
1778 cmpi.b %d1,&ZERO # is operand a ZERO?
1779 bne.b _L6_3x # no
1780 bsr.l src_zero # yes
1781 bra.b _L6_6x
1782 _L6_3x:
1783 cmpi.b %d1,&INF # is operand an INF?
1784 bne.b _L6_4x # no
1785 bsr.l spi_2 # yes
1786 bra.b _L6_6x
1787 _L6_4x:
1788 cmpi.b %d1,&QNAN # is operand a QNAN?
1789 bne.b _L6_5x # no
1790 bsr.l src_qnan # yes
1791 bra.b _L6_6x
1792 _L6_5x:
1793 bsr.l satand # operand is a DENORM
1794 _L6_6x:
1795
1796 #
1797 # Result is now in FP0
1798 #
1799 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1800 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1801 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1802 unlk %a6
1803 rts
1804
1805
1806 #########################################################################
1807 # MONADIC TEMPLATE #
1808 #########################################################################
1809 global _fasins_
1810 _fasins_:
1811 link %a6,&-LOCAL_SIZE
1812
1813 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1814 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1815 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1816
1817 fmov.l &0x0,%fpcr # zero FPCR
1818
1819 #
1820 # copy, convert, and tag input argument
1821 #
1822 fmov.s 0x8(%a6),%fp0 # load sgl input
1823 fmov.x %fp0,FP_SRC(%a6)
1824 lea FP_SRC(%a6),%a0
1825 bsr.l tag # fetch operand type
1826 mov.b %d0,STAG(%a6)
1827 mov.b %d0,%d1
1828
1829 andi.l &0x00ff00ff,USER_FPSR(%a6)
1830
1831 clr.l %d0
1832 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1833
1834 tst.b %d1
1835 bne.b _L7_2s
1836 bsr.l sasin # operand is a NORM
1837 bra.b _L7_6s
1838 _L7_2s:
1839 cmpi.b %d1,&ZERO # is operand a ZERO?
1840 bne.b _L7_3s # no
1841 bsr.l src_zero # yes
1842 bra.b _L7_6s
1843 _L7_3s:
1844 cmpi.b %d1,&INF # is operand an INF?
1845 bne.b _L7_4s # no
1846 bsr.l t_operr # yes
1847 bra.b _L7_6s
1848 _L7_4s:
1849 cmpi.b %d1,&QNAN # is operand a QNAN?
1850 bne.b _L7_5s # no
1851 bsr.l src_qnan # yes
1852 bra.b _L7_6s
1853 _L7_5s:
1854 bsr.l sasind # operand is a DENORM
1855 _L7_6s:
1856
1857 #
1858 # Result is now in FP0
1859 #
1860 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1861 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1862 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1863 unlk %a6
1864 rts
1865
1866 global _fasind_
1867 _fasind_:
1868 link %a6,&-LOCAL_SIZE
1869
1870 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1871 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1872 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1873
1874 fmov.l &0x0,%fpcr # zero FPCR
1875
1876 #
1877 # copy, convert, and tag input argument
1878 #
1879 fmov.d 0x8(%a6),%fp0 # load dbl input
1880 fmov.x %fp0,FP_SRC(%a6)
1881 lea FP_SRC(%a6),%a0
1882 bsr.l tag # fetch operand type
1883 mov.b %d0,STAG(%a6)
1884 mov.b %d0,%d1
1885
1886 andi.l &0x00ff00ff,USER_FPSR(%a6)
1887
1888 clr.l %d0
1889 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1890
1891 mov.b %d1,STAG(%a6)
1892 tst.b %d1
1893 bne.b _L7_2d
1894 bsr.l sasin # operand is a NORM
1895 bra.b _L7_6d
1896 _L7_2d:
1897 cmpi.b %d1,&ZERO # is operand a ZERO?
1898 bne.b _L7_3d # no
1899 bsr.l src_zero # yes
1900 bra.b _L7_6d
1901 _L7_3d:
1902 cmpi.b %d1,&INF # is operand an INF?
1903 bne.b _L7_4d # no
1904 bsr.l t_operr # yes
1905 bra.b _L7_6d
1906 _L7_4d:
1907 cmpi.b %d1,&QNAN # is operand a QNAN?
1908 bne.b _L7_5d # no
1909 bsr.l src_qnan # yes
1910 bra.b _L7_6d
1911 _L7_5d:
1912 bsr.l sasind # operand is a DENORM
1913 _L7_6d:
1914
1915 #
1916 # Result is now in FP0
1917 #
1918 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1919 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1920 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1921 unlk %a6
1922 rts
1923
1924 global _fasinx_
1925 _fasinx_:
1926 link %a6,&-LOCAL_SIZE
1927
1928 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1929 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1930 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1931
1932 fmov.l &0x0,%fpcr # zero FPCR
1933
1934 #
1935 # copy, convert, and tag input argument
1936 #
1937 lea FP_SRC(%a6),%a0
1938 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
1939 mov.l 0x8+0x4(%a6),0x4(%a0)
1940 mov.l 0x8+0x8(%a6),0x8(%a0)
1941 bsr.l tag # fetch operand type
1942 mov.b %d0,STAG(%a6)
1943 mov.b %d0,%d1
1944
1945 andi.l &0x00ff00ff,USER_FPSR(%a6)
1946
1947 clr.l %d0
1948 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
1949
1950 tst.b %d1
1951 bne.b _L7_2x
1952 bsr.l sasin # operand is a NORM
1953 bra.b _L7_6x
1954 _L7_2x:
1955 cmpi.b %d1,&ZERO # is operand a ZERO?
1956 bne.b _L7_3x # no
1957 bsr.l src_zero # yes
1958 bra.b _L7_6x
1959 _L7_3x:
1960 cmpi.b %d1,&INF # is operand an INF?
1961 bne.b _L7_4x # no
1962 bsr.l t_operr # yes
1963 bra.b _L7_6x
1964 _L7_4x:
1965 cmpi.b %d1,&QNAN # is operand a QNAN?
1966 bne.b _L7_5x # no
1967 bsr.l src_qnan # yes
1968 bra.b _L7_6x
1969 _L7_5x:
1970 bsr.l sasind # operand is a DENORM
1971 _L7_6x:
1972
1973 #
1974 # Result is now in FP0
1975 #
1976 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
1977 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
1978 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
1979 unlk %a6
1980 rts
1981
1982
1983 #########################################################################
1984 # MONADIC TEMPLATE #
1985 #########################################################################
1986 global _fatanhs_
1987 _fatanhs_:
1988 link %a6,&-LOCAL_SIZE
1989
1990 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
1991 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
1992 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
1993
1994 fmov.l &0x0,%fpcr # zero FPCR
1995
1996 #
1997 # copy, convert, and tag input argument
1998 #
1999 fmov.s 0x8(%a6),%fp0 # load sgl input
2000 fmov.x %fp0,FP_SRC(%a6)
2001 lea FP_SRC(%a6),%a0
2002 bsr.l tag # fetch operand type
2003 mov.b %d0,STAG(%a6)
2004 mov.b %d0,%d1
2005
2006 andi.l &0x00ff00ff,USER_FPSR(%a6)
2007
2008 clr.l %d0
2009 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2010
2011 tst.b %d1
2012 bne.b _L8_2s
2013 bsr.l satanh # operand is a NORM
2014 bra.b _L8_6s
2015 _L8_2s:
2016 cmpi.b %d1,&ZERO # is operand a ZERO?
2017 bne.b _L8_3s # no
2018 bsr.l src_zero # yes
2019 bra.b _L8_6s
2020 _L8_3s:
2021 cmpi.b %d1,&INF # is operand an INF?
2022 bne.b _L8_4s # no
2023 bsr.l t_operr # yes
2024 bra.b _L8_6s
2025 _L8_4s:
2026 cmpi.b %d1,&QNAN # is operand a QNAN?
2027 bne.b _L8_5s # no
2028 bsr.l src_qnan # yes
2029 bra.b _L8_6s
2030 _L8_5s:
2031 bsr.l satanhd # operand is a DENORM
2032 _L8_6s:
2033
2034 #
2035 # Result is now in FP0
2036 #
2037 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2038 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2039 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2040 unlk %a6
2041 rts
2042
2043 global _fatanhd_
2044 _fatanhd_:
2045 link %a6,&-LOCAL_SIZE
2046
2047 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2048 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2049 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2050
2051 fmov.l &0x0,%fpcr # zero FPCR
2052
2053 #
2054 # copy, convert, and tag input argument
2055 #
2056 fmov.d 0x8(%a6),%fp0 # load dbl input
2057 fmov.x %fp0,FP_SRC(%a6)
2058 lea FP_SRC(%a6),%a0
2059 bsr.l tag # fetch operand type
2060 mov.b %d0,STAG(%a6)
2061 mov.b %d0,%d1
2062
2063 andi.l &0x00ff00ff,USER_FPSR(%a6)
2064
2065 clr.l %d0
2066 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2067
2068 mov.b %d1,STAG(%a6)
2069 tst.b %d1
2070 bne.b _L8_2d
2071 bsr.l satanh # operand is a NORM
2072 bra.b _L8_6d
2073 _L8_2d:
2074 cmpi.b %d1,&ZERO # is operand a ZERO?
2075 bne.b _L8_3d # no
2076 bsr.l src_zero # yes
2077 bra.b _L8_6d
2078 _L8_3d:
2079 cmpi.b %d1,&INF # is operand an INF?
2080 bne.b _L8_4d # no
2081 bsr.l t_operr # yes
2082 bra.b _L8_6d
2083 _L8_4d:
2084 cmpi.b %d1,&QNAN # is operand a QNAN?
2085 bne.b _L8_5d # no
2086 bsr.l src_qnan # yes
2087 bra.b _L8_6d
2088 _L8_5d:
2089 bsr.l satanhd # operand is a DENORM
2090 _L8_6d:
2091
2092 #
2093 # Result is now in FP0
2094 #
2095 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2096 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2097 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2098 unlk %a6
2099 rts
2100
2101 global _fatanhx_
2102 _fatanhx_:
2103 link %a6,&-LOCAL_SIZE
2104
2105 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2106 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2107 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2108
2109 fmov.l &0x0,%fpcr # zero FPCR
2110
2111 #
2112 # copy, convert, and tag input argument
2113 #
2114 lea FP_SRC(%a6),%a0
2115 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2116 mov.l 0x8+0x4(%a6),0x4(%a0)
2117 mov.l 0x8+0x8(%a6),0x8(%a0)
2118 bsr.l tag # fetch operand type
2119 mov.b %d0,STAG(%a6)
2120 mov.b %d0,%d1
2121
2122 andi.l &0x00ff00ff,USER_FPSR(%a6)
2123
2124 clr.l %d0
2125 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2126
2127 tst.b %d1
2128 bne.b _L8_2x
2129 bsr.l satanh # operand is a NORM
2130 bra.b _L8_6x
2131 _L8_2x:
2132 cmpi.b %d1,&ZERO # is operand a ZERO?
2133 bne.b _L8_3x # no
2134 bsr.l src_zero # yes
2135 bra.b _L8_6x
2136 _L8_3x:
2137 cmpi.b %d1,&INF # is operand an INF?
2138 bne.b _L8_4x # no
2139 bsr.l t_operr # yes
2140 bra.b _L8_6x
2141 _L8_4x:
2142 cmpi.b %d1,&QNAN # is operand a QNAN?
2143 bne.b _L8_5x # no
2144 bsr.l src_qnan # yes
2145 bra.b _L8_6x
2146 _L8_5x:
2147 bsr.l satanhd # operand is a DENORM
2148 _L8_6x:
2149
2150 #
2151 # Result is now in FP0
2152 #
2153 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2154 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2155 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2156 unlk %a6
2157 rts
2158
2159
2160 #########################################################################
2161 # MONADIC TEMPLATE #
2162 #########################################################################
2163 global _ftans_
2164 _ftans_:
2165 link %a6,&-LOCAL_SIZE
2166
2167 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2168 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2169 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2170
2171 fmov.l &0x0,%fpcr # zero FPCR
2172
2173 #
2174 # copy, convert, and tag input argument
2175 #
2176 fmov.s 0x8(%a6),%fp0 # load sgl input
2177 fmov.x %fp0,FP_SRC(%a6)
2178 lea FP_SRC(%a6),%a0
2179 bsr.l tag # fetch operand type
2180 mov.b %d0,STAG(%a6)
2181 mov.b %d0,%d1
2182
2183 andi.l &0x00ff00ff,USER_FPSR(%a6)
2184
2185 clr.l %d0
2186 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2187
2188 tst.b %d1
2189 bne.b _L9_2s
2190 bsr.l stan # operand is a NORM
2191 bra.b _L9_6s
2192 _L9_2s:
2193 cmpi.b %d1,&ZERO # is operand a ZERO?
2194 bne.b _L9_3s # no
2195 bsr.l src_zero # yes
2196 bra.b _L9_6s
2197 _L9_3s:
2198 cmpi.b %d1,&INF # is operand an INF?
2199 bne.b _L9_4s # no
2200 bsr.l t_operr # yes
2201 bra.b _L9_6s
2202 _L9_4s:
2203 cmpi.b %d1,&QNAN # is operand a QNAN?
2204 bne.b _L9_5s # no
2205 bsr.l src_qnan # yes
2206 bra.b _L9_6s
2207 _L9_5s:
2208 bsr.l stand # operand is a DENORM
2209 _L9_6s:
2210
2211 #
2212 # Result is now in FP0
2213 #
2214 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2215 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2216 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2217 unlk %a6
2218 rts
2219
2220 global _ftand_
2221 _ftand_:
2222 link %a6,&-LOCAL_SIZE
2223
2224 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2225 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2226 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2227
2228 fmov.l &0x0,%fpcr # zero FPCR
2229
2230 #
2231 # copy, convert, and tag input argument
2232 #
2233 fmov.d 0x8(%a6),%fp0 # load dbl input
2234 fmov.x %fp0,FP_SRC(%a6)
2235 lea FP_SRC(%a6),%a0
2236 bsr.l tag # fetch operand type
2237 mov.b %d0,STAG(%a6)
2238 mov.b %d0,%d1
2239
2240 andi.l &0x00ff00ff,USER_FPSR(%a6)
2241
2242 clr.l %d0
2243 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2244
2245 mov.b %d1,STAG(%a6)
2246 tst.b %d1
2247 bne.b _L9_2d
2248 bsr.l stan # operand is a NORM
2249 bra.b _L9_6d
2250 _L9_2d:
2251 cmpi.b %d1,&ZERO # is operand a ZERO?
2252 bne.b _L9_3d # no
2253 bsr.l src_zero # yes
2254 bra.b _L9_6d
2255 _L9_3d:
2256 cmpi.b %d1,&INF # is operand an INF?
2257 bne.b _L9_4d # no
2258 bsr.l t_operr # yes
2259 bra.b _L9_6d
2260 _L9_4d:
2261 cmpi.b %d1,&QNAN # is operand a QNAN?
2262 bne.b _L9_5d # no
2263 bsr.l src_qnan # yes
2264 bra.b _L9_6d
2265 _L9_5d:
2266 bsr.l stand # operand is a DENORM
2267 _L9_6d:
2268
2269 #
2270 # Result is now in FP0
2271 #
2272 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2273 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2274 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2275 unlk %a6
2276 rts
2277
2278 global _ftanx_
2279 _ftanx_:
2280 link %a6,&-LOCAL_SIZE
2281
2282 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2283 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2284 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2285
2286 fmov.l &0x0,%fpcr # zero FPCR
2287
2288 #
2289 # copy, convert, and tag input argument
2290 #
2291 lea FP_SRC(%a6),%a0
2292 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2293 mov.l 0x8+0x4(%a6),0x4(%a0)
2294 mov.l 0x8+0x8(%a6),0x8(%a0)
2295 bsr.l tag # fetch operand type
2296 mov.b %d0,STAG(%a6)
2297 mov.b %d0,%d1
2298
2299 andi.l &0x00ff00ff,USER_FPSR(%a6)
2300
2301 clr.l %d0
2302 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2303
2304 tst.b %d1
2305 bne.b _L9_2x
2306 bsr.l stan # operand is a NORM
2307 bra.b _L9_6x
2308 _L9_2x:
2309 cmpi.b %d1,&ZERO # is operand a ZERO?
2310 bne.b _L9_3x # no
2311 bsr.l src_zero # yes
2312 bra.b _L9_6x
2313 _L9_3x:
2314 cmpi.b %d1,&INF # is operand an INF?
2315 bne.b _L9_4x # no
2316 bsr.l t_operr # yes
2317 bra.b _L9_6x
2318 _L9_4x:
2319 cmpi.b %d1,&QNAN # is operand a QNAN?
2320 bne.b _L9_5x # no
2321 bsr.l src_qnan # yes
2322 bra.b _L9_6x
2323 _L9_5x:
2324 bsr.l stand # operand is a DENORM
2325 _L9_6x:
2326
2327 #
2328 # Result is now in FP0
2329 #
2330 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2331 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2332 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2333 unlk %a6
2334 rts
2335
2336
2337 #########################################################################
2338 # MONADIC TEMPLATE #
2339 #########################################################################
2340 global _fetoxs_
2341 _fetoxs_:
2342 link %a6,&-LOCAL_SIZE
2343
2344 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2345 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2346 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2347
2348 fmov.l &0x0,%fpcr # zero FPCR
2349
2350 #
2351 # copy, convert, and tag input argument
2352 #
2353 fmov.s 0x8(%a6),%fp0 # load sgl input
2354 fmov.x %fp0,FP_SRC(%a6)
2355 lea FP_SRC(%a6),%a0
2356 bsr.l tag # fetch operand type
2357 mov.b %d0,STAG(%a6)
2358 mov.b %d0,%d1
2359
2360 andi.l &0x00ff00ff,USER_FPSR(%a6)
2361
2362 clr.l %d0
2363 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2364
2365 tst.b %d1
2366 bne.b _L10_2s
2367 bsr.l setox # operand is a NORM
2368 bra.b _L10_6s
2369 _L10_2s:
2370 cmpi.b %d1,&ZERO # is operand a ZERO?
2371 bne.b _L10_3s # no
2372 bsr.l ld_pone # yes
2373 bra.b _L10_6s
2374 _L10_3s:
2375 cmpi.b %d1,&INF # is operand an INF?
2376 bne.b _L10_4s # no
2377 bsr.l szr_inf # yes
2378 bra.b _L10_6s
2379 _L10_4s:
2380 cmpi.b %d1,&QNAN # is operand a QNAN?
2381 bne.b _L10_5s # no
2382 bsr.l src_qnan # yes
2383 bra.b _L10_6s
2384 _L10_5s:
2385 bsr.l setoxd # operand is a DENORM
2386 _L10_6s:
2387
2388 #
2389 # Result is now in FP0
2390 #
2391 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2392 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2393 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2394 unlk %a6
2395 rts
2396
2397 global _fetoxd_
2398 _fetoxd_:
2399 link %a6,&-LOCAL_SIZE
2400
2401 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2402 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2403 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2404
2405 fmov.l &0x0,%fpcr # zero FPCR
2406
2407 #
2408 # copy, convert, and tag input argument
2409 #
2410 fmov.d 0x8(%a6),%fp0 # load dbl input
2411 fmov.x %fp0,FP_SRC(%a6)
2412 lea FP_SRC(%a6),%a0
2413 bsr.l tag # fetch operand type
2414 mov.b %d0,STAG(%a6)
2415 mov.b %d0,%d1
2416
2417 andi.l &0x00ff00ff,USER_FPSR(%a6)
2418
2419 clr.l %d0
2420 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2421
2422 mov.b %d1,STAG(%a6)
2423 tst.b %d1
2424 bne.b _L10_2d
2425 bsr.l setox # operand is a NORM
2426 bra.b _L10_6d
2427 _L10_2d:
2428 cmpi.b %d1,&ZERO # is operand a ZERO?
2429 bne.b _L10_3d # no
2430 bsr.l ld_pone # yes
2431 bra.b _L10_6d
2432 _L10_3d:
2433 cmpi.b %d1,&INF # is operand an INF?
2434 bne.b _L10_4d # no
2435 bsr.l szr_inf # yes
2436 bra.b _L10_6d
2437 _L10_4d:
2438 cmpi.b %d1,&QNAN # is operand a QNAN?
2439 bne.b _L10_5d # no
2440 bsr.l src_qnan # yes
2441 bra.b _L10_6d
2442 _L10_5d:
2443 bsr.l setoxd # operand is a DENORM
2444 _L10_6d:
2445
2446 #
2447 # Result is now in FP0
2448 #
2449 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2450 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2451 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2452 unlk %a6
2453 rts
2454
2455 global _fetoxx_
2456 _fetoxx_:
2457 link %a6,&-LOCAL_SIZE
2458
2459 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2460 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2461 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2462
2463 fmov.l &0x0,%fpcr # zero FPCR
2464
2465 #
2466 # copy, convert, and tag input argument
2467 #
2468 lea FP_SRC(%a6),%a0
2469 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2470 mov.l 0x8+0x4(%a6),0x4(%a0)
2471 mov.l 0x8+0x8(%a6),0x8(%a0)
2472 bsr.l tag # fetch operand type
2473 mov.b %d0,STAG(%a6)
2474 mov.b %d0,%d1
2475
2476 andi.l &0x00ff00ff,USER_FPSR(%a6)
2477
2478 clr.l %d0
2479 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2480
2481 tst.b %d1
2482 bne.b _L10_2x
2483 bsr.l setox # operand is a NORM
2484 bra.b _L10_6x
2485 _L10_2x:
2486 cmpi.b %d1,&ZERO # is operand a ZERO?
2487 bne.b _L10_3x # no
2488 bsr.l ld_pone # yes
2489 bra.b _L10_6x
2490 _L10_3x:
2491 cmpi.b %d1,&INF # is operand an INF?
2492 bne.b _L10_4x # no
2493 bsr.l szr_inf # yes
2494 bra.b _L10_6x
2495 _L10_4x:
2496 cmpi.b %d1,&QNAN # is operand a QNAN?
2497 bne.b _L10_5x # no
2498 bsr.l src_qnan # yes
2499 bra.b _L10_6x
2500 _L10_5x:
2501 bsr.l setoxd # operand is a DENORM
2502 _L10_6x:
2503
2504 #
2505 # Result is now in FP0
2506 #
2507 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2508 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2509 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2510 unlk %a6
2511 rts
2512
2513
2514 #########################################################################
2515 # MONADIC TEMPLATE #
2516 #########################################################################
2517 global _ftwotoxs_
2518 _ftwotoxs_:
2519 link %a6,&-LOCAL_SIZE
2520
2521 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2522 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2523 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2524
2525 fmov.l &0x0,%fpcr # zero FPCR
2526
2527 #
2528 # copy, convert, and tag input argument
2529 #
2530 fmov.s 0x8(%a6),%fp0 # load sgl input
2531 fmov.x %fp0,FP_SRC(%a6)
2532 lea FP_SRC(%a6),%a0
2533 bsr.l tag # fetch operand type
2534 mov.b %d0,STAG(%a6)
2535 mov.b %d0,%d1
2536
2537 andi.l &0x00ff00ff,USER_FPSR(%a6)
2538
2539 clr.l %d0
2540 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2541
2542 tst.b %d1
2543 bne.b _L11_2s
2544 bsr.l stwotox # operand is a NORM
2545 bra.b _L11_6s
2546 _L11_2s:
2547 cmpi.b %d1,&ZERO # is operand a ZERO?
2548 bne.b _L11_3s # no
2549 bsr.l ld_pone # yes
2550 bra.b _L11_6s
2551 _L11_3s:
2552 cmpi.b %d1,&INF # is operand an INF?
2553 bne.b _L11_4s # no
2554 bsr.l szr_inf # yes
2555 bra.b _L11_6s
2556 _L11_4s:
2557 cmpi.b %d1,&QNAN # is operand a QNAN?
2558 bne.b _L11_5s # no
2559 bsr.l src_qnan # yes
2560 bra.b _L11_6s
2561 _L11_5s:
2562 bsr.l stwotoxd # operand is a DENORM
2563 _L11_6s:
2564
2565 #
2566 # Result is now in FP0
2567 #
2568 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2569 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2570 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2571 unlk %a6
2572 rts
2573
2574 global _ftwotoxd_
2575 _ftwotoxd_:
2576 link %a6,&-LOCAL_SIZE
2577
2578 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2579 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2580 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2581
2582 fmov.l &0x0,%fpcr # zero FPCR
2583
2584 #
2585 # copy, convert, and tag input argument
2586 #
2587 fmov.d 0x8(%a6),%fp0 # load dbl input
2588 fmov.x %fp0,FP_SRC(%a6)
2589 lea FP_SRC(%a6),%a0
2590 bsr.l tag # fetch operand type
2591 mov.b %d0,STAG(%a6)
2592 mov.b %d0,%d1
2593
2594 andi.l &0x00ff00ff,USER_FPSR(%a6)
2595
2596 clr.l %d0
2597 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2598
2599 mov.b %d1,STAG(%a6)
2600 tst.b %d1
2601 bne.b _L11_2d
2602 bsr.l stwotox # operand is a NORM
2603 bra.b _L11_6d
2604 _L11_2d:
2605 cmpi.b %d1,&ZERO # is operand a ZERO?
2606 bne.b _L11_3d # no
2607 bsr.l ld_pone # yes
2608 bra.b _L11_6d
2609 _L11_3d:
2610 cmpi.b %d1,&INF # is operand an INF?
2611 bne.b _L11_4d # no
2612 bsr.l szr_inf # yes
2613 bra.b _L11_6d
2614 _L11_4d:
2615 cmpi.b %d1,&QNAN # is operand a QNAN?
2616 bne.b _L11_5d # no
2617 bsr.l src_qnan # yes
2618 bra.b _L11_6d
2619 _L11_5d:
2620 bsr.l stwotoxd # operand is a DENORM
2621 _L11_6d:
2622
2623 #
2624 # Result is now in FP0
2625 #
2626 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2627 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2628 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2629 unlk %a6
2630 rts
2631
2632 global _ftwotoxx_
2633 _ftwotoxx_:
2634 link %a6,&-LOCAL_SIZE
2635
2636 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2637 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2638 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2639
2640 fmov.l &0x0,%fpcr # zero FPCR
2641
2642 #
2643 # copy, convert, and tag input argument
2644 #
2645 lea FP_SRC(%a6),%a0
2646 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2647 mov.l 0x8+0x4(%a6),0x4(%a0)
2648 mov.l 0x8+0x8(%a6),0x8(%a0)
2649 bsr.l tag # fetch operand type
2650 mov.b %d0,STAG(%a6)
2651 mov.b %d0,%d1
2652
2653 andi.l &0x00ff00ff,USER_FPSR(%a6)
2654
2655 clr.l %d0
2656 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2657
2658 tst.b %d1
2659 bne.b _L11_2x
2660 bsr.l stwotox # operand is a NORM
2661 bra.b _L11_6x
2662 _L11_2x:
2663 cmpi.b %d1,&ZERO # is operand a ZERO?
2664 bne.b _L11_3x # no
2665 bsr.l ld_pone # yes
2666 bra.b _L11_6x
2667 _L11_3x:
2668 cmpi.b %d1,&INF # is operand an INF?
2669 bne.b _L11_4x # no
2670 bsr.l szr_inf # yes
2671 bra.b _L11_6x
2672 _L11_4x:
2673 cmpi.b %d1,&QNAN # is operand a QNAN?
2674 bne.b _L11_5x # no
2675 bsr.l src_qnan # yes
2676 bra.b _L11_6x
2677 _L11_5x:
2678 bsr.l stwotoxd # operand is a DENORM
2679 _L11_6x:
2680
2681 #
2682 # Result is now in FP0
2683 #
2684 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2685 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2686 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2687 unlk %a6
2688 rts
2689
2690
2691 #########################################################################
2692 # MONADIC TEMPLATE #
2693 #########################################################################
2694 global _ftentoxs_
2695 _ftentoxs_:
2696 link %a6,&-LOCAL_SIZE
2697
2698 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2699 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2700 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2701
2702 fmov.l &0x0,%fpcr # zero FPCR
2703
2704 #
2705 # copy, convert, and tag input argument
2706 #
2707 fmov.s 0x8(%a6),%fp0 # load sgl input
2708 fmov.x %fp0,FP_SRC(%a6)
2709 lea FP_SRC(%a6),%a0
2710 bsr.l tag # fetch operand type
2711 mov.b %d0,STAG(%a6)
2712 mov.b %d0,%d1
2713
2714 andi.l &0x00ff00ff,USER_FPSR(%a6)
2715
2716 clr.l %d0
2717 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2718
2719 tst.b %d1
2720 bne.b _L12_2s
2721 bsr.l stentox # operand is a NORM
2722 bra.b _L12_6s
2723 _L12_2s:
2724 cmpi.b %d1,&ZERO # is operand a ZERO?
2725 bne.b _L12_3s # no
2726 bsr.l ld_pone # yes
2727 bra.b _L12_6s
2728 _L12_3s:
2729 cmpi.b %d1,&INF # is operand an INF?
2730 bne.b _L12_4s # no
2731 bsr.l szr_inf # yes
2732 bra.b _L12_6s
2733 _L12_4s:
2734 cmpi.b %d1,&QNAN # is operand a QNAN?
2735 bne.b _L12_5s # no
2736 bsr.l src_qnan # yes
2737 bra.b _L12_6s
2738 _L12_5s:
2739 bsr.l stentoxd # operand is a DENORM
2740 _L12_6s:
2741
2742 #
2743 # Result is now in FP0
2744 #
2745 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2746 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2747 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2748 unlk %a6
2749 rts
2750
2751 global _ftentoxd_
2752 _ftentoxd_:
2753 link %a6,&-LOCAL_SIZE
2754
2755 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2756 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2757 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2758
2759 fmov.l &0x0,%fpcr # zero FPCR
2760
2761 #
2762 # copy, convert, and tag input argument
2763 #
2764 fmov.d 0x8(%a6),%fp0 # load dbl input
2765 fmov.x %fp0,FP_SRC(%a6)
2766 lea FP_SRC(%a6),%a0
2767 bsr.l tag # fetch operand type
2768 mov.b %d0,STAG(%a6)
2769 mov.b %d0,%d1
2770
2771 andi.l &0x00ff00ff,USER_FPSR(%a6)
2772
2773 clr.l %d0
2774 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2775
2776 mov.b %d1,STAG(%a6)
2777 tst.b %d1
2778 bne.b _L12_2d
2779 bsr.l stentox # operand is a NORM
2780 bra.b _L12_6d
2781 _L12_2d:
2782 cmpi.b %d1,&ZERO # is operand a ZERO?
2783 bne.b _L12_3d # no
2784 bsr.l ld_pone # yes
2785 bra.b _L12_6d
2786 _L12_3d:
2787 cmpi.b %d1,&INF # is operand an INF?
2788 bne.b _L12_4d # no
2789 bsr.l szr_inf # yes
2790 bra.b _L12_6d
2791 _L12_4d:
2792 cmpi.b %d1,&QNAN # is operand a QNAN?
2793 bne.b _L12_5d # no
2794 bsr.l src_qnan # yes
2795 bra.b _L12_6d
2796 _L12_5d:
2797 bsr.l stentoxd # operand is a DENORM
2798 _L12_6d:
2799
2800 #
2801 # Result is now in FP0
2802 #
2803 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2804 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2805 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2806 unlk %a6
2807 rts
2808
2809 global _ftentoxx_
2810 _ftentoxx_:
2811 link %a6,&-LOCAL_SIZE
2812
2813 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2814 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2815 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2816
2817 fmov.l &0x0,%fpcr # zero FPCR
2818
2819 #
2820 # copy, convert, and tag input argument
2821 #
2822 lea FP_SRC(%a6),%a0
2823 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
2824 mov.l 0x8+0x4(%a6),0x4(%a0)
2825 mov.l 0x8+0x8(%a6),0x8(%a0)
2826 bsr.l tag # fetch operand type
2827 mov.b %d0,STAG(%a6)
2828 mov.b %d0,%d1
2829
2830 andi.l &0x00ff00ff,USER_FPSR(%a6)
2831
2832 clr.l %d0
2833 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2834
2835 tst.b %d1
2836 bne.b _L12_2x
2837 bsr.l stentox # operand is a NORM
2838 bra.b _L12_6x
2839 _L12_2x:
2840 cmpi.b %d1,&ZERO # is operand a ZERO?
2841 bne.b _L12_3x # no
2842 bsr.l ld_pone # yes
2843 bra.b _L12_6x
2844 _L12_3x:
2845 cmpi.b %d1,&INF # is operand an INF?
2846 bne.b _L12_4x # no
2847 bsr.l szr_inf # yes
2848 bra.b _L12_6x
2849 _L12_4x:
2850 cmpi.b %d1,&QNAN # is operand a QNAN?
2851 bne.b _L12_5x # no
2852 bsr.l src_qnan # yes
2853 bra.b _L12_6x
2854 _L12_5x:
2855 bsr.l stentoxd # operand is a DENORM
2856 _L12_6x:
2857
2858 #
2859 # Result is now in FP0
2860 #
2861 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2862 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2863 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2864 unlk %a6
2865 rts
2866
2867
2868 #########################################################################
2869 # MONADIC TEMPLATE #
2870 #########################################################################
2871 global _flogns_
2872 _flogns_:
2873 link %a6,&-LOCAL_SIZE
2874
2875 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2876 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2877 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2878
2879 fmov.l &0x0,%fpcr # zero FPCR
2880
2881 #
2882 # copy, convert, and tag input argument
2883 #
2884 fmov.s 0x8(%a6),%fp0 # load sgl input
2885 fmov.x %fp0,FP_SRC(%a6)
2886 lea FP_SRC(%a6),%a0
2887 bsr.l tag # fetch operand type
2888 mov.b %d0,STAG(%a6)
2889 mov.b %d0,%d1
2890
2891 andi.l &0x00ff00ff,USER_FPSR(%a6)
2892
2893 clr.l %d0
2894 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2895
2896 tst.b %d1
2897 bne.b _L13_2s
2898 bsr.l slogn # operand is a NORM
2899 bra.b _L13_6s
2900 _L13_2s:
2901 cmpi.b %d1,&ZERO # is operand a ZERO?
2902 bne.b _L13_3s # no
2903 bsr.l t_dz2 # yes
2904 bra.b _L13_6s
2905 _L13_3s:
2906 cmpi.b %d1,&INF # is operand an INF?
2907 bne.b _L13_4s # no
2908 bsr.l sopr_inf # yes
2909 bra.b _L13_6s
2910 _L13_4s:
2911 cmpi.b %d1,&QNAN # is operand a QNAN?
2912 bne.b _L13_5s # no
2913 bsr.l src_qnan # yes
2914 bra.b _L13_6s
2915 _L13_5s:
2916 bsr.l slognd # operand is a DENORM
2917 _L13_6s:
2918
2919 #
2920 # Result is now in FP0
2921 #
2922 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2923 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2924 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2925 unlk %a6
2926 rts
2927
2928 global _flognd_
2929 _flognd_:
2930 link %a6,&-LOCAL_SIZE
2931
2932 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2933 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2934 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2935
2936 fmov.l &0x0,%fpcr # zero FPCR
2937
2938 #
2939 # copy, convert, and tag input argument
2940 #
2941 fmov.d 0x8(%a6),%fp0 # load dbl input
2942 fmov.x %fp0,FP_SRC(%a6)
2943 lea FP_SRC(%a6),%a0
2944 bsr.l tag # fetch operand type
2945 mov.b %d0,STAG(%a6)
2946 mov.b %d0,%d1
2947
2948 andi.l &0x00ff00ff,USER_FPSR(%a6)
2949
2950 clr.l %d0
2951 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
2952
2953 mov.b %d1,STAG(%a6)
2954 tst.b %d1
2955 bne.b _L13_2d
2956 bsr.l slogn # operand is a NORM
2957 bra.b _L13_6d
2958 _L13_2d:
2959 cmpi.b %d1,&ZERO # is operand a ZERO?
2960 bne.b _L13_3d # no
2961 bsr.l t_dz2 # yes
2962 bra.b _L13_6d
2963 _L13_3d:
2964 cmpi.b %d1,&INF # is operand an INF?
2965 bne.b _L13_4d # no
2966 bsr.l sopr_inf # yes
2967 bra.b _L13_6d
2968 _L13_4d:
2969 cmpi.b %d1,&QNAN # is operand a QNAN?
2970 bne.b _L13_5d # no
2971 bsr.l src_qnan # yes
2972 bra.b _L13_6d
2973 _L13_5d:
2974 bsr.l slognd # operand is a DENORM
2975 _L13_6d:
2976
2977 #
2978 # Result is now in FP0
2979 #
2980 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
2981 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
2982 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
2983 unlk %a6
2984 rts
2985
2986 global _flognx_
2987 _flognx_:
2988 link %a6,&-LOCAL_SIZE
2989
2990 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
2991 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
2992 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
2993
2994 fmov.l &0x0,%fpcr # zero FPCR
2995
2996 #
2997 # copy, convert, and tag input argument
2998 #
2999 lea FP_SRC(%a6),%a0
3000 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3001 mov.l 0x8+0x4(%a6),0x4(%a0)
3002 mov.l 0x8+0x8(%a6),0x8(%a0)
3003 bsr.l tag # fetch operand type
3004 mov.b %d0,STAG(%a6)
3005 mov.b %d0,%d1
3006
3007 andi.l &0x00ff00ff,USER_FPSR(%a6)
3008
3009 clr.l %d0
3010 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3011
3012 tst.b %d1
3013 bne.b _L13_2x
3014 bsr.l slogn # operand is a NORM
3015 bra.b _L13_6x
3016 _L13_2x:
3017 cmpi.b %d1,&ZERO # is operand a ZERO?
3018 bne.b _L13_3x # no
3019 bsr.l t_dz2 # yes
3020 bra.b _L13_6x
3021 _L13_3x:
3022 cmpi.b %d1,&INF # is operand an INF?
3023 bne.b _L13_4x # no
3024 bsr.l sopr_inf # yes
3025 bra.b _L13_6x
3026 _L13_4x:
3027 cmpi.b %d1,&QNAN # is operand a QNAN?
3028 bne.b _L13_5x # no
3029 bsr.l src_qnan # yes
3030 bra.b _L13_6x
3031 _L13_5x:
3032 bsr.l slognd # operand is a DENORM
3033 _L13_6x:
3034
3035 #
3036 # Result is now in FP0
3037 #
3038 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3039 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3040 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3041 unlk %a6
3042 rts
3043
3044
3045 #########################################################################
3046 # MONADIC TEMPLATE #
3047 #########################################################################
3048 global _flog10s_
3049 _flog10s_:
3050 link %a6,&-LOCAL_SIZE
3051
3052 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3053 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3054 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3055
3056 fmov.l &0x0,%fpcr # zero FPCR
3057
3058 #
3059 # copy, convert, and tag input argument
3060 #
3061 fmov.s 0x8(%a6),%fp0 # load sgl input
3062 fmov.x %fp0,FP_SRC(%a6)
3063 lea FP_SRC(%a6),%a0
3064 bsr.l tag # fetch operand type
3065 mov.b %d0,STAG(%a6)
3066 mov.b %d0,%d1
3067
3068 andi.l &0x00ff00ff,USER_FPSR(%a6)
3069
3070 clr.l %d0
3071 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3072
3073 tst.b %d1
3074 bne.b _L14_2s
3075 bsr.l slog10 # operand is a NORM
3076 bra.b _L14_6s
3077 _L14_2s:
3078 cmpi.b %d1,&ZERO # is operand a ZERO?
3079 bne.b _L14_3s # no
3080 bsr.l t_dz2 # yes
3081 bra.b _L14_6s
3082 _L14_3s:
3083 cmpi.b %d1,&INF # is operand an INF?
3084 bne.b _L14_4s # no
3085 bsr.l sopr_inf # yes
3086 bra.b _L14_6s
3087 _L14_4s:
3088 cmpi.b %d1,&QNAN # is operand a QNAN?
3089 bne.b _L14_5s # no
3090 bsr.l src_qnan # yes
3091 bra.b _L14_6s
3092 _L14_5s:
3093 bsr.l slog10d # operand is a DENORM
3094 _L14_6s:
3095
3096 #
3097 # Result is now in FP0
3098 #
3099 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3100 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3101 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3102 unlk %a6
3103 rts
3104
3105 global _flog10d_
3106 _flog10d_:
3107 link %a6,&-LOCAL_SIZE
3108
3109 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3110 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3111 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3112
3113 fmov.l &0x0,%fpcr # zero FPCR
3114
3115 #
3116 # copy, convert, and tag input argument
3117 #
3118 fmov.d 0x8(%a6),%fp0 # load dbl input
3119 fmov.x %fp0,FP_SRC(%a6)
3120 lea FP_SRC(%a6),%a0
3121 bsr.l tag # fetch operand type
3122 mov.b %d0,STAG(%a6)
3123 mov.b %d0,%d1
3124
3125 andi.l &0x00ff00ff,USER_FPSR(%a6)
3126
3127 clr.l %d0
3128 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3129
3130 mov.b %d1,STAG(%a6)
3131 tst.b %d1
3132 bne.b _L14_2d
3133 bsr.l slog10 # operand is a NORM
3134 bra.b _L14_6d
3135 _L14_2d:
3136 cmpi.b %d1,&ZERO # is operand a ZERO?
3137 bne.b _L14_3d # no
3138 bsr.l t_dz2 # yes
3139 bra.b _L14_6d
3140 _L14_3d:
3141 cmpi.b %d1,&INF # is operand an INF?
3142 bne.b _L14_4d # no
3143 bsr.l sopr_inf # yes
3144 bra.b _L14_6d
3145 _L14_4d:
3146 cmpi.b %d1,&QNAN # is operand a QNAN?
3147 bne.b _L14_5d # no
3148 bsr.l src_qnan # yes
3149 bra.b _L14_6d
3150 _L14_5d:
3151 bsr.l slog10d # operand is a DENORM
3152 _L14_6d:
3153
3154 #
3155 # Result is now in FP0
3156 #
3157 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3158 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3159 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3160 unlk %a6
3161 rts
3162
3163 global _flog10x_
3164 _flog10x_:
3165 link %a6,&-LOCAL_SIZE
3166
3167 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3168 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3169 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3170
3171 fmov.l &0x0,%fpcr # zero FPCR
3172
3173 #
3174 # copy, convert, and tag input argument
3175 #
3176 lea FP_SRC(%a6),%a0
3177 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3178 mov.l 0x8+0x4(%a6),0x4(%a0)
3179 mov.l 0x8+0x8(%a6),0x8(%a0)
3180 bsr.l tag # fetch operand type
3181 mov.b %d0,STAG(%a6)
3182 mov.b %d0,%d1
3183
3184 andi.l &0x00ff00ff,USER_FPSR(%a6)
3185
3186 clr.l %d0
3187 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3188
3189 tst.b %d1
3190 bne.b _L14_2x
3191 bsr.l slog10 # operand is a NORM
3192 bra.b _L14_6x
3193 _L14_2x:
3194 cmpi.b %d1,&ZERO # is operand a ZERO?
3195 bne.b _L14_3x # no
3196 bsr.l t_dz2 # yes
3197 bra.b _L14_6x
3198 _L14_3x:
3199 cmpi.b %d1,&INF # is operand an INF?
3200 bne.b _L14_4x # no
3201 bsr.l sopr_inf # yes
3202 bra.b _L14_6x
3203 _L14_4x:
3204 cmpi.b %d1,&QNAN # is operand a QNAN?
3205 bne.b _L14_5x # no
3206 bsr.l src_qnan # yes
3207 bra.b _L14_6x
3208 _L14_5x:
3209 bsr.l slog10d # operand is a DENORM
3210 _L14_6x:
3211
3212 #
3213 # Result is now in FP0
3214 #
3215 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3216 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3217 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3218 unlk %a6
3219 rts
3220
3221
3222 #########################################################################
3223 # MONADIC TEMPLATE #
3224 #########################################################################
3225 global _flog2s_
3226 _flog2s_:
3227 link %a6,&-LOCAL_SIZE
3228
3229 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3230 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3231 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3232
3233 fmov.l &0x0,%fpcr # zero FPCR
3234
3235 #
3236 # copy, convert, and tag input argument
3237 #
3238 fmov.s 0x8(%a6),%fp0 # load sgl input
3239 fmov.x %fp0,FP_SRC(%a6)
3240 lea FP_SRC(%a6),%a0
3241 bsr.l tag # fetch operand type
3242 mov.b %d0,STAG(%a6)
3243 mov.b %d0,%d1
3244
3245 andi.l &0x00ff00ff,USER_FPSR(%a6)
3246
3247 clr.l %d0
3248 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3249
3250 tst.b %d1
3251 bne.b _L15_2s
3252 bsr.l slog2 # operand is a NORM
3253 bra.b _L15_6s
3254 _L15_2s:
3255 cmpi.b %d1,&ZERO # is operand a ZERO?
3256 bne.b _L15_3s # no
3257 bsr.l t_dz2 # yes
3258 bra.b _L15_6s
3259 _L15_3s:
3260 cmpi.b %d1,&INF # is operand an INF?
3261 bne.b _L15_4s # no
3262 bsr.l sopr_inf # yes
3263 bra.b _L15_6s
3264 _L15_4s:
3265 cmpi.b %d1,&QNAN # is operand a QNAN?
3266 bne.b _L15_5s # no
3267 bsr.l src_qnan # yes
3268 bra.b _L15_6s
3269 _L15_5s:
3270 bsr.l slog2d # operand is a DENORM
3271 _L15_6s:
3272
3273 #
3274 # Result is now in FP0
3275 #
3276 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3277 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3278 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3279 unlk %a6
3280 rts
3281
3282 global _flog2d_
3283 _flog2d_:
3284 link %a6,&-LOCAL_SIZE
3285
3286 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3287 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3288 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3289
3290 fmov.l &0x0,%fpcr # zero FPCR
3291
3292 #
3293 # copy, convert, and tag input argument
3294 #
3295 fmov.d 0x8(%a6),%fp0 # load dbl input
3296 fmov.x %fp0,FP_SRC(%a6)
3297 lea FP_SRC(%a6),%a0
3298 bsr.l tag # fetch operand type
3299 mov.b %d0,STAG(%a6)
3300 mov.b %d0,%d1
3301
3302 andi.l &0x00ff00ff,USER_FPSR(%a6)
3303
3304 clr.l %d0
3305 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3306
3307 mov.b %d1,STAG(%a6)
3308 tst.b %d1
3309 bne.b _L15_2d
3310 bsr.l slog2 # operand is a NORM
3311 bra.b _L15_6d
3312 _L15_2d:
3313 cmpi.b %d1,&ZERO # is operand a ZERO?
3314 bne.b _L15_3d # no
3315 bsr.l t_dz2 # yes
3316 bra.b _L15_6d
3317 _L15_3d:
3318 cmpi.b %d1,&INF # is operand an INF?
3319 bne.b _L15_4d # no
3320 bsr.l sopr_inf # yes
3321 bra.b _L15_6d
3322 _L15_4d:
3323 cmpi.b %d1,&QNAN # is operand a QNAN?
3324 bne.b _L15_5d # no
3325 bsr.l src_qnan # yes
3326 bra.b _L15_6d
3327 _L15_5d:
3328 bsr.l slog2d # operand is a DENORM
3329 _L15_6d:
3330
3331 #
3332 # Result is now in FP0
3333 #
3334 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3335 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3336 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3337 unlk %a6
3338 rts
3339
3340 global _flog2x_
3341 _flog2x_:
3342 link %a6,&-LOCAL_SIZE
3343
3344 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3345 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3346 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3347
3348 fmov.l &0x0,%fpcr # zero FPCR
3349
3350 #
3351 # copy, convert, and tag input argument
3352 #
3353 lea FP_SRC(%a6),%a0
3354 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3355 mov.l 0x8+0x4(%a6),0x4(%a0)
3356 mov.l 0x8+0x8(%a6),0x8(%a0)
3357 bsr.l tag # fetch operand type
3358 mov.b %d0,STAG(%a6)
3359 mov.b %d0,%d1
3360
3361 andi.l &0x00ff00ff,USER_FPSR(%a6)
3362
3363 clr.l %d0
3364 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3365
3366 tst.b %d1
3367 bne.b _L15_2x
3368 bsr.l slog2 # operand is a NORM
3369 bra.b _L15_6x
3370 _L15_2x:
3371 cmpi.b %d1,&ZERO # is operand a ZERO?
3372 bne.b _L15_3x # no
3373 bsr.l t_dz2 # yes
3374 bra.b _L15_6x
3375 _L15_3x:
3376 cmpi.b %d1,&INF # is operand an INF?
3377 bne.b _L15_4x # no
3378 bsr.l sopr_inf # yes
3379 bra.b _L15_6x
3380 _L15_4x:
3381 cmpi.b %d1,&QNAN # is operand a QNAN?
3382 bne.b _L15_5x # no
3383 bsr.l src_qnan # yes
3384 bra.b _L15_6x
3385 _L15_5x:
3386 bsr.l slog2d # operand is a DENORM
3387 _L15_6x:
3388
3389 #
3390 # Result is now in FP0
3391 #
3392 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3393 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3394 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3395 unlk %a6
3396 rts
3397
3398
3399 #########################################################################
3400 # MONADIC TEMPLATE #
3401 #########################################################################
3402 global _fcoshs_
3403 _fcoshs_:
3404 link %a6,&-LOCAL_SIZE
3405
3406 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3407 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3408 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3409
3410 fmov.l &0x0,%fpcr # zero FPCR
3411
3412 #
3413 # copy, convert, and tag input argument
3414 #
3415 fmov.s 0x8(%a6),%fp0 # load sgl input
3416 fmov.x %fp0,FP_SRC(%a6)
3417 lea FP_SRC(%a6),%a0
3418 bsr.l tag # fetch operand type
3419 mov.b %d0,STAG(%a6)
3420 mov.b %d0,%d1
3421
3422 andi.l &0x00ff00ff,USER_FPSR(%a6)
3423
3424 clr.l %d0
3425 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3426
3427 tst.b %d1
3428 bne.b _L16_2s
3429 bsr.l scosh # operand is a NORM
3430 bra.b _L16_6s
3431 _L16_2s:
3432 cmpi.b %d1,&ZERO # is operand a ZERO?
3433 bne.b _L16_3s # no
3434 bsr.l ld_pone # yes
3435 bra.b _L16_6s
3436 _L16_3s:
3437 cmpi.b %d1,&INF # is operand an INF?
3438 bne.b _L16_4s # no
3439 bsr.l ld_pinf # yes
3440 bra.b _L16_6s
3441 _L16_4s:
3442 cmpi.b %d1,&QNAN # is operand a QNAN?
3443 bne.b _L16_5s # no
3444 bsr.l src_qnan # yes
3445 bra.b _L16_6s
3446 _L16_5s:
3447 bsr.l scoshd # operand is a DENORM
3448 _L16_6s:
3449
3450 #
3451 # Result is now in FP0
3452 #
3453 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3454 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3455 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3456 unlk %a6
3457 rts
3458
3459 global _fcoshd_
3460 _fcoshd_:
3461 link %a6,&-LOCAL_SIZE
3462
3463 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3464 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3465 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3466
3467 fmov.l &0x0,%fpcr # zero FPCR
3468
3469 #
3470 # copy, convert, and tag input argument
3471 #
3472 fmov.d 0x8(%a6),%fp0 # load dbl input
3473 fmov.x %fp0,FP_SRC(%a6)
3474 lea FP_SRC(%a6),%a0
3475 bsr.l tag # fetch operand type
3476 mov.b %d0,STAG(%a6)
3477 mov.b %d0,%d1
3478
3479 andi.l &0x00ff00ff,USER_FPSR(%a6)
3480
3481 clr.l %d0
3482 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3483
3484 mov.b %d1,STAG(%a6)
3485 tst.b %d1
3486 bne.b _L16_2d
3487 bsr.l scosh # operand is a NORM
3488 bra.b _L16_6d
3489 _L16_2d:
3490 cmpi.b %d1,&ZERO # is operand a ZERO?
3491 bne.b _L16_3d # no
3492 bsr.l ld_pone # yes
3493 bra.b _L16_6d
3494 _L16_3d:
3495 cmpi.b %d1,&INF # is operand an INF?
3496 bne.b _L16_4d # no
3497 bsr.l ld_pinf # yes
3498 bra.b _L16_6d
3499 _L16_4d:
3500 cmpi.b %d1,&QNAN # is operand a QNAN?
3501 bne.b _L16_5d # no
3502 bsr.l src_qnan # yes
3503 bra.b _L16_6d
3504 _L16_5d:
3505 bsr.l scoshd # operand is a DENORM
3506 _L16_6d:
3507
3508 #
3509 # Result is now in FP0
3510 #
3511 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3512 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3513 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3514 unlk %a6
3515 rts
3516
3517 global _fcoshx_
3518 _fcoshx_:
3519 link %a6,&-LOCAL_SIZE
3520
3521 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3522 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3523 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3524
3525 fmov.l &0x0,%fpcr # zero FPCR
3526
3527 #
3528 # copy, convert, and tag input argument
3529 #
3530 lea FP_SRC(%a6),%a0
3531 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3532 mov.l 0x8+0x4(%a6),0x4(%a0)
3533 mov.l 0x8+0x8(%a6),0x8(%a0)
3534 bsr.l tag # fetch operand type
3535 mov.b %d0,STAG(%a6)
3536 mov.b %d0,%d1
3537
3538 andi.l &0x00ff00ff,USER_FPSR(%a6)
3539
3540 clr.l %d0
3541 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3542
3543 tst.b %d1
3544 bne.b _L16_2x
3545 bsr.l scosh # operand is a NORM
3546 bra.b _L16_6x
3547 _L16_2x:
3548 cmpi.b %d1,&ZERO # is operand a ZERO?
3549 bne.b _L16_3x # no
3550 bsr.l ld_pone # yes
3551 bra.b _L16_6x
3552 _L16_3x:
3553 cmpi.b %d1,&INF # is operand an INF?
3554 bne.b _L16_4x # no
3555 bsr.l ld_pinf # yes
3556 bra.b _L16_6x
3557 _L16_4x:
3558 cmpi.b %d1,&QNAN # is operand a QNAN?
3559 bne.b _L16_5x # no
3560 bsr.l src_qnan # yes
3561 bra.b _L16_6x
3562 _L16_5x:
3563 bsr.l scoshd # operand is a DENORM
3564 _L16_6x:
3565
3566 #
3567 # Result is now in FP0
3568 #
3569 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3570 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3571 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3572 unlk %a6
3573 rts
3574
3575
3576 #########################################################################
3577 # MONADIC TEMPLATE #
3578 #########################################################################
3579 global _facoss_
3580 _facoss_:
3581 link %a6,&-LOCAL_SIZE
3582
3583 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3584 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3585 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3586
3587 fmov.l &0x0,%fpcr # zero FPCR
3588
3589 #
3590 # copy, convert, and tag input argument
3591 #
3592 fmov.s 0x8(%a6),%fp0 # load sgl input
3593 fmov.x %fp0,FP_SRC(%a6)
3594 lea FP_SRC(%a6),%a0
3595 bsr.l tag # fetch operand type
3596 mov.b %d0,STAG(%a6)
3597 mov.b %d0,%d1
3598
3599 andi.l &0x00ff00ff,USER_FPSR(%a6)
3600
3601 clr.l %d0
3602 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3603
3604 tst.b %d1
3605 bne.b _L17_2s
3606 bsr.l sacos # operand is a NORM
3607 bra.b _L17_6s
3608 _L17_2s:
3609 cmpi.b %d1,&ZERO # is operand a ZERO?
3610 bne.b _L17_3s # no
3611 bsr.l ld_ppi2 # yes
3612 bra.b _L17_6s
3613 _L17_3s:
3614 cmpi.b %d1,&INF # is operand an INF?
3615 bne.b _L17_4s # no
3616 bsr.l t_operr # yes
3617 bra.b _L17_6s
3618 _L17_4s:
3619 cmpi.b %d1,&QNAN # is operand a QNAN?
3620 bne.b _L17_5s # no
3621 bsr.l src_qnan # yes
3622 bra.b _L17_6s
3623 _L17_5s:
3624 bsr.l sacosd # operand is a DENORM
3625 _L17_6s:
3626
3627 #
3628 # Result is now in FP0
3629 #
3630 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3631 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3632 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3633 unlk %a6
3634 rts
3635
3636 global _facosd_
3637 _facosd_:
3638 link %a6,&-LOCAL_SIZE
3639
3640 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3641 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3642 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3643
3644 fmov.l &0x0,%fpcr # zero FPCR
3645
3646 #
3647 # copy, convert, and tag input argument
3648 #
3649 fmov.d 0x8(%a6),%fp0 # load dbl input
3650 fmov.x %fp0,FP_SRC(%a6)
3651 lea FP_SRC(%a6),%a0
3652 bsr.l tag # fetch operand type
3653 mov.b %d0,STAG(%a6)
3654 mov.b %d0,%d1
3655
3656 andi.l &0x00ff00ff,USER_FPSR(%a6)
3657
3658 clr.l %d0
3659 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3660
3661 mov.b %d1,STAG(%a6)
3662 tst.b %d1
3663 bne.b _L17_2d
3664 bsr.l sacos # operand is a NORM
3665 bra.b _L17_6d
3666 _L17_2d:
3667 cmpi.b %d1,&ZERO # is operand a ZERO?
3668 bne.b _L17_3d # no
3669 bsr.l ld_ppi2 # yes
3670 bra.b _L17_6d
3671 _L17_3d:
3672 cmpi.b %d1,&INF # is operand an INF?
3673 bne.b _L17_4d # no
3674 bsr.l t_operr # yes
3675 bra.b _L17_6d
3676 _L17_4d:
3677 cmpi.b %d1,&QNAN # is operand a QNAN?
3678 bne.b _L17_5d # no
3679 bsr.l src_qnan # yes
3680 bra.b _L17_6d
3681 _L17_5d:
3682 bsr.l sacosd # operand is a DENORM
3683 _L17_6d:
3684
3685 #
3686 # Result is now in FP0
3687 #
3688 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3689 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3690 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3691 unlk %a6
3692 rts
3693
3694 global _facosx_
3695 _facosx_:
3696 link %a6,&-LOCAL_SIZE
3697
3698 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3699 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3700 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3701
3702 fmov.l &0x0,%fpcr # zero FPCR
3703
3704 #
3705 # copy, convert, and tag input argument
3706 #
3707 lea FP_SRC(%a6),%a0
3708 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3709 mov.l 0x8+0x4(%a6),0x4(%a0)
3710 mov.l 0x8+0x8(%a6),0x8(%a0)
3711 bsr.l tag # fetch operand type
3712 mov.b %d0,STAG(%a6)
3713 mov.b %d0,%d1
3714
3715 andi.l &0x00ff00ff,USER_FPSR(%a6)
3716
3717 clr.l %d0
3718 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3719
3720 tst.b %d1
3721 bne.b _L17_2x
3722 bsr.l sacos # operand is a NORM
3723 bra.b _L17_6x
3724 _L17_2x:
3725 cmpi.b %d1,&ZERO # is operand a ZERO?
3726 bne.b _L17_3x # no
3727 bsr.l ld_ppi2 # yes
3728 bra.b _L17_6x
3729 _L17_3x:
3730 cmpi.b %d1,&INF # is operand an INF?
3731 bne.b _L17_4x # no
3732 bsr.l t_operr # yes
3733 bra.b _L17_6x
3734 _L17_4x:
3735 cmpi.b %d1,&QNAN # is operand a QNAN?
3736 bne.b _L17_5x # no
3737 bsr.l src_qnan # yes
3738 bra.b _L17_6x
3739 _L17_5x:
3740 bsr.l sacosd # operand is a DENORM
3741 _L17_6x:
3742
3743 #
3744 # Result is now in FP0
3745 #
3746 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3747 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3748 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3749 unlk %a6
3750 rts
3751
3752
3753 #########################################################################
3754 # MONADIC TEMPLATE #
3755 #########################################################################
3756 global _fgetexps_
3757 _fgetexps_:
3758 link %a6,&-LOCAL_SIZE
3759
3760 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3761 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3762 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3763
3764 fmov.l &0x0,%fpcr # zero FPCR
3765
3766 #
3767 # copy, convert, and tag input argument
3768 #
3769 fmov.s 0x8(%a6),%fp0 # load sgl input
3770 fmov.x %fp0,FP_SRC(%a6)
3771 lea FP_SRC(%a6),%a0
3772 bsr.l tag # fetch operand type
3773 mov.b %d0,STAG(%a6)
3774 mov.b %d0,%d1
3775
3776 andi.l &0x00ff00ff,USER_FPSR(%a6)
3777
3778 clr.l %d0
3779 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3780
3781 tst.b %d1
3782 bne.b _L18_2s
3783 bsr.l sgetexp # operand is a NORM
3784 bra.b _L18_6s
3785 _L18_2s:
3786 cmpi.b %d1,&ZERO # is operand a ZERO?
3787 bne.b _L18_3s # no
3788 bsr.l src_zero # yes
3789 bra.b _L18_6s
3790 _L18_3s:
3791 cmpi.b %d1,&INF # is operand an INF?
3792 bne.b _L18_4s # no
3793 bsr.l t_operr # yes
3794 bra.b _L18_6s
3795 _L18_4s:
3796 cmpi.b %d1,&QNAN # is operand a QNAN?
3797 bne.b _L18_5s # no
3798 bsr.l src_qnan # yes
3799 bra.b _L18_6s
3800 _L18_5s:
3801 bsr.l sgetexpd # operand is a DENORM
3802 _L18_6s:
3803
3804 #
3805 # Result is now in FP0
3806 #
3807 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3808 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3809 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3810 unlk %a6
3811 rts
3812
3813 global _fgetexpd_
3814 _fgetexpd_:
3815 link %a6,&-LOCAL_SIZE
3816
3817 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3818 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3819 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3820
3821 fmov.l &0x0,%fpcr # zero FPCR
3822
3823 #
3824 # copy, convert, and tag input argument
3825 #
3826 fmov.d 0x8(%a6),%fp0 # load dbl input
3827 fmov.x %fp0,FP_SRC(%a6)
3828 lea FP_SRC(%a6),%a0
3829 bsr.l tag # fetch operand type
3830 mov.b %d0,STAG(%a6)
3831 mov.b %d0,%d1
3832
3833 andi.l &0x00ff00ff,USER_FPSR(%a6)
3834
3835 clr.l %d0
3836 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3837
3838 mov.b %d1,STAG(%a6)
3839 tst.b %d1
3840 bne.b _L18_2d
3841 bsr.l sgetexp # operand is a NORM
3842 bra.b _L18_6d
3843 _L18_2d:
3844 cmpi.b %d1,&ZERO # is operand a ZERO?
3845 bne.b _L18_3d # no
3846 bsr.l src_zero # yes
3847 bra.b _L18_6d
3848 _L18_3d:
3849 cmpi.b %d1,&INF # is operand an INF?
3850 bne.b _L18_4d # no
3851 bsr.l t_operr # yes
3852 bra.b _L18_6d
3853 _L18_4d:
3854 cmpi.b %d1,&QNAN # is operand a QNAN?
3855 bne.b _L18_5d # no
3856 bsr.l src_qnan # yes
3857 bra.b _L18_6d
3858 _L18_5d:
3859 bsr.l sgetexpd # operand is a DENORM
3860 _L18_6d:
3861
3862 #
3863 # Result is now in FP0
3864 #
3865 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3866 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3867 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3868 unlk %a6
3869 rts
3870
3871 global _fgetexpx_
3872 _fgetexpx_:
3873 link %a6,&-LOCAL_SIZE
3874
3875 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3876 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3877 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3878
3879 fmov.l &0x0,%fpcr # zero FPCR
3880
3881 #
3882 # copy, convert, and tag input argument
3883 #
3884 lea FP_SRC(%a6),%a0
3885 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
3886 mov.l 0x8+0x4(%a6),0x4(%a0)
3887 mov.l 0x8+0x8(%a6),0x8(%a0)
3888 bsr.l tag # fetch operand type
3889 mov.b %d0,STAG(%a6)
3890 mov.b %d0,%d1
3891
3892 andi.l &0x00ff00ff,USER_FPSR(%a6)
3893
3894 clr.l %d0
3895 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3896
3897 tst.b %d1
3898 bne.b _L18_2x
3899 bsr.l sgetexp # operand is a NORM
3900 bra.b _L18_6x
3901 _L18_2x:
3902 cmpi.b %d1,&ZERO # is operand a ZERO?
3903 bne.b _L18_3x # no
3904 bsr.l src_zero # yes
3905 bra.b _L18_6x
3906 _L18_3x:
3907 cmpi.b %d1,&INF # is operand an INF?
3908 bne.b _L18_4x # no
3909 bsr.l t_operr # yes
3910 bra.b _L18_6x
3911 _L18_4x:
3912 cmpi.b %d1,&QNAN # is operand a QNAN?
3913 bne.b _L18_5x # no
3914 bsr.l src_qnan # yes
3915 bra.b _L18_6x
3916 _L18_5x:
3917 bsr.l sgetexpd # operand is a DENORM
3918 _L18_6x:
3919
3920 #
3921 # Result is now in FP0
3922 #
3923 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3924 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3925 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3926 unlk %a6
3927 rts
3928
3929
3930 #########################################################################
3931 # MONADIC TEMPLATE #
3932 #########################################################################
3933 global _fgetmans_
3934 _fgetmans_:
3935 link %a6,&-LOCAL_SIZE
3936
3937 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3938 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3939 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3940
3941 fmov.l &0x0,%fpcr # zero FPCR
3942
3943 #
3944 # copy, convert, and tag input argument
3945 #
3946 fmov.s 0x8(%a6),%fp0 # load sgl input
3947 fmov.x %fp0,FP_SRC(%a6)
3948 lea FP_SRC(%a6),%a0
3949 bsr.l tag # fetch operand type
3950 mov.b %d0,STAG(%a6)
3951 mov.b %d0,%d1
3952
3953 andi.l &0x00ff00ff,USER_FPSR(%a6)
3954
3955 clr.l %d0
3956 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
3957
3958 tst.b %d1
3959 bne.b _L19_2s
3960 bsr.l sgetman # operand is a NORM
3961 bra.b _L19_6s
3962 _L19_2s:
3963 cmpi.b %d1,&ZERO # is operand a ZERO?
3964 bne.b _L19_3s # no
3965 bsr.l src_zero # yes
3966 bra.b _L19_6s
3967 _L19_3s:
3968 cmpi.b %d1,&INF # is operand an INF?
3969 bne.b _L19_4s # no
3970 bsr.l t_operr # yes
3971 bra.b _L19_6s
3972 _L19_4s:
3973 cmpi.b %d1,&QNAN # is operand a QNAN?
3974 bne.b _L19_5s # no
3975 bsr.l src_qnan # yes
3976 bra.b _L19_6s
3977 _L19_5s:
3978 bsr.l sgetmand # operand is a DENORM
3979 _L19_6s:
3980
3981 #
3982 # Result is now in FP0
3983 #
3984 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
3985 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
3986 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
3987 unlk %a6
3988 rts
3989
3990 global _fgetmand_
3991 _fgetmand_:
3992 link %a6,&-LOCAL_SIZE
3993
3994 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
3995 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
3996 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
3997
3998 fmov.l &0x0,%fpcr # zero FPCR
3999
4000 #
4001 # copy, convert, and tag input argument
4002 #
4003 fmov.d 0x8(%a6),%fp0 # load dbl input
4004 fmov.x %fp0,FP_SRC(%a6)
4005 lea FP_SRC(%a6),%a0
4006 bsr.l tag # fetch operand type
4007 mov.b %d0,STAG(%a6)
4008 mov.b %d0,%d1
4009
4010 andi.l &0x00ff00ff,USER_FPSR(%a6)
4011
4012 clr.l %d0
4013 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4014
4015 mov.b %d1,STAG(%a6)
4016 tst.b %d1
4017 bne.b _L19_2d
4018 bsr.l sgetman # operand is a NORM
4019 bra.b _L19_6d
4020 _L19_2d:
4021 cmpi.b %d1,&ZERO # is operand a ZERO?
4022 bne.b _L19_3d # no
4023 bsr.l src_zero # yes
4024 bra.b _L19_6d
4025 _L19_3d:
4026 cmpi.b %d1,&INF # is operand an INF?
4027 bne.b _L19_4d # no
4028 bsr.l t_operr # yes
4029 bra.b _L19_6d
4030 _L19_4d:
4031 cmpi.b %d1,&QNAN # is operand a QNAN?
4032 bne.b _L19_5d # no
4033 bsr.l src_qnan # yes
4034 bra.b _L19_6d
4035 _L19_5d:
4036 bsr.l sgetmand # operand is a DENORM
4037 _L19_6d:
4038
4039 #
4040 # Result is now in FP0
4041 #
4042 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4043 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4044 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4045 unlk %a6
4046 rts
4047
4048 global _fgetmanx_
4049 _fgetmanx_:
4050 link %a6,&-LOCAL_SIZE
4051
4052 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4053 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4054 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4055
4056 fmov.l &0x0,%fpcr # zero FPCR
4057
4058 #
4059 # copy, convert, and tag input argument
4060 #
4061 lea FP_SRC(%a6),%a0
4062 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
4063 mov.l 0x8+0x4(%a6),0x4(%a0)
4064 mov.l 0x8+0x8(%a6),0x8(%a0)
4065 bsr.l tag # fetch operand type
4066 mov.b %d0,STAG(%a6)
4067 mov.b %d0,%d1
4068
4069 andi.l &0x00ff00ff,USER_FPSR(%a6)
4070
4071 clr.l %d0
4072 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4073
4074 tst.b %d1
4075 bne.b _L19_2x
4076 bsr.l sgetman # operand is a NORM
4077 bra.b _L19_6x
4078 _L19_2x:
4079 cmpi.b %d1,&ZERO # is operand a ZERO?
4080 bne.b _L19_3x # no
4081 bsr.l src_zero # yes
4082 bra.b _L19_6x
4083 _L19_3x:
4084 cmpi.b %d1,&INF # is operand an INF?
4085 bne.b _L19_4x # no
4086 bsr.l t_operr # yes
4087 bra.b _L19_6x
4088 _L19_4x:
4089 cmpi.b %d1,&QNAN # is operand a QNAN?
4090 bne.b _L19_5x # no
4091 bsr.l src_qnan # yes
4092 bra.b _L19_6x
4093 _L19_5x:
4094 bsr.l sgetmand # operand is a DENORM
4095 _L19_6x:
4096
4097 #
4098 # Result is now in FP0
4099 #
4100 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4101 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4102 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4103 unlk %a6
4104 rts
4105
4106
4107 #########################################################################
4108 # MONADIC TEMPLATE #
4109 #########################################################################
4110 global _fsincoss_
4111 _fsincoss_:
4112 link %a6,&-LOCAL_SIZE
4113
4114 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4115 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4116 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4117
4118 fmov.l &0x0,%fpcr # zero FPCR
4119
4120 #
4121 # copy, convert, and tag input argument
4122 #
4123 fmov.s 0x8(%a6),%fp0 # load sgl input
4124 fmov.x %fp0,FP_SRC(%a6)
4125 lea FP_SRC(%a6),%a0
4126 bsr.l tag # fetch operand type
4127 mov.b %d0,STAG(%a6)
4128 mov.b %d0,%d1
4129
4130 andi.l &0x00ff00ff,USER_FPSR(%a6)
4131
4132 clr.l %d0
4133 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4134
4135 tst.b %d1
4136 bne.b _L20_2s
4137 bsr.l ssincos # operand is a NORM
4138 bra.b _L20_6s
4139 _L20_2s:
4140 cmpi.b %d1,&ZERO # is operand a ZERO?
4141 bne.b _L20_3s # no
4142 bsr.l ssincosz # yes
4143 bra.b _L20_6s
4144 _L20_3s:
4145 cmpi.b %d1,&INF # is operand an INF?
4146 bne.b _L20_4s # no
4147 bsr.l ssincosi # yes
4148 bra.b _L20_6s
4149 _L20_4s:
4150 cmpi.b %d1,&QNAN # is operand a QNAN?
4151 bne.b _L20_5s # no
4152 bsr.l ssincosqnan # yes
4153 bra.b _L20_6s
4154 _L20_5s:
4155 bsr.l ssincosd # operand is a DENORM
4156 _L20_6s:
4157
4158 #
4159 # Result is now in FP0
4160 #
4161 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4162 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4163 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4164 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4165 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4166 unlk %a6
4167 rts
4168
4169 global _fsincosd_
4170 _fsincosd_:
4171 link %a6,&-LOCAL_SIZE
4172
4173 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4174 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4175 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4176
4177 fmov.l &0x0,%fpcr # zero FPCR
4178
4179 #
4180 # copy, convert, and tag input argument
4181 #
4182 fmov.d 0x8(%a6),%fp0 # load dbl input
4183 fmov.x %fp0,FP_SRC(%a6)
4184 lea FP_SRC(%a6),%a0
4185 bsr.l tag # fetch operand type
4186 mov.b %d0,STAG(%a6)
4187 mov.b %d0,%d1
4188
4189 andi.l &0x00ff00ff,USER_FPSR(%a6)
4190
4191 clr.l %d0
4192 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4193
4194 mov.b %d1,STAG(%a6)
4195 tst.b %d1
4196 bne.b _L20_2d
4197 bsr.l ssincos # operand is a NORM
4198 bra.b _L20_6d
4199 _L20_2d:
4200 cmpi.b %d1,&ZERO # is operand a ZERO?
4201 bne.b _L20_3d # no
4202 bsr.l ssincosz # yes
4203 bra.b _L20_6d
4204 _L20_3d:
4205 cmpi.b %d1,&INF # is operand an INF?
4206 bne.b _L20_4d # no
4207 bsr.l ssincosi # yes
4208 bra.b _L20_6d
4209 _L20_4d:
4210 cmpi.b %d1,&QNAN # is operand a QNAN?
4211 bne.b _L20_5d # no
4212 bsr.l ssincosqnan # yes
4213 bra.b _L20_6d
4214 _L20_5d:
4215 bsr.l ssincosd # operand is a DENORM
4216 _L20_6d:
4217
4218 #
4219 # Result is now in FP0
4220 #
4221 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4222 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4223 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4224 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4225 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4226 unlk %a6
4227 rts
4228
4229 global _fsincosx_
4230 _fsincosx_:
4231 link %a6,&-LOCAL_SIZE
4232
4233 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4234 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4235 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4236
4237 fmov.l &0x0,%fpcr # zero FPCR
4238
4239 #
4240 # copy, convert, and tag input argument
4241 #
4242 lea FP_SRC(%a6),%a0
4243 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext input
4244 mov.l 0x8+0x4(%a6),0x4(%a0)
4245 mov.l 0x8+0x8(%a6),0x8(%a0)
4246 bsr.l tag # fetch operand type
4247 mov.b %d0,STAG(%a6)
4248 mov.b %d0,%d1
4249
4250 andi.l &0x00ff00ff,USER_FPSR(%a6)
4251
4252 clr.l %d0
4253 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4254
4255 tst.b %d1
4256 bne.b _L20_2x
4257 bsr.l ssincos # operand is a NORM
4258 bra.b _L20_6x
4259 _L20_2x:
4260 cmpi.b %d1,&ZERO # is operand a ZERO?
4261 bne.b _L20_3x # no
4262 bsr.l ssincosz # yes
4263 bra.b _L20_6x
4264 _L20_3x:
4265 cmpi.b %d1,&INF # is operand an INF?
4266 bne.b _L20_4x # no
4267 bsr.l ssincosi # yes
4268 bra.b _L20_6x
4269 _L20_4x:
4270 cmpi.b %d1,&QNAN # is operand a QNAN?
4271 bne.b _L20_5x # no
4272 bsr.l ssincosqnan # yes
4273 bra.b _L20_6x
4274 _L20_5x:
4275 bsr.l ssincosd # operand is a DENORM
4276 _L20_6x:
4277
4278 #
4279 # Result is now in FP0
4280 #
4281 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4282 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4283 fmovm.x &0x03,-(%sp) # store off fp0/fp1
4284 fmovm.x (%sp)+,&0x40 # fp0 now in fp1
4285 fmovm.x (%sp)+,&0x80 # fp1 now in fp0
4286 unlk %a6
4287 rts
4288
4289
4290 #########################################################################
4291 # DYADIC TEMPLATE #
4292 #########################################################################
4293 global _frems_
4294 _frems_:
4295 link %a6,&-LOCAL_SIZE
4296
4297 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4298 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4299 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4300
4301 fmov.l &0x0,%fpcr # zero FPCR
4302
4303 #
4304 # copy, convert, and tag input argument
4305 #
4306 fmov.s 0x8(%a6),%fp0 # load sgl dst
4307 fmov.x %fp0,FP_DST(%a6)
4308 lea FP_DST(%a6),%a0
4309 bsr.l tag # fetch operand type
4310 mov.b %d0,DTAG(%a6)
4311
4312 fmov.s 0xc(%a6),%fp0 # load sgl src
4313 fmov.x %fp0,FP_SRC(%a6)
4314 lea FP_SRC(%a6),%a0
4315 bsr.l tag # fetch operand type
4316 mov.b %d0,STAG(%a6)
4317 mov.l %d0,%d1
4318
4319 andi.l &0x00ff00ff,USER_FPSR(%a6)
4320
4321 clr.l %d0
4322 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4323
4324 lea FP_SRC(%a6),%a0 # pass ptr to src
4325 lea FP_DST(%a6),%a1 # pass ptr to dst
4326
4327 tst.b %d1
4328 bne.b _L21_2s
4329 bsr.l srem_snorm # operand is a NORM
4330 bra.b _L21_6s
4331 _L21_2s:
4332 cmpi.b %d1,&ZERO # is operand a ZERO?
4333 bne.b _L21_3s # no
4334 bsr.l srem_szero # yes
4335 bra.b _L21_6s
4336 _L21_3s:
4337 cmpi.b %d1,&INF # is operand an INF?
4338 bne.b _L21_4s # no
4339 bsr.l srem_sinf # yes
4340 bra.b _L21_6s
4341 _L21_4s:
4342 cmpi.b %d1,&QNAN # is operand a QNAN?
4343 bne.b _L21_5s # no
4344 bsr.l sop_sqnan # yes
4345 bra.b _L21_6s
4346 _L21_5s:
4347 bsr.l srem_sdnrm # operand is a DENORM
4348 _L21_6s:
4349
4350 #
4351 # Result is now in FP0
4352 #
4353 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4354 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4355 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4356 unlk %a6
4357 rts
4358
4359 global _fremd_
4360 _fremd_:
4361 link %a6,&-LOCAL_SIZE
4362
4363 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4364 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4365 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4366
4367 fmov.l &0x0,%fpcr # zero FPCR
4368
4369 #
4370 # copy, convert, and tag input argument
4371 #
4372 fmov.d 0x8(%a6),%fp0 # load dbl dst
4373 fmov.x %fp0,FP_DST(%a6)
4374 lea FP_DST(%a6),%a0
4375 bsr.l tag # fetch operand type
4376 mov.b %d0,DTAG(%a6)
4377
4378 fmov.d 0x10(%a6),%fp0 # load dbl src
4379 fmov.x %fp0,FP_SRC(%a6)
4380 lea FP_SRC(%a6),%a0
4381 bsr.l tag # fetch operand type
4382 mov.b %d0,STAG(%a6)
4383 mov.l %d0,%d1
4384
4385 andi.l &0x00ff00ff,USER_FPSR(%a6)
4386
4387 clr.l %d0
4388 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4389
4390 lea FP_SRC(%a6),%a0 # pass ptr to src
4391 lea FP_DST(%a6),%a1 # pass ptr to dst
4392
4393 tst.b %d1
4394 bne.b _L21_2d
4395 bsr.l srem_snorm # operand is a NORM
4396 bra.b _L21_6d
4397 _L21_2d:
4398 cmpi.b %d1,&ZERO # is operand a ZERO?
4399 bne.b _L21_3d # no
4400 bsr.l srem_szero # yes
4401 bra.b _L21_6d
4402 _L21_3d:
4403 cmpi.b %d1,&INF # is operand an INF?
4404 bne.b _L21_4d # no
4405 bsr.l srem_sinf # yes
4406 bra.b _L21_6d
4407 _L21_4d:
4408 cmpi.b %d1,&QNAN # is operand a QNAN?
4409 bne.b _L21_5d # no
4410 bsr.l sop_sqnan # yes
4411 bra.b _L21_6d
4412 _L21_5d:
4413 bsr.l srem_sdnrm # operand is a DENORM
4414 _L21_6d:
4415
4416 #
4417 # Result is now in FP0
4418 #
4419 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4420 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4421 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4422 unlk %a6
4423 rts
4424
4425 global _fremx_
4426 _fremx_:
4427 link %a6,&-LOCAL_SIZE
4428
4429 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4430 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4431 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4432
4433 fmov.l &0x0,%fpcr # zero FPCR
4434
4435 #
4436 # copy, convert, and tag input argument
4437 #
4438 lea FP_DST(%a6),%a0
4439 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4440 mov.l 0x8+0x4(%a6),0x4(%a0)
4441 mov.l 0x8+0x8(%a6),0x8(%a0)
4442 bsr.l tag # fetch operand type
4443 mov.b %d0,DTAG(%a6)
4444
4445 lea FP_SRC(%a6),%a0
4446 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4447 mov.l 0x14+0x4(%a6),0x4(%a0)
4448 mov.l 0x14+0x8(%a6),0x8(%a0)
4449 bsr.l tag # fetch operand type
4450 mov.b %d0,STAG(%a6)
4451 mov.l %d0,%d1
4452
4453 andi.l &0x00ff00ff,USER_FPSR(%a6)
4454
4455 clr.l %d0
4456 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4457
4458 lea FP_SRC(%a6),%a0 # pass ptr to src
4459 lea FP_DST(%a6),%a1 # pass ptr to dst
4460
4461 tst.b %d1
4462 bne.b _L21_2x
4463 bsr.l srem_snorm # operand is a NORM
4464 bra.b _L21_6x
4465 _L21_2x:
4466 cmpi.b %d1,&ZERO # is operand a ZERO?
4467 bne.b _L21_3x # no
4468 bsr.l srem_szero # yes
4469 bra.b _L21_6x
4470 _L21_3x:
4471 cmpi.b %d1,&INF # is operand an INF?
4472 bne.b _L21_4x # no
4473 bsr.l srem_sinf # yes
4474 bra.b _L21_6x
4475 _L21_4x:
4476 cmpi.b %d1,&QNAN # is operand a QNAN?
4477 bne.b _L21_5x # no
4478 bsr.l sop_sqnan # yes
4479 bra.b _L21_6x
4480 _L21_5x:
4481 bsr.l srem_sdnrm # operand is a DENORM
4482 _L21_6x:
4483
4484 #
4485 # Result is now in FP0
4486 #
4487 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4488 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4489 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4490 unlk %a6
4491 rts
4492
4493
4494 #########################################################################
4495 # DYADIC TEMPLATE #
4496 #########################################################################
4497 global _fmods_
4498 _fmods_:
4499 link %a6,&-LOCAL_SIZE
4500
4501 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4502 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4503 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4504
4505 fmov.l &0x0,%fpcr # zero FPCR
4506
4507 #
4508 # copy, convert, and tag input argument
4509 #
4510 fmov.s 0x8(%a6),%fp0 # load sgl dst
4511 fmov.x %fp0,FP_DST(%a6)
4512 lea FP_DST(%a6),%a0
4513 bsr.l tag # fetch operand type
4514 mov.b %d0,DTAG(%a6)
4515
4516 fmov.s 0xc(%a6),%fp0 # load sgl src
4517 fmov.x %fp0,FP_SRC(%a6)
4518 lea FP_SRC(%a6),%a0
4519 bsr.l tag # fetch operand type
4520 mov.b %d0,STAG(%a6)
4521 mov.l %d0,%d1
4522
4523 andi.l &0x00ff00ff,USER_FPSR(%a6)
4524
4525 clr.l %d0
4526 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4527
4528 lea FP_SRC(%a6),%a0 # pass ptr to src
4529 lea FP_DST(%a6),%a1 # pass ptr to dst
4530
4531 tst.b %d1
4532 bne.b _L22_2s
4533 bsr.l smod_snorm # operand is a NORM
4534 bra.b _L22_6s
4535 _L22_2s:
4536 cmpi.b %d1,&ZERO # is operand a ZERO?
4537 bne.b _L22_3s # no
4538 bsr.l smod_szero # yes
4539 bra.b _L22_6s
4540 _L22_3s:
4541 cmpi.b %d1,&INF # is operand an INF?
4542 bne.b _L22_4s # no
4543 bsr.l smod_sinf # yes
4544 bra.b _L22_6s
4545 _L22_4s:
4546 cmpi.b %d1,&QNAN # is operand a QNAN?
4547 bne.b _L22_5s # no
4548 bsr.l sop_sqnan # yes
4549 bra.b _L22_6s
4550 _L22_5s:
4551 bsr.l smod_sdnrm # operand is a DENORM
4552 _L22_6s:
4553
4554 #
4555 # Result is now in FP0
4556 #
4557 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4558 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4559 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4560 unlk %a6
4561 rts
4562
4563 global _fmodd_
4564 _fmodd_:
4565 link %a6,&-LOCAL_SIZE
4566
4567 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4568 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4569 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4570
4571 fmov.l &0x0,%fpcr # zero FPCR
4572
4573 #
4574 # copy, convert, and tag input argument
4575 #
4576 fmov.d 0x8(%a6),%fp0 # load dbl dst
4577 fmov.x %fp0,FP_DST(%a6)
4578 lea FP_DST(%a6),%a0
4579 bsr.l tag # fetch operand type
4580 mov.b %d0,DTAG(%a6)
4581
4582 fmov.d 0x10(%a6),%fp0 # load dbl src
4583 fmov.x %fp0,FP_SRC(%a6)
4584 lea FP_SRC(%a6),%a0
4585 bsr.l tag # fetch operand type
4586 mov.b %d0,STAG(%a6)
4587 mov.l %d0,%d1
4588
4589 andi.l &0x00ff00ff,USER_FPSR(%a6)
4590
4591 clr.l %d0
4592 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4593
4594 lea FP_SRC(%a6),%a0 # pass ptr to src
4595 lea FP_DST(%a6),%a1 # pass ptr to dst
4596
4597 tst.b %d1
4598 bne.b _L22_2d
4599 bsr.l smod_snorm # operand is a NORM
4600 bra.b _L22_6d
4601 _L22_2d:
4602 cmpi.b %d1,&ZERO # is operand a ZERO?
4603 bne.b _L22_3d # no
4604 bsr.l smod_szero # yes
4605 bra.b _L22_6d
4606 _L22_3d:
4607 cmpi.b %d1,&INF # is operand an INF?
4608 bne.b _L22_4d # no
4609 bsr.l smod_sinf # yes
4610 bra.b _L22_6d
4611 _L22_4d:
4612 cmpi.b %d1,&QNAN # is operand a QNAN?
4613 bne.b _L22_5d # no
4614 bsr.l sop_sqnan # yes
4615 bra.b _L22_6d
4616 _L22_5d:
4617 bsr.l smod_sdnrm # operand is a DENORM
4618 _L22_6d:
4619
4620 #
4621 # Result is now in FP0
4622 #
4623 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4624 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4625 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4626 unlk %a6
4627 rts
4628
4629 global _fmodx_
4630 _fmodx_:
4631 link %a6,&-LOCAL_SIZE
4632
4633 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4634 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4635 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4636
4637 fmov.l &0x0,%fpcr # zero FPCR
4638
4639 #
4640 # copy, convert, and tag input argument
4641 #
4642 lea FP_DST(%a6),%a0
4643 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4644 mov.l 0x8+0x4(%a6),0x4(%a0)
4645 mov.l 0x8+0x8(%a6),0x8(%a0)
4646 bsr.l tag # fetch operand type
4647 mov.b %d0,DTAG(%a6)
4648
4649 lea FP_SRC(%a6),%a0
4650 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4651 mov.l 0x14+0x4(%a6),0x4(%a0)
4652 mov.l 0x14+0x8(%a6),0x8(%a0)
4653 bsr.l tag # fetch operand type
4654 mov.b %d0,STAG(%a6)
4655 mov.l %d0,%d1
4656
4657 andi.l &0x00ff00ff,USER_FPSR(%a6)
4658
4659 clr.l %d0
4660 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4661
4662 lea FP_SRC(%a6),%a0 # pass ptr to src
4663 lea FP_DST(%a6),%a1 # pass ptr to dst
4664
4665 tst.b %d1
4666 bne.b _L22_2x
4667 bsr.l smod_snorm # operand is a NORM
4668 bra.b _L22_6x
4669 _L22_2x:
4670 cmpi.b %d1,&ZERO # is operand a ZERO?
4671 bne.b _L22_3x # no
4672 bsr.l smod_szero # yes
4673 bra.b _L22_6x
4674 _L22_3x:
4675 cmpi.b %d1,&INF # is operand an INF?
4676 bne.b _L22_4x # no
4677 bsr.l smod_sinf # yes
4678 bra.b _L22_6x
4679 _L22_4x:
4680 cmpi.b %d1,&QNAN # is operand a QNAN?
4681 bne.b _L22_5x # no
4682 bsr.l sop_sqnan # yes
4683 bra.b _L22_6x
4684 _L22_5x:
4685 bsr.l smod_sdnrm # operand is a DENORM
4686 _L22_6x:
4687
4688 #
4689 # Result is now in FP0
4690 #
4691 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4692 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4693 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4694 unlk %a6
4695 rts
4696
4697
4698 #########################################################################
4699 # DYADIC TEMPLATE #
4700 #########################################################################
4701 global _fscales_
4702 _fscales_:
4703 link %a6,&-LOCAL_SIZE
4704
4705 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4706 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4707 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4708
4709 fmov.l &0x0,%fpcr # zero FPCR
4710
4711 #
4712 # copy, convert, and tag input argument
4713 #
4714 fmov.s 0x8(%a6),%fp0 # load sgl dst
4715 fmov.x %fp0,FP_DST(%a6)
4716 lea FP_DST(%a6),%a0
4717 bsr.l tag # fetch operand type
4718 mov.b %d0,DTAG(%a6)
4719
4720 fmov.s 0xc(%a6),%fp0 # load sgl src
4721 fmov.x %fp0,FP_SRC(%a6)
4722 lea FP_SRC(%a6),%a0
4723 bsr.l tag # fetch operand type
4724 mov.b %d0,STAG(%a6)
4725 mov.l %d0,%d1
4726
4727 andi.l &0x00ff00ff,USER_FPSR(%a6)
4728
4729 clr.l %d0
4730 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4731
4732 lea FP_SRC(%a6),%a0 # pass ptr to src
4733 lea FP_DST(%a6),%a1 # pass ptr to dst
4734
4735 tst.b %d1
4736 bne.b _L23_2s
4737 bsr.l sscale_snorm # operand is a NORM
4738 bra.b _L23_6s
4739 _L23_2s:
4740 cmpi.b %d1,&ZERO # is operand a ZERO?
4741 bne.b _L23_3s # no
4742 bsr.l sscale_szero # yes
4743 bra.b _L23_6s
4744 _L23_3s:
4745 cmpi.b %d1,&INF # is operand an INF?
4746 bne.b _L23_4s # no
4747 bsr.l sscale_sinf # yes
4748 bra.b _L23_6s
4749 _L23_4s:
4750 cmpi.b %d1,&QNAN # is operand a QNAN?
4751 bne.b _L23_5s # no
4752 bsr.l sop_sqnan # yes
4753 bra.b _L23_6s
4754 _L23_5s:
4755 bsr.l sscale_sdnrm # operand is a DENORM
4756 _L23_6s:
4757
4758 #
4759 # Result is now in FP0
4760 #
4761 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4762 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4763 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4764 unlk %a6
4765 rts
4766
4767 global _fscaled_
4768 _fscaled_:
4769 link %a6,&-LOCAL_SIZE
4770
4771 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4772 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4773 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4774
4775 fmov.l &0x0,%fpcr # zero FPCR
4776
4777 #
4778 # copy, convert, and tag input argument
4779 #
4780 fmov.d 0x8(%a6),%fp0 # load dbl dst
4781 fmov.x %fp0,FP_DST(%a6)
4782 lea FP_DST(%a6),%a0
4783 bsr.l tag # fetch operand type
4784 mov.b %d0,DTAG(%a6)
4785
4786 fmov.d 0x10(%a6),%fp0 # load dbl src
4787 fmov.x %fp0,FP_SRC(%a6)
4788 lea FP_SRC(%a6),%a0
4789 bsr.l tag # fetch operand type
4790 mov.b %d0,STAG(%a6)
4791 mov.l %d0,%d1
4792
4793 andi.l &0x00ff00ff,USER_FPSR(%a6)
4794
4795 clr.l %d0
4796 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4797
4798 lea FP_SRC(%a6),%a0 # pass ptr to src
4799 lea FP_DST(%a6),%a1 # pass ptr to dst
4800
4801 tst.b %d1
4802 bne.b _L23_2d
4803 bsr.l sscale_snorm # operand is a NORM
4804 bra.b _L23_6d
4805 _L23_2d:
4806 cmpi.b %d1,&ZERO # is operand a ZERO?
4807 bne.b _L23_3d # no
4808 bsr.l sscale_szero # yes
4809 bra.b _L23_6d
4810 _L23_3d:
4811 cmpi.b %d1,&INF # is operand an INF?
4812 bne.b _L23_4d # no
4813 bsr.l sscale_sinf # yes
4814 bra.b _L23_6d
4815 _L23_4d:
4816 cmpi.b %d1,&QNAN # is operand a QNAN?
4817 bne.b _L23_5d # no
4818 bsr.l sop_sqnan # yes
4819 bra.b _L23_6d
4820 _L23_5d:
4821 bsr.l sscale_sdnrm # operand is a DENORM
4822 _L23_6d:
4823
4824 #
4825 # Result is now in FP0
4826 #
4827 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4828 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4829 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4830 unlk %a6
4831 rts
4832
4833 global _fscalex_
4834 _fscalex_:
4835 link %a6,&-LOCAL_SIZE
4836
4837 movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
4838 fmovm.l %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
4839 fmovm.x &0xc0,EXC_FP0(%a6) # save fp0/fp1
4840
4841 fmov.l &0x0,%fpcr # zero FPCR
4842
4843 #
4844 # copy, convert, and tag input argument
4845 #
4846 lea FP_DST(%a6),%a0
4847 mov.l 0x8+0x0(%a6),0x0(%a0) # load ext dst
4848 mov.l 0x8+0x4(%a6),0x4(%a0)
4849 mov.l 0x8+0x8(%a6),0x8(%a0)
4850 bsr.l tag # fetch operand type
4851 mov.b %d0,DTAG(%a6)
4852
4853 lea FP_SRC(%a6),%a0
4854 mov.l 0x14+0x0(%a6),0x0(%a0) # load ext src
4855 mov.l 0x14+0x4(%a6),0x4(%a0)
4856 mov.l 0x14+0x8(%a6),0x8(%a0)
4857 bsr.l tag # fetch operand type
4858 mov.b %d0,STAG(%a6)
4859 mov.l %d0,%d1
4860
4861 andi.l &0x00ff00ff,USER_FPSR(%a6)
4862
4863 clr.l %d0
4864 mov.b FPCR_MODE(%a6),%d0 # pass rnd mode,prec
4865
4866 lea FP_SRC(%a6),%a0 # pass ptr to src
4867 lea FP_DST(%a6),%a1 # pass ptr to dst
4868
4869 tst.b %d1
4870 bne.b _L23_2x
4871 bsr.l sscale_snorm # operand is a NORM
4872 bra.b _L23_6x
4873 _L23_2x:
4874 cmpi.b %d1,&ZERO # is operand a ZERO?
4875 bne.b _L23_3x # no
4876 bsr.l sscale_szero # yes
4877 bra.b _L23_6x
4878 _L23_3x:
4879 cmpi.b %d1,&INF # is operand an INF?
4880 bne.b _L23_4x # no
4881 bsr.l sscale_sinf # yes
4882 bra.b _L23_6x
4883 _L23_4x:
4884 cmpi.b %d1,&QNAN # is operand a QNAN?
4885 bne.b _L23_5x # no
4886 bsr.l sop_sqnan # yes
4887 bra.b _L23_6x
4888 _L23_5x:
4889 bsr.l sscale_sdnrm # operand is a DENORM
4890 _L23_6x:
4891
4892 #
4893 # Result is now in FP0
4894 #
4895 movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
4896 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
4897 fmovm.x EXC_FP1(%a6),&0x40 # restore fp1
4898 unlk %a6
4899 rts
4900
4901
4902 #########################################################################
4903 # ssin(): computes the sine of a normalized input #
4904 # ssind(): computes the sine of a denormalized input #
4905 # scos(): computes the cosine of a normalized input #
4906 # scosd(): computes the cosine of a denormalized input #
4907 # ssincos(): computes the sine and cosine of a normalized input #
4908 # ssincosd(): computes the sine and cosine of a denormalized input #
4909 # #
4910 # INPUT *************************************************************** #
4911 # a0 = pointer to extended precision input #
4912 # d0 = round precision,mode #
4913 # #
4914 # OUTPUT ************************************************************** #
4915 # fp0 = sin(X) or cos(X) #
4916 # #
4917 # For ssincos(X): #
4918 # fp0 = sin(X) #
4919 # fp1 = cos(X) #
4920 # #
4921 # ACCURACY and MONOTONICITY ******************************************* #
4922 # The returned result is within 1 ulp in 64 significant bit, i.e. #
4923 # within 0.5001 ulp to 53 bits if the result is subsequently #
4924 # rounded to double precision. The result is provably monotonic #
4925 # in double precision. #
4926 # #
4927 # ALGORITHM *********************************************************** #
4928 # #
4929 # SIN and COS: #
4930 # 1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1. #
4931 # #
4932 # 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7. #
4933 # #
4934 # 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
4935 # k = N mod 4, so in particular, k = 0,1,2,or 3. #
4936 # Overwrite k by k := k + AdjN. #
4937 # #
4938 # 4. If k is even, go to 6. #
4939 # #
4940 # 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. #
4941 # Return sgn*cos(r) where cos(r) is approximated by an #
4942 # even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)), #
4943 # s = r*r. #
4944 # Exit. #
4945 # #
4946 # 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r) #
4947 # where sin(r) is approximated by an odd polynomial in r #
4948 # r + r*s*(A1+s*(A2+ ... + s*A7)), s = r*r. #
4949 # Exit. #
4950 # #
4951 # 7. If |X| > 1, go to 9. #
4952 # #
4953 # 8. (|X|<2**(-40)) If SIN is invoked, return X; #
4954 # otherwise return 1. #
4955 # #
4956 # 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
4957 # go back to 3. #
4958 # #
4959 # SINCOS: #
4960 # 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
4961 # #
4962 # 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
4963 # k = N mod 4, so in particular, k = 0,1,2,or 3. #
4964 # #
4965 # 3. If k is even, go to 5. #
4966 # #
4967 # 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie. #
4968 # j1 exclusive or with the l.s.b. of k. #
4969 # sgn1 := (-1)**j1, sgn2 := (-1)**j2. #
4970 # SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where #
4971 # sin(r) and cos(r) are computed as odd and even #
4972 # polynomials in r, respectively. Exit #
4973 # #
4974 # 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1. #
4975 # SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where #
4976 # sin(r) and cos(r) are computed as odd and even #
4977 # polynomials in r, respectively. Exit #
4978 # #
4979 # 6. If |X| > 1, go to 8. #
4980 # #
4981 # 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit. #
4982 # #
4983 # 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, #
4984 # go back to 2. #
4985 # #
4986 #########################################################################
4987
4988 SINA7: long 0xBD6AAA77,0xCCC994F5
4989 SINA6: long 0x3DE61209,0x7AAE8DA1
4990 SINA5: long 0xBE5AE645,0x2A118AE4
4991 SINA4: long 0x3EC71DE3,0xA5341531
4992 SINA3: long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
4993 SINA2: long 0x3FF80000,0x88888888,0x888859AF,0x00000000
4994 SINA1: long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
4995
4996 COSB8: long 0x3D2AC4D0,0xD6011EE3
4997 COSB7: long 0xBDA9396F,0x9F45AC19
4998 COSB6: long 0x3E21EED9,0x0612C972
4999 COSB5: long 0xBE927E4F,0xB79D9FCF
5000 COSB4: long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
5001 COSB3: long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
5002 COSB2: long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
5003 COSB1: long 0xBF000000
5004
5005 set INARG,FP_SCR0
5006
5007 set X,FP_SCR0
5008 # set XDCARE,X+2
5009 set XFRAC,X+4
5010
5011 set RPRIME,FP_SCR0
5012 set SPRIME,FP_SCR1
5013
5014 set POSNEG1,L_SCR1
5015 set TWOTO63,L_SCR1
5016
5017 set ENDFLAG,L_SCR2
5018 set INT,L_SCR2
5019
5020 set ADJN,L_SCR3
5021
5022 ############################################
5023 global ssin
5024 ssin:
5025 mov.l &0,ADJN(%a6) # yes; SET ADJN TO 0
5026 bra.b SINBGN
5027
5028 ############################################
5029 global scos
5030 scos:
5031 mov.l &1,ADJN(%a6) # yes; SET ADJN TO 1
5032
5033 ############################################
5034 SINBGN:
5035 #--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
5036
5037 fmov.x (%a0),%fp0 # LOAD INPUT
5038 fmov.x %fp0,X(%a6) # save input at X
5039
5040 # "COMPACTIFY" X
5041 mov.l (%a0),%d1 # put exp in hi word
5042 mov.w 4(%a0),%d1 # fetch hi(man)
5043 and.l &0x7FFFFFFF,%d1 # strip sign
5044
5045 cmpi.l %d1,&0x3FD78000 # is |X| >= 2**(-40)?
5046 bge.b SOK1 # no
5047 bra.w SINSM # yes; input is very small
5048
5049 SOK1:
5050 cmp.l %d1,&0x4004BC7E # is |X| < 15 PI?
5051 blt.b SINMAIN # no
5052 bra.w SREDUCEX # yes; input is very large
5053
5054 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5055 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5056 SINMAIN:
5057 fmov.x %fp0,%fp1
5058 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5059
5060 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5061
5062 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5063
5064 mov.l INT(%a6),%d1 # make a copy of N
5065 asl.l &4,%d1 # N *= 16
5066 add.l %d1,%a1 # tbl_addr = a1 + (N*16)
5067
5068 # A1 IS THE ADDRESS OF N*PIBY2
5069 # ...WHICH IS IN TWO PIECES Y1 & Y2
5070 fsub.x (%a1)+,%fp0 # X-Y1
5071 fsub.s (%a1),%fp0 # fp0 = R = (X-Y1)-Y2
5072
5073 SINCONT:
5074 #--continuation from REDUCEX
5075
5076 #--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
5077 mov.l INT(%a6),%d1
5078 add.l ADJN(%a6),%d1 # SEE IF D0 IS ODD OR EVEN
5079 ror.l &1,%d1 # D0 WAS ODD IFF D0 IS NEGATIVE
5080 cmp.l %d1,&0
5081 blt.w COSPOLY
5082
5083 #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5084 #--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
5085 #--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
5086 #--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
5087 #--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
5088 #--WHERE T=S*S.
5089 #--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
5090 #--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
5091 SINPOLY:
5092 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5093
5094 fmov.x %fp0,X(%a6) # X IS R
5095 fmul.x %fp0,%fp0 # FP0 IS S
5096
5097 fmov.d SINA7(%pc),%fp3
5098 fmov.d SINA6(%pc),%fp2
5099
5100 fmov.x %fp0,%fp1
5101 fmul.x %fp1,%fp1 # FP1 IS T
5102
5103 ror.l &1,%d1
5104 and.l &0x80000000,%d1
5105 # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5106 eor.l %d1,X(%a6) # X IS NOW R'= SGN*R
5107
5108 fmul.x %fp1,%fp3 # TA7
5109 fmul.x %fp1,%fp2 # TA6
5110
5111 fadd.d SINA5(%pc),%fp3 # A5+TA7
5112 fadd.d SINA4(%pc),%fp2 # A4+TA6
5113
5114 fmul.x %fp1,%fp3 # T(A5+TA7)
5115 fmul.x %fp1,%fp2 # T(A4+TA6)
5116
5117 fadd.d SINA3(%pc),%fp3 # A3+T(A5+TA7)
5118 fadd.x SINA2(%pc),%fp2 # A2+T(A4+TA6)
5119
5120 fmul.x %fp3,%fp1 # T(A3+T(A5+TA7))
5121
5122 fmul.x %fp0,%fp2 # S(A2+T(A4+TA6))
5123 fadd.x SINA1(%pc),%fp1 # A1+T(A3+T(A5+TA7))
5124 fmul.x X(%a6),%fp0 # R'*S
5125
5126 fadd.x %fp2,%fp1 # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
5127
5128 fmul.x %fp1,%fp0 # SIN(R')-R'
5129
5130 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5131
5132 fmov.l %d0,%fpcr # restore users round mode,prec
5133 fadd.x X(%a6),%fp0 # last inst - possible exception set
5134 bra t_inx2
5135
5136 #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
5137 #--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY
5138 #--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
5139 #--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
5140 #--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
5141 #--WHERE T=S*S.
5142 #--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
5143 #--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
5144 #--AND IS THEREFORE STORED AS SINGLE PRECISION.
5145 COSPOLY:
5146 fmovm.x &0x0c,-(%sp) # save fp2/fp3
5147
5148 fmul.x %fp0,%fp0 # FP0 IS S
5149
5150 fmov.d COSB8(%pc),%fp2
5151 fmov.d COSB7(%pc),%fp3
5152
5153 fmov.x %fp0,%fp1
5154 fmul.x %fp1,%fp1 # FP1 IS T
5155
5156 fmov.x %fp0,X(%a6) # X IS S
5157 ror.l &1,%d1
5158 and.l &0x80000000,%d1
5159 # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
5160
5161 fmul.x %fp1,%fp2 # TB8
5162
5163 eor.l %d1,X(%a6) # X IS NOW S'= SGN*S
5164 and.l &0x80000000,%d1
5165
5166 fmul.x %fp1,%fp3 # TB7
5167
5168 or.l &0x3F800000,%d1 # D0 IS SGN IN SINGLE
5169 mov.l %d1,POSNEG1(%a6)
5170
5171 fadd.d COSB6(%pc),%fp2 # B6+TB8
5172 fadd.d COSB5(%pc),%fp3 # B5+TB7
5173
5174 fmul.x %fp1,%fp2 # T(B6+TB8)
5175 fmul.x %fp1,%fp3 # T(B5+TB7)
5176
5177 fadd.d COSB4(%pc),%fp2 # B4+T(B6+TB8)
5178 fadd.x COSB3(%pc),%fp3 # B3+T(B5+TB7)
5179
5180 fmul.x %fp1,%fp2 # T(B4+T(B6+TB8))
5181 fmul.x %fp3,%fp1 # T(B3+T(B5+TB7))
5182
5183 fadd.x COSB2(%pc),%fp2 # B2+T(B4+T(B6+TB8))
5184 fadd.s COSB1(%pc),%fp1 # B1+T(B3+T(B5+TB7))
5185
5186 fmul.x %fp2,%fp0 # S(B2+T(B4+T(B6+TB8)))
5187
5188 fadd.x %fp1,%fp0
5189
5190 fmul.x X(%a6),%fp0
5191
5192 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
5193
5194 fmov.l %d0,%fpcr # restore users round mode,prec
5195 fadd.s POSNEG1(%a6),%fp0 # last inst - possible exception set
5196 bra t_inx2
5197
5198 ##############################################
5199
5200 # SINe: Big OR Small?
5201 #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5202 #--IF |X| < 2**(-40), RETURN X OR 1.
5203 SINBORS:
5204 cmp.l %d1,&0x3FFF8000
5205 bgt.l SREDUCEX
5206
5207 SINSM:
5208 mov.l ADJN(%a6),%d1
5209 cmp.l %d1,&0
5210 bgt.b COSTINY
5211
5212 # here, the operation may underflow iff the precision is sgl or dbl.
5213 # extended denorms are handled through another entry point.
5214 SINTINY:
5215 # mov.w &0x0000,XDCARE(%a6) # JUST IN CASE
5216
5217 fmov.l %d0,%fpcr # restore users round mode,prec
5218 mov.b &FMOV_OP,%d1 # last inst is MOVE
5219 fmov.x X(%a6),%fp0 # last inst - possible exception set
5220 bra t_catch
5221
5222 COSTINY:
5223 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5224 fmov.l %d0,%fpcr # restore users round mode,prec
5225 fadd.s &0x80800000,%fp0 # last inst - possible exception set
5226 bra t_pinx2
5227
5228 ################################################
5229 global ssind
5230 #--SIN(X) = X FOR DENORMALIZED X
5231 ssind:
5232 bra t_extdnrm
5233
5234 ############################################
5235 global scosd
5236 #--COS(X) = 1 FOR DENORMALIZED X
5237 scosd:
5238 fmov.s &0x3F800000,%fp0 # fp0 = 1.0
5239 bra t_pinx2
5240
5241 ##################################################
5242
5243 global ssincos
5244 ssincos:
5245 #--SET ADJN TO 4
5246 mov.l &4,ADJN(%a6)
5247
5248 fmov.x (%a0),%fp0 # LOAD INPUT
5249 fmov.x %fp0,X(%a6)
5250
5251 mov.l (%a0),%d1
5252 mov.w 4(%a0),%d1
5253 and.l &0x7FFFFFFF,%d1 # COMPACTIFY X
5254
5255 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5256 bge.b SCOK1
5257 bra.w SCSM
5258
5259 SCOK1:
5260 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5261 blt.b SCMAIN
5262 bra.w SREDUCEX
5263
5264
5265 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5266 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5267 SCMAIN:
5268 fmov.x %fp0,%fp1
5269
5270 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5271
5272 lea PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5273
5274 fmov.l %fp1,INT(%a6) # CONVERT TO INTEGER
5275
5276 mov.l INT(%a6),%d1
5277 asl.l &4,%d1
5278 add.l %d1,%a1 # ADDRESS OF N*PIBY2, IN Y1, Y2
5279
5280 fsub.x (%a1)+,%fp0 # X-Y1
5281 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5282
5283 SCCONT:
5284 #--continuation point from REDUCEX
5285
5286 mov.l INT(%a6),%d1
5287 ror.l &1,%d1
5288 cmp.l %d1,&0 # D0 < 0 IFF N IS ODD
5289 bge.w NEVEN
5290
5291 SNODD:
5292 #--REGISTERS SAVED SO FAR: D0, A0, FP2.
5293 fmovm.x &0x04,-(%sp) # save fp2
5294
5295 fmov.x %fp0,RPRIME(%a6)
5296 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5297 fmov.d SINA7(%pc),%fp1 # A7
5298 fmov.d COSB8(%pc),%fp2 # B8
5299 fmul.x %fp0,%fp1 # SA7
5300 fmul.x %fp0,%fp2 # SB8
5301
5302 mov.l %d2,-(%sp)
5303 mov.l %d1,%d2
5304 ror.l &1,%d2
5305 and.l &0x80000000,%d2
5306 eor.l %d1,%d2
5307 and.l &0x80000000,%d2
5308
5309 fadd.d SINA6(%pc),%fp1 # A6+SA7
5310 fadd.d COSB7(%pc),%fp2 # B7+SB8
5311
5312 fmul.x %fp0,%fp1 # S(A6+SA7)
5313 eor.l %d2,RPRIME(%a6)
5314 mov.l (%sp)+,%d2
5315 fmul.x %fp0,%fp2 # S(B7+SB8)
5316 ror.l &1,%d1
5317 and.l &0x80000000,%d1
5318 mov.l &0x3F800000,POSNEG1(%a6)
5319 eor.l %d1,POSNEG1(%a6)
5320
5321 fadd.d SINA5(%pc),%fp1 # A5+S(A6+SA7)
5322 fadd.d COSB6(%pc),%fp2 # B6+S(B7+SB8)
5323
5324 fmul.x %fp0,%fp1 # S(A5+S(A6+SA7))
5325 fmul.x %fp0,%fp2 # S(B6+S(B7+SB8))
5326 fmov.x %fp0,SPRIME(%a6)
5327
5328 fadd.d SINA4(%pc),%fp1 # A4+S(A5+S(A6+SA7))
5329 eor.l %d1,SPRIME(%a6)
5330 fadd.d COSB5(%pc),%fp2 # B5+S(B6+S(B7+SB8))
5331
5332 fmul.x %fp0,%fp1 # S(A4+...)
5333 fmul.x %fp0,%fp2 # S(B5+...)
5334
5335 fadd.d SINA3(%pc),%fp1 # A3+S(A4+...)
5336 fadd.d COSB4(%pc),%fp2 # B4+S(B5+...)
5337
5338 fmul.x %fp0,%fp1 # S(A3+...)
5339 fmul.x %fp0,%fp2 # S(B4+...)
5340
5341 fadd.x SINA2(%pc),%fp1 # A2+S(A3+...)
5342 fadd.x COSB3(%pc),%fp2 # B3+S(B4+...)
5343
5344 fmul.x %fp0,%fp1 # S(A2+...)
5345 fmul.x %fp0,%fp2 # S(B3+...)
5346
5347 fadd.x SINA1(%pc),%fp1 # A1+S(A2+...)
5348 fadd.x COSB2(%pc),%fp2 # B2+S(B3+...)
5349
5350 fmul.x %fp0,%fp1 # S(A1+...)
5351 fmul.x %fp2,%fp0 # S(B2+...)
5352
5353 fmul.x RPRIME(%a6),%fp1 # R'S(A1+...)
5354 fadd.s COSB1(%pc),%fp0 # B1+S(B2...)
5355 fmul.x SPRIME(%a6),%fp0 # S'(B1+S(B2+...))
5356
5357 fmovm.x (%sp)+,&0x20 # restore fp2
5358
5359 fmov.l %d0,%fpcr
5360 fadd.x RPRIME(%a6),%fp1 # COS(X)
5361 bsr sto_cos # store cosine result
5362 fadd.s POSNEG1(%a6),%fp0 # SIN(X)
5363 bra t_inx2
5364
5365 NEVEN:
5366 #--REGISTERS SAVED SO FAR: FP2.
5367 fmovm.x &0x04,-(%sp) # save fp2
5368
5369 fmov.x %fp0,RPRIME(%a6)
5370 fmul.x %fp0,%fp0 # FP0 IS S = R*R
5371
5372 fmov.d COSB8(%pc),%fp1 # B8
5373 fmov.d SINA7(%pc),%fp2 # A7
5374
5375 fmul.x %fp0,%fp1 # SB8
5376 fmov.x %fp0,SPRIME(%a6)
5377 fmul.x %fp0,%fp2 # SA7
5378
5379 ror.l &1,%d1
5380 and.l &0x80000000,%d1
5381
5382 fadd.d COSB7(%pc),%fp1 # B7+SB8
5383 fadd.d SINA6(%pc),%fp2 # A6+SA7
5384
5385 eor.l %d1,RPRIME(%a6)
5386 eor.l %d1,SPRIME(%a6)
5387
5388 fmul.x %fp0,%fp1 # S(B7+SB8)
5389
5390 or.l &0x3F800000,%d1
5391 mov.l %d1,POSNEG1(%a6)
5392
5393 fmul.x %fp0,%fp2 # S(A6+SA7)
5394
5395 fadd.d COSB6(%pc),%fp1 # B6+S(B7+SB8)
5396 fadd.d SINA5(%pc),%fp2 # A5+S(A6+SA7)
5397
5398 fmul.x %fp0,%fp1 # S(B6+S(B7+SB8))
5399 fmul.x %fp0,%fp2 # S(A5+S(A6+SA7))
5400
5401 fadd.d COSB5(%pc),%fp1 # B5+S(B6+S(B7+SB8))
5402 fadd.d SINA4(%pc),%fp2 # A4+S(A5+S(A6+SA7))
5403
5404 fmul.x %fp0,%fp1 # S(B5+...)
5405 fmul.x %fp0,%fp2 # S(A4+...)
5406
5407 fadd.d COSB4(%pc),%fp1 # B4+S(B5+...)
5408 fadd.d SINA3(%pc),%fp2 # A3+S(A4+...)
5409
5410 fmul.x %fp0,%fp1 # S(B4+...)
5411 fmul.x %fp0,%fp2 # S(A3+...)
5412
5413 fadd.x COSB3(%pc),%fp1 # B3+S(B4+...)
5414 fadd.x SINA2(%pc),%fp2 # A2+S(A3+...)
5415
5416 fmul.x %fp0,%fp1 # S(B3+...)
5417 fmul.x %fp0,%fp2 # S(A2+...)
5418
5419 fadd.x COSB2(%pc),%fp1 # B2+S(B3+...)
5420 fadd.x SINA1(%pc),%fp2 # A1+S(A2+...)
5421
5422 fmul.x %fp0,%fp1 # S(B2+...)
5423 fmul.x %fp2,%fp0 # s(a1+...)
5424
5425
5426 fadd.s COSB1(%pc),%fp1 # B1+S(B2...)
5427 fmul.x RPRIME(%a6),%fp0 # R'S(A1+...)
5428 fmul.x SPRIME(%a6),%fp1 # S'(B1+S(B2+...))
5429
5430 fmovm.x (%sp)+,&0x20 # restore fp2
5431
5432 fmov.l %d0,%fpcr
5433 fadd.s POSNEG1(%a6),%fp1 # COS(X)
5434 bsr sto_cos # store cosine result
5435 fadd.x RPRIME(%a6),%fp0 # SIN(X)
5436 bra t_inx2
5437
5438 ################################################
5439
5440 SCBORS:
5441 cmp.l %d1,&0x3FFF8000
5442 bgt.w SREDUCEX
5443
5444 ################################################
5445
5446 SCSM:
5447 # mov.w &0x0000,XDCARE(%a6)
5448 fmov.s &0x3F800000,%fp1
5449
5450 fmov.l %d0,%fpcr
5451 fsub.s &0x00800000,%fp1
5452 bsr sto_cos # store cosine result
5453 fmov.l %fpcr,%d0 # d0 must have fpcr,too
5454 mov.b &FMOV_OP,%d1 # last inst is MOVE
5455 fmov.x X(%a6),%fp0
5456 bra t_catch
5457
5458 ##############################################
5459
5460 global ssincosd
5461 #--SIN AND COS OF X FOR DENORMALIZED X
5462 ssincosd:
5463 mov.l %d0,-(%sp) # save d0
5464 fmov.s &0x3F800000,%fp1
5465 bsr sto_cos # store cosine result
5466 mov.l (%sp)+,%d0 # restore d0
5467 bra t_extdnrm
5468
5469 ############################################
5470
5471 #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5472 #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5473 #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5474 SREDUCEX:
5475 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
5476 mov.l %d2,-(%sp) # save d2
5477 fmov.s &0x00000000,%fp1 # fp1 = 0
5478
5479 #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5480 #--there is a danger of unwanted overflow in first LOOP iteration. In this
5481 #--case, reduce argument by one remainder step to make subsequent reduction
5482 #--safe.
5483 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
5484 bne.b SLOOP # no
5485
5486 # yes; create 2**16383*PI/2
5487 mov.w &0x7ffe,FP_SCR0_EX(%a6)
5488 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
5489 clr.l FP_SCR0_LO(%a6)
5490
5491 # create low half of 2**16383*PI/2 at FP_SCR1
5492 mov.w &0x7fdc,FP_SCR1_EX(%a6)
5493 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
5494 clr.l FP_SCR1_LO(%a6)
5495
5496 ftest.x %fp0 # test sign of argument
5497 fblt.w sred_neg
5498
5499 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
5500 or.b &0x80,FP_SCR1_EX(%a6)
5501 sred_neg:
5502 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
5503 fmov.x %fp0,%fp1 # save high result in fp1
5504 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
5505 fsub.x %fp0,%fp1 # determine low component of result
5506 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
5507
5508 #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5509 #--integer quotient will be stored in N
5510 #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5511 SLOOP:
5512 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
5513 mov.w INARG(%a6),%d1
5514 mov.l %d1,%a1 # save a copy of D0
5515 and.l &0x00007FFF,%d1
5516 sub.l &0x00003FFF,%d1 # d0 = K
5517 cmp.l %d1,&28
5518 ble.b SLASTLOOP
5519 SCONTLOOP:
5520 sub.l &27,%d1 # d0 = L := K-27
5521 mov.b &0,ENDFLAG(%a6)
5522 bra.b SWORK
5523 SLASTLOOP:
5524 clr.l %d1 # d0 = L := 0
5525 mov.b &1,ENDFLAG(%a6)
5526
5527 SWORK:
5528 #--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
5529 #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5530
5531 #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5532 #--2**L * (PIby2_1), 2**L * (PIby2_2)
5533
5534 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
5535 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
5536
5537 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
5538 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
5539 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
5540
5541 fmov.x %fp0,%fp2
5542 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
5543
5544 #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5545 #--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
5546 #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5547 #--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
5548 #--US THE DESIRED VALUE IN FLOATING POINT.
5549 mov.l %a1,%d2
5550 swap %d2
5551 and.l &0x80000000,%d2
5552 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
5553 mov.l %d2,TWOTO63(%a6)
5554 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
5555 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
5556 # fint.x %fp2
5557
5558 #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5559 mov.l %d1,%d2 # d2 = L
5560
5561 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
5562 mov.w %d2,FP_SCR0_EX(%a6)
5563 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
5564 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
5565
5566 add.l &0x00003FDD,%d1
5567 mov.w %d1,FP_SCR1_EX(%a6)
5568 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
5569 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
5570
5571 mov.b ENDFLAG(%a6),%d1
5572
5573 #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
5574 #--P2 = 2**(L) * Piby2_2
5575 fmov.x %fp2,%fp4 # fp4 = N
5576 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
5577 fmov.x %fp2,%fp5 # fp5 = N
5578 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
5579 fmov.x %fp4,%fp3 # fp3 = W = N*P1
5580
5581 #--we want P+p = W+w but |p| <= half ulp of P
5582 #--Then, we need to compute A := R-P and a := r-p
5583 fadd.x %fp5,%fp3 # fp3 = P
5584 fsub.x %fp3,%fp4 # fp4 = W-P
5585
5586 fsub.x %fp3,%fp0 # fp0 = A := R - P
5587 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
5588
5589 fmov.x %fp0,%fp3 # fp3 = A
5590 fsub.x %fp4,%fp1 # fp1 = a := r - p
5591
5592 #--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
5593 #--|r| <= half ulp of R.
5594 fadd.x %fp1,%fp0 # fp0 = R := A+a
5595 #--No need to calculate r if this is the last loop
5596 cmp.b %d1,&0
5597 bgt.w SRESTORE
5598
5599 #--Need to calculate r
5600 fsub.x %fp0,%fp3 # fp3 = A-R
5601 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
5602 bra.w SLOOP
5603
5604 SRESTORE:
5605 fmov.l %fp2,INT(%a6)
5606 mov.l (%sp)+,%d2 # restore d2
5607 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
5608
5609 mov.l ADJN(%a6),%d1
5610 cmp.l %d1,&4
5611
5612 blt.w SINCONT
5613 bra.w SCCONT
5614
5615 #########################################################################
5616 # stan(): computes the tangent of a normalized input #
5617 # stand(): computes the tangent of a denormalized input #
5618 # #
5619 # INPUT *************************************************************** #
5620 # a0 = pointer to extended precision input #
5621 # d0 = round precision,mode #
5622 # #
5623 # OUTPUT ************************************************************** #
5624 # fp0 = tan(X) #
5625 # #
5626 # ACCURACY and MONOTONICITY ******************************************* #
5627 # The returned result is within 3 ulp in 64 significant bit, i.e. #
5628 # within 0.5001 ulp to 53 bits if the result is subsequently #
5629 # rounded to double precision. The result is provably monotonic #
5630 # in double precision. #
5631 # #
5632 # ALGORITHM *********************************************************** #
5633 # #
5634 # 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6. #
5635 # #
5636 # 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let #
5637 # k = N mod 2, so in particular, k = 0 or 1. #
5638 # #
5639 # 3. If k is odd, go to 5. #
5640 # #
5641 # 4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a #
5642 # rational function U/V where #
5643 # U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5644 # V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r. #
5645 # Exit. #
5646 # #
5647 # 4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
5648 # a rational function U/V where #
5649 # U = r + r*s*(P1 + s*(P2 + s*P3)), and #
5650 # V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r, #
5651 # -Cot(r) = -V/U. Exit. #
5652 # #
5653 # 6. If |X| > 1, go to 8. #
5654 # #
5655 # 7. (|X|<2**(-40)) Tan(X) = X. Exit. #
5656 # #
5657 # 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back #
5658 # to 2. #
5659 # #
5660 #########################################################################
5661
5662 TANQ4:
5663 long 0x3EA0B759,0xF50F8688
5664 TANP3:
5665 long 0xBEF2BAA5,0xA8924F04
5666
5667 TANQ3:
5668 long 0xBF346F59,0xB39BA65F,0x00000000,0x00000000
5669
5670 TANP2:
5671 long 0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
5672
5673 TANQ2:
5674 long 0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
5675
5676 TANP1:
5677 long 0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
5678
5679 TANQ1:
5680 long 0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
5681
5682 INVTWOPI:
5683 long 0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
5684
5685 TWOPI1:
5686 long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
5687 TWOPI2:
5688 long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
5689
5690 #--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
5691 #--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
5692 #--MOST 69 BITS LONG.
5693 # global PITBL
5694 PITBL:
5695 long 0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
5696 long 0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
5697 long 0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
5698 long 0xC0040000,0xB6365E22,0xEE46F000,0x21480000
5699 long 0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
5700 long 0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
5701 long 0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
5702 long 0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
5703 long 0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
5704 long 0xC0040000,0x90836524,0x88034B96,0x20B00000
5705 long 0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
5706 long 0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
5707 long 0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
5708 long 0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
5709 long 0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
5710 long 0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
5711 long 0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
5712 long 0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
5713 long 0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
5714 long 0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
5715 long 0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
5716 long 0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
5717 long 0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
5718 long 0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
5719 long 0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
5720 long 0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
5721 long 0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
5722 long 0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
5723 long 0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
5724 long 0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
5725 long 0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
5726 long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
5727 long 0x00000000,0x00000000,0x00000000,0x00000000
5728 long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
5729 long 0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
5730 long 0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
5731 long 0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
5732 long 0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
5733 long 0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
5734 long 0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
5735 long 0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
5736 long 0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
5737 long 0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
5738 long 0x40030000,0x8A3AE64F,0x76F80584,0x21080000
5739 long 0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
5740 long 0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
5741 long 0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
5742 long 0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
5743 long 0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
5744 long 0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
5745 long 0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
5746 long 0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
5747 long 0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
5748 long 0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
5749 long 0x40040000,0x8A3AE64F,0x76F80584,0x21880000
5750 long 0x40040000,0x90836524,0x88034B96,0xA0B00000
5751 long 0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
5752 long 0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
5753 long 0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
5754 long 0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
5755 long 0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
5756 long 0x40040000,0xB6365E22,0xEE46F000,0xA1480000
5757 long 0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
5758 long 0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
5759 long 0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
5760
5761 set INARG,FP_SCR0
5762
5763 set TWOTO63,L_SCR1
5764 set INT,L_SCR1
5765 set ENDFLAG,L_SCR2
5766
5767 global stan
5768 stan:
5769 fmov.x (%a0),%fp0 # LOAD INPUT
5770
5771 mov.l (%a0),%d1
5772 mov.w 4(%a0),%d1
5773 and.l &0x7FFFFFFF,%d1
5774
5775 cmp.l %d1,&0x3FD78000 # |X| >= 2**(-40)?
5776 bge.b TANOK1
5777 bra.w TANSM
5778 TANOK1:
5779 cmp.l %d1,&0x4004BC7E # |X| < 15 PI?
5780 blt.b TANMAIN
5781 bra.w REDUCEX
5782
5783 TANMAIN:
5784 #--THIS IS THE USUAL CASE, |X| <= 15 PI.
5785 #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
5786 fmov.x %fp0,%fp1
5787 fmul.d TWOBYPI(%pc),%fp1 # X*2/PI
5788
5789 lea.l PITBL+0x200(%pc),%a1 # TABLE OF N*PI/2, N = -32,...,32
5790
5791 fmov.l %fp1,%d1 # CONVERT TO INTEGER
5792
5793 asl.l &4,%d1
5794 add.l %d1,%a1 # ADDRESS N*PIBY2 IN Y1, Y2
5795
5796 fsub.x (%a1)+,%fp0 # X-Y1
5797
5798 fsub.s (%a1),%fp0 # FP0 IS R = (X-Y1)-Y2
5799
5800 ror.l &5,%d1
5801 and.l &0x80000000,%d1 # D0 WAS ODD IFF D0 < 0
5802
5803 TANCONT:
5804 fmovm.x &0x0c,-(%sp) # save fp2,fp3
5805
5806 cmp.l %d1,&0
5807 blt.w NODD
5808
5809 fmov.x %fp0,%fp1
5810 fmul.x %fp1,%fp1 # S = R*R
5811
5812 fmov.d TANQ4(%pc),%fp3
5813 fmov.d TANP3(%pc),%fp2
5814
5815 fmul.x %fp1,%fp3 # SQ4
5816 fmul.x %fp1,%fp2 # SP3
5817
5818 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5819 fadd.x TANP2(%pc),%fp2 # P2+SP3
5820
5821 fmul.x %fp1,%fp3 # S(Q3+SQ4)
5822 fmul.x %fp1,%fp2 # S(P2+SP3)
5823
5824 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5825 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5826
5827 fmul.x %fp1,%fp3 # S(Q2+S(Q3+SQ4))
5828 fmul.x %fp1,%fp2 # S(P1+S(P2+SP3))
5829
5830 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5831 fmul.x %fp0,%fp2 # RS(P1+S(P2+SP3))
5832
5833 fmul.x %fp3,%fp1 # S(Q1+S(Q2+S(Q3+SQ4)))
5834
5835 fadd.x %fp2,%fp0 # R+RS(P1+S(P2+SP3))
5836
5837 fadd.s &0x3F800000,%fp1 # 1+S(Q1+...)
5838
5839 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5840
5841 fmov.l %d0,%fpcr # restore users round mode,prec
5842 fdiv.x %fp1,%fp0 # last inst - possible exception set
5843 bra t_inx2
5844
5845 NODD:
5846 fmov.x %fp0,%fp1
5847 fmul.x %fp0,%fp0 # S = R*R
5848
5849 fmov.d TANQ4(%pc),%fp3
5850 fmov.d TANP3(%pc),%fp2
5851
5852 fmul.x %fp0,%fp3 # SQ4
5853 fmul.x %fp0,%fp2 # SP3
5854
5855 fadd.d TANQ3(%pc),%fp3 # Q3+SQ4
5856 fadd.x TANP2(%pc),%fp2 # P2+SP3
5857
5858 fmul.x %fp0,%fp3 # S(Q3+SQ4)
5859 fmul.x %fp0,%fp2 # S(P2+SP3)
5860
5861 fadd.x TANQ2(%pc),%fp3 # Q2+S(Q3+SQ4)
5862 fadd.x TANP1(%pc),%fp2 # P1+S(P2+SP3)
5863
5864 fmul.x %fp0,%fp3 # S(Q2+S(Q3+SQ4))
5865 fmul.x %fp0,%fp2 # S(P1+S(P2+SP3))
5866
5867 fadd.x TANQ1(%pc),%fp3 # Q1+S(Q2+S(Q3+SQ4))
5868 fmul.x %fp1,%fp2 # RS(P1+S(P2+SP3))
5869
5870 fmul.x %fp3,%fp0 # S(Q1+S(Q2+S(Q3+SQ4)))
5871
5872 fadd.x %fp2,%fp1 # R+RS(P1+S(P2+SP3))
5873 fadd.s &0x3F800000,%fp0 # 1+S(Q1+...)
5874
5875 fmovm.x (%sp)+,&0x30 # restore fp2,fp3
5876
5877 fmov.x %fp1,-(%sp)
5878 eor.l &0x80000000,(%sp)
5879
5880 fmov.l %d0,%fpcr # restore users round mode,prec
5881 fdiv.x (%sp)+,%fp0 # last inst - possible exception set
5882 bra t_inx2
5883
5884 TANBORS:
5885 #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
5886 #--IF |X| < 2**(-40), RETURN X OR 1.
5887 cmp.l %d1,&0x3FFF8000
5888 bgt.b REDUCEX
5889
5890 TANSM:
5891 fmov.x %fp0,-(%sp)
5892 fmov.l %d0,%fpcr # restore users round mode,prec
5893 mov.b &FMOV_OP,%d1 # last inst is MOVE
5894 fmov.x (%sp)+,%fp0 # last inst - posibble exception set
5895 bra t_catch
5896
5897 global stand
5898 #--TAN(X) = X FOR DENORMALIZED X
5899 stand:
5900 bra t_extdnrm
5901
5902 #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
5903 #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
5904 #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
5905 REDUCEX:
5906 fmovm.x &0x3c,-(%sp) # save {fp2-fp5}
5907 mov.l %d2,-(%sp) # save d2
5908 fmov.s &0x00000000,%fp1 # fp1 = 0
5909
5910 #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
5911 #--there is a danger of unwanted overflow in first LOOP iteration. In this
5912 #--case, reduce argument by one remainder step to make subsequent reduction
5913 #--safe.
5914 cmp.l %d1,&0x7ffeffff # is arg dangerously large?
5915 bne.b LOOP # no
5916
5917 # yes; create 2**16383*PI/2
5918 mov.w &0x7ffe,FP_SCR0_EX(%a6)
5919 mov.l &0xc90fdaa2,FP_SCR0_HI(%a6)
5920 clr.l FP_SCR0_LO(%a6)
5921
5922 # create low half of 2**16383*PI/2 at FP_SCR1
5923 mov.w &0x7fdc,FP_SCR1_EX(%a6)
5924 mov.l &0x85a308d3,FP_SCR1_HI(%a6)
5925 clr.l FP_SCR1_LO(%a6)
5926
5927 ftest.x %fp0 # test sign of argument
5928 fblt.w red_neg
5929
5930 or.b &0x80,FP_SCR0_EX(%a6) # positive arg
5931 or.b &0x80,FP_SCR1_EX(%a6)
5932 red_neg:
5933 fadd.x FP_SCR0(%a6),%fp0 # high part of reduction is exact
5934 fmov.x %fp0,%fp1 # save high result in fp1
5935 fadd.x FP_SCR1(%a6),%fp0 # low part of reduction
5936 fsub.x %fp0,%fp1 # determine low component of result
5937 fadd.x FP_SCR1(%a6),%fp1 # fp0/fp1 are reduced argument.
5938
5939 #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
5940 #--integer quotient will be stored in N
5941 #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
5942 LOOP:
5943 fmov.x %fp0,INARG(%a6) # +-2**K * F, 1 <= F < 2
5944 mov.w INARG(%a6),%d1
5945 mov.l %d1,%a1 # save a copy of D0
5946 and.l &0x00007FFF,%d1
5947 sub.l &0x00003FFF,%d1 # d0 = K
5948 cmp.l %d1,&28
5949 ble.b LASTLOOP
5950 CONTLOOP:
5951 sub.l &27,%d1 # d0 = L := K-27
5952 mov.b &0,ENDFLAG(%a6)
5953 bra.b WORK
5954 LASTLOOP:
5955 clr.l %d1 # d0 = L := 0
5956 mov.b &1,ENDFLAG(%a6)
5957
5958 WORK:
5959 #--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
5960 #--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
5961
5962 #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
5963 #--2**L * (PIby2_1), 2**L * (PIby2_2)
5964
5965 mov.l &0x00003FFE,%d2 # BIASED EXP OF 2/PI
5966 sub.l %d1,%d2 # BIASED EXP OF 2**(-L)*(2/PI)
5967
5968 mov.l &0xA2F9836E,FP_SCR0_HI(%a6)
5969 mov.l &0x4E44152A,FP_SCR0_LO(%a6)
5970 mov.w %d2,FP_SCR0_EX(%a6) # FP_SCR0 = 2**(-L)*(2/PI)
5971
5972 fmov.x %fp0,%fp2
5973 fmul.x FP_SCR0(%a6),%fp2 # fp2 = X * 2**(-L)*(2/PI)
5974
5975 #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
5976 #--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.L FP <--> N
5977 #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
5978 #--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
5979 #--US THE DESIRED VALUE IN FLOATING POINT.
5980 mov.l %a1,%d2
5981 swap %d2
5982 and.l &0x80000000,%d2
5983 or.l &0x5F000000,%d2 # d2 = SIGN(INARG)*2**63 IN SGL
5984 mov.l %d2,TWOTO63(%a6)
5985 fadd.s TWOTO63(%a6),%fp2 # THE FRACTIONAL PART OF FP1 IS ROUNDED
5986 fsub.s TWOTO63(%a6),%fp2 # fp2 = N
5987 # fintrz.x %fp2,%fp2
5988
5989 #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
5990 mov.l %d1,%d2 # d2 = L
5991
5992 add.l &0x00003FFF,%d2 # BIASED EXP OF 2**L * (PI/2)
5993 mov.w %d2,FP_SCR0_EX(%a6)
5994 mov.l &0xC90FDAA2,FP_SCR0_HI(%a6)
5995 clr.l FP_SCR0_LO(%a6) # FP_SCR0 = 2**(L) * Piby2_1
5996
5997 add.l &0x00003FDD,%d1
5998 mov.w %d1,FP_SCR1_EX(%a6)
5999 mov.l &0x85A308D3,FP_SCR1_HI(%a6)
6000 clr.l FP_SCR1_LO(%a6) # FP_SCR1 = 2**(L) * Piby2_2
6001
6002 mov.b ENDFLAG(%a6),%d1
6003
6004 #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
6005 #--P2 = 2**(L) * Piby2_2
6006 fmov.x %fp2,%fp4 # fp4 = N
6007 fmul.x FP_SCR0(%a6),%fp4 # fp4 = W = N*P1
6008 fmov.x %fp2,%fp5 # fp5 = N
6009 fmul.x FP_SCR1(%a6),%fp5 # fp5 = w = N*P2
6010 fmov.x %fp4,%fp3 # fp3 = W = N*P1
6011
6012 #--we want P+p = W+w but |p| <= half ulp of P
6013 #--Then, we need to compute A := R-P and a := r-p
6014 fadd.x %fp5,%fp3 # fp3 = P
6015 fsub.x %fp3,%fp4 # fp4 = W-P
6016
6017 fsub.x %fp3,%fp0 # fp0 = A := R - P
6018 fadd.x %fp5,%fp4 # fp4 = p = (W-P)+w
6019
6020 fmov.x %fp0,%fp3 # fp3 = A
6021 fsub.x %fp4,%fp1 # fp1 = a := r - p
6022
6023 #--Now we need to normalize (A,a) to "new (R,r)" where R+r = A+a but
6024 #--|r| <= half ulp of R.
6025 fadd.x %fp1,%fp0 # fp0 = R := A+a
6026 #--No need to calculate r if this is the last loop
6027 cmp.b %d1,&0
6028 bgt.w RESTORE
6029
6030 #--Need to calculate r
6031 fsub.x %fp0,%fp3 # fp3 = A-R
6032 fadd.x %fp3,%fp1 # fp1 = r := (A-R)+a
6033 bra.w LOOP
6034
6035 RESTORE:
6036 fmov.l %fp2,INT(%a6)
6037 mov.l (%sp)+,%d2 # restore d2
6038 fmovm.x (%sp)+,&0x3c # restore {fp2-fp5}
6039
6040 mov.l INT(%a6),%d1
6041 ror.l &1,%d1
6042
6043 bra.w TANCONT
6044
6045 #########################################################################
6046 # satan(): computes the arctangent of a normalized number #
6047 # satand(): computes the arctangent of a denormalized number #
6048 # #
6049 # INPUT *************************************************************** #
6050 # a0 = pointer to extended precision input #
6051 # d0 = round precision,mode #
6052 # #
6053 # OUTPUT ************************************************************** #
6054 # fp0 = arctan(X) #
6055 # #
6056 # ACCURACY and MONOTONICITY ******************************************* #
6057 # The returned result is within 2 ulps in 64 significant bit, #
6058 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6059 # rounded to double precision. The result is provably monotonic #
6060 # in double precision. #
6061 # #
6062 # ALGORITHM *********************************************************** #
6063 # Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5. #
6064 # #
6065 # Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x. #
6066 # Note that k = -4, -3,..., or 3. #
6067 # Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5 #
6068 # significant bits of X with a bit-1 attached at the 6-th #
6069 # bit position. Define u to be u = (X-F) / (1 + X*F). #
6070 # #
6071 # Step 3. Approximate arctan(u) by a polynomial poly. #
6072 # #
6073 # Step 4. Return arctan(F) + poly, arctan(F) is fetched from a #
6074 # table of values calculated beforehand. Exit. #
6075 # #
6076 # Step 5. If |X| >= 16, go to Step 7. #
6077 # #
6078 # Step 6. Approximate arctan(X) by an odd polynomial in X. Exit. #
6079 # #
6080 # Step 7. Define X' = -1/X. Approximate arctan(X') by an odd #
6081 # polynomial in X'. #
6082 # Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit. #
6083 # #
6084 #########################################################################
6085
6086 ATANA3: long 0xBFF6687E,0x314987D8
6087 ATANA2: long 0x4002AC69,0x34A26DB3
6088 ATANA1: long 0xBFC2476F,0x4E1DA28E
6089
6090 ATANB6: long 0x3FB34444,0x7F876989
6091 ATANB5: long 0xBFB744EE,0x7FAF45DB
6092 ATANB4: long 0x3FBC71C6,0x46940220
6093 ATANB3: long 0xBFC24924,0x921872F9
6094 ATANB2: long 0x3FC99999,0x99998FA9
6095 ATANB1: long 0xBFD55555,0x55555555
6096
6097 ATANC5: long 0xBFB70BF3,0x98539E6A
6098 ATANC4: long 0x3FBC7187,0x962D1D7D
6099 ATANC3: long 0xBFC24924,0x827107B8
6100 ATANC2: long 0x3FC99999,0x9996263E
6101 ATANC1: long 0xBFD55555,0x55555536
6102
6103 PPIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
6104 NPIBY2: long 0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
6105
6106 PTINY: long 0x00010000,0x80000000,0x00000000,0x00000000
6107 NTINY: long 0x80010000,0x80000000,0x00000000,0x00000000
6108
6109 ATANTBL:
6110 long 0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
6111 long 0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
6112 long 0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
6113 long 0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
6114 long 0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
6115 long 0x3FFB0000,0xAB98E943,0x62765619,0x00000000
6116 long 0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
6117 long 0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
6118 long 0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
6119 long 0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
6120 long 0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
6121 long 0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
6122 long 0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
6123 long 0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
6124 long 0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
6125 long 0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
6126 long 0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
6127 long 0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
6128 long 0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
6129 long 0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
6130 long 0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
6131 long 0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
6132 long 0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
6133 long 0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
6134 long 0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
6135 long 0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
6136 long 0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
6137 long 0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
6138 long 0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
6139 long 0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
6140 long 0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
6141 long 0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
6142 long 0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
6143 long 0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
6144 long 0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
6145 long 0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
6146 long 0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
6147 long 0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
6148 long 0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
6149 long 0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
6150 long 0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
6151 long 0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
6152 long 0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
6153 long 0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
6154 long 0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
6155 long 0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
6156 long 0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
6157 long 0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
6158 long 0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
6159 long 0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
6160 long 0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
6161 long 0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
6162 long 0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
6163 long 0x3FFE0000,0x97731420,0x365E538C,0x00000000
6164 long 0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
6165 long 0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
6166 long 0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
6167 long 0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
6168 long 0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
6169 long 0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
6170 long 0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
6171 long 0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
6172 long 0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
6173 long 0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
6174 long 0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
6175 long 0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
6176 long 0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
6177 long 0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
6178 long 0x3FFE0000,0xE8771129,0xC4353259,0x00000000
6179 long 0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
6180 long 0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
6181 long 0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
6182 long 0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
6183 long 0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
6184 long 0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
6185 long 0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
6186 long 0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
6187 long 0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
6188 long 0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
6189 long 0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
6190 long 0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
6191 long 0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
6192 long 0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
6193 long 0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
6194 long 0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
6195 long 0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
6196 long 0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
6197 long 0x3FFF0000,0x9F100575,0x006CC571,0x00000000
6198 long 0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
6199 long 0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
6200 long 0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
6201 long 0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
6202 long 0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
6203 long 0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
6204 long 0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
6205 long 0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
6206 long 0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
6207 long 0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
6208 long 0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
6209 long 0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
6210 long 0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
6211 long 0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
6212 long 0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
6213 long 0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
6214 long 0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
6215 long 0x3FFF0000,0xB525529D,0x562246BD,0x00000000
6216 long 0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
6217 long 0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
6218 long 0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
6219 long 0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
6220 long 0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
6221 long 0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
6222 long 0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
6223 long 0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
6224 long 0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
6225 long 0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
6226 long 0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
6227 long 0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
6228 long 0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
6229 long 0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
6230 long 0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
6231 long 0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
6232 long 0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
6233 long 0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
6234 long 0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
6235 long 0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
6236 long 0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
6237 long 0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
6238
6239 set X,FP_SCR0
6240 set XDCARE,X+2
6241 set XFRAC,X+4
6242 set XFRACLO,X+8
6243
6244 set ATANF,FP_SCR1
6245 set ATANFHI,ATANF+4
6246 set ATANFLO,ATANF+8
6247
6248 global satan
6249 #--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
6250 satan:
6251 fmov.x (%a0),%fp0 # LOAD INPUT
6252
6253 mov.l (%a0),%d1
6254 mov.w 4(%a0),%d1
6255 fmov.x %fp0,X(%a6)
6256 and.l &0x7FFFFFFF,%d1
6257
6258 cmp.l %d1,&0x3FFB8000 # |X| >= 1/16?
6259 bge.b ATANOK1
6260 bra.w ATANSM
6261
6262 ATANOK1:
6263 cmp.l %d1,&0x4002FFFF # |X| < 16 ?
6264 ble.b ATANMAIN
6265 bra.w ATANBIG
6266
6267 #--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
6268 #--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
6269 #--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
6270 #--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
6271 #--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
6272 #--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
6273 #--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
6274 #--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
6275 #--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
6276 #--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
6277 #--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
6278 #--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
6279 #--WILL INVOLVE A VERY LONG POLYNOMIAL.
6280
6281 #--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
6282 #--WE CHOSE F TO BE +-2^K * 1.BBBB1
6283 #--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
6284 #--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
6285 #--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
6286 #-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
6287
6288 ATANMAIN:
6289
6290 and.l &0xF8000000,XFRAC(%a6) # FIRST 5 BITS
6291 or.l &0x04000000,XFRAC(%a6) # SET 6-TH BIT TO 1
6292 mov.l &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
6293
6294 fmov.x %fp0,%fp1 # FP1 IS X
6295 fmul.x X(%a6),%fp1 # FP1 IS X*F, NOTE THAT X*F > 0
6296 fsub.x X(%a6),%fp0 # FP0 IS X-F
6297 fadd.s &0x3F800000,%fp1 # FP1 IS 1 + X*F
6298 fdiv.x %fp1,%fp0 # FP0 IS U = (X-F)/(1+X*F)
6299
6300 #--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
6301 #--CREATE ATAN(F) AND STORE IT IN ATANF, AND
6302 #--SAVE REGISTERS FP2.
6303
6304 mov.l %d2,-(%sp) # SAVE d2 TEMPORARILY
6305 mov.l %d1,%d2 # THE EXP AND 16 BITS OF X
6306 and.l &0x00007800,%d1 # 4 VARYING BITS OF F'S FRACTION
6307 and.l &0x7FFF0000,%d2 # EXPONENT OF F
6308 sub.l &0x3FFB0000,%d2 # K+4
6309 asr.l &1,%d2
6310 add.l %d2,%d1 # THE 7 BITS IDENTIFYING F
6311 asr.l &7,%d1 # INDEX INTO TBL OF ATAN(|F|)
6312 lea ATANTBL(%pc),%a1
6313 add.l %d1,%a1 # ADDRESS OF ATAN(|F|)
6314 mov.l (%a1)+,ATANF(%a6)
6315 mov.l (%a1)+,ATANFHI(%a6)
6316 mov.l (%a1)+,ATANFLO(%a6) # ATANF IS NOW ATAN(|F|)
6317 mov.l X(%a6),%d1 # LOAD SIGN AND EXPO. AGAIN
6318 and.l &0x80000000,%d1 # SIGN(F)
6319 or.l %d1,ATANF(%a6) # ATANF IS NOW SIGN(F)*ATAN(|F|)
6320 mov.l (%sp)+,%d2 # RESTORE d2
6321
6322 #--THAT'S ALL I HAVE TO DO FOR NOW,
6323 #--BUT ALAS, THE DIVIDE IS STILL CRANKING!
6324
6325 #--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
6326 #--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
6327 #--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
6328 #--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
6329 #--WHAT WE HAVE HERE IS MERELY A1 = A3, A2 = A1/A3, A3 = A2/A3.
6330 #--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
6331 #--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
6332
6333 fmovm.x &0x04,-(%sp) # save fp2
6334
6335 fmov.x %fp0,%fp1
6336 fmul.x %fp1,%fp1
6337 fmov.d ATANA3(%pc),%fp2
6338 fadd.x %fp1,%fp2 # A3+V
6339 fmul.x %fp1,%fp2 # V*(A3+V)
6340 fmul.x %fp0,%fp1 # U*V
6341 fadd.d ATANA2(%pc),%fp2 # A2+V*(A3+V)
6342 fmul.d ATANA1(%pc),%fp1 # A1*U*V
6343 fmul.x %fp2,%fp1 # A1*U*V*(A2+V*(A3+V))
6344 fadd.x %fp1,%fp0 # ATAN(U), FP1 RELEASED
6345
6346 fmovm.x (%sp)+,&0x20 # restore fp2
6347
6348 fmov.l %d0,%fpcr # restore users rnd mode,prec
6349 fadd.x ATANF(%a6),%fp0 # ATAN(X)
6350 bra t_inx2
6351
6352 ATANBORS:
6353 #--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
6354 #--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
6355 cmp.l %d1,&0x3FFF8000
6356 bgt.w ATANBIG # I.E. |X| >= 16
6357
6358 ATANSM:
6359 #--|X| <= 1/16
6360 #--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
6361 #--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
6362 #--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
6363 #--WHERE Y = X*X, AND Z = Y*Y.
6364
6365 cmp.l %d1,&0x3FD78000
6366 blt.w ATANTINY
6367
6368 #--COMPUTE POLYNOMIAL
6369 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6370
6371 fmul.x %fp0,%fp0 # FPO IS Y = X*X
6372
6373 fmov.x %fp0,%fp1
6374 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6375
6376 fmov.d ATANB6(%pc),%fp2
6377 fmov.d ATANB5(%pc),%fp3
6378
6379 fmul.x %fp1,%fp2 # Z*B6
6380 fmul.x %fp1,%fp3 # Z*B5
6381
6382 fadd.d ATANB4(%pc),%fp2 # B4+Z*B6
6383 fadd.d ATANB3(%pc),%fp3 # B3+Z*B5
6384
6385 fmul.x %fp1,%fp2 # Z*(B4+Z*B6)
6386 fmul.x %fp3,%fp1 # Z*(B3+Z*B5)
6387
6388 fadd.d ATANB2(%pc),%fp2 # B2+Z*(B4+Z*B6)
6389 fadd.d ATANB1(%pc),%fp1 # B1+Z*(B3+Z*B5)
6390
6391 fmul.x %fp0,%fp2 # Y*(B2+Z*(B4+Z*B6))
6392 fmul.x X(%a6),%fp0 # X*Y
6393
6394 fadd.x %fp2,%fp1 # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
6395
6396 fmul.x %fp1,%fp0 # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
6397
6398 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6399
6400 fmov.l %d0,%fpcr # restore users rnd mode,prec
6401 fadd.x X(%a6),%fp0
6402 bra t_inx2
6403
6404 ATANTINY:
6405 #--|X| < 2^(-40), ATAN(X) = X
6406
6407 fmov.l %d0,%fpcr # restore users rnd mode,prec
6408 mov.b &FMOV_OP,%d1 # last inst is MOVE
6409 fmov.x X(%a6),%fp0 # last inst - possible exception set
6410
6411 bra t_catch
6412
6413 ATANBIG:
6414 #--IF |X| > 2^(100), RETURN SIGN(X)*(PI/2 - TINY). OTHERWISE,
6415 #--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
6416 cmp.l %d1,&0x40638000
6417 bgt.w ATANHUGE
6418
6419 #--APPROXIMATE ATAN(-1/X) BY
6420 #--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
6421 #--THIS CAN BE RE-WRITTEN AS
6422 #--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
6423
6424 fmovm.x &0x0c,-(%sp) # save fp2/fp3
6425
6426 fmov.s &0xBF800000,%fp1 # LOAD -1
6427 fdiv.x %fp0,%fp1 # FP1 IS -1/X
6428
6429 #--DIVIDE IS STILL CRANKING
6430
6431 fmov.x %fp1,%fp0 # FP0 IS X'
6432 fmul.x %fp0,%fp0 # FP0 IS Y = X'*X'
6433 fmov.x %fp1,X(%a6) # X IS REALLY X'
6434
6435 fmov.x %fp0,%fp1
6436 fmul.x %fp1,%fp1 # FP1 IS Z = Y*Y
6437
6438 fmov.d ATANC5(%pc),%fp3
6439 fmov.d ATANC4(%pc),%fp2
6440
6441 fmul.x %fp1,%fp3 # Z*C5
6442 fmul.x %fp1,%fp2 # Z*B4
6443
6444 fadd.d ATANC3(%pc),%fp3 # C3+Z*C5
6445 fadd.d ATANC2(%pc),%fp2 # C2+Z*C4
6446
6447 fmul.x %fp3,%fp1 # Z*(C3+Z*C5), FP3 RELEASED
6448 fmul.x %fp0,%fp2 # Y*(C2+Z*C4)
6449
6450 fadd.d ATANC1(%pc),%fp1 # C1+Z*(C3+Z*C5)
6451 fmul.x X(%a6),%fp0 # X'*Y
6452
6453 fadd.x %fp2,%fp1 # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
6454
6455 fmul.x %fp1,%fp0 # X'*Y*([B1+Z*(B3+Z*B5)]
6456 # ... +[Y*(B2+Z*(B4+Z*B6))])
6457 fadd.x X(%a6),%fp0
6458
6459 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
6460
6461 fmov.l %d0,%fpcr # restore users rnd mode,prec
6462 tst.b (%a0)
6463 bpl.b pos_big
6464
6465 neg_big:
6466 fadd.x NPIBY2(%pc),%fp0
6467 bra t_minx2
6468
6469 pos_big:
6470 fadd.x PPIBY2(%pc),%fp0
6471 bra t_pinx2
6472
6473 ATANHUGE:
6474 #--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
6475 tst.b (%a0)
6476 bpl.b pos_huge
6477
6478 neg_huge:
6479 fmov.x NPIBY2(%pc),%fp0
6480 fmov.l %d0,%fpcr
6481 fadd.x PTINY(%pc),%fp0
6482 bra t_minx2
6483
6484 pos_huge:
6485 fmov.x PPIBY2(%pc),%fp0
6486 fmov.l %d0,%fpcr
6487 fadd.x NTINY(%pc),%fp0
6488 bra t_pinx2
6489
6490 global satand
6491 #--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
6492 satand:
6493 bra t_extdnrm
6494
6495 #########################################################################
6496 # sasin(): computes the inverse sine of a normalized input #
6497 # sasind(): computes the inverse sine of a denormalized input #
6498 # #
6499 # INPUT *************************************************************** #
6500 # a0 = pointer to extended precision input #
6501 # d0 = round precision,mode #
6502 # #
6503 # OUTPUT ************************************************************** #
6504 # fp0 = arcsin(X) #
6505 # #
6506 # ACCURACY and MONOTONICITY ******************************************* #
6507 # The returned result is within 3 ulps in 64 significant bit, #
6508 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6509 # rounded to double precision. The result is provably monotonic #
6510 # in double precision. #
6511 # #
6512 # ALGORITHM *********************************************************** #
6513 # #
6514 # ASIN #
6515 # 1. If |X| >= 1, go to 3. #
6516 # #
6517 # 2. (|X| < 1) Calculate asin(X) by #
6518 # z := sqrt( [1-X][1+X] ) #
6519 # asin(X) = atan( x / z ). #
6520 # Exit. #
6521 # #
6522 # 3. If |X| > 1, go to 5. #
6523 # #
6524 # 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
6525 # #
6526 # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6527 # Exit. #
6528 # #
6529 #########################################################################
6530
6531 global sasin
6532 sasin:
6533 fmov.x (%a0),%fp0 # LOAD INPUT
6534
6535 mov.l (%a0),%d1
6536 mov.w 4(%a0),%d1
6537 and.l &0x7FFFFFFF,%d1
6538 cmp.l %d1,&0x3FFF8000
6539 bge.b ASINBIG
6540
6541 # This catch is added here for the '060 QSP. Originally, the call to
6542 # satan() would handle this case by causing the exception which would
6543 # not be caught until gen_except(). Now, with the exceptions being
6544 # detected inside of satan(), the exception would have been handled there
6545 # instead of inside sasin() as expected.
6546 cmp.l %d1,&0x3FD78000
6547 blt.w ASINTINY
6548
6549 #--THIS IS THE USUAL CASE, |X| < 1
6550 #--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
6551
6552 ASINMAIN:
6553 fmov.s &0x3F800000,%fp1
6554 fsub.x %fp0,%fp1 # 1-X
6555 fmovm.x &0x4,-(%sp) # {fp2}
6556 fmov.s &0x3F800000,%fp2
6557 fadd.x %fp0,%fp2 # 1+X
6558 fmul.x %fp2,%fp1 # (1+X)(1-X)
6559 fmovm.x (%sp)+,&0x20 # {fp2}
6560 fsqrt.x %fp1 # SQRT([1-X][1+X])
6561 fdiv.x %fp1,%fp0 # X/SQRT([1-X][1+X])
6562 fmovm.x &0x01,-(%sp) # save X/SQRT(...)
6563 lea (%sp),%a0 # pass ptr to X/SQRT(...)
6564 bsr satan
6565 add.l &0xc,%sp # clear X/SQRT(...) from stack
6566 bra t_inx2
6567
6568 ASINBIG:
6569 fabs.x %fp0 # |X|
6570 fcmp.s %fp0,&0x3F800000
6571 fbgt t_operr # cause an operr exception
6572
6573 #--|X| = 1, ASIN(X) = +- PI/2.
6574 ASINONE:
6575 fmov.x PIBY2(%pc),%fp0
6576 mov.l (%a0),%d1
6577 and.l &0x80000000,%d1 # SIGN BIT OF X
6578 or.l &0x3F800000,%d1 # +-1 IN SGL FORMAT
6579 mov.l %d1,-(%sp) # push SIGN(X) IN SGL-FMT
6580 fmov.l %d0,%fpcr
6581 fmul.s (%sp)+,%fp0
6582 bra t_inx2
6583
6584 #--|X| < 2^(-40), ATAN(X) = X
6585 ASINTINY:
6586 fmov.l %d0,%fpcr # restore users rnd mode,prec
6587 mov.b &FMOV_OP,%d1 # last inst is MOVE
6588 fmov.x (%a0),%fp0 # last inst - possible exception
6589 bra t_catch
6590
6591 global sasind
6592 #--ASIN(X) = X FOR DENORMALIZED X
6593 sasind:
6594 bra t_extdnrm
6595
6596 #########################################################################
6597 # sacos(): computes the inverse cosine of a normalized input #
6598 # sacosd(): computes the inverse cosine of a denormalized input #
6599 # #
6600 # INPUT *************************************************************** #
6601 # a0 = pointer to extended precision input #
6602 # d0 = round precision,mode #
6603 # #
6604 # OUTPUT ************************************************************** #
6605 # fp0 = arccos(X) #
6606 # #
6607 # ACCURACY and MONOTONICITY ******************************************* #
6608 # The returned result is within 3 ulps in 64 significant bit, #
6609 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6610 # rounded to double precision. The result is provably monotonic #
6611 # in double precision. #
6612 # #
6613 # ALGORITHM *********************************************************** #
6614 # #
6615 # ACOS #
6616 # 1. If |X| >= 1, go to 3. #
6617 # #
6618 # 2. (|X| < 1) Calculate acos(X) by #
6619 # z := (1-X) / (1+X) #
6620 # acos(X) = 2 * atan( sqrt(z) ). #
6621 # Exit. #
6622 # #
6623 # 3. If |X| > 1, go to 5. #
6624 # #
6625 # 4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit. #
6626 # #
6627 # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
6628 # Exit. #
6629 # #
6630 #########################################################################
6631
6632 global sacos
6633 sacos:
6634 fmov.x (%a0),%fp0 # LOAD INPUT
6635
6636 mov.l (%a0),%d1 # pack exp w/ upper 16 fraction
6637 mov.w 4(%a0),%d1
6638 and.l &0x7FFFFFFF,%d1
6639 cmp.l %d1,&0x3FFF8000
6640 bge.b ACOSBIG
6641
6642 #--THIS IS THE USUAL CASE, |X| < 1
6643 #--ACOS(X) = 2 * ATAN( SQRT( (1-X)/(1+X) ) )
6644
6645 ACOSMAIN:
6646 fmov.s &0x3F800000,%fp1
6647 fadd.x %fp0,%fp1 # 1+X
6648 fneg.x %fp0 # -X
6649 fadd.s &0x3F800000,%fp0 # 1-X
6650 fdiv.x %fp1,%fp0 # (1-X)/(1+X)
6651 fsqrt.x %fp0 # SQRT((1-X)/(1+X))
6652 mov.l %d0,-(%sp) # save original users fpcr
6653 clr.l %d0
6654 fmovm.x &0x01,-(%sp) # save SQRT(...) to stack
6655 lea (%sp),%a0 # pass ptr to sqrt
6656 bsr satan # ATAN(SQRT([1-X]/[1+X]))
6657 add.l &0xc,%sp # clear SQRT(...) from stack
6658
6659 fmov.l (%sp)+,%fpcr # restore users round prec,mode
6660 fadd.x %fp0,%fp0 # 2 * ATAN( STUFF )
6661 bra t_pinx2
6662
6663 ACOSBIG:
6664 fabs.x %fp0
6665 fcmp.s %fp0,&0x3F800000
6666 fbgt t_operr # cause an operr exception
6667
6668 #--|X| = 1, ACOS(X) = 0 OR PI
6669 tst.b (%a0) # is X positive or negative?
6670 bpl.b ACOSP1
6671
6672 #--X = -1
6673 #Returns PI and inexact exception
6674 ACOSM1:
6675 fmov.x PI(%pc),%fp0 # load PI
6676 fmov.l %d0,%fpcr # load round mode,prec
6677 fadd.s &0x00800000,%fp0 # add a small value
6678 bra t_pinx2
6679
6680 ACOSP1:
6681 bra ld_pzero # answer is positive zero
6682
6683 global sacosd
6684 #--ACOS(X) = PI/2 FOR DENORMALIZED X
6685 sacosd:
6686 fmov.l %d0,%fpcr # load user's rnd mode/prec
6687 fmov.x PIBY2(%pc),%fp0
6688 bra t_pinx2
6689
6690 #########################################################################
6691 # setox(): computes the exponential for a normalized input #
6692 # setoxd(): computes the exponential for a denormalized input #
6693 # setoxm1(): computes the exponential minus 1 for a normalized input #
6694 # setoxm1d(): computes the exponential minus 1 for a denormalized input #
6695 # #
6696 # INPUT *************************************************************** #
6697 # a0 = pointer to extended precision input #
6698 # d0 = round precision,mode #
6699 # #
6700 # OUTPUT ************************************************************** #
6701 # fp0 = exp(X) or exp(X)-1 #
6702 # #
6703 # ACCURACY and MONOTONICITY ******************************************* #
6704 # The returned result is within 0.85 ulps in 64 significant bit, #
6705 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
6706 # rounded to double precision. The result is provably monotonic #
6707 # in double precision. #
6708 # #
6709 # ALGORITHM and IMPLEMENTATION **************************************** #
6710 # #
6711 # setoxd #
6712 # ------ #
6713 # Step 1. Set ans := 1.0 #
6714 # #
6715 # Step 2. Return ans := ans + sign(X)*2^(-126). Exit. #
6716 # Notes: This will always generate one exception -- inexact. #
6717 # #
6718 # #
6719 # setox #
6720 # ----- #
6721 # #
6722 # Step 1. Filter out extreme cases of input argument. #
6723 # 1.1 If |X| >= 2^(-65), go to Step 1.3. #
6724 # 1.2 Go to Step 7. #
6725 # 1.3 If |X| < 16380 log(2), go to Step 2. #
6726 # 1.4 Go to Step 8. #
6727 # Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6728 # To avoid the use of floating-point comparisons, a #
6729 # compact representation of |X| is used. This format is a #
6730 # 32-bit integer, the upper (more significant) 16 bits #
6731 # are the sign and biased exponent field of |X|; the #
6732 # lower 16 bits are the 16 most significant fraction #
6733 # (including the explicit bit) bits of |X|. Consequently, #
6734 # the comparisons in Steps 1.1 and 1.3 can be performed #
6735 # by integer comparison. Note also that the constant #
6736 # 16380 log(2) used in Step 1.3 is also in the compact #
6737 # form. Thus taking the branch to Step 2 guarantees #
6738 # |X| < 16380 log(2). There is no harm to have a small #
6739 # number of cases where |X| is less than, but close to, #
6740 # 16380 log(2) and the branch to Step 9 is taken. #
6741 # #
6742 # Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6743 # 2.1 Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
6744 # was taken) #
6745 # 2.2 N := round-to-nearest-integer( X * 64/log2 ). #
6746 # 2.3 Calculate J = N mod 64; so J = 0,1,2,..., #
6747 # or 63. #
6748 # 2.4 Calculate M = (N - J)/64; so N = 64M + J. #
6749 # 2.5 Calculate the address of the stored value of #
6750 # 2^(J/64). #
6751 # 2.6 Create the value Scale = 2^M. #
6752 # Notes: The calculation in 2.2 is really performed by #
6753 # Z := X * constant #
6754 # N := round-to-nearest-integer(Z) #
6755 # where #
6756 # constant := single-precision( 64/log 2 ). #
6757 # #
6758 # Using a single-precision constant avoids memory #
6759 # access. Another effect of using a single-precision #
6760 # "constant" is that the calculated value Z is #
6761 # #
6762 # Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24). #
6763 # #
6764 # This error has to be considered later in Steps 3 and 4. #
6765 # #
6766 # Step 3. Calculate X - N*log2/64. #
6767 # 3.1 R := X + N*L1, #
6768 # where L1 := single-precision(-log2/64). #
6769 # 3.2 R := R + N*L2, #
6770 # L2 := extended-precision(-log2/64 - L1).#
6771 # Notes: a) The way L1 and L2 are chosen ensures L1+L2 #
6772 # approximate the value -log2/64 to 88 bits of accuracy. #
6773 # b) N*L1 is exact because N is no longer than 22 bits #
6774 # and L1 is no longer than 24 bits. #
6775 # c) The calculation X+N*L1 is also exact due to #
6776 # cancellation. Thus, R is practically X+N(L1+L2) to full #
6777 # 64 bits. #
6778 # d) It is important to estimate how large can |R| be #
6779 # after Step 3.2. #
6780 # #
6781 # N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24) #
6782 # X*64/log2 (1+eps) = N + f, |f| <= 0.5 #
6783 # X*64/log2 - N = f - eps*X 64/log2 #
6784 # X - N*log2/64 = f*log2/64 - eps*X #
6785 # #
6786 # #
6787 # Now |X| <= 16446 log2, thus #
6788 # #
6789 # |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64 #
6790 # <= 0.57 log2/64. #
6791 # This bound will be used in Step 4. #
6792 # #
6793 # Step 4. Approximate exp(R)-1 by a polynomial #
6794 # p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5)))) #
6795 # Notes: a) In order to reduce memory access, the coefficients #
6796 # are made as "short" as possible: A1 (which is 1/2), A4 #
6797 # and A5 are single precision; A2 and A3 are double #
6798 # precision. #
6799 # b) Even with the restrictions above, #
6800 # |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062. #
6801 # Note that 0.0062 is slightly bigger than 0.57 log2/64. #
6802 # c) To fully utilize the pipeline, p is separated into #
6803 # two independent pieces of roughly equal complexities #
6804 # p = [ R + R*S*(A2 + S*A4) ] + #
6805 # [ S*(A1 + S*(A3 + S*A5)) ] #
6806 # where S = R*R. #
6807 # #
6808 # Step 5. Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by #
6809 # ans := T + ( T*p + t) #
6810 # where T and t are the stored values for 2^(J/64). #
6811 # Notes: 2^(J/64) is stored as T and t where T+t approximates #
6812 # 2^(J/64) to roughly 85 bits; T is in extended precision #
6813 # and t is in single precision. Note also that T is #
6814 # rounded to 62 bits so that the last two bits of T are #
6815 # zero. The reason for such a special form is that T-1, #
6816 # T-2, and T-8 will all be exact --- a property that will #
6817 # give much more accurate computation of the function #
6818 # EXPM1. #
6819 # #
6820 # Step 6. Reconstruction of exp(X) #
6821 # exp(X) = 2^M * 2^(J/64) * exp(R). #
6822 # 6.1 If AdjFlag = 0, go to 6.3 #
6823 # 6.2 ans := ans * AdjScale #
6824 # 6.3 Restore the user FPCR #
6825 # 6.4 Return ans := ans * Scale. Exit. #
6826 # Notes: If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R, #
6827 # |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will #
6828 # neither overflow nor underflow. If AdjFlag = 1, that #
6829 # means that #
6830 # X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380. #
6831 # Hence, exp(X) may overflow or underflow or neither. #
6832 # When that is the case, AdjScale = 2^(M1) where M1 is #
6833 # approximately M. Thus 6.2 will never cause #
6834 # over/underflow. Possible exception in 6.4 is overflow #
6835 # or underflow. The inexact exception is not generated in #
6836 # 6.4. Although one can argue that the inexact flag #
6837 # should always be raised, to simulate that exception #
6838 # cost to much than the flag is worth in practical uses. #
6839 # #
6840 # Step 7. Return 1 + X. #
6841 # 7.1 ans := X #
6842 # 7.2 Restore user FPCR. #
6843 # 7.3 Return ans := 1 + ans. Exit #
6844 # Notes: For non-zero X, the inexact exception will always be #
6845 # raised by 7.3. That is the only exception raised by 7.3.#
6846 # Note also that we use the FMOVEM instruction to move X #
6847 # in Step 7.1 to avoid unnecessary trapping. (Although #
6848 # the FMOVEM may not seem relevant since X is normalized, #
6849 # the precaution will be useful in the library version of #
6850 # this code where the separate entry for denormalized #
6851 # inputs will be done away with.) #
6852 # #
6853 # Step 8. Handle exp(X) where |X| >= 16380log2. #
6854 # 8.1 If |X| > 16480 log2, go to Step 9. #
6855 # (mimic 2.2 - 2.6) #
6856 # 8.2 N := round-to-integer( X * 64/log2 ) #
6857 # 8.3 Calculate J = N mod 64, J = 0,1,...,63 #
6858 # 8.4 K := (N-J)/64, M1 := truncate(K/2), M = K-M1, #
6859 # AdjFlag := 1. #
6860 # 8.5 Calculate the address of the stored value #
6861 # 2^(J/64). #
6862 # 8.6 Create the values Scale = 2^M, AdjScale = 2^M1. #
6863 # 8.7 Go to Step 3. #
6864 # Notes: Refer to notes for 2.2 - 2.6. #
6865 # #
6866 # Step 9. Handle exp(X), |X| > 16480 log2. #
6867 # 9.1 If X < 0, go to 9.3 #
6868 # 9.2 ans := Huge, go to 9.4 #
6869 # 9.3 ans := Tiny. #
6870 # 9.4 Restore user FPCR. #
6871 # 9.5 Return ans := ans * ans. Exit. #
6872 # Notes: Exp(X) will surely overflow or underflow, depending on #
6873 # X's sign. "Huge" and "Tiny" are respectively large/tiny #
6874 # extended-precision numbers whose square over/underflow #
6875 # with an inexact result. Thus, 9.5 always raises the #
6876 # inexact together with either overflow or underflow. #
6877 # #
6878 # setoxm1d #
6879 # -------- #
6880 # #
6881 # Step 1. Set ans := 0 #
6882 # #
6883 # Step 2. Return ans := X + ans. Exit. #
6884 # Notes: This will return X with the appropriate rounding #
6885 # precision prescribed by the user FPCR. #
6886 # #
6887 # setoxm1 #
6888 # ------- #
6889 # #
6890 # Step 1. Check |X| #
6891 # 1.1 If |X| >= 1/4, go to Step 1.3. #
6892 # 1.2 Go to Step 7. #
6893 # 1.3 If |X| < 70 log(2), go to Step 2. #
6894 # 1.4 Go to Step 10. #
6895 # Notes: The usual case should take the branches 1.1 -> 1.3 -> 2.#
6896 # However, it is conceivable |X| can be small very often #
6897 # because EXPM1 is intended to evaluate exp(X)-1 #
6898 # accurately when |X| is small. For further details on #
6899 # the comparisons, see the notes on Step 1 of setox. #
6900 # #
6901 # Step 2. Calculate N = round-to-nearest-int( X * 64/log2 ). #
6902 # 2.1 N := round-to-nearest-integer( X * 64/log2 ). #
6903 # 2.2 Calculate J = N mod 64; so J = 0,1,2,..., #
6904 # or 63. #
6905 # 2.3 Calculate M = (N - J)/64; so N = 64M + J. #
6906 # 2.4 Calculate the address of the stored value of #
6907 # 2^(J/64). #
6908 # 2.5 Create the values Sc = 2^M and #
6909 # OnebySc := -2^(-M). #
6910 # Notes: See the notes on Step 2 of setox. #
6911 # #
6912 # Step 3. Calculate X - N*log2/64. #
6913 # 3.1 R := X + N*L1, #
6914 # where L1 := single-precision(-log2/64). #
6915 # 3.2 R := R + N*L2, #
6916 # L2 := extended-precision(-log2/64 - L1).#
6917 # Notes: Applying the analysis of Step 3 of setox in this case #
6918 # shows that |R| <= 0.0055 (note that |X| <= 70 log2 in #
6919 # this case). #
6920 # #
6921 # Step 4. Approximate exp(R)-1 by a polynomial #
6922 # p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6))))) #
6923 # Notes: a) In order to reduce memory access, the coefficients #
6924 # are made as "short" as possible: A1 (which is 1/2), A5 #
6925 # and A6 are single precision; A2, A3 and A4 are double #
6926 # precision. #
6927 # b) Even with the restriction above, #
6928 # |p - (exp(R)-1)| < |R| * 2^(-72.7) #
6929 # for all |R| <= 0.0055. #
6930 # c) To fully utilize the pipeline, p is separated into #
6931 # two independent pieces of roughly equal complexity #
6932 # p = [ R*S*(A2 + S*(A4 + S*A6)) ] + #
6933 # [ R + S*(A1 + S*(A3 + S*A5)) ] #
6934 # where S = R*R. #
6935 # #
6936 # Step 5. Compute 2^(J/64)*p by #
6937 # p := T*p #
6938 # where T and t are the stored values for 2^(J/64). #
6939 # Notes: 2^(J/64) is stored as T and t where T+t approximates #
6940 # 2^(J/64) to roughly 85 bits; T is in extended precision #
6941 # and t is in single precision. Note also that T is #
6942 # rounded to 62 bits so that the last two bits of T are #
6943 # zero. The reason for such a special form is that T-1, #
6944 # T-2, and T-8 will all be exact --- a property that will #
6945 # be exploited in Step 6 below. The total relative error #
6946 # in p is no bigger than 2^(-67.7) compared to the final #
6947 # result. #
6948 # #
6949 # Step 6. Reconstruction of exp(X)-1 #
6950 # exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ). #
6951 # 6.1 If M <= 63, go to Step 6.3. #
6952 # 6.2 ans := T + (p + (t + OnebySc)). Go to 6.6 #
6953 # 6.3 If M >= -3, go to 6.5. #
6954 # 6.4 ans := (T + (p + t)) + OnebySc. Go to 6.6 #
6955 # 6.5 ans := (T + OnebySc) + (p + t). #
6956 # 6.6 Restore user FPCR. #
6957 # 6.7 Return ans := Sc * ans. Exit. #
6958 # Notes: The various arrangements of the expressions give #
6959 # accurate evaluations. #
6960 # #
6961 # Step 7. exp(X)-1 for |X| < 1/4. #
6962 # 7.1 If |X| >= 2^(-65), go to Step 9. #
6963 # 7.2 Go to Step 8. #
6964 # #
6965 # Step 8. Calculate exp(X)-1, |X| < 2^(-65). #
6966 # 8.1 If |X| < 2^(-16312), goto 8.3 #
6967 # 8.2 Restore FPCR; return ans := X - 2^(-16382). #
6968 # Exit. #
6969 # 8.3 X := X * 2^(140). #
6970 # 8.4 Restore FPCR; ans := ans - 2^(-16382). #
6971 # Return ans := ans*2^(140). Exit #
6972 # Notes: The idea is to return "X - tiny" under the user #
6973 # precision and rounding modes. To avoid unnecessary #
6974 # inefficiency, we stay away from denormalized numbers #
6975 # the best we can. For |X| >= 2^(-16312), the #
6976 # straightforward 8.2 generates the inexact exception as #
6977 # the case warrants. #
6978 # #
6979 # Step 9. Calculate exp(X)-1, |X| < 1/4, by a polynomial #
6980 # p = X + X*X*(B1 + X*(B2 + ... + X*B12)) #
6981 # Notes: a) In order to reduce memory access, the coefficients #
6982 # are made as "short" as possible: B1 (which is 1/2), B9 #
6983 # to B12 are single precision; B3 to B8 are double #
6984 # precision; and B2 is double extended. #
6985 # b) Even with the restriction above, #
6986 # |p - (exp(X)-1)| < |X| 2^(-70.6) #
6987 # for all |X| <= 0.251. #
6988 # Note that 0.251 is slightly bigger than 1/4. #
6989 # c) To fully preserve accuracy, the polynomial is #
6990 # computed as #
6991 # X + ( S*B1 + Q ) where S = X*X and #
6992 # Q = X*S*(B2 + X*(B3 + ... + X*B12)) #
6993 # d) To fully utilize the pipeline, Q is separated into #
6994 # two independent pieces of roughly equal complexity #
6995 # Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] + #
6996 # [ S*S*(B3 + S*(B5 + ... + S*B11)) ] #
6997 # #
6998 # Step 10. Calculate exp(X)-1 for |X| >= 70 log 2. #
6999 # 10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all #
7000 # practical purposes. Therefore, go to Step 1 of setox. #
7001 # 10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical #
7002 # purposes. #
7003 # ans := -1 #
7004 # Restore user FPCR #
7005 # Return ans := ans + 2^(-126). Exit. #
7006 # Notes: 10.2 will always create an inexact and return -1 + tiny #
7007 # in the user rounding precision and mode. #
7008 # #
7009 #########################################################################
7010
7011 L2: long 0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
7012
7013 EEXPA3: long 0x3FA55555,0x55554CC1
7014 EEXPA2: long 0x3FC55555,0x55554A54
7015
7016 EM1A4: long 0x3F811111,0x11174385
7017 EM1A3: long 0x3FA55555,0x55554F5A
7018
7019 EM1A2: long 0x3FC55555,0x55555555,0x00000000,0x00000000
7020
7021 EM1B8: long 0x3EC71DE3,0xA5774682
7022 EM1B7: long 0x3EFA01A0,0x19D7CB68
7023
7024 EM1B6: long 0x3F2A01A0,0x1A019DF3
7025 EM1B5: long 0x3F56C16C,0x16C170E2
7026
7027 EM1B4: long 0x3F811111,0x11111111
7028 EM1B3: long 0x3FA55555,0x55555555
7029
7030 EM1B2: long 0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
7031 long 0x00000000
7032
7033 TWO140: long 0x48B00000,0x00000000
7034 TWON140:
7035 long 0x37300000,0x00000000
7036
7037 EEXPTBL:
7038 long 0x3FFF0000,0x80000000,0x00000000,0x00000000
7039 long 0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
7040 long 0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
7041 long 0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
7042 long 0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
7043 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
7044 long 0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
7045 long 0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
7046 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
7047 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
7048 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
7049 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
7050 long 0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
7051 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
7052 long 0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
7053 long 0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
7054 long 0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
7055 long 0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
7056 long 0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
7057 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
7058 long 0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
7059 long 0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
7060 long 0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
7061 long 0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
7062 long 0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
7063 long 0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
7064 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
7065 long 0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
7066 long 0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
7067 long 0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
7068 long 0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
7069 long 0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
7070 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
7071 long 0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
7072 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
7073 long 0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
7074 long 0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
7075 long 0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
7076 long 0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
7077 long 0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
7078 long 0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
7079 long 0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
7080 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
7081 long 0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
7082 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
7083 long 0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
7084 long 0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
7085 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
7086 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
7087 long 0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
7088 long 0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
7089 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
7090 long 0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
7091 long 0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
7092 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
7093 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
7094 long 0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
7095 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
7096 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
7097 long 0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
7098 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
7099 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
7100 long 0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
7101 long 0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
7102
7103 set ADJFLAG,L_SCR2
7104 set SCALE,FP_SCR0
7105 set ADJSCALE,FP_SCR1
7106 set SC,FP_SCR0
7107 set ONEBYSC,FP_SCR1
7108
7109 global setox
7110 setox:
7111 #--entry point for EXP(X), here X is finite, non-zero, and not NaN's
7112
7113 #--Step 1.
7114 mov.l (%a0),%d1 # load part of input X
7115 and.l &0x7FFF0000,%d1 # biased expo. of X
7116 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7117 bge.b EXPC1 # normal case
7118 bra EXPSM
7119
7120 EXPC1:
7121 #--The case |X| >= 2^(-65)
7122 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7123 cmp.l %d1,&0x400CB167 # 16380 log2 trunc. 16 bits
7124 blt.b EXPMAIN # normal case
7125 bra EEXPBIG
7126
7127 EXPMAIN:
7128 #--Step 2.
7129 #--This is the normal branch: 2^(-65) <= |X| < 16380 log2.
7130 fmov.x (%a0),%fp0 # load input from (a0)
7131
7132 fmov.x %fp0,%fp1
7133 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7134 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7135 mov.l &0,ADJFLAG(%a6)
7136 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7137 lea EEXPTBL(%pc),%a1
7138 fmov.l %d1,%fp0 # convert to floating-format
7139
7140 mov.l %d1,L_SCR1(%a6) # save N temporarily
7141 and.l &0x3F,%d1 # D0 is J = N mod 64
7142 lsl.l &4,%d1
7143 add.l %d1,%a1 # address of 2^(J/64)
7144 mov.l L_SCR1(%a6),%d1
7145 asr.l &6,%d1 # D0 is M
7146 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7147 mov.w L2(%pc),L_SCR1(%a6) # prefetch L2, no need in CB
7148
7149 EXPCONT1:
7150 #--Step 3.
7151 #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7152 #--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
7153 fmov.x %fp0,%fp2
7154 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7155 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7156 fadd.x %fp1,%fp0 # X + N*L1
7157 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7158
7159 #--Step 4.
7160 #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7161 #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
7162 #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7163 #--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
7164
7165 fmov.x %fp0,%fp1
7166 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7167
7168 fmov.s &0x3AB60B70,%fp2 # fp2 IS A5
7169
7170 fmul.x %fp1,%fp2 # fp2 IS S*A5
7171 fmov.x %fp1,%fp3
7172 fmul.s &0x3C088895,%fp3 # fp3 IS S*A4
7173
7174 fadd.d EEXPA3(%pc),%fp2 # fp2 IS A3+S*A5
7175 fadd.d EEXPA2(%pc),%fp3 # fp3 IS A2+S*A4
7176
7177 fmul.x %fp1,%fp2 # fp2 IS S*(A3+S*A5)
7178 mov.w %d1,SCALE(%a6) # SCALE is 2^(M) in extended
7179 mov.l &0x80000000,SCALE+4(%a6)
7180 clr.l SCALE+8(%a6)
7181
7182 fmul.x %fp1,%fp3 # fp3 IS S*(A2+S*A4)
7183
7184 fadd.s &0x3F000000,%fp2 # fp2 IS A1+S*(A3+S*A5)
7185 fmul.x %fp0,%fp3 # fp3 IS R*S*(A2+S*A4)
7186
7187 fmul.x %fp1,%fp2 # fp2 IS S*(A1+S*(A3+S*A5))
7188 fadd.x %fp3,%fp0 # fp0 IS R+R*S*(A2+S*A4),
7189
7190 fmov.x (%a1)+,%fp1 # fp1 is lead. pt. of 2^(J/64)
7191 fadd.x %fp2,%fp0 # fp0 is EXP(R) - 1
7192
7193 #--Step 5
7194 #--final reconstruction process
7195 #--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
7196
7197 fmul.x %fp1,%fp0 # 2^(J/64)*(Exp(R)-1)
7198 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7199 fadd.s (%a1),%fp0 # accurate 2^(J/64)
7200
7201 fadd.x %fp1,%fp0 # 2^(J/64) + 2^(J/64)*...
7202 mov.l ADJFLAG(%a6),%d1
7203
7204 #--Step 6
7205 tst.l %d1
7206 beq.b NORMAL
7207 ADJUST:
7208 fmul.x ADJSCALE(%a6),%fp0
7209 NORMAL:
7210 fmov.l %d0,%fpcr # restore user FPCR
7211 mov.b &FMUL_OP,%d1 # last inst is MUL
7212 fmul.x SCALE(%a6),%fp0 # multiply 2^(M)
7213 bra t_catch
7214
7215 EXPSM:
7216 #--Step 7
7217 fmovm.x (%a0),&0x80 # load X
7218 fmov.l %d0,%fpcr
7219 fadd.s &0x3F800000,%fp0 # 1+X in user mode
7220 bra t_pinx2
7221
7222 EEXPBIG:
7223 #--Step 8
7224 cmp.l %d1,&0x400CB27C # 16480 log2
7225 bgt.b EXP2BIG
7226 #--Steps 8.2 -- 8.6
7227 fmov.x (%a0),%fp0 # load input from (a0)
7228
7229 fmov.x %fp0,%fp1
7230 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7231 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7232 mov.l &1,ADJFLAG(%a6)
7233 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7234 lea EEXPTBL(%pc),%a1
7235 fmov.l %d1,%fp0 # convert to floating-format
7236 mov.l %d1,L_SCR1(%a6) # save N temporarily
7237 and.l &0x3F,%d1 # D0 is J = N mod 64
7238 lsl.l &4,%d1
7239 add.l %d1,%a1 # address of 2^(J/64)
7240 mov.l L_SCR1(%a6),%d1
7241 asr.l &6,%d1 # D0 is K
7242 mov.l %d1,L_SCR1(%a6) # save K temporarily
7243 asr.l &1,%d1 # D0 is M1
7244 sub.l %d1,L_SCR1(%a6) # a1 is M
7245 add.w &0x3FFF,%d1 # biased expo. of 2^(M1)
7246 mov.w %d1,ADJSCALE(%a6) # ADJSCALE := 2^(M1)
7247 mov.l &0x80000000,ADJSCALE+4(%a6)
7248 clr.l ADJSCALE+8(%a6)
7249 mov.l L_SCR1(%a6),%d1 # D0 is M
7250 add.w &0x3FFF,%d1 # biased expo. of 2^(M)
7251 bra.w EXPCONT1 # go back to Step 3
7252
7253 EXP2BIG:
7254 #--Step 9
7255 tst.b (%a0) # is X positive or negative?
7256 bmi t_unfl2
7257 bra t_ovfl2
7258
7259 global setoxd
7260 setoxd:
7261 #--entry point for EXP(X), X is denormalized
7262 mov.l (%a0),-(%sp)
7263 andi.l &0x80000000,(%sp)
7264 ori.l &0x00800000,(%sp) # sign(X)*2^(-126)
7265
7266 fmov.s &0x3F800000,%fp0
7267
7268 fmov.l %d0,%fpcr
7269 fadd.s (%sp)+,%fp0
7270 bra t_pinx2
7271
7272 global setoxm1
7273 setoxm1:
7274 #--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
7275
7276 #--Step 1.
7277 #--Step 1.1
7278 mov.l (%a0),%d1 # load part of input X
7279 and.l &0x7FFF0000,%d1 # biased expo. of X
7280 cmp.l %d1,&0x3FFD0000 # 1/4
7281 bge.b EM1CON1 # |X| >= 1/4
7282 bra EM1SM
7283
7284 EM1CON1:
7285 #--Step 1.3
7286 #--The case |X| >= 1/4
7287 mov.w 4(%a0),%d1 # expo. and partial sig. of |X|
7288 cmp.l %d1,&0x4004C215 # 70log2 rounded up to 16 bits
7289 ble.b EM1MAIN # 1/4 <= |X| <= 70log2
7290 bra EM1BIG
7291
7292 EM1MAIN:
7293 #--Step 2.
7294 #--This is the case: 1/4 <= |X| <= 70 log2.
7295 fmov.x (%a0),%fp0 # load input from (a0)
7296
7297 fmov.x %fp0,%fp1
7298 fmul.s &0x42B8AA3B,%fp0 # 64/log2 * X
7299 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7300 fmov.l %fp0,%d1 # N = int( X * 64/log2 )
7301 lea EEXPTBL(%pc),%a1
7302 fmov.l %d1,%fp0 # convert to floating-format
7303
7304 mov.l %d1,L_SCR1(%a6) # save N temporarily
7305 and.l &0x3F,%d1 # D0 is J = N mod 64
7306 lsl.l &4,%d1
7307 add.l %d1,%a1 # address of 2^(J/64)
7308 mov.l L_SCR1(%a6),%d1
7309 asr.l &6,%d1 # D0 is M
7310 mov.l %d1,L_SCR1(%a6) # save a copy of M
7311
7312 #--Step 3.
7313 #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
7314 #--a0 points to 2^(J/64), D0 and a1 both contain M
7315 fmov.x %fp0,%fp2
7316 fmul.s &0xBC317218,%fp0 # N * L1, L1 = lead(-log2/64)
7317 fmul.x L2(%pc),%fp2 # N * L2, L1+L2 = -log2/64
7318 fadd.x %fp1,%fp0 # X + N*L1
7319 fadd.x %fp2,%fp0 # fp0 is R, reduced arg.
7320 add.w &0x3FFF,%d1 # D0 is biased expo. of 2^M
7321
7322 #--Step 4.
7323 #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
7324 #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
7325 #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
7326 #--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
7327
7328 fmov.x %fp0,%fp1
7329 fmul.x %fp1,%fp1 # fp1 IS S = R*R
7330
7331 fmov.s &0x3950097B,%fp2 # fp2 IS a6
7332
7333 fmul.x %fp1,%fp2 # fp2 IS S*A6
7334 fmov.x %fp1,%fp3
7335 fmul.s &0x3AB60B6A,%fp3 # fp3 IS S*A5
7336
7337 fadd.d EM1A4(%pc),%fp2 # fp2 IS A4+S*A6
7338 fadd.d EM1A3(%pc),%fp3 # fp3 IS A3+S*A5
7339 mov.w %d1,SC(%a6) # SC is 2^(M) in extended
7340 mov.l &0x80000000,SC+4(%a6)
7341 clr.l SC+8(%a6)
7342
7343 fmul.x %fp1,%fp2 # fp2 IS S*(A4+S*A6)
7344 mov.l L_SCR1(%a6),%d1 # D0 is M
7345 neg.w %d1 # D0 is -M
7346 fmul.x %fp1,%fp3 # fp3 IS S*(A3+S*A5)
7347 add.w &0x3FFF,%d1 # biased expo. of 2^(-M)
7348 fadd.d EM1A2(%pc),%fp2 # fp2 IS A2+S*(A4+S*A6)
7349 fadd.s &0x3F000000,%fp3 # fp3 IS A1+S*(A3+S*A5)
7350
7351 fmul.x %fp1,%fp2 # fp2 IS S*(A2+S*(A4+S*A6))
7352 or.w &0x8000,%d1 # signed/expo. of -2^(-M)
7353 mov.w %d1,ONEBYSC(%a6) # OnebySc is -2^(-M)
7354 mov.l &0x80000000,ONEBYSC+4(%a6)
7355 clr.l ONEBYSC+8(%a6)
7356 fmul.x %fp3,%fp1 # fp1 IS S*(A1+S*(A3+S*A5))
7357
7358 fmul.x %fp0,%fp2 # fp2 IS R*S*(A2+S*(A4+S*A6))
7359 fadd.x %fp1,%fp0 # fp0 IS R+S*(A1+S*(A3+S*A5))
7360
7361 fadd.x %fp2,%fp0 # fp0 IS EXP(R)-1
7362
7363 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7364
7365 #--Step 5
7366 #--Compute 2^(J/64)*p
7367
7368 fmul.x (%a1),%fp0 # 2^(J/64)*(Exp(R)-1)
7369
7370 #--Step 6
7371 #--Step 6.1
7372 mov.l L_SCR1(%a6),%d1 # retrieve M
7373 cmp.l %d1,&63
7374 ble.b MLE63
7375 #--Step 6.2 M >= 64
7376 fmov.s 12(%a1),%fp1 # fp1 is t
7377 fadd.x ONEBYSC(%a6),%fp1 # fp1 is t+OnebySc
7378 fadd.x %fp1,%fp0 # p+(t+OnebySc), fp1 released
7379 fadd.x (%a1),%fp0 # T+(p+(t+OnebySc))
7380 bra EM1SCALE
7381 MLE63:
7382 #--Step 6.3 M <= 63
7383 cmp.l %d1,&-3
7384 bge.b MGEN3
7385 MLTN3:
7386 #--Step 6.4 M <= -4
7387 fadd.s 12(%a1),%fp0 # p+t
7388 fadd.x (%a1),%fp0 # T+(p+t)
7389 fadd.x ONEBYSC(%a6),%fp0 # OnebySc + (T+(p+t))
7390 bra EM1SCALE
7391 MGEN3:
7392 #--Step 6.5 -3 <= M <= 63
7393 fmov.x (%a1)+,%fp1 # fp1 is T
7394 fadd.s (%a1),%fp0 # fp0 is p+t
7395 fadd.x ONEBYSC(%a6),%fp1 # fp1 is T+OnebySc
7396 fadd.x %fp1,%fp0 # (T+OnebySc)+(p+t)
7397
7398 EM1SCALE:
7399 #--Step 6.6
7400 fmov.l %d0,%fpcr
7401 fmul.x SC(%a6),%fp0
7402 bra t_inx2
7403
7404 EM1SM:
7405 #--Step 7 |X| < 1/4.
7406 cmp.l %d1,&0x3FBE0000 # 2^(-65)
7407 bge.b EM1POLY
7408
7409 EM1TINY:
7410 #--Step 8 |X| < 2^(-65)
7411 cmp.l %d1,&0x00330000 # 2^(-16312)
7412 blt.b EM12TINY
7413 #--Step 8.2
7414 mov.l &0x80010000,SC(%a6) # SC is -2^(-16382)
7415 mov.l &0x80000000,SC+4(%a6)
7416 clr.l SC+8(%a6)
7417 fmov.x (%a0),%fp0
7418 fmov.l %d0,%fpcr
7419 mov.b &FADD_OP,%d1 # last inst is ADD
7420 fadd.x SC(%a6),%fp0
7421 bra t_catch
7422
7423 EM12TINY:
7424 #--Step 8.3
7425 fmov.x (%a0),%fp0
7426 fmul.d TWO140(%pc),%fp0
7427 mov.l &0x80010000,SC(%a6)
7428 mov.l &0x80000000,SC+4(%a6)
7429 clr.l SC+8(%a6)
7430 fadd.x SC(%a6),%fp0
7431 fmov.l %d0,%fpcr
7432 mov.b &FMUL_OP,%d1 # last inst is MUL
7433 fmul.d TWON140(%pc),%fp0
7434 bra t_catch
7435
7436 EM1POLY:
7437 #--Step 9 exp(X)-1 by a simple polynomial
7438 fmov.x (%a0),%fp0 # fp0 is X
7439 fmul.x %fp0,%fp0 # fp0 is S := X*X
7440 fmovm.x &0xc,-(%sp) # save fp2 {%fp2/%fp3}
7441 fmov.s &0x2F30CAA8,%fp1 # fp1 is B12
7442 fmul.x %fp0,%fp1 # fp1 is S*B12
7443 fmov.s &0x310F8290,%fp2 # fp2 is B11
7444 fadd.s &0x32D73220,%fp1 # fp1 is B10+S*B12
7445
7446 fmul.x %fp0,%fp2 # fp2 is S*B11
7447 fmul.x %fp0,%fp1 # fp1 is S*(B10 + ...
7448
7449 fadd.s &0x3493F281,%fp2 # fp2 is B9+S*...
7450 fadd.d EM1B8(%pc),%fp1 # fp1 is B8+S*...
7451
7452 fmul.x %fp0,%fp2 # fp2 is S*(B9+...
7453 fmul.x %fp0,%fp1 # fp1 is S*(B8+...
7454
7455 fadd.d EM1B7(%pc),%fp2 # fp2 is B7+S*...
7456 fadd.d EM1B6(%pc),%fp1 # fp1 is B6+S*...
7457
7458 fmul.x %fp0,%fp2 # fp2 is S*(B7+...
7459 fmul.x %fp0,%fp1 # fp1 is S*(B6+...
7460
7461 fadd.d EM1B5(%pc),%fp2 # fp2 is B5+S*...
7462 fadd.d EM1B4(%pc),%fp1 # fp1 is B4+S*...
7463
7464 fmul.x %fp0,%fp2 # fp2 is S*(B5+...
7465 fmul.x %fp0,%fp1 # fp1 is S*(B4+...
7466
7467 fadd.d EM1B3(%pc),%fp2 # fp2 is B3+S*...
7468 fadd.x EM1B2(%pc),%fp1 # fp1 is B2+S*...
7469
7470 fmul.x %fp0,%fp2 # fp2 is S*(B3+...
7471 fmul.x %fp0,%fp1 # fp1 is S*(B2+...
7472
7473 fmul.x %fp0,%fp2 # fp2 is S*S*(B3+...)
7474 fmul.x (%a0),%fp1 # fp1 is X*S*(B2...
7475
7476 fmul.s &0x3F000000,%fp0 # fp0 is S*B1
7477 fadd.x %fp2,%fp1 # fp1 is Q
7478
7479 fmovm.x (%sp)+,&0x30 # fp2 restored {%fp2/%fp3}
7480
7481 fadd.x %fp1,%fp0 # fp0 is S*B1+Q
7482
7483 fmov.l %d0,%fpcr
7484 fadd.x (%a0),%fp0
7485 bra t_inx2
7486
7487 EM1BIG:
7488 #--Step 10 |X| > 70 log2
7489 mov.l (%a0),%d1
7490 cmp.l %d1,&0
7491 bgt.w EXPC1
7492 #--Step 10.2
7493 fmov.s &0xBF800000,%fp0 # fp0 is -1
7494 fmov.l %d0,%fpcr
7495 fadd.s &0x00800000,%fp0 # -1 + 2^(-126)
7496 bra t_minx2
7497
7498 global setoxm1d
7499 setoxm1d:
7500 #--entry point for EXPM1(X), here X is denormalized
7501 #--Step 0.
7502 bra t_extdnrm
7503
7504 #########################################################################
7505 # sgetexp(): returns the exponent portion of the input argument. #
7506 # The exponent bias is removed and the exponent value is #
7507 # returned as an extended precision number in fp0. #
7508 # sgetexpd(): handles denormalized numbers. #
7509 # #
7510 # sgetman(): extracts the mantissa of the input argument. The #
7511 # mantissa is converted to an extended precision number w/ #
7512 # an exponent of $3fff and is returned in fp0. The range of #
7513 # the result is [1.0 - 2.0). #
7514 # sgetmand(): handles denormalized numbers. #
7515 # #
7516 # INPUT *************************************************************** #
7517 # a0 = pointer to extended precision input #
7518 # #
7519 # OUTPUT ************************************************************** #
7520 # fp0 = exponent(X) or mantissa(X) #
7521 # #
7522 #########################################################################
7523
7524 global sgetexp
7525 sgetexp:
7526 mov.w SRC_EX(%a0),%d0 # get the exponent
7527 bclr &0xf,%d0 # clear the sign bit
7528 subi.w &0x3fff,%d0 # subtract off the bias
7529 fmov.w %d0,%fp0 # return exp in fp0
7530 blt.b sgetexpn # it's negative
7531 rts
7532
7533 sgetexpn:
7534 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7535 rts
7536
7537 global sgetexpd
7538 sgetexpd:
7539 bsr.l norm # normalize
7540 neg.w %d0 # new exp = -(shft amt)
7541 subi.w &0x3fff,%d0 # subtract off the bias
7542 fmov.w %d0,%fp0 # return exp in fp0
7543 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7544 rts
7545
7546 global sgetman
7547 sgetman:
7548 mov.w SRC_EX(%a0),%d0 # get the exp
7549 ori.w &0x7fff,%d0 # clear old exp
7550 bclr &0xe,%d0 # make it the new exp +-3fff
7551
7552 # here, we build the result in a tmp location so as not to disturb the input
7553 mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
7554 mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
7555 mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
7556 fmov.x FP_SCR0(%a6),%fp0 # put new value back in fp0
7557 bmi.b sgetmann # it's negative
7558 rts
7559
7560 sgetmann:
7561 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
7562 rts
7563
7564 #
7565 # For denormalized numbers, shift the mantissa until the j-bit = 1,
7566 # then load the exponent with +/1 $3fff.
7567 #
7568 global sgetmand
7569 sgetmand:
7570 bsr.l norm # normalize exponent
7571 bra.b sgetman
7572
7573 #########################################################################
7574 # scosh(): computes the hyperbolic cosine of a normalized input #
7575 # scoshd(): computes the hyperbolic cosine of a denormalized input #
7576 # #
7577 # INPUT *************************************************************** #
7578 # a0 = pointer to extended precision input #
7579 # d0 = round precision,mode #
7580 # #
7581 # OUTPUT ************************************************************** #
7582 # fp0 = cosh(X) #
7583 # #
7584 # ACCURACY and MONOTONICITY ******************************************* #
7585 # The returned result is within 3 ulps in 64 significant bit, #
7586 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7587 # rounded to double precision. The result is provably monotonic #
7588 # in double precision. #
7589 # #
7590 # ALGORITHM *********************************************************** #
7591 # #
7592 # COSH #
7593 # 1. If |X| > 16380 log2, go to 3. #
7594 # #
7595 # 2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae #
7596 # y = |X|, z = exp(Y), and #
7597 # cosh(X) = (1/2)*( z + 1/z ). #
7598 # Exit. #
7599 # #
7600 # 3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5. #
7601 # #
7602 # 4. (16380 log2 < |X| <= 16480 log2) #
7603 # cosh(X) = sign(X) * exp(|X|)/2. #
7604 # However, invoking exp(|X|) may cause premature #
7605 # overflow. Thus, we calculate sinh(X) as follows: #
7606 # Y := |X| #
7607 # Fact := 2**(16380) #
7608 # Y' := Y - 16381 log2 #
7609 # cosh(X) := Fact * exp(Y'). #
7610 # Exit. #
7611 # #
7612 # 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7613 # Huge*Huge to generate overflow and an infinity with #
7614 # the appropriate sign. Huge is the largest finite number #
7615 # in extended format. Exit. #
7616 # #
7617 #########################################################################
7618
7619 TWO16380:
7620 long 0x7FFB0000,0x80000000,0x00000000,0x00000000
7621
7622 global scosh
7623 scosh:
7624 fmov.x (%a0),%fp0 # LOAD INPUT
7625
7626 mov.l (%a0),%d1
7627 mov.w 4(%a0),%d1
7628 and.l &0x7FFFFFFF,%d1
7629 cmp.l %d1,&0x400CB167
7630 bgt.b COSHBIG
7631
7632 #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7633 #--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
7634
7635 fabs.x %fp0 # |X|
7636
7637 mov.l %d0,-(%sp)
7638 clr.l %d0
7639 fmovm.x &0x01,-(%sp) # save |X| to stack
7640 lea (%sp),%a0 # pass ptr to |X|
7641 bsr setox # FP0 IS EXP(|X|)
7642 add.l &0xc,%sp # erase |X| from stack
7643 fmul.s &0x3F000000,%fp0 # (1/2)EXP(|X|)
7644 mov.l (%sp)+,%d0
7645
7646 fmov.s &0x3E800000,%fp1 # (1/4)
7647 fdiv.x %fp0,%fp1 # 1/(2 EXP(|X|))
7648
7649 fmov.l %d0,%fpcr
7650 mov.b &FADD_OP,%d1 # last inst is ADD
7651 fadd.x %fp1,%fp0
7652 bra t_catch
7653
7654 COSHBIG:
7655 cmp.l %d1,&0x400CB2B3
7656 bgt.b COSHHUGE
7657
7658 fabs.x %fp0
7659 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7660 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7661
7662 mov.l %d0,-(%sp)
7663 clr.l %d0
7664 fmovm.x &0x01,-(%sp) # save fp0 to stack
7665 lea (%sp),%a0 # pass ptr to fp0
7666 bsr setox
7667 add.l &0xc,%sp # clear fp0 from stack
7668 mov.l (%sp)+,%d0
7669
7670 fmov.l %d0,%fpcr
7671 mov.b &FMUL_OP,%d1 # last inst is MUL
7672 fmul.x TWO16380(%pc),%fp0
7673 bra t_catch
7674
7675 COSHHUGE:
7676 bra t_ovfl2
7677
7678 global scoshd
7679 #--COSH(X) = 1 FOR DENORMALIZED X
7680 scoshd:
7681 fmov.s &0x3F800000,%fp0
7682
7683 fmov.l %d0,%fpcr
7684 fadd.s &0x00800000,%fp0
7685 bra t_pinx2
7686
7687 #########################################################################
7688 # ssinh(): computes the hyperbolic sine of a normalized input #
7689 # ssinhd(): computes the hyperbolic sine of a denormalized input #
7690 # #
7691 # INPUT *************************************************************** #
7692 # a0 = pointer to extended precision input #
7693 # d0 = round precision,mode #
7694 # #
7695 # OUTPUT ************************************************************** #
7696 # fp0 = sinh(X) #
7697 # #
7698 # ACCURACY and MONOTONICITY ******************************************* #
7699 # The returned result is within 3 ulps in 64 significant bit, #
7700 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7701 # rounded to double precision. The result is provably monotonic #
7702 # in double precision. #
7703 # #
7704 # ALGORITHM *********************************************************** #
7705 # #
7706 # SINH #
7707 # 1. If |X| > 16380 log2, go to 3. #
7708 # #
7709 # 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula #
7710 # y = |X|, sgn = sign(X), and z = expm1(Y), #
7711 # sinh(X) = sgn*(1/2)*( z + z/(1+z) ). #
7712 # Exit. #
7713 # #
7714 # 3. If |X| > 16480 log2, go to 5. #
7715 # #
7716 # 4. (16380 log2 < |X| <= 16480 log2) #
7717 # sinh(X) = sign(X) * exp(|X|)/2. #
7718 # However, invoking exp(|X|) may cause premature overflow. #
7719 # Thus, we calculate sinh(X) as follows: #
7720 # Y := |X| #
7721 # sgn := sign(X) #
7722 # sgnFact := sgn * 2**(16380) #
7723 # Y' := Y - 16381 log2 #
7724 # sinh(X) := sgnFact * exp(Y'). #
7725 # Exit. #
7726 # #
7727 # 5. (|X| > 16480 log2) sinh(X) must overflow. Return #
7728 # sign(X)*Huge*Huge to generate overflow and an infinity with #
7729 # the appropriate sign. Huge is the largest finite number in #
7730 # extended format. Exit. #
7731 # #
7732 #########################################################################
7733
7734 global ssinh
7735 ssinh:
7736 fmov.x (%a0),%fp0 # LOAD INPUT
7737
7738 mov.l (%a0),%d1
7739 mov.w 4(%a0),%d1
7740 mov.l %d1,%a1 # save (compacted) operand
7741 and.l &0x7FFFFFFF,%d1
7742 cmp.l %d1,&0x400CB167
7743 bgt.b SINHBIG
7744
7745 #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
7746 #--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
7747
7748 fabs.x %fp0 # Y = |X|
7749
7750 movm.l &0x8040,-(%sp) # {a1/d0}
7751 fmovm.x &0x01,-(%sp) # save Y on stack
7752 lea (%sp),%a0 # pass ptr to Y
7753 clr.l %d0
7754 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7755 add.l &0xc,%sp # clear Y from stack
7756 fmov.l &0,%fpcr
7757 movm.l (%sp)+,&0x0201 # {a1/d0}
7758
7759 fmov.x %fp0,%fp1
7760 fadd.s &0x3F800000,%fp1 # 1+Z
7761 fmov.x %fp0,-(%sp)
7762 fdiv.x %fp1,%fp0 # Z/(1+Z)
7763 mov.l %a1,%d1
7764 and.l &0x80000000,%d1
7765 or.l &0x3F000000,%d1
7766 fadd.x (%sp)+,%fp0
7767 mov.l %d1,-(%sp)
7768
7769 fmov.l %d0,%fpcr
7770 mov.b &FMUL_OP,%d1 # last inst is MUL
7771 fmul.s (%sp)+,%fp0 # last fp inst - possible exceptions set
7772 bra t_catch
7773
7774 SINHBIG:
7775 cmp.l %d1,&0x400CB2B3
7776 bgt t_ovfl
7777 fabs.x %fp0
7778 fsub.d T1(%pc),%fp0 # (|X|-16381LOG2_LEAD)
7779 mov.l &0,-(%sp)
7780 mov.l &0x80000000,-(%sp)
7781 mov.l %a1,%d1
7782 and.l &0x80000000,%d1
7783 or.l &0x7FFB0000,%d1
7784 mov.l %d1,-(%sp) # EXTENDED FMT
7785 fsub.d T2(%pc),%fp0 # |X| - 16381 LOG2, ACCURATE
7786
7787 mov.l %d0,-(%sp)
7788 clr.l %d0
7789 fmovm.x &0x01,-(%sp) # save fp0 on stack
7790 lea (%sp),%a0 # pass ptr to fp0
7791 bsr setox
7792 add.l &0xc,%sp # clear fp0 from stack
7793
7794 mov.l (%sp)+,%d0
7795 fmov.l %d0,%fpcr
7796 mov.b &FMUL_OP,%d1 # last inst is MUL
7797 fmul.x (%sp)+,%fp0 # possible exception
7798 bra t_catch
7799
7800 global ssinhd
7801 #--SINH(X) = X FOR DENORMALIZED X
7802 ssinhd:
7803 bra t_extdnrm
7804
7805 #########################################################################
7806 # stanh(): computes the hyperbolic tangent of a normalized input #
7807 # stanhd(): computes the hyperbolic tangent of a denormalized input #
7808 # #
7809 # INPUT *************************************************************** #
7810 # a0 = pointer to extended precision input #
7811 # d0 = round precision,mode #
7812 # #
7813 # OUTPUT ************************************************************** #
7814 # fp0 = tanh(X) #
7815 # #
7816 # ACCURACY and MONOTONICITY ******************************************* #
7817 # The returned result is within 3 ulps in 64 significant bit, #
7818 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7819 # rounded to double precision. The result is provably monotonic #
7820 # in double precision. #
7821 # #
7822 # ALGORITHM *********************************************************** #
7823 # #
7824 # TANH #
7825 # 1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3. #
7826 # #
7827 # 2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by #
7828 # sgn := sign(X), y := 2|X|, z := expm1(Y), and #
7829 # tanh(X) = sgn*( z/(2+z) ). #
7830 # Exit. #
7831 # #
7832 # 3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1, #
7833 # go to 7. #
7834 # #
7835 # 4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6. #
7836 # #
7837 # 5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by #
7838 # sgn := sign(X), y := 2|X|, z := exp(Y), #
7839 # tanh(X) = sgn - [ sgn*2/(1+z) ]. #
7840 # Exit. #
7841 # #
7842 # 6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we #
7843 # calculate Tanh(X) by #
7844 # sgn := sign(X), Tiny := 2**(-126), #
7845 # tanh(X) := sgn - sgn*Tiny. #
7846 # Exit. #
7847 # #
7848 # 7. (|X| < 2**(-40)). Tanh(X) = X. Exit. #
7849 # #
7850 #########################################################################
7851
7852 set X,FP_SCR0
7853 set XFRAC,X+4
7854
7855 set SGN,L_SCR3
7856
7857 set V,FP_SCR0
7858
7859 global stanh
7860 stanh:
7861 fmov.x (%a0),%fp0 # LOAD INPUT
7862
7863 fmov.x %fp0,X(%a6)
7864 mov.l (%a0),%d1
7865 mov.w 4(%a0),%d1
7866 mov.l %d1,X(%a6)
7867 and.l &0x7FFFFFFF,%d1
7868 cmp.l %d1, &0x3fd78000 # is |X| < 2^(-40)?
7869 blt.w TANHBORS # yes
7870 cmp.l %d1, &0x3fffddce # is |X| > (5/2)LOG2?
7871 bgt.w TANHBORS # yes
7872
7873 #--THIS IS THE USUAL CASE
7874 #--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
7875
7876 mov.l X(%a6),%d1
7877 mov.l %d1,SGN(%a6)
7878 and.l &0x7FFF0000,%d1
7879 add.l &0x00010000,%d1 # EXPONENT OF 2|X|
7880 mov.l %d1,X(%a6)
7881 and.l &0x80000000,SGN(%a6)
7882 fmov.x X(%a6),%fp0 # FP0 IS Y = 2|X|
7883
7884 mov.l %d0,-(%sp)
7885 clr.l %d0
7886 fmovm.x &0x1,-(%sp) # save Y on stack
7887 lea (%sp),%a0 # pass ptr to Y
7888 bsr setoxm1 # FP0 IS Z = EXPM1(Y)
7889 add.l &0xc,%sp # clear Y from stack
7890 mov.l (%sp)+,%d0
7891
7892 fmov.x %fp0,%fp1
7893 fadd.s &0x40000000,%fp1 # Z+2
7894 mov.l SGN(%a6),%d1
7895 fmov.x %fp1,V(%a6)
7896 eor.l %d1,V(%a6)
7897
7898 fmov.l %d0,%fpcr # restore users round prec,mode
7899 fdiv.x V(%a6),%fp0
7900 bra t_inx2
7901
7902 TANHBORS:
7903 cmp.l %d1,&0x3FFF8000
7904 blt.w TANHSM
7905
7906 cmp.l %d1,&0x40048AA1
7907 bgt.w TANHHUGE
7908
7909 #-- (5/2) LOG2 < |X| < 50 LOG2,
7910 #--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
7911 #--TANH(X) = SGN - SGN*2/[EXP(Y)+1].
7912
7913 mov.l X(%a6),%d1
7914 mov.l %d1,SGN(%a6)
7915 and.l &0x7FFF0000,%d1
7916 add.l &0x00010000,%d1 # EXPO OF 2|X|
7917 mov.l %d1,X(%a6) # Y = 2|X|
7918 and.l &0x80000000,SGN(%a6)
7919 mov.l SGN(%a6),%d1
7920 fmov.x X(%a6),%fp0 # Y = 2|X|
7921
7922 mov.l %d0,-(%sp)
7923 clr.l %d0
7924 fmovm.x &0x01,-(%sp) # save Y on stack
7925 lea (%sp),%a0 # pass ptr to Y
7926 bsr setox # FP0 IS EXP(Y)
7927 add.l &0xc,%sp # clear Y from stack
7928 mov.l (%sp)+,%d0
7929 mov.l SGN(%a6),%d1
7930 fadd.s &0x3F800000,%fp0 # EXP(Y)+1
7931
7932 eor.l &0xC0000000,%d1 # -SIGN(X)*2
7933 fmov.s %d1,%fp1 # -SIGN(X)*2 IN SGL FMT
7934 fdiv.x %fp0,%fp1 # -SIGN(X)2 / [EXP(Y)+1 ]
7935
7936 mov.l SGN(%a6),%d1
7937 or.l &0x3F800000,%d1 # SGN
7938 fmov.s %d1,%fp0 # SGN IN SGL FMT
7939
7940 fmov.l %d0,%fpcr # restore users round prec,mode
7941 mov.b &FADD_OP,%d1 # last inst is ADD
7942 fadd.x %fp1,%fp0
7943 bra t_inx2
7944
7945 TANHSM:
7946 fmov.l %d0,%fpcr # restore users round prec,mode
7947 mov.b &FMOV_OP,%d1 # last inst is MOVE
7948 fmov.x X(%a6),%fp0 # last inst - possible exception set
7949 bra t_catch
7950
7951 #---RETURN SGN(X) - SGN(X)EPS
7952 TANHHUGE:
7953 mov.l X(%a6),%d1
7954 and.l &0x80000000,%d1
7955 or.l &0x3F800000,%d1
7956 fmov.s %d1,%fp0
7957 and.l &0x80000000,%d1
7958 eor.l &0x80800000,%d1 # -SIGN(X)*EPS
7959
7960 fmov.l %d0,%fpcr # restore users round prec,mode
7961 fadd.s %d1,%fp0
7962 bra t_inx2
7963
7964 global stanhd
7965 #--TANH(X) = X FOR DENORMALIZED X
7966 stanhd:
7967 bra t_extdnrm
7968
7969 #########################################################################
7970 # slogn(): computes the natural logarithm of a normalized input #
7971 # slognd(): computes the natural logarithm of a denormalized input #
7972 # slognp1(): computes the log(1+X) of a normalized input #
7973 # slognp1d(): computes the log(1+X) of a denormalized input #
7974 # #
7975 # INPUT *************************************************************** #
7976 # a0 = pointer to extended precision input #
7977 # d0 = round precision,mode #
7978 # #
7979 # OUTPUT ************************************************************** #
7980 # fp0 = log(X) or log(1+X) #
7981 # #
7982 # ACCURACY and MONOTONICITY ******************************************* #
7983 # The returned result is within 2 ulps in 64 significant bit, #
7984 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
7985 # rounded to double precision. The result is provably monotonic #
7986 # in double precision. #
7987 # #
7988 # ALGORITHM *********************************************************** #
7989 # LOGN: #
7990 # Step 1. If |X-1| < 1/16, approximate log(X) by an odd #
7991 # polynomial in u, where u = 2(X-1)/(X+1). Otherwise, #
7992 # move on to Step 2. #
7993 # #
7994 # Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first #
7995 # seven significant bits of Y plus 2**(-7), i.e. #
7996 # F = 1.xxxxxx1 in base 2 where the six "x" match those #
7997 # of Y. Note that |Y-F| <= 2**(-7). #
7998 # #
7999 # Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a #
8000 # polynomial in u, log(1+u) = poly. #
8001 # #
8002 # Step 4. Reconstruct #
8003 # log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u) #
8004 # by k*log(2) + (log(F) + poly). The values of log(F) are #
8005 # calculated beforehand and stored in the program. #
8006 # #
8007 # lognp1: #
8008 # Step 1: If |X| < 1/16, approximate log(1+X) by an odd #
8009 # polynomial in u where u = 2X/(2+X). Otherwise, move on #
8010 # to Step 2. #
8011 # #
8012 # Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done #
8013 # in Step 2 of the algorithm for LOGN and compute #
8014 # log(1+X) as k*log(2) + log(F) + poly where poly #
8015 # approximates log(1+u), u = (Y-F)/F. #
8016 # #
8017 # Implementation Notes: #
8018 # Note 1. There are 64 different possible values for F, thus 64 #
8019 # log(F)'s need to be tabulated. Moreover, the values of #
8020 # 1/F are also tabulated so that the division in (Y-F)/F #
8021 # can be performed by a multiplication. #
8022 # #
8023 # Note 2. In Step 2 of lognp1, in order to preserved accuracy, #
8024 # the value Y-F has to be calculated carefully when #
8025 # 1/2 <= X < 3/2. #
8026 # #
8027 # Note 3. To fully exploit the pipeline, polynomials are usually #
8028 # separated into two parts evaluated independently before #
8029 # being added up. #
8030 # #
8031 #########################################################################
8032 LOGOF2:
8033 long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8034
8035 one:
8036 long 0x3F800000
8037 zero:
8038 long 0x00000000
8039 infty:
8040 long 0x7F800000
8041 negone:
8042 long 0xBF800000
8043
8044 LOGA6:
8045 long 0x3FC2499A,0xB5E4040B
8046 LOGA5:
8047 long 0xBFC555B5,0x848CB7DB
8048
8049 LOGA4:
8050 long 0x3FC99999,0x987D8730
8051 LOGA3:
8052 long 0xBFCFFFFF,0xFF6F7E97
8053
8054 LOGA2:
8055 long 0x3FD55555,0x555555A4
8056 LOGA1:
8057 long 0xBFE00000,0x00000008
8058
8059 LOGB5:
8060 long 0x3F175496,0xADD7DAD6
8061 LOGB4:
8062 long 0x3F3C71C2,0xFE80C7E0
8063
8064 LOGB3:
8065 long 0x3F624924,0x928BCCFF
8066 LOGB2:
8067 long 0x3F899999,0x999995EC
8068
8069 LOGB1:
8070 long 0x3FB55555,0x55555555
8071 TWO:
8072 long 0x40000000,0x00000000
8073
8074 LTHOLD:
8075 long 0x3f990000,0x80000000,0x00000000,0x00000000
8076
8077 LOGTBL:
8078 long 0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
8079 long 0x3FF70000,0xFF015358,0x833C47E2,0x00000000
8080 long 0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
8081 long 0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
8082 long 0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
8083 long 0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
8084 long 0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
8085 long 0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
8086 long 0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
8087 long 0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
8088 long 0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
8089 long 0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
8090 long 0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
8091 long 0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
8092 long 0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
8093 long 0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
8094 long 0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
8095 long 0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
8096 long 0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
8097 long 0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
8098 long 0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
8099 long 0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
8100 long 0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
8101 long 0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
8102 long 0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
8103 long 0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
8104 long 0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
8105 long 0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
8106 long 0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
8107 long 0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
8108 long 0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
8109 long 0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
8110 long 0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
8111 long 0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
8112 long 0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
8113 long 0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
8114 long 0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
8115 long 0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
8116 long 0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
8117 long 0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
8118 long 0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
8119 long 0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
8120 long 0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
8121 long 0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
8122 long 0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
8123 long 0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
8124 long 0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
8125 long 0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
8126 long 0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
8127 long 0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
8128 long 0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
8129 long 0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
8130 long 0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
8131 long 0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
8132 long 0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
8133 long 0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
8134 long 0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
8135 long 0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
8136 long 0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
8137 long 0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
8138 long 0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
8139 long 0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
8140 long 0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
8141 long 0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
8142 long 0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
8143 long 0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
8144 long 0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
8145 long 0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
8146 long 0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
8147 long 0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
8148 long 0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
8149 long 0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
8150 long 0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
8151 long 0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
8152 long 0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
8153 long 0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
8154 long 0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
8155 long 0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
8156 long 0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
8157 long 0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
8158 long 0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
8159 long 0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
8160 long 0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
8161 long 0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
8162 long 0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
8163 long 0x3FFE0000,0x825EFCED,0x49369330,0x00000000
8164 long 0x3FFE0000,0x9868C809,0x868C8098,0x00000000
8165 long 0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
8166 long 0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
8167 long 0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
8168 long 0x3FFE0000,0x95A02568,0x095A0257,0x00000000
8169 long 0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
8170 long 0x3FFE0000,0x94458094,0x45809446,0x00000000
8171 long 0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
8172 long 0x3FFE0000,0x92F11384,0x0497889C,0x00000000
8173 long 0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
8174 long 0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
8175 long 0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
8176 long 0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
8177 long 0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
8178 long 0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
8179 long 0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
8180 long 0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
8181 long 0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
8182 long 0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
8183 long 0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
8184 long 0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
8185 long 0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
8186 long 0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
8187 long 0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
8188 long 0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
8189 long 0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
8190 long 0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
8191 long 0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
8192 long 0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
8193 long 0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
8194 long 0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
8195 long 0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
8196 long 0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
8197 long 0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
8198 long 0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
8199 long 0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
8200 long 0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
8201 long 0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
8202 long 0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
8203 long 0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
8204 long 0x3FFE0000,0x80808080,0x80808081,0x00000000
8205 long 0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
8206
8207 set ADJK,L_SCR1
8208
8209 set X,FP_SCR0
8210 set XDCARE,X+2
8211 set XFRAC,X+4
8212
8213 set F,FP_SCR1
8214 set FFRAC,F+4
8215
8216 set KLOG2,FP_SCR0
8217
8218 set SAVEU,FP_SCR0
8219
8220 global slogn
8221 #--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
8222 slogn:
8223 fmov.x (%a0),%fp0 # LOAD INPUT
8224 mov.l &0x00000000,ADJK(%a6)
8225
8226 LOGBGN:
8227 #--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
8228 #--A FINITE, NON-ZERO, NORMALIZED NUMBER.
8229
8230 mov.l (%a0),%d1
8231 mov.w 4(%a0),%d1
8232
8233 mov.l (%a0),X(%a6)
8234 mov.l 4(%a0),X+4(%a6)
8235 mov.l 8(%a0),X+8(%a6)
8236
8237 cmp.l %d1,&0 # CHECK IF X IS NEGATIVE
8238 blt.w LOGNEG # LOG OF NEGATIVE ARGUMENT IS INVALID
8239 # X IS POSITIVE, CHECK IF X IS NEAR 1
8240 cmp.l %d1,&0x3ffef07d # IS X < 15/16?
8241 blt.b LOGMAIN # YES
8242 cmp.l %d1,&0x3fff8841 # IS X > 17/16?
8243 ble.w LOGNEAR1 # NO
8244
8245 LOGMAIN:
8246 #--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
8247
8248 #--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
8249 #--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
8250 #--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
8251 #-- = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
8252 #--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
8253 #--LOG(1+U) CAN BE VERY EFFICIENT.
8254 #--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
8255 #--DIVISION IS NEEDED TO CALCULATE (Y-F)/F.
8256
8257 #--GET K, Y, F, AND ADDRESS OF 1/F.
8258 asr.l &8,%d1
8259 asr.l &8,%d1 # SHIFTED 16 BITS, BIASED EXPO. OF X
8260 sub.l &0x3FFF,%d1 # THIS IS K
8261 add.l ADJK(%a6),%d1 # ADJUST K, ORIGINAL INPUT MAY BE DENORM.
8262 lea LOGTBL(%pc),%a0 # BASE ADDRESS OF 1/F AND LOG(F)
8263 fmov.l %d1,%fp1 # CONVERT K TO FLOATING-POINT FORMAT
8264
8265 #--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
8266 mov.l &0x3FFF0000,X(%a6) # X IS NOW Y, I.E. 2^(-K)*X
8267 mov.l XFRAC(%a6),FFRAC(%a6)
8268 and.l &0xFE000000,FFRAC(%a6) # FIRST 7 BITS OF Y
8269 or.l &0x01000000,FFRAC(%a6) # GET F: ATTACH A 1 AT THE EIGHTH BIT
8270 mov.l FFRAC(%a6),%d1 # READY TO GET ADDRESS OF 1/F
8271 and.l &0x7E000000,%d1
8272 asr.l &8,%d1
8273 asr.l &8,%d1
8274 asr.l &4,%d1 # SHIFTED 20, D0 IS THE DISPLACEMENT
8275 add.l %d1,%a0 # A0 IS THE ADDRESS FOR 1/F
8276
8277 fmov.x X(%a6),%fp0
8278 mov.l &0x3fff0000,F(%a6)
8279 clr.l F+8(%a6)
8280 fsub.x F(%a6),%fp0 # Y-F
8281 fmovm.x &0xc,-(%sp) # SAVE FP2-3 WHILE FP0 IS NOT READY
8282 #--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
8283 #--REGISTERS SAVED: FPCR, FP1, FP2
8284
8285 LP1CONT1:
8286 #--AN RE-ENTRY POINT FOR LOGNP1
8287 fmul.x (%a0),%fp0 # FP0 IS U = (Y-F)/F
8288 fmul.x LOGOF2(%pc),%fp1 # GET K*LOG2 WHILE FP0 IS NOT READY
8289 fmov.x %fp0,%fp2
8290 fmul.x %fp2,%fp2 # FP2 IS V=U*U
8291 fmov.x %fp1,KLOG2(%a6) # PUT K*LOG2 IN MEMEORY, FREE FP1
8292
8293 #--LOG(1+U) IS APPROXIMATED BY
8294 #--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
8295 #--[U + V*(A1+V*(A3+V*A5))] + [U*V*(A2+V*(A4+V*A6))]
8296
8297 fmov.x %fp2,%fp3
8298 fmov.x %fp2,%fp1
8299
8300 fmul.d LOGA6(%pc),%fp1 # V*A6
8301 fmul.d LOGA5(%pc),%fp2 # V*A5
8302
8303 fadd.d LOGA4(%pc),%fp1 # A4+V*A6
8304 fadd.d LOGA3(%pc),%fp2 # A3+V*A5
8305
8306 fmul.x %fp3,%fp1 # V*(A4+V*A6)
8307 fmul.x %fp3,%fp2 # V*(A3+V*A5)
8308
8309 fadd.d LOGA2(%pc),%fp1 # A2+V*(A4+V*A6)
8310 fadd.d LOGA1(%pc),%fp2 # A1+V*(A3+V*A5)
8311
8312 fmul.x %fp3,%fp1 # V*(A2+V*(A4+V*A6))
8313 add.l &16,%a0 # ADDRESS OF LOG(F)
8314 fmul.x %fp3,%fp2 # V*(A1+V*(A3+V*A5))
8315
8316 fmul.x %fp0,%fp1 # U*V*(A2+V*(A4+V*A6))
8317 fadd.x %fp2,%fp0 # U+V*(A1+V*(A3+V*A5))
8318
8319 fadd.x (%a0),%fp1 # LOG(F)+U*V*(A2+V*(A4+V*A6))
8320 fmovm.x (%sp)+,&0x30 # RESTORE FP2-3
8321 fadd.x %fp1,%fp0 # FP0 IS LOG(F) + LOG(1+U)
8322
8323 fmov.l %d0,%fpcr
8324 fadd.x KLOG2(%a6),%fp0 # FINAL ADD
8325 bra t_inx2
8326
8327
8328 LOGNEAR1:
8329
8330 # if the input is exactly equal to one, then exit through ld_pzero.
8331 # if these 2 lines weren't here, the correct answer would be returned
8332 # but the INEX2 bit would be set.
8333 fcmp.b %fp0,&0x1 # is it equal to one?
8334 fbeq.l ld_pzero # yes
8335
8336 #--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
8337 fmov.x %fp0,%fp1
8338 fsub.s one(%pc),%fp1 # FP1 IS X-1
8339 fadd.s one(%pc),%fp0 # FP0 IS X+1
8340 fadd.x %fp1,%fp1 # FP1 IS 2(X-1)
8341 #--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
8342 #--IN U, U = 2(X-1)/(X+1) = FP1/FP0
8343
8344 LP1CONT2:
8345 #--THIS IS AN RE-ENTRY POINT FOR LOGNP1
8346 fdiv.x %fp0,%fp1 # FP1 IS U
8347 fmovm.x &0xc,-(%sp) # SAVE FP2-3
8348 #--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
8349 #--LET V=U*U, W=V*V, CALCULATE
8350 #--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
8351 #--U + U*V*( [B1 + W*(B3 + W*B5)] + [V*(B2 + W*B4)] )
8352 fmov.x %fp1,%fp0
8353 fmul.x %fp0,%fp0 # FP0 IS V
8354 fmov.x %fp1,SAVEU(%a6) # STORE U IN MEMORY, FREE FP1
8355 fmov.x %fp0,%fp1
8356 fmul.x %fp1,%fp1 # FP1 IS W
8357
8358 fmov.d LOGB5(%pc),%fp3
8359 fmov.d LOGB4(%pc),%fp2
8360
8361 fmul.x %fp1,%fp3 # W*B5
8362 fmul.x %fp1,%fp2 # W*B4
8363
8364 fadd.d LOGB3(%pc),%fp3 # B3+W*B5
8365 fadd.d LOGB2(%pc),%fp2 # B2+W*B4
8366
8367 fmul.x %fp3,%fp1 # W*(B3+W*B5), FP3 RELEASED
8368
8369 fmul.x %fp0,%fp2 # V*(B2+W*B4)
8370
8371 fadd.d LOGB1(%pc),%fp1 # B1+W*(B3+W*B5)
8372 fmul.x SAVEU(%a6),%fp0 # FP0 IS U*V
8373
8374 fadd.x %fp2,%fp1 # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
8375 fmovm.x (%sp)+,&0x30 # FP2-3 RESTORED
8376
8377 fmul.x %fp1,%fp0 # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
8378
8379 fmov.l %d0,%fpcr
8380 fadd.x SAVEU(%a6),%fp0
8381 bra t_inx2
8382
8383 #--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
8384 LOGNEG:
8385 bra t_operr
8386
8387 global slognd
8388 slognd:
8389 #--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
8390
8391 mov.l &-100,ADJK(%a6) # INPUT = 2^(ADJK) * FP0
8392
8393 #----normalize the input value by left shifting k bits (k to be determined
8394 #----below), adjusting exponent and storing -k to ADJK
8395 #----the value TWOTO100 is no longer needed.
8396 #----Note that this code assumes the denormalized input is NON-ZERO.
8397
8398 movm.l &0x3f00,-(%sp) # save some registers {d2-d7}
8399 mov.l (%a0),%d3 # D3 is exponent of smallest norm. #
8400 mov.l 4(%a0),%d4
8401 mov.l 8(%a0),%d5 # (D4,D5) is (Hi_X,Lo_X)
8402 clr.l %d2 # D2 used for holding K
8403
8404 tst.l %d4
8405 bne.b Hi_not0
8406
8407 Hi_0:
8408 mov.l %d5,%d4
8409 clr.l %d5
8410 mov.l &32,%d2
8411 clr.l %d6
8412 bfffo %d4{&0:&32},%d6
8413 lsl.l %d6,%d4
8414 add.l %d6,%d2 # (D3,D4,D5) is normalized
8415
8416 mov.l %d3,X(%a6)
8417 mov.l %d4,XFRAC(%a6)
8418 mov.l %d5,XFRAC+4(%a6)
8419 neg.l %d2
8420 mov.l %d2,ADJK(%a6)
8421 fmov.x X(%a6),%fp0
8422 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8423 lea X(%a6),%a0
8424 bra.w LOGBGN # begin regular log(X)
8425
8426 Hi_not0:
8427 clr.l %d6
8428 bfffo %d4{&0:&32},%d6 # find first 1
8429 mov.l %d6,%d2 # get k
8430 lsl.l %d6,%d4
8431 mov.l %d5,%d7 # a copy of D5
8432 lsl.l %d6,%d5
8433 neg.l %d6
8434 add.l &32,%d6
8435 lsr.l %d6,%d7
8436 or.l %d7,%d4 # (D3,D4,D5) normalized
8437
8438 mov.l %d3,X(%a6)
8439 mov.l %d4,XFRAC(%a6)
8440 mov.l %d5,XFRAC+4(%a6)
8441 neg.l %d2
8442 mov.l %d2,ADJK(%a6)
8443 fmov.x X(%a6),%fp0
8444 movm.l (%sp)+,&0xfc # restore registers {d2-d7}
8445 lea X(%a6),%a0
8446 bra.w LOGBGN # begin regular log(X)
8447
8448 global slognp1
8449 #--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
8450 slognp1:
8451 fmov.x (%a0),%fp0 # LOAD INPUT
8452 fabs.x %fp0 # test magnitude
8453 fcmp.x %fp0,LTHOLD(%pc) # compare with min threshold
8454 fbgt.w LP1REAL # if greater, continue
8455 fmov.l %d0,%fpcr
8456 mov.b &FMOV_OP,%d1 # last inst is MOVE
8457 fmov.x (%a0),%fp0 # return signed argument
8458 bra t_catch
8459
8460 LP1REAL:
8461 fmov.x (%a0),%fp0 # LOAD INPUT
8462 mov.l &0x00000000,ADJK(%a6)
8463 fmov.x %fp0,%fp1 # FP1 IS INPUT Z
8464 fadd.s one(%pc),%fp0 # X := ROUND(1+Z)
8465 fmov.x %fp0,X(%a6)
8466 mov.w XFRAC(%a6),XDCARE(%a6)
8467 mov.l X(%a6),%d1
8468 cmp.l %d1,&0
8469 ble.w LP1NEG0 # LOG OF ZERO OR -VE
8470 cmp.l %d1,&0x3ffe8000 # IS BOUNDS [1/2,3/2]?
8471 blt.w LOGMAIN
8472 cmp.l %d1,&0x3fffc000
8473 bgt.w LOGMAIN
8474 #--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
8475 #--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
8476 #--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
8477
8478 LP1NEAR1:
8479 #--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
8480 cmp.l %d1,&0x3ffef07d
8481 blt.w LP1CARE
8482 cmp.l %d1,&0x3fff8841
8483 bgt.w LP1CARE
8484
8485 LP1ONE16:
8486 #--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
8487 #--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
8488 fadd.x %fp1,%fp1 # FP1 IS 2Z
8489 fadd.s one(%pc),%fp0 # FP0 IS 1+X
8490 #--U = FP1/FP0
8491 bra.w LP1CONT2
8492
8493 LP1CARE:
8494 #--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
8495 #--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
8496 #--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
8497 #--THERE ARE ONLY TWO CASES.
8498 #--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
8499 #--CASE 2: 1+Z > 1, THEN K = 0 AND Y-F = (1-F) + Z
8500 #--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
8501 #--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
8502
8503 mov.l XFRAC(%a6),FFRAC(%a6)
8504 and.l &0xFE000000,FFRAC(%a6)
8505 or.l &0x01000000,FFRAC(%a6) # F OBTAINED
8506 cmp.l %d1,&0x3FFF8000 # SEE IF 1+Z > 1
8507 bge.b KISZERO
8508
8509 KISNEG1:
8510 fmov.s TWO(%pc),%fp0
8511 mov.l &0x3fff0000,F(%a6)
8512 clr.l F+8(%a6)
8513 fsub.x F(%a6),%fp0 # 2-F
8514 mov.l FFRAC(%a6),%d1
8515 and.l &0x7E000000,%d1
8516 asr.l &8,%d1
8517 asr.l &8,%d1
8518 asr.l &4,%d1 # D0 CONTAINS DISPLACEMENT FOR 1/F
8519 fadd.x %fp1,%fp1 # GET 2Z
8520 fmovm.x &0xc,-(%sp) # SAVE FP2 {%fp2/%fp3}
8521 fadd.x %fp1,%fp0 # FP0 IS Y-F = (2-F)+2Z
8522 lea LOGTBL(%pc),%a0 # A0 IS ADDRESS OF 1/F
8523 add.l %d1,%a0
8524 fmov.s negone(%pc),%fp1 # FP1 IS K = -1
8525 bra.w LP1CONT1
8526
8527 KISZERO:
8528 fmov.s one(%pc),%fp0
8529 mov.l &0x3fff0000,F(%a6)
8530 clr.l F+8(%a6)
8531 fsub.x F(%a6),%fp0 # 1-F
8532 mov.l FFRAC(%a6),%d1
8533 and.l &0x7E000000,%d1
8534 asr.l &8,%d1
8535 asr.l &8,%d1
8536 asr.l &4,%d1
8537 fadd.x %fp1,%fp0 # FP0 IS Y-F
8538 fmovm.x &0xc,-(%sp) # FP2 SAVED {%fp2/%fp3}
8539 lea LOGTBL(%pc),%a0
8540 add.l %d1,%a0 # A0 IS ADDRESS OF 1/F
8541 fmov.s zero(%pc),%fp1 # FP1 IS K = 0
8542 bra.w LP1CONT1
8543
8544 LP1NEG0:
8545 #--FPCR SAVED. D0 IS X IN COMPACT FORM.
8546 cmp.l %d1,&0
8547 blt.b LP1NEG
8548 LP1ZERO:
8549 fmov.s negone(%pc),%fp0
8550
8551 fmov.l %d0,%fpcr
8552 bra t_dz
8553
8554 LP1NEG:
8555 fmov.s zero(%pc),%fp0
8556
8557 fmov.l %d0,%fpcr
8558 bra t_operr
8559
8560 global slognp1d
8561 #--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
8562 # Simply return the denorm
8563 slognp1d:
8564 bra t_extdnrm
8565
8566 #########################################################################
8567 # satanh(): computes the inverse hyperbolic tangent of a norm input #
8568 # satanhd(): computes the inverse hyperbolic tangent of a denorm input #
8569 # #
8570 # INPUT *************************************************************** #
8571 # a0 = pointer to extended precision input #
8572 # d0 = round precision,mode #
8573 # #
8574 # OUTPUT ************************************************************** #
8575 # fp0 = arctanh(X) #
8576 # #
8577 # ACCURACY and MONOTONICITY ******************************************* #
8578 # The returned result is within 3 ulps in 64 significant bit, #
8579 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8580 # rounded to double precision. The result is provably monotonic #
8581 # in double precision. #
8582 # #
8583 # ALGORITHM *********************************************************** #
8584 # #
8585 # ATANH #
8586 # 1. If |X| >= 1, go to 3. #
8587 # #
8588 # 2. (|X| < 1) Calculate atanh(X) by #
8589 # sgn := sign(X) #
8590 # y := |X| #
8591 # z := 2y/(1-y) #
8592 # atanh(X) := sgn * (1/2) * logp1(z) #
8593 # Exit. #
8594 # #
8595 # 3. If |X| > 1, go to 5. #
8596 # #
8597 # 4. (|X| = 1) Generate infinity with an appropriate sign and #
8598 # divide-by-zero by #
8599 # sgn := sign(X) #
8600 # atan(X) := sgn / (+0). #
8601 # Exit. #
8602 # #
8603 # 5. (|X| > 1) Generate an invalid operation by 0 * infinity. #
8604 # Exit. #
8605 # #
8606 #########################################################################
8607
8608 global satanh
8609 satanh:
8610 mov.l (%a0),%d1
8611 mov.w 4(%a0),%d1
8612 and.l &0x7FFFFFFF,%d1
8613 cmp.l %d1,&0x3FFF8000
8614 bge.b ATANHBIG
8615
8616 #--THIS IS THE USUAL CASE, |X| < 1
8617 #--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
8618
8619 fabs.x (%a0),%fp0 # Y = |X|
8620 fmov.x %fp0,%fp1
8621 fneg.x %fp1 # -Y
8622 fadd.x %fp0,%fp0 # 2Y
8623 fadd.s &0x3F800000,%fp1 # 1-Y
8624 fdiv.x %fp1,%fp0 # 2Y/(1-Y)
8625 mov.l (%a0),%d1
8626 and.l &0x80000000,%d1
8627 or.l &0x3F000000,%d1 # SIGN(X)*HALF
8628 mov.l %d1,-(%sp)
8629
8630 mov.l %d0,-(%sp) # save rnd prec,mode
8631 clr.l %d0 # pass ext prec,RN
8632 fmovm.x &0x01,-(%sp) # save Z on stack
8633 lea (%sp),%a0 # pass ptr to Z
8634 bsr slognp1 # LOG1P(Z)
8635 add.l &0xc,%sp # clear Z from stack
8636
8637 mov.l (%sp)+,%d0 # fetch old prec,mode
8638 fmov.l %d0,%fpcr # load it
8639 mov.b &FMUL_OP,%d1 # last inst is MUL
8640 fmul.s (%sp)+,%fp0
8641 bra t_catch
8642
8643 ATANHBIG:
8644 fabs.x (%a0),%fp0 # |X|
8645 fcmp.s %fp0,&0x3F800000
8646 fbgt t_operr
8647 bra t_dz
8648
8649 global satanhd
8650 #--ATANH(X) = X FOR DENORMALIZED X
8651 satanhd:
8652 bra t_extdnrm
8653
8654 #########################################################################
8655 # slog10(): computes the base-10 logarithm of a normalized input #
8656 # slog10d(): computes the base-10 logarithm of a denormalized input #
8657 # slog2(): computes the base-2 logarithm of a normalized input #
8658 # slog2d(): computes the base-2 logarithm of a denormalized input #
8659 # #
8660 # INPUT *************************************************************** #
8661 # a0 = pointer to extended precision input #
8662 # d0 = round precision,mode #
8663 # #
8664 # OUTPUT ************************************************************** #
8665 # fp0 = log_10(X) or log_2(X) #
8666 # #
8667 # ACCURACY and MONOTONICITY ******************************************* #
8668 # The returned result is within 1.7 ulps in 64 significant bit, #
8669 # i.e. within 0.5003 ulp to 53 bits if the result is subsequently #
8670 # rounded to double precision. The result is provably monotonic #
8671 # in double precision. #
8672 # #
8673 # ALGORITHM *********************************************************** #
8674 # #
8675 # slog10d: #
8676 # #
8677 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8678 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8679 # Notes: Default means round-to-nearest mode, no floating-point #
8680 # traps, and precision control = double extended. #
8681 # #
8682 # Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8683 # Notes: Even if X is denormalized, log(X) is always normalized. #
8684 # #
8685 # Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8686 # 2.1 Restore the user FPCR #
8687 # 2.2 Return ans := Y * INV_L10. #
8688 # #
8689 # slog10: #
8690 # #
8691 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8692 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8693 # Notes: Default means round-to-nearest mode, no floating-point #
8694 # traps, and precision control = double extended. #
8695 # #
8696 # Step 1. Call sLogN to obtain Y = log(X), the natural log of X. #
8697 # #
8698 # Step 2. Compute log_10(X) = log(X) * (1/log(10)). #
8699 # 2.1 Restore the user FPCR #
8700 # 2.2 Return ans := Y * INV_L10. #
8701 # #
8702 # sLog2d: #
8703 # #
8704 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8705 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8706 # Notes: Default means round-to-nearest mode, no floating-point #
8707 # traps, and precision control = double extended. #
8708 # #
8709 # Step 1. Call slognd to obtain Y = log(X), the natural log of X. #
8710 # Notes: Even if X is denormalized, log(X) is always normalized. #
8711 # #
8712 # Step 2. Compute log_10(X) = log(X) * (1/log(2)). #
8713 # 2.1 Restore the user FPCR #
8714 # 2.2 Return ans := Y * INV_L2. #
8715 # #
8716 # sLog2: #
8717 # #
8718 # Step 0. If X < 0, create a NaN and raise the invalid operation #
8719 # flag. Otherwise, save FPCR in D1; set FpCR to default. #
8720 # Notes: Default means round-to-nearest mode, no floating-point #
8721 # traps, and precision control = double extended. #
8722 # #
8723 # Step 1. If X is not an integer power of two, i.e., X != 2^k, #
8724 # go to Step 3. #
8725 # #
8726 # Step 2. Return k. #
8727 # 2.1 Get integer k, X = 2^k. #
8728 # 2.2 Restore the user FPCR. #
8729 # 2.3 Return ans := convert-to-double-extended(k). #
8730 # #
8731 # Step 3. Call sLogN to obtain Y = log(X), the natural log of X. #
8732 # #
8733 # Step 4. Compute log_2(X) = log(X) * (1/log(2)). #
8734 # 4.1 Restore the user FPCR #
8735 # 4.2 Return ans := Y * INV_L2. #
8736 # #
8737 #########################################################################
8738
8739 INV_L10:
8740 long 0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
8741
8742 INV_L2:
8743 long 0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
8744
8745 global slog10
8746 #--entry point for Log10(X), X is normalized
8747 slog10:
8748 fmov.b &0x1,%fp0
8749 fcmp.x %fp0,(%a0) # if operand == 1,
8750 fbeq.l ld_pzero # return an EXACT zero
8751
8752 mov.l (%a0),%d1
8753 blt.w invalid
8754 mov.l %d0,-(%sp)
8755 clr.l %d0
8756 bsr slogn # log(X), X normal.
8757 fmov.l (%sp)+,%fpcr
8758 fmul.x INV_L10(%pc),%fp0
8759 bra t_inx2
8760
8761 global slog10d
8762 #--entry point for Log10(X), X is denormalized
8763 slog10d:
8764 mov.l (%a0),%d1
8765 blt.w invalid
8766 mov.l %d0,-(%sp)
8767 clr.l %d0
8768 bsr slognd # log(X), X denorm.
8769 fmov.l (%sp)+,%fpcr
8770 fmul.x INV_L10(%pc),%fp0
8771 bra t_minx2
8772
8773 global slog2
8774 #--entry point for Log2(X), X is normalized
8775 slog2:
8776 mov.l (%a0),%d1
8777 blt.w invalid
8778
8779 mov.l 8(%a0),%d1
8780 bne.b continue # X is not 2^k
8781
8782 mov.l 4(%a0),%d1
8783 and.l &0x7FFFFFFF,%d1
8784 bne.b continue
8785
8786 #--X = 2^k.
8787 mov.w (%a0),%d1
8788 and.l &0x00007FFF,%d1
8789 sub.l &0x3FFF,%d1
8790 beq.l ld_pzero
8791 fmov.l %d0,%fpcr
8792 fmov.l %d1,%fp0
8793 bra t_inx2
8794
8795 continue:
8796 mov.l %d0,-(%sp)
8797 clr.l %d0
8798 bsr slogn # log(X), X normal.
8799 fmov.l (%sp)+,%fpcr
8800 fmul.x INV_L2(%pc),%fp0
8801 bra t_inx2
8802
8803 invalid:
8804 bra t_operr
8805
8806 global slog2d
8807 #--entry point for Log2(X), X is denormalized
8808 slog2d:
8809 mov.l (%a0),%d1
8810 blt.w invalid
8811 mov.l %d0,-(%sp)
8812 clr.l %d0
8813 bsr slognd # log(X), X denorm.
8814 fmov.l (%sp)+,%fpcr
8815 fmul.x INV_L2(%pc),%fp0
8816 bra t_minx2
8817
8818 #########################################################################
8819 # stwotox(): computes 2**X for a normalized input #
8820 # stwotoxd(): computes 2**X for a denormalized input #
8821 # stentox(): computes 10**X for a normalized input #
8822 # stentoxd(): computes 10**X for a denormalized input #
8823 # #
8824 # INPUT *************************************************************** #
8825 # a0 = pointer to extended precision input #
8826 # d0 = round precision,mode #
8827 # #
8828 # OUTPUT ************************************************************** #
8829 # fp0 = 2**X or 10**X #
8830 # #
8831 # ACCURACY and MONOTONICITY ******************************************* #
8832 # The returned result is within 2 ulps in 64 significant bit, #
8833 # i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
8834 # rounded to double precision. The result is provably monotonic #
8835 # in double precision. #
8836 # #
8837 # ALGORITHM *********************************************************** #
8838 # #
8839 # twotox #
8840 # 1. If |X| > 16480, go to ExpBig. #
8841 # #
8842 # 2. If |X| < 2**(-70), go to ExpSm. #
8843 # #
8844 # 3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore #
8845 # decompose N as #
8846 # N = 64(M + M') + j, j = 0,1,2,...,63. #
8847 # #
8848 # 4. Overwrite r := r * log2. Then #
8849 # 2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8850 # Go to expr to compute that expression. #
8851 # #
8852 # tentox #
8853 # 1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig. #
8854 # #
8855 # 2. If |X| < 2**(-70), go to ExpSm. #
8856 # #
8857 # 3. Set y := X*log_2(10)*64 (base 2 log of 10). Set #
8858 # N := round-to-int(y). Decompose N as #
8859 # N = 64(M + M') + j, j = 0,1,2,...,63. #
8860 # #
8861 # 4. Define r as #
8862 # r := ((X - N*L1)-N*L2) * L10 #
8863 # where L1, L2 are the leading and trailing parts of #
8864 # log_10(2)/64 and L10 is the natural log of 10. Then #
8865 # 10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r). #
8866 # Go to expr to compute that expression. #
8867 # #
8868 # expr #
8869 # 1. Fetch 2**(j/64) from table as Fact1 and Fact2. #
8870 # #
8871 # 2. Overwrite Fact1 and Fact2 by #
8872 # Fact1 := 2**(M) * Fact1 #
8873 # Fact2 := 2**(M) * Fact2 #
8874 # Thus Fact1 + Fact2 = 2**(M) * 2**(j/64). #
8875 # #
8876 # 3. Calculate P where 1 + P approximates exp(r): #
8877 # P = r + r*r*(A1+r*(A2+...+r*A5)). #
8878 # #
8879 # 4. Let AdjFact := 2**(M'). Return #
8880 # AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ). #
8881 # Exit. #
8882 # #
8883 # ExpBig #
8884 # 1. Generate overflow by Huge * Huge if X > 0; otherwise, #
8885 # generate underflow by Tiny * Tiny. #
8886 # #
8887 # ExpSm #
8888 # 1. Return 1 + X. #
8889 # #
8890 #########################################################################
8891
8892 L2TEN64:
8893 long 0x406A934F,0x0979A371 # 64LOG10/LOG2
8894 L10TWO1:
8895 long 0x3F734413,0x509F8000 # LOG2/64LOG10
8896
8897 L10TWO2:
8898 long 0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
8899
8900 LOG10: long 0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
8901
8902 LOG2: long 0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
8903
8904 EXPA5: long 0x3F56C16D,0x6F7BD0B2
8905 EXPA4: long 0x3F811112,0x302C712C
8906 EXPA3: long 0x3FA55555,0x55554CC1
8907 EXPA2: long 0x3FC55555,0x55554A54
8908 EXPA1: long 0x3FE00000,0x00000000,0x00000000,0x00000000
8909
8910 TEXPTBL:
8911 long 0x3FFF0000,0x80000000,0x00000000,0x3F738000
8912 long 0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
8913 long 0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
8914 long 0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
8915 long 0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
8916 long 0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
8917 long 0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
8918 long 0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
8919 long 0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
8920 long 0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
8921 long 0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
8922 long 0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
8923 long 0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
8924 long 0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
8925 long 0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
8926 long 0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
8927 long 0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
8928 long 0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
8929 long 0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
8930 long 0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
8931 long 0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
8932 long 0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
8933 long 0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
8934 long 0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
8935 long 0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
8936 long 0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
8937 long 0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
8938 long 0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
8939 long 0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
8940 long 0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
8941 long 0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
8942 long 0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
8943 long 0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
8944 long 0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
8945 long 0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
8946 long 0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
8947 long 0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
8948 long 0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
8949 long 0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
8950 long 0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
8951 long 0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
8952 long 0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
8953 long 0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
8954 long 0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
8955 long 0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
8956 long 0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
8957 long 0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
8958 long 0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
8959 long 0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
8960 long 0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
8961 long 0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
8962 long 0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
8963 long 0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
8964 long 0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
8965 long 0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
8966 long 0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
8967 long 0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
8968 long 0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
8969 long 0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
8970 long 0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
8971 long 0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
8972 long 0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
8973 long 0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
8974 long 0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
8975
8976 set INT,L_SCR1
8977
8978 set X,FP_SCR0
8979 set XDCARE,X+2
8980 set XFRAC,X+4
8981
8982 set ADJFACT,FP_SCR0
8983
8984 set FACT1,FP_SCR0
8985 set FACT1HI,FACT1+4
8986 set FACT1LOW,FACT1+8
8987
8988 set FACT2,FP_SCR1
8989 set FACT2HI,FACT2+4
8990 set FACT2LOW,FACT2+8
8991
8992 global stwotox
8993 #--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
8994 stwotox:
8995 fmovm.x (%a0),&0x80 # LOAD INPUT
8996
8997 mov.l (%a0),%d1
8998 mov.w 4(%a0),%d1
8999 fmov.x %fp0,X(%a6)
9000 and.l &0x7FFFFFFF,%d1
9001
9002 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
9003 bge.b TWOOK1
9004 bra.w EXPBORS
9005
9006 TWOOK1:
9007 cmp.l %d1,&0x400D80C0 # |X| > 16480?
9008 ble.b TWOMAIN
9009 bra.w EXPBORS
9010
9011 TWOMAIN:
9012 #--USUAL CASE, 2^(-70) <= |X| <= 16480
9013
9014 fmov.x %fp0,%fp1
9015 fmul.s &0x42800000,%fp1 # 64 * X
9016 fmov.l %fp1,INT(%a6) # N = ROUND-TO-INT(64 X)
9017 mov.l %d2,-(%sp)
9018 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9019 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9020 mov.l INT(%a6),%d1
9021 mov.l %d1,%d2
9022 and.l &0x3F,%d1 # D0 IS J
9023 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9024 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9025 asr.l &6,%d2 # d2 IS L, N = 64L + J
9026 mov.l %d2,%d1
9027 asr.l &1,%d1 # D0 IS M
9028 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9029 add.l &0x3FFF,%d2
9030
9031 #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9032 #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9033 #--ADJFACT = 2^(M').
9034 #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9035
9036 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9037
9038 fmul.s &0x3C800000,%fp1 # (1/64)*N
9039 mov.l (%a1)+,FACT1(%a6)
9040 mov.l (%a1)+,FACT1HI(%a6)
9041 mov.l (%a1)+,FACT1LOW(%a6)
9042 mov.w (%a1)+,FACT2(%a6)
9043
9044 fsub.x %fp1,%fp0 # X - (1/64)*INT(64 X)
9045
9046 mov.w (%a1)+,FACT2HI(%a6)
9047 clr.w FACT2HI+2(%a6)
9048 clr.l FACT2LOW(%a6)
9049 add.w %d1,FACT1(%a6)
9050 fmul.x LOG2(%pc),%fp0 # FP0 IS R
9051 add.w %d1,FACT2(%a6)
9052
9053 bra.w expr
9054
9055 EXPBORS:
9056 #--FPCR, D0 SAVED
9057 cmp.l %d1,&0x3FFF8000
9058 bgt.b TEXPBIG
9059
9060 #--|X| IS SMALL, RETURN 1 + X
9061
9062 fmov.l %d0,%fpcr # restore users round prec,mode
9063 fadd.s &0x3F800000,%fp0 # RETURN 1 + X
9064 bra t_pinx2
9065
9066 TEXPBIG:
9067 #--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
9068 #--REGISTERS SAVE SO FAR ARE FPCR AND D0
9069 mov.l X(%a6),%d1
9070 cmp.l %d1,&0
9071 blt.b EXPNEG
9072
9073 bra t_ovfl2 # t_ovfl expects positive value
9074
9075 EXPNEG:
9076 bra t_unfl2 # t_unfl expects positive value
9077
9078 global stwotoxd
9079 stwotoxd:
9080 #--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
9081
9082 fmov.l %d0,%fpcr # set user's rounding mode/precision
9083 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9084 mov.l (%a0),%d1
9085 or.l &0x00800001,%d1
9086 fadd.s %d1,%fp0
9087 bra t_pinx2
9088
9089 global stentox
9090 #--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
9091 stentox:
9092 fmovm.x (%a0),&0x80 # LOAD INPUT
9093
9094 mov.l (%a0),%d1
9095 mov.w 4(%a0),%d1
9096 fmov.x %fp0,X(%a6)
9097 and.l &0x7FFFFFFF,%d1
9098
9099 cmp.l %d1,&0x3FB98000 # |X| >= 2**(-70)?
9100 bge.b TENOK1
9101 bra.w EXPBORS
9102
9103 TENOK1:
9104 cmp.l %d1,&0x400B9B07 # |X| <= 16480*log2/log10 ?
9105 ble.b TENMAIN
9106 bra.w EXPBORS
9107
9108 TENMAIN:
9109 #--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
9110
9111 fmov.x %fp0,%fp1
9112 fmul.d L2TEN64(%pc),%fp1 # X*64*LOG10/LOG2
9113 fmov.l %fp1,INT(%a6) # N=INT(X*64*LOG10/LOG2)
9114 mov.l %d2,-(%sp)
9115 lea TEXPTBL(%pc),%a1 # LOAD ADDRESS OF TABLE OF 2^(J/64)
9116 fmov.l INT(%a6),%fp1 # N --> FLOATING FMT
9117 mov.l INT(%a6),%d1
9118 mov.l %d1,%d2
9119 and.l &0x3F,%d1 # D0 IS J
9120 asl.l &4,%d1 # DISPLACEMENT FOR 2^(J/64)
9121 add.l %d1,%a1 # ADDRESS FOR 2^(J/64)
9122 asr.l &6,%d2 # d2 IS L, N = 64L + J
9123 mov.l %d2,%d1
9124 asr.l &1,%d1 # D0 IS M
9125 sub.l %d1,%d2 # d2 IS M', N = 64(M+M') + J
9126 add.l &0x3FFF,%d2
9127
9128 #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
9129 #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
9130 #--ADJFACT = 2^(M').
9131 #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
9132 fmovm.x &0x0c,-(%sp) # save fp2/fp3
9133
9134 fmov.x %fp1,%fp2
9135
9136 fmul.d L10TWO1(%pc),%fp1 # N*(LOG2/64LOG10)_LEAD
9137 mov.l (%a1)+,FACT1(%a6)
9138
9139 fmul.x L10TWO2(%pc),%fp2 # N*(LOG2/64LOG10)_TRAIL
9140
9141 mov.l (%a1)+,FACT1HI(%a6)
9142 mov.l (%a1)+,FACT1LOW(%a6)
9143 fsub.x %fp1,%fp0 # X - N L_LEAD
9144 mov.w (%a1)+,FACT2(%a6)
9145
9146 fsub.x %fp2,%fp0 # X - N L_TRAIL
9147
9148 mov.w (%a1)+,FACT2HI(%a6)
9149 clr.w FACT2HI+2(%a6)
9150 clr.l FACT2LOW(%a6)
9151
9152 fmul.x LOG10(%pc),%fp0 # FP0 IS R
9153 add.w %d1,FACT1(%a6)
9154 add.w %d1,FACT2(%a6)
9155
9156 expr:
9157 #--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
9158 #--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
9159 #--FP0 IS R. THE FOLLOWING CODE COMPUTES
9160 #-- 2**(M'+M) * 2**(J/64) * EXP(R)
9161
9162 fmov.x %fp0,%fp1
9163 fmul.x %fp1,%fp1 # FP1 IS S = R*R
9164
9165 fmov.d EXPA5(%pc),%fp2 # FP2 IS A5
9166 fmov.d EXPA4(%pc),%fp3 # FP3 IS A4
9167
9168 fmul.x %fp1,%fp2 # FP2 IS S*A5
9169 fmul.x %fp1,%fp3 # FP3 IS S*A4
9170
9171 fadd.d EXPA3(%pc),%fp2 # FP2 IS A3+S*A5
9172 fadd.d EXPA2(%pc),%fp3 # FP3 IS A2+S*A4
9173
9174 fmul.x %fp1,%fp2 # FP2 IS S*(A3+S*A5)
9175 fmul.x %fp1,%fp3 # FP3 IS S*(A2+S*A4)
9176
9177 fadd.d EXPA1(%pc),%fp2 # FP2 IS A1+S*(A3+S*A5)
9178 fmul.x %fp0,%fp3 # FP3 IS R*S*(A2+S*A4)
9179
9180 fmul.x %fp1,%fp2 # FP2 IS S*(A1+S*(A3+S*A5))
9181 fadd.x %fp3,%fp0 # FP0 IS R+R*S*(A2+S*A4)
9182 fadd.x %fp2,%fp0 # FP0 IS EXP(R) - 1
9183
9184 fmovm.x (%sp)+,&0x30 # restore fp2/fp3
9185
9186 #--FINAL RECONSTRUCTION PROCESS
9187 #--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1) - (1 OR 0)
9188
9189 fmul.x FACT1(%a6),%fp0
9190 fadd.x FACT2(%a6),%fp0
9191 fadd.x FACT1(%a6),%fp0
9192
9193 fmov.l %d0,%fpcr # restore users round prec,mode
9194 mov.w %d2,ADJFACT(%a6) # INSERT EXPONENT
9195 mov.l (%sp)+,%d2
9196 mov.l &0x80000000,ADJFACT+4(%a6)
9197 clr.l ADJFACT+8(%a6)
9198 mov.b &FMUL_OP,%d1 # last inst is MUL
9199 fmul.x ADJFACT(%a6),%fp0 # FINAL ADJUSTMENT
9200 bra t_catch
9201
9202 global stentoxd
9203 stentoxd:
9204 #--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
9205
9206 fmov.l %d0,%fpcr # set user's rounding mode/precision
9207 fmov.s &0x3F800000,%fp0 # RETURN 1 + X
9208 mov.l (%a0),%d1
9209 or.l &0x00800001,%d1
9210 fadd.s %d1,%fp0
9211 bra t_pinx2
9212
9213 #########################################################################
9214 # sscale(): computes the destination operand scaled by the source #
9215 # operand. If the absoulute value of the source operand is #
9216 # >= 2^14, an overflow or underflow is returned. #
9217 # #
9218 # INPUT *************************************************************** #
9219 # a0 = pointer to double-extended source operand X #
9220 # a1 = pointer to double-extended destination operand Y #
9221 # #
9222 # OUTPUT ************************************************************** #
9223 # fp0 = scale(X,Y) #
9224 # #
9225 #########################################################################
9226
9227 set SIGN, L_SCR1
9228
9229 global sscale
9230 sscale:
9231 mov.l %d0,-(%sp) # store off ctrl bits for now
9232
9233 mov.w DST_EX(%a1),%d1 # get dst exponent
9234 smi.b SIGN(%a6) # use SIGN to hold dst sign
9235 andi.l &0x00007fff,%d1 # strip sign from dst exp
9236
9237 mov.w SRC_EX(%a0),%d0 # check src bounds
9238 andi.w &0x7fff,%d0 # clr src sign bit
9239 cmpi.w %d0,&0x3fff # is src ~ ZERO?
9240 blt.w src_small # yes
9241 cmpi.w %d0,&0x400c # no; is src too big?
9242 bgt.w src_out # yes
9243
9244 #
9245 # Source is within 2^14 range.
9246 #
9247 src_ok:
9248 fintrz.x SRC(%a0),%fp0 # calc int of src
9249 fmov.l %fp0,%d0 # int src to d0
9250 # don't want any accrued bits from the fintrz showing up later since
9251 # we may need to read the fpsr for the last fp op in t_catch2().
9252 fmov.l &0x0,%fpsr
9253
9254 tst.b DST_HI(%a1) # is dst denormalized?
9255 bmi.b sok_norm
9256
9257 # the dst is a DENORM. normalize the DENORM and add the adjustment to
9258 # the src value. then, jump to the norm part of the routine.
9259 sok_dnrm:
9260 mov.l %d0,-(%sp) # save src for now
9261
9262 mov.w DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
9263 mov.l DST_HI(%a1),FP_SCR0_HI(%a6)
9264 mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
9265
9266 lea FP_SCR0(%a6),%a0 # pass ptr to DENORM
9267 bsr.l norm # normalize the DENORM
9268 neg.l %d0
9269 add.l (%sp)+,%d0 # add adjustment to src
9270
9271 fmovm.x FP_SCR0(%a6),&0x80 # load normalized DENORM
9272
9273 cmpi.w %d0,&-0x3fff # is the shft amt really low?
9274 bge.b sok_norm2 # thank goodness no
9275
9276 # the multiply factor that we're trying to create should be a denorm
9277 # for the multiply to work. therefore, we're going to actually do a
9278 # multiply with a denorm which will cause an unimplemented data type
9279 # exception to be put into the machine which will be caught and corrected
9280 # later. we don't do this with the DENORMs above because this method
9281 # is slower. but, don't fret, I don't see it being used much either.
9282 fmov.l (%sp)+,%fpcr # restore user fpcr
9283 mov.l &0x80000000,%d1 # load normalized mantissa
9284 subi.l &-0x3fff,%d0 # how many should we shift?
9285 neg.l %d0 # make it positive
9286 cmpi.b %d0,&0x20 # is it > 32?
9287 bge.b sok_dnrm_32 # yes
9288 lsr.l %d0,%d1 # no; bit stays in upper lw
9289 clr.l -(%sp) # insert zero low mantissa
9290 mov.l %d1,-(%sp) # insert new high mantissa
9291 clr.l -(%sp) # make zero exponent
9292 bra.b sok_norm_cont
9293 sok_dnrm_32:
9294 subi.b &0x20,%d0 # get shift count
9295 lsr.l %d0,%d1 # make low mantissa longword
9296 mov.l %d1,-(%sp) # insert new low mantissa
9297 clr.l -(%sp) # insert zero high mantissa
9298 clr.l -(%sp) # make zero exponent
9299 bra.b sok_norm_cont
9300
9301 # the src will force the dst to a DENORM value or worse. so, let's
9302 # create an fp multiply that will create the result.
9303 sok_norm:
9304 fmovm.x DST(%a1),&0x80 # load fp0 with normalized src
9305 sok_norm2:
9306 fmov.l (%sp)+,%fpcr # restore user fpcr
9307
9308 addi.w &0x3fff,%d0 # turn src amt into exp value
9309 swap %d0 # put exponent in high word
9310 clr.l -(%sp) # insert new exponent
9311 mov.l &0x80000000,-(%sp) # insert new high mantissa
9312 mov.l %d0,-(%sp) # insert new lo mantissa
9313
9314 sok_norm_cont:
9315 fmov.l %fpcr,%d0 # d0 needs fpcr for t_catch2
9316 mov.b &FMUL_OP,%d1 # last inst is MUL
9317 fmul.x (%sp)+,%fp0 # do the multiply
9318 bra t_catch2 # catch any exceptions
9319
9320 #
9321 # Source is outside of 2^14 range. Test the sign and branch
9322 # to the appropriate exception handler.
9323 #
9324 src_out:
9325 mov.l (%sp)+,%d0 # restore ctrl bits
9326 exg %a0,%a1 # swap src,dst ptrs
9327 tst.b SRC_EX(%a1) # is src negative?
9328 bmi t_unfl # yes; underflow
9329 bra t_ovfl_sc # no; overflow
9330
9331 #
9332 # The source input is below 1, so we check for denormalized numbers
9333 # and set unfl.
9334 #
9335 src_small:
9336 tst.b DST_HI(%a1) # is dst denormalized?
9337 bpl.b ssmall_done # yes
9338
9339 mov.l (%sp)+,%d0
9340 fmov.l %d0,%fpcr # no; load control bits
9341 mov.b &FMOV_OP,%d1 # last inst is MOVE
9342 fmov.x DST(%a1),%fp0 # simply return dest
9343 bra t_catch2
9344 ssmall_done:
9345 mov.l (%sp)+,%d0 # load control bits into d1
9346 mov.l %a1,%a0 # pass ptr to dst
9347 bra t_resdnrm
9348
9349 #########################################################################
9350 # smod(): computes the fp MOD of the input values X,Y. #
9351 # srem(): computes the fp (IEEE) REM of the input values X,Y. #
9352 # #
9353 # INPUT *************************************************************** #
9354 # a0 = pointer to extended precision input X #
9355 # a1 = pointer to extended precision input Y #
9356 # d0 = round precision,mode #
9357 # #
9358 # The input operands X and Y can be either normalized or #
9359 # denormalized. #
9360 # #
9361 # OUTPUT ************************************************************** #
9362 # fp0 = FREM(X,Y) or FMOD(X,Y) #
9363 # #
9364 # ALGORITHM *********************************************************** #
9365 # #
9366 # Step 1. Save and strip signs of X and Y: signX := sign(X), #
9367 # signY := sign(Y), X := |X|, Y := |Y|, #
9368 # signQ := signX EOR signY. Record whether MOD or REM #
9369 # is requested. #
9370 # #
9371 # Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0. #
9372 # If (L < 0) then #
9373 # R := X, go to Step 4. #
9374 # else #
9375 # R := 2^(-L)X, j := L. #
9376 # endif #
9377 # #
9378 # Step 3. Perform MOD(X,Y) #
9379 # 3.1 If R = Y, go to Step 9. #
9380 # 3.2 If R > Y, then { R := R - Y, Q := Q + 1} #
9381 # 3.3 If j = 0, go to Step 4. #
9382 # 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to #
9383 # Step 3.1. #
9384 # #
9385 # Step 4. At this point, R = X - QY = MOD(X,Y). Set #
9386 # Last_Subtract := false (used in Step 7 below). If #
9387 # MOD is requested, go to Step 6. #
9388 # #
9389 # Step 5. R = MOD(X,Y), but REM(X,Y) is requested. #
9390 # 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to #
9391 # Step 6. #
9392 # 5.2 If R > Y/2, then { set Last_Subtract := true, #
9393 # Q := Q + 1, Y := signY*Y }. Go to Step 6. #
9394 # 5.3 This is the tricky case of R = Y/2. If Q is odd, #
9395 # then { Q := Q + 1, signX := -signX }. #
9396 # #
9397 # Step 6. R := signX*R. #
9398 # #
9399 # Step 7. If Last_Subtract = true, R := R - Y. #
9400 # #
9401 # Step 8. Return signQ, last 7 bits of Q, and R as required. #
9402 # #
9403 # Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus, #
9404 # X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), #
9405 # R := 0. Return signQ, last 7 bits of Q, and R. #
9406 # #
9407 #########################################################################
9408
9409 set Mod_Flag,L_SCR3
9410 set Sc_Flag,L_SCR3+1
9411
9412 set SignY,L_SCR2
9413 set SignX,L_SCR2+2
9414 set SignQ,L_SCR3+2
9415
9416 set Y,FP_SCR0
9417 set Y_Hi,Y+4
9418 set Y_Lo,Y+8
9419
9420 set R,FP_SCR1
9421 set R_Hi,R+4
9422 set R_Lo,R+8
9423
9424 Scale:
9425 long 0x00010000,0x80000000,0x00000000,0x00000000
9426
9427 global smod
9428 smod:
9429 clr.b FPSR_QBYTE(%a6)
9430 mov.l %d0,-(%sp) # save ctrl bits
9431 clr.b Mod_Flag(%a6)
9432 bra.b Mod_Rem
9433
9434 global srem
9435 srem:
9436 clr.b FPSR_QBYTE(%a6)
9437 mov.l %d0,-(%sp) # save ctrl bits
9438 mov.b &0x1,Mod_Flag(%a6)
9439
9440 Mod_Rem:
9441 #..Save sign of X and Y
9442 movm.l &0x3f00,-(%sp) # save data registers
9443 mov.w SRC_EX(%a0),%d3
9444 mov.w %d3,SignY(%a6)
9445 and.l &0x00007FFF,%d3 # Y := |Y|
9446
9447 #
9448 mov.l SRC_HI(%a0),%d4
9449 mov.l SRC_LO(%a0),%d5 # (D3,D4,D5) is |Y|
9450
9451 tst.l %d3
9452 bne.b Y_Normal
9453
9454 mov.l &0x00003FFE,%d3 # $3FFD + 1
9455 tst.l %d4
9456 bne.b HiY_not0
9457
9458 HiY_0:
9459 mov.l %d5,%d4
9460 clr.l %d5
9461 sub.l &32,%d3
9462 clr.l %d6
9463 bfffo %d4{&0:&32},%d6
9464 lsl.l %d6,%d4
9465 sub.l %d6,%d3 # (D3,D4,D5) is normalized
9466 # ...with bias $7FFD
9467 bra.b Chk_X
9468
9469 HiY_not0:
9470 clr.l %d6
9471 bfffo %d4{&0:&32},%d6
9472 sub.l %d6,%d3
9473 lsl.l %d6,%d4
9474 mov.l %d5,%d7 # a copy of D5
9475 lsl.l %d6,%d5
9476 neg.l %d6
9477 add.l &32,%d6
9478 lsr.l %d6,%d7
9479 or.l %d7,%d4 # (D3,D4,D5) normalized
9480 # ...with bias $7FFD
9481 bra.b Chk_X
9482
9483 Y_Normal:
9484 add.l &0x00003FFE,%d3 # (D3,D4,D5) normalized
9485 # ...with bias $7FFD
9486
9487 Chk_X:
9488 mov.w DST_EX(%a1),%d0
9489 mov.w %d0,SignX(%a6)
9490 mov.w SignY(%a6),%d1
9491 eor.l %d0,%d1
9492 and.l &0x00008000,%d1
9493 mov.w %d1,SignQ(%a6) # sign(Q) obtained
9494 and.l &0x00007FFF,%d0
9495 mov.l DST_HI(%a1),%d1
9496 mov.l DST_LO(%a1),%d2 # (D0,D1,D2) is |X|
9497 tst.l %d0
9498 bne.b X_Normal
9499 mov.l &0x00003FFE,%d0
9500 tst.l %d1
9501 bne.b HiX_not0
9502
9503 HiX_0:
9504 mov.l %d2,%d1
9505 clr.l %d2
9506 sub.l &32,%d0
9507 clr.l %d6
9508 bfffo %d1{&0:&32},%d6
9509 lsl.l %d6,%d1
9510 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9511 # ...with bias $7FFD
9512 bra.b Init
9513
9514 HiX_not0:
9515 clr.l %d6
9516 bfffo %d1{&0:&32},%d6
9517 sub.l %d6,%d0
9518 lsl.l %d6,%d1
9519 mov.l %d2,%d7 # a copy of D2
9520 lsl.l %d6,%d2
9521 neg.l %d6
9522 add.l &32,%d6
9523 lsr.l %d6,%d7
9524 or.l %d7,%d1 # (D0,D1,D2) normalized
9525 # ...with bias $7FFD
9526 bra.b Init
9527
9528 X_Normal:
9529 add.l &0x00003FFE,%d0 # (D0,D1,D2) normalized
9530 # ...with bias $7FFD
9531
9532 Init:
9533 #
9534 mov.l %d3,L_SCR1(%a6) # save biased exp(Y)
9535 mov.l %d0,-(%sp) # save biased exp(X)
9536 sub.l %d3,%d0 # L := expo(X)-expo(Y)
9537
9538 clr.l %d6 # D6 := carry <- 0
9539 clr.l %d3 # D3 is Q
9540 mov.l &0,%a1 # A1 is k; j+k=L, Q=0
9541
9542 #..(Carry,D1,D2) is R
9543 tst.l %d0
9544 bge.b Mod_Loop_pre
9545
9546 #..expo(X) < expo(Y). Thus X = mod(X,Y)
9547 #
9548 mov.l (%sp)+,%d0 # restore d0
9549 bra.w Get_Mod
9550
9551 Mod_Loop_pre:
9552 addq.l &0x4,%sp # erase exp(X)
9553 #..At this point R = 2^(-L)X; Q = 0; k = 0; and k+j = L
9554 Mod_Loop:
9555 tst.l %d6 # test carry bit
9556 bgt.b R_GT_Y
9557
9558 #..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
9559 cmp.l %d1,%d4 # compare hi(R) and hi(Y)
9560 bne.b R_NE_Y
9561 cmp.l %d2,%d5 # compare lo(R) and lo(Y)
9562 bne.b R_NE_Y
9563
9564 #..At this point, R = Y
9565 bra.w Rem_is_0
9566
9567 R_NE_Y:
9568 #..use the borrow of the previous compare
9569 bcs.b R_LT_Y # borrow is set iff R < Y
9570
9571 R_GT_Y:
9572 #..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
9573 #..and Y < (D1,D2) < 2Y. Either way, perform R - Y
9574 sub.l %d5,%d2 # lo(R) - lo(Y)
9575 subx.l %d4,%d1 # hi(R) - hi(Y)
9576 clr.l %d6 # clear carry
9577 addq.l &1,%d3 # Q := Q + 1
9578
9579 R_LT_Y:
9580 #..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
9581 tst.l %d0 # see if j = 0.
9582 beq.b PostLoop
9583
9584 add.l %d3,%d3 # Q := 2Q
9585 add.l %d2,%d2 # lo(R) = 2lo(R)
9586 roxl.l &1,%d1 # hi(R) = 2hi(R) + carry
9587 scs %d6 # set Carry if 2(R) overflows
9588 addq.l &1,%a1 # k := k+1
9589 subq.l &1,%d0 # j := j - 1
9590 #..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
9591
9592 bra.b Mod_Loop
9593
9594 PostLoop:
9595 #..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
9596
9597 #..normalize R.
9598 mov.l L_SCR1(%a6),%d0 # new biased expo of R
9599 tst.l %d1
9600 bne.b HiR_not0
9601
9602 HiR_0:
9603 mov.l %d2,%d1
9604 clr.l %d2
9605 sub.l &32,%d0
9606 clr.l %d6
9607 bfffo %d1{&0:&32},%d6
9608 lsl.l %d6,%d1
9609 sub.l %d6,%d0 # (D0,D1,D2) is normalized
9610 # ...with bias $7FFD
9611 bra.b Get_Mod
9612
9613 HiR_not0:
9614 clr.l %d6
9615 bfffo %d1{&0:&32},%d6
9616 bmi.b Get_Mod # already normalized
9617 sub.l %d6,%d0
9618 lsl.l %d6,%d1
9619 mov.l %d2,%d7 # a copy of D2
9620 lsl.l %d6,%d2
9621 neg.l %d6
9622 add.l &32,%d6
9623 lsr.l %d6,%d7
9624 or.l %d7,%d1 # (D0,D1,D2) normalized
9625
9626 #
9627 Get_Mod:
9628 cmp.l %d0,&0x000041FE
9629 bge.b No_Scale
9630 Do_Scale:
9631 mov.w %d0,R(%a6)
9632 mov.l %d1,R_Hi(%a6)
9633 mov.l %d2,R_Lo(%a6)
9634 mov.l L_SCR1(%a6),%d6
9635 mov.w %d6,Y(%a6)
9636 mov.l %d4,Y_Hi(%a6)
9637 mov.l %d5,Y_Lo(%a6)
9638 fmov.x R(%a6),%fp0 # no exception
9639 mov.b &1,Sc_Flag(%a6)
9640 bra.b ModOrRem
9641 No_Scale:
9642 mov.l %d1,R_Hi(%a6)
9643 mov.l %d2,R_Lo(%a6)
9644 sub.l &0x3FFE,%d0
9645 mov.w %d0,R(%a6)
9646 mov.l L_SCR1(%a6),%d6
9647 sub.l &0x3FFE,%d6
9648 mov.l %d6,L_SCR1(%a6)
9649 fmov.x R(%a6),%fp0
9650 mov.w %d6,Y(%a6)
9651 mov.l %d4,Y_Hi(%a6)
9652 mov.l %d5,Y_Lo(%a6)
9653 clr.b Sc_Flag(%a6)
9654
9655 #
9656 ModOrRem:
9657 tst.b Mod_Flag(%a6)
9658 beq.b Fix_Sign
9659
9660 mov.l L_SCR1(%a6),%d6 # new biased expo(Y)
9661 subq.l &1,%d6 # biased expo(Y/2)
9662 cmp.l %d0,%d6
9663 blt.b Fix_Sign
9664 bgt.b Last_Sub
9665
9666 cmp.l %d1,%d4
9667 bne.b Not_EQ
9668 cmp.l %d2,%d5
9669 bne.b Not_EQ
9670 bra.w Tie_Case
9671
9672 Not_EQ:
9673 bcs.b Fix_Sign
9674
9675 Last_Sub:
9676 #
9677 fsub.x Y(%a6),%fp0 # no exceptions
9678 addq.l &1,%d3 # Q := Q + 1
9679
9680 #
9681 Fix_Sign:
9682 #..Get sign of X
9683 mov.w SignX(%a6),%d6
9684 bge.b Get_Q
9685 fneg.x %fp0
9686
9687 #..Get Q
9688 #
9689 Get_Q:
9690 clr.l %d6
9691 mov.w SignQ(%a6),%d6 # D6 is sign(Q)
9692 mov.l &8,%d7
9693 lsr.l %d7,%d6
9694 and.l &0x0000007F,%d3 # 7 bits of Q
9695 or.l %d6,%d3 # sign and bits of Q
9696 # swap %d3
9697 # fmov.l %fpsr,%d6
9698 # and.l &0xFF00FFFF,%d6
9699 # or.l %d3,%d6
9700 # fmov.l %d6,%fpsr # put Q in fpsr
9701 mov.b %d3,FPSR_QBYTE(%a6) # put Q in fpsr
9702
9703 #
9704 Restore:
9705 movm.l (%sp)+,&0xfc # {%d2-%d7}
9706 mov.l (%sp)+,%d0
9707 fmov.l %d0,%fpcr
9708 tst.b Sc_Flag(%a6)
9709 beq.b Finish
9710 mov.b &FMUL_OP,%d1 # last inst is MUL
9711 fmul.x Scale(%pc),%fp0 # may cause underflow
9712 bra t_catch2
9713 # the '040 package did this apparently to see if the dst operand for the
9714 # preceding fmul was a denorm. but, it better not have been since the
9715 # algorithm just got done playing with fp0 and expected no exceptions
9716 # as a result. trust me...
9717 # bra t_avoid_unsupp # check for denorm as a
9718 # ;result of the scaling
9719
9720 Finish:
9721 mov.b &FMOV_OP,%d1 # last inst is MOVE
9722 fmov.x %fp0,%fp0 # capture exceptions & round
9723 bra t_catch2
9724
9725 Rem_is_0:
9726 #..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
9727 addq.l &1,%d3
9728 cmp.l %d0,&8 # D0 is j
9729 bge.b Q_Big
9730
9731 lsl.l %d0,%d3
9732 bra.b Set_R_0
9733
9734 Q_Big:
9735 clr.l %d3
9736
9737 Set_R_0:
9738 fmov.s &0x00000000,%fp0
9739 clr.b Sc_Flag(%a6)
9740 bra.w Fix_Sign
9741
9742 Tie_Case:
9743 #..Check parity of Q
9744 mov.l %d3,%d6
9745 and.l &0x00000001,%d6
9746 tst.l %d6
9747 beq.w Fix_Sign # Q is even
9748
9749 #..Q is odd, Q := Q + 1, signX := -signX
9750 addq.l &1,%d3
9751 mov.w SignX(%a6),%d6
9752 eor.l &0x00008000,%d6
9753 mov.w %d6,SignX(%a6)
9754 bra.w Fix_Sign
9755
9756 #########################################################################
9757 # XDEF **************************************************************** #
9758 # tag(): return the optype of the input ext fp number #
9759 # #
9760 # This routine is used by the 060FPLSP. #
9761 # #
9762 # XREF **************************************************************** #
9763 # None #
9764 # #
9765 # INPUT *************************************************************** #
9766 # a0 = pointer to extended precision operand #
9767 # #
9768 # OUTPUT ************************************************************** #
9769 # d0 = value of type tag #
9770 # one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
9771 # #
9772 # ALGORITHM *********************************************************** #
9773 # Simply test the exponent, j-bit, and mantissa values to #
9774 # determine the type of operand. #
9775 # If it's an unnormalized zero, alter the operand and force it #
9776 # to be a normal zero. #
9777 # #
9778 #########################################################################
9779
9780 global tag
9781 tag:
9782 mov.w FTEMP_EX(%a0), %d0 # extract exponent
9783 andi.w &0x7fff, %d0 # strip off sign
9784 cmpi.w %d0, &0x7fff # is (EXP == MAX)?
9785 beq.b inf_or_nan_x
9786 not_inf_or_nan_x:
9787 btst &0x7,FTEMP_HI(%a0)
9788 beq.b not_norm_x
9789 is_norm_x:
9790 mov.b &NORM, %d0
9791 rts
9792 not_norm_x:
9793 tst.w %d0 # is exponent = 0?
9794 bne.b is_unnorm_x
9795 not_unnorm_x:
9796 tst.l FTEMP_HI(%a0)
9797 bne.b is_denorm_x
9798 tst.l FTEMP_LO(%a0)
9799 bne.b is_denorm_x
9800 is_zero_x:
9801 mov.b &ZERO, %d0
9802 rts
9803 is_denorm_x:
9804 mov.b &DENORM, %d0
9805 rts
9806 is_unnorm_x:
9807 bsr.l unnorm_fix # convert to norm,denorm,or zero
9808 rts
9809 is_unnorm_reg_x:
9810 mov.b &UNNORM, %d0
9811 rts
9812 inf_or_nan_x:
9813 tst.l FTEMP_LO(%a0)
9814 bne.b is_nan_x
9815 mov.l FTEMP_HI(%a0), %d0
9816 and.l &0x7fffffff, %d0 # msb is a don't care!
9817 bne.b is_nan_x
9818 is_inf_x:
9819 mov.b &INF, %d0
9820 rts
9821 is_nan_x:
9822 mov.b &QNAN, %d0
9823 rts
9824
9825 #############################################################
9826
9827 qnan: long 0x7fff0000, 0xffffffff, 0xffffffff
9828
9829 #########################################################################
9830 # XDEF **************************************************************** #
9831 # t_dz(): Handle 060FPLSP dz exception for "flogn" emulation. #
9832 # t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation. #
9833 # #
9834 # These rouitnes are used by the 060FPLSP package. #
9835 # #
9836 # XREF **************************************************************** #
9837 # None #
9838 # #
9839 # INPUT *************************************************************** #
9840 # a0 = pointer to extended precision source operand. #
9841 # #
9842 # OUTPUT ************************************************************** #
9843 # fp0 = default DZ result. #
9844 # #
9845 # ALGORITHM *********************************************************** #
9846 # Transcendental emulation for the 060FPLSP has detected that #
9847 # a DZ exception should occur for the instruction. If DZ is disabled, #
9848 # return the default result. #
9849 # If DZ is enabled, the dst operand should be returned unscathed #
9850 # in fp0 while fp1 is used to create a DZ exception so that the #
9851 # operating system can log that such an event occurred. #
9852 # #
9853 #########################################################################
9854
9855 global t_dz
9856 t_dz:
9857 tst.b SRC_EX(%a0) # check sign for neg or pos
9858 bpl.b dz_pinf # branch if pos sign
9859
9860 global t_dz2
9861 t_dz2:
9862 ori.l &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
9863
9864 btst &dz_bit,FPCR_ENABLE(%a6)
9865 bne.b dz_minf_ena
9866
9867 # dz is disabled. return a -INF.
9868 fmov.s &0xff800000,%fp0 # return -INF
9869 rts
9870
9871 # dz is enabled. create a dz exception so the user can record it
9872 # but use fp1 instead. return the dst operand unscathed in fp0.
9873 dz_minf_ena:
9874 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9875 fmov.l USER_FPCR(%a6),%fpcr
9876 fmov.s &0xbf800000,%fp1 # load -1
9877 fdiv.s &0x00000000,%fp1 # -1 / 0
9878 rts
9879
9880 dz_pinf:
9881 ori.l &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
9882
9883 btst &dz_bit,FPCR_ENABLE(%a6)
9884 bne.b dz_pinf_ena
9885
9886 # dz is disabled. return a +INF.
9887 fmov.s &0x7f800000,%fp0 # return +INF
9888 rts
9889
9890 # dz is enabled. create a dz exception so the user can record it
9891 # but use fp1 instead. return the dst operand unscathed in fp0.
9892 dz_pinf_ena:
9893 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9894 fmov.l USER_FPCR(%a6),%fpcr
9895 fmov.s &0x3f800000,%fp1 # load +1
9896 fdiv.s &0x00000000,%fp1 # +1 / 0
9897 rts
9898
9899 #########################################################################
9900 # XDEF **************************************************************** #
9901 # t_operr(): Handle 060FPLSP OPERR exception during emulation. #
9902 # #
9903 # This routine is used by the 060FPLSP package. #
9904 # #
9905 # XREF **************************************************************** #
9906 # None. #
9907 # #
9908 # INPUT *************************************************************** #
9909 # fp1 = source operand #
9910 # #
9911 # OUTPUT ************************************************************** #
9912 # fp0 = default result #
9913 # fp1 = unchanged #
9914 # #
9915 # ALGORITHM *********************************************************** #
9916 # An operand error should occur as the result of transcendental #
9917 # emulation in the 060FPLSP. If OPERR is disabled, just return a NAN #
9918 # in fp0. If OPERR is enabled, return the dst operand unscathed in fp0 #
9919 # and the source operand in fp1. Use fp2 to create an OPERR exception #
9920 # so that the operating system can log the event. #
9921 # #
9922 #########################################################################
9923
9924 global t_operr
9925 t_operr:
9926 ori.l &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
9927
9928 btst &operr_bit,FPCR_ENABLE(%a6)
9929 bne.b operr_ena
9930
9931 # operr is disabled. return a QNAN in fp0
9932 fmovm.x qnan(%pc),&0x80 # return QNAN
9933 rts
9934
9935 # operr is enabled. create an operr exception so the user can record it
9936 # but use fp2 instead. return the dst operand unscathed in fp0.
9937 operr_ena:
9938 fmovm.x EXC_FP0(%a6),&0x80 # return fp0 unscathed
9939 fmov.l USER_FPCR(%a6),%fpcr
9940 fmovm.x &0x04,-(%sp) # save fp2
9941 fmov.s &0x7f800000,%fp2 # load +INF
9942 fmul.s &0x00000000,%fp2 # +INF x 0
9943 fmovm.x (%sp)+,&0x20 # restore fp2
9944 rts
9945
9946 pls_huge:
9947 long 0x7ffe0000,0xffffffff,0xffffffff
9948 mns_huge:
9949 long 0xfffe0000,0xffffffff,0xffffffff
9950 pls_tiny:
9951 long 0x00000000,0x80000000,0x00000000
9952 mns_tiny:
9953 long 0x80000000,0x80000000,0x00000000
9954
9955 #########################################################################
9956 # XDEF **************************************************************** #
9957 # t_unfl(): Handle 060FPLSP underflow exception during emulation. #
9958 # t_unfl2(): Handle 060FPLSP underflow exception during #
9959 # emulation. result always positive. #
9960 # #
9961 # This routine is used by the 060FPLSP package. #
9962 # #
9963 # XREF **************************************************************** #
9964 # None. #
9965 # #
9966 # INPUT *************************************************************** #
9967 # a0 = pointer to extended precision source operand #
9968 # #
9969 # OUTPUT ************************************************************** #
9970 # fp0 = default underflow result #
9971 # #
9972 # ALGORITHM *********************************************************** #
9973 # An underflow should occur as the result of transcendental #
9974 # emulation in the 060FPLSP. Create an underflow by using "fmul" #
9975 # and two very small numbers of appropriate sign so that the operating #
9976 # system can log the event. #
9977 # #
9978 #########################################################################
9979
9980 global t_unfl
9981 t_unfl:
9982 tst.b SRC_EX(%a0)
9983 bpl.b unf_pos
9984
9985 global t_unfl2
9986 t_unfl2:
9987 ori.l &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
9988
9989 fmov.l USER_FPCR(%a6),%fpcr
9990 fmovm.x mns_tiny(%pc),&0x80
9991 fmul.x pls_tiny(%pc),%fp0
9992
9993 fmov.l %fpsr,%d0
9994 rol.l &0x8,%d0
9995 mov.b %d0,FPSR_CC(%a6)
9996 rts
9997 unf_pos:
9998 ori.w &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
9999
10000 fmov.l USER_FPCR(%a6),%fpcr
10001 fmovm.x pls_tiny(%pc),&0x80
10002 fmul.x %fp0,%fp0
10003
10004 fmov.l %fpsr,%d0
10005 rol.l &0x8,%d0
10006 mov.b %d0,FPSR_CC(%a6)
10007 rts
10008
10009 #########################################################################
10010 # XDEF **************************************************************** #
10011 # t_ovfl(): Handle 060FPLSP overflow exception during emulation. #
10012 # (monadic) #
10013 # t_ovfl2(): Handle 060FPLSP overflow exception during #
10014 # emulation. result always positive. (dyadic) #
10015 # t_ovfl_sc(): Handle 060FPLSP overflow exception during #
10016 # emulation for "fscale". #
10017 # #
10018 # This routine is used by the 060FPLSP package. #
10019 # #
10020 # XREF **************************************************************** #
10021 # None. #
10022 # #
10023 # INPUT *************************************************************** #
10024 # a0 = pointer to extended precision source operand #
10025 # #
10026 # OUTPUT ************************************************************** #
10027 # fp0 = default underflow result #
10028 # #
10029 # ALGORITHM *********************************************************** #
10030 # An overflow should occur as the result of transcendental #
10031 # emulation in the 060FPLSP. Create an overflow by using "fmul" #
10032 # and two very lareg numbers of appropriate sign so that the operating #
10033 # system can log the event. #
10034 # For t_ovfl_sc() we take special care not to lose the INEX2 bit. #
10035 # #
10036 #########################################################################
10037
10038 global t_ovfl_sc
10039 t_ovfl_sc:
10040 ori.l &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
10041
10042 mov.b %d0,%d1 # fetch rnd prec,mode
10043 andi.b &0xc0,%d1 # extract prec
10044 beq.w ovfl_work
10045
10046 # dst op is a DENORM. we have to normalize the mantissa to see if the
10047 # result would be inexact for the given precision. make a copy of the
10048 # dst so we don't screw up the version passed to us.
10049 mov.w LOCAL_EX(%a0),FP_SCR0_EX(%a6)
10050 mov.l LOCAL_HI(%a0),FP_SCR0_HI(%a6)
10051 mov.l LOCAL_LO(%a0),FP_SCR0_LO(%a6)
10052 lea FP_SCR0(%a6),%a0 # pass ptr to FP_SCR0
10053 movm.l &0xc080,-(%sp) # save d0-d1/a0
10054 bsr.l norm # normalize mantissa
10055 movm.l (%sp)+,&0x0103 # restore d0-d1/a0
10056
10057 cmpi.b %d1,&0x40 # is precision sgl?
10058 bne.b ovfl_sc_dbl # no; dbl
10059 ovfl_sc_sgl:
10060 tst.l LOCAL_LO(%a0) # is lo lw of sgl set?
10061 bne.b ovfl_sc_inx # yes
10062 tst.b 3+LOCAL_HI(%a0) # is lo byte of hi lw set?
10063 bne.b ovfl_sc_inx # yes
10064 bra.w ovfl_work # don't set INEX2
10065 ovfl_sc_dbl:
10066 mov.l LOCAL_LO(%a0),%d1 # are any of lo 11 bits of
10067 andi.l &0x7ff,%d1 # dbl mantissa set?
10068 beq.w ovfl_work # no; don't set INEX2
10069 ovfl_sc_inx:
10070 ori.l &inex2_mask,USER_FPSR(%a6) # set INEX2
10071 bra.b ovfl_work # continue
10072
10073 global t_ovfl
10074 t_ovfl:
10075 ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10076 ovfl_work:
10077 tst.b SRC_EX(%a0)
10078 bpl.b ovfl_p
10079 ovfl_m:
10080 fmov.l USER_FPCR(%a6),%fpcr
10081 fmovm.x mns_huge(%pc),&0x80
10082 fmul.x pls_huge(%pc),%fp0
10083
10084 fmov.l %fpsr,%d0
10085 rol.l &0x8,%d0
10086 ori.b &neg_mask,%d0
10087 mov.b %d0,FPSR_CC(%a6)
10088 rts
10089 ovfl_p:
10090 fmov.l USER_FPCR(%a6),%fpcr
10091 fmovm.x pls_huge(%pc),&0x80
10092 fmul.x pls_huge(%pc),%fp0
10093
10094 fmov.l %fpsr,%d0
10095 rol.l &0x8,%d0
10096 mov.b %d0,FPSR_CC(%a6)
10097 rts
10098
10099 global t_ovfl2
10100 t_ovfl2:
10101 ori.w &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
10102 fmov.l USER_FPCR(%a6),%fpcr
10103 fmovm.x pls_huge(%pc),&0x80
10104 fmul.x pls_huge(%pc),%fp0
10105
10106 fmov.l %fpsr,%d0
10107 rol.l &0x8,%d0
10108 mov.b %d0,FPSR_CC(%a6)
10109 rts
10110
10111 #########################################################################
10112 # XDEF **************************************************************** #
10113 # t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10114 # emulation. #
10115 # t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during #
10116 # emulation. #
10117 # #
10118 # These routines are used by the 060FPLSP package. #
10119 # #
10120 # XREF **************************************************************** #
10121 # None. #
10122 # #
10123 # INPUT *************************************************************** #
10124 # fp0 = default underflow or overflow result #
10125 # #
10126 # OUTPUT ************************************************************** #
10127 # fp0 = default result #
10128 # #
10129 # ALGORITHM *********************************************************** #
10130 # If an overflow or underflow occurred during the last #
10131 # instruction of transcendental 060FPLSP emulation, then it has already #
10132 # occurred and has been logged. Now we need to see if an inexact #
10133 # exception should occur. #
10134 # #
10135 #########################################################################
10136
10137 global t_catch2
10138 t_catch2:
10139 fmov.l %fpsr,%d0
10140 or.l %d0,USER_FPSR(%a6)
10141 bra.b inx2_work
10142
10143 global t_catch
10144 t_catch:
10145 fmov.l %fpsr,%d0
10146 or.l %d0,USER_FPSR(%a6)
10147
10148 #########################################################################
10149 # XDEF **************************************************************** #
10150 # t_inx2(): Handle inexact 060FPLSP exception during emulation. #
10151 # t_pinx2(): Handle inexact 060FPLSP exception for "+" results. #
10152 # t_minx2(): Handle inexact 060FPLSP exception for "-" results. #
10153 # #
10154 # XREF **************************************************************** #
10155 # None. #
10156 # #
10157 # INPUT *************************************************************** #
10158 # fp0 = default result #
10159 # #
10160 # OUTPUT ************************************************************** #
10161 # fp0 = default result #
10162 # #
10163 # ALGORITHM *********************************************************** #
10164 # The last instruction of transcendental emulation for the #
10165 # 060FPLSP should be inexact. So, if inexact is enabled, then we create #
10166 # the event here by adding a large and very small number together #
10167 # so that the operating system can log the event. #
10168 # Must check, too, if the result was zero, in which case we just #
10169 # set the FPSR bits and return. #
10170 # #
10171 #########################################################################
10172
10173 global t_inx2
10174 t_inx2:
10175 fblt.w t_minx2
10176 fbeq.w inx2_zero
10177
10178 global t_pinx2
10179 t_pinx2:
10180 ori.w &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
10181 bra.b inx2_work
10182
10183 global t_minx2
10184 t_minx2:
10185 ori.l &inx2a_mask+neg_mask,USER_FPSR(%a6)
10186
10187 inx2_work:
10188 btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
10189 bne.b inx2_work_ena # yes
10190 rts
10191 inx2_work_ena:
10192 fmov.l USER_FPCR(%a6),%fpcr # insert user's exceptions
10193 fmov.s &0x3f800000,%fp1 # load +1
10194 fadd.x pls_tiny(%pc),%fp1 # cause exception
10195 rts
10196
10197 inx2_zero:
10198 mov.b &z_bmask,FPSR_CC(%a6)
10199 ori.w &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
10200 rts
10201
10202 #########################################################################
10203 # XDEF **************************************************************** #
10204 # t_extdnrm(): Handle DENORM inputs in 060FPLSP. #
10205 # t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale". #
10206 # #
10207 # This routine is used by the 060FPLSP package. #
10208 # #
10209 # XREF **************************************************************** #
10210 # None. #
10211 # #
10212 # INPUT *************************************************************** #
10213 # a0 = pointer to extended precision input operand #
10214 # #
10215 # OUTPUT ************************************************************** #
10216 # fp0 = default result #
10217 # #
10218 # ALGORITHM *********************************************************** #
10219 # For all functions that have a denormalized input and that #
10220 # f(x)=x, this is the entry point. #
10221 # DENORM value is moved using "fmove" which triggers an exception #
10222 # if enabled so the operating system can log the event. #
10223 # #
10224 #########################################################################
10225
10226 global t_extdnrm
10227 t_extdnrm:
10228 fmov.l USER_FPCR(%a6),%fpcr
10229 fmov.x SRC_EX(%a0),%fp0
10230 fmov.l %fpsr,%d0
10231 ori.l &unfinx_mask,%d0
10232 or.l %d0,USER_FPSR(%a6)
10233 rts
10234
10235 global t_resdnrm
10236 t_resdnrm:
10237 fmov.l USER_FPCR(%a6),%fpcr
10238 fmov.x SRC_EX(%a0),%fp0
10239 fmov.l %fpsr,%d0
10240 or.l %d0,USER_FPSR(%a6)
10241 rts
10242
10243 ##########################################
10244
10245 #
10246 # sto_cos:
10247 # This is used by fsincos library emulation. The correct
10248 # values are already in fp0 and fp1 so we do nothing here.
10249 #
10250 global sto_cos
10251 sto_cos:
10252 rts
10253
10254 ##########################################
10255
10256 #
10257 # dst_qnan --- force result when destination is a NaN
10258 #
10259 global dst_qnan
10260 dst_qnan:
10261 fmov.x DST(%a1),%fp0
10262 tst.b DST_EX(%a1)
10263 bmi.b dst_qnan_m
10264 dst_qnan_p:
10265 mov.b &nan_bmask,FPSR_CC(%a6)
10266 rts
10267 dst_qnan_m:
10268 mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
10269 rts
10270
10271 #
10272 # src_qnan --- force result when source is a NaN
10273 #
10274 global src_qnan
10275 src_qnan:
10276 fmov.x SRC(%a0),%fp0
10277 tst.b SRC_EX(%a0)
10278 bmi.b src_qnan_m
10279 src_qnan_p:
10280 mov.b &nan_bmask,FPSR_CC(%a6)
10281 rts
10282 src_qnan_m:
10283 mov.b &nan_bmask+neg_bmask,FPSR_CC(%a6)
10284 rts
10285
10286 ##########################################
10287
10288 #
10289 # Native instruction support
10290 #
10291 # Some systems may need entry points even for 68060 native
10292 # instructions. These routines are provided for
10293 # convenience.
10294 #
10295 global _fadds_
10296 _fadds_:
10297 fmov.l %fpcr,-(%sp) # save fpcr
10298 fmov.l &0x00000000,%fpcr # clear fpcr for load
10299 fmov.s 0x8(%sp),%fp0 # load sgl dst
10300 fmov.l (%sp)+,%fpcr # restore fpcr
10301 fadd.s 0x8(%sp),%fp0 # fadd w/ sgl src
10302 rts
10303
10304 global _faddd_
10305 _faddd_:
10306 fmov.l %fpcr,-(%sp) # save fpcr
10307 fmov.l &0x00000000,%fpcr # clear fpcr for load
10308 fmov.d 0x8(%sp),%fp0 # load dbl dst
10309 fmov.l (%sp)+,%fpcr # restore fpcr
10310 fadd.d 0xc(%sp),%fp0 # fadd w/ dbl src
10311 rts
10312
10313 global _faddx_
10314 _faddx_:
10315 fmovm.x 0x4(%sp),&0x80 # load ext dst
10316 fadd.x 0x10(%sp),%fp0 # fadd w/ ext src
10317 rts
10318
10319 global _fsubs_
10320 _fsubs_:
10321 fmov.l %fpcr,-(%sp) # save fpcr
10322 fmov.l &0x00000000,%fpcr # clear fpcr for load
10323 fmov.s 0x8(%sp),%fp0 # load sgl dst
10324 fmov.l (%sp)+,%fpcr # restore fpcr
10325 fsub.s 0x8(%sp),%fp0 # fsub w/ sgl src
10326 rts
10327
10328 global _fsubd_
10329 _fsubd_:
10330 fmov.l %fpcr,-(%sp) # save fpcr
10331 fmov.l &0x00000000,%fpcr # clear fpcr for load
10332 fmov.d 0x8(%sp),%fp0 # load dbl dst
10333 fmov.l (%sp)+,%fpcr # restore fpcr
10334 fsub.d 0xc(%sp),%fp0 # fsub w/ dbl src
10335 rts
10336
10337 global _fsubx_
10338 _fsubx_:
10339 fmovm.x 0x4(%sp),&0x80 # load ext dst
10340 fsub.x 0x10(%sp),%fp0 # fsub w/ ext src
10341 rts
10342
10343 global _fmuls_
10344 _fmuls_:
10345 fmov.l %fpcr,-(%sp) # save fpcr
10346 fmov.l &0x00000000,%fpcr # clear fpcr for load
10347 fmov.s 0x8(%sp),%fp0 # load sgl dst
10348 fmov.l (%sp)+,%fpcr # restore fpcr
10349 fmul.s 0x8(%sp),%fp0 # fmul w/ sgl src
10350 rts
10351
10352 global _fmuld_
10353 _fmuld_:
10354 fmov.l %fpcr,-(%sp) # save fpcr
10355 fmov.l &0x00000000,%fpcr # clear fpcr for load
10356 fmov.d 0x8(%sp),%fp0 # load dbl dst
10357 fmov.l (%sp)+,%fpcr # restore fpcr
10358 fmul.d 0xc(%sp),%fp0 # fmul w/ dbl src
10359 rts
10360
10361 global _fmulx_
10362 _fmulx_:
10363 fmovm.x 0x4(%sp),&0x80 # load ext dst
10364 fmul.x 0x10(%sp),%fp0 # fmul w/ ext src
10365 rts
10366
10367 global _fdivs_
10368 _fdivs_:
10369 fmov.l %fpcr,-(%sp) # save fpcr
10370 fmov.l &0x00000000,%fpcr # clear fpcr for load
10371 fmov.s 0x8(%sp),%fp0 # load sgl dst
10372 fmov.l (%sp)+,%fpcr # restore fpcr
10373 fdiv.s 0x8(%sp),%fp0 # fdiv w/ sgl src
10374 rts
10375
10376 global _fdivd_
10377 _fdivd_:
10378 fmov.l %fpcr,-(%sp) # save fpcr
10379 fmov.l &0x00000000,%fpcr # clear fpcr for load
10380 fmov.d 0x8(%sp),%fp0 # load dbl dst
10381 fmov.l (%sp)+,%fpcr # restore fpcr
10382 fdiv.d 0xc(%sp),%fp0 # fdiv w/ dbl src
10383 rts
10384
10385 global _fdivx_
10386 _fdivx_:
10387 fmovm.x 0x4(%sp),&0x80 # load ext dst
10388 fdiv.x 0x10(%sp),%fp0 # fdiv w/ ext src
10389 rts
10390
10391 global _fabss_
10392 _fabss_:
10393 fabs.s 0x4(%sp),%fp0 # fabs w/ sgl src
10394 rts
10395
10396 global _fabsd_
10397 _fabsd_:
10398 fabs.d 0x4(%sp),%fp0 # fabs w/ dbl src
10399 rts
10400
10401 global _fabsx_
10402 _fabsx_:
10403 fabs.x 0x4(%sp),%fp0 # fabs w/ ext src
10404 rts
10405
10406 global _fnegs_
10407 _fnegs_:
10408 fneg.s 0x4(%sp),%fp0 # fneg w/ sgl src
10409 rts
10410
10411 global _fnegd_
10412 _fnegd_:
10413 fneg.d 0x4(%sp),%fp0 # fneg w/ dbl src
10414 rts
10415
10416 global _fnegx_
10417 _fnegx_:
10418 fneg.x 0x4(%sp),%fp0 # fneg w/ ext src
10419 rts
10420
10421 global _fsqrts_
10422 _fsqrts_:
10423 fsqrt.s 0x4(%sp),%fp0 # fsqrt w/ sgl src
10424 rts
10425
10426 global _fsqrtd_
10427 _fsqrtd_:
10428 fsqrt.d 0x4(%sp),%fp0 # fsqrt w/ dbl src
10429 rts
10430
10431 global _fsqrtx_
10432 _fsqrtx_:
10433 fsqrt.x 0x4(%sp),%fp0 # fsqrt w/ ext src
10434 rts
10435
10436 global _fints_
10437 _fints_:
10438 fint.s 0x4(%sp),%fp0 # fint w/ sgl src
10439 rts
10440
10441 global _fintd_
10442 _fintd_:
10443 fint.d 0x4(%sp),%fp0 # fint w/ dbl src
10444 rts
10445
10446 global _fintx_
10447 _fintx_:
10448 fint.x 0x4(%sp),%fp0 # fint w/ ext src
10449 rts
10450
10451 global _fintrzs_
10452 _fintrzs_:
10453 fintrz.s 0x4(%sp),%fp0 # fintrz w/ sgl src
10454 rts
10455
10456 global _fintrzd_
10457 _fintrzd_:
10458 fintrz.d 0x4(%sp),%fp0 # fintrx w/ dbl src
10459 rts
10460
10461 global _fintrzx_
10462 _fintrzx_:
10463 fintrz.x 0x4(%sp),%fp0 # fintrz w/ ext src
10464 rts
10465
10466 ########################################################################
10467
10468 #########################################################################
10469 # src_zero(): Return signed zero according to sign of src operand. #
10470 #########################################################################
10471 global src_zero
10472 src_zero:
10473 tst.b SRC_EX(%a0) # get sign of src operand
10474 bmi.b ld_mzero # if neg, load neg zero
10475
10476 #
10477 # ld_pzero(): return a positive zero.
10478 #
10479 global ld_pzero
10480 ld_pzero:
10481 fmov.s &0x00000000,%fp0 # load +0
10482 mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
10483 rts
10484
10485 # ld_mzero(): return a negative zero.
10486 global ld_mzero
10487 ld_mzero:
10488 fmov.s &0x80000000,%fp0 # load -0
10489 mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
10490 rts
10491
10492 #########################################################################
10493 # dst_zero(): Return signed zero according to sign of dst operand. #
10494 #########################################################################
10495 global dst_zero
10496 dst_zero:
10497 tst.b DST_EX(%a1) # get sign of dst operand
10498 bmi.b ld_mzero # if neg, load neg zero
10499 bra.b ld_pzero # load positive zero
10500
10501 #########################################################################
10502 # src_inf(): Return signed inf according to sign of src operand. #
10503 #########################################################################
10504 global src_inf
10505 src_inf:
10506 tst.b SRC_EX(%a0) # get sign of src operand
10507 bmi.b ld_minf # if negative branch
10508
10509 #
10510 # ld_pinf(): return a positive infinity.
10511 #
10512 global ld_pinf
10513 ld_pinf:
10514 fmov.s &0x7f800000,%fp0 # load +INF
10515 mov.b &inf_bmask,FPSR_CC(%a6) # set 'INF' ccode bit
10516 rts
10517
10518 #
10519 # ld_minf():return a negative infinity.
10520 #
10521 global ld_minf
10522 ld_minf:
10523 fmov.s &0xff800000,%fp0 # load -INF
10524 mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
10525 rts
10526
10527 #########################################################################
10528 # dst_inf(): Return signed inf according to sign of dst operand. #
10529 #########################################################################
10530 global dst_inf
10531 dst_inf:
10532 tst.b DST_EX(%a1) # get sign of dst operand
10533 bmi.b ld_minf # if negative branch
10534 bra.b ld_pinf
10535
10536 global szr_inf
10537 #################################################################
10538 # szr_inf(): Return +ZERO for a negative src operand or #
10539 # +INF for a positive src operand. #
10540 # Routine used for fetox, ftwotox, and ftentox. #
10541 #################################################################
10542 szr_inf:
10543 tst.b SRC_EX(%a0) # check sign of source
10544 bmi.b ld_pzero
10545 bra.b ld_pinf
10546
10547 #########################################################################
10548 # sopr_inf(): Return +INF for a positive src operand or #
10549 # jump to operand error routine for a negative src operand. #
10550 # Routine used for flogn, flognp1, flog10, and flog2. #
10551 #########################################################################
10552 global sopr_inf
10553 sopr_inf:
10554 tst.b SRC_EX(%a0) # check sign of source
10555 bmi.w t_operr
10556 bra.b ld_pinf
10557
10558 #################################################################
10559 # setoxm1i(): Return minus one for a negative src operand or #
10560 # positive infinity for a positive src operand. #
10561 # Routine used for fetoxm1. #
10562 #################################################################
10563 global setoxm1i
10564 setoxm1i:
10565 tst.b SRC_EX(%a0) # check sign of source
10566 bmi.b ld_mone
10567 bra.b ld_pinf
10568
10569 #########################################################################
10570 # src_one(): Return signed one according to sign of src operand. #
10571 #########################################################################
10572 global src_one
10573 src_one:
10574 tst.b SRC_EX(%a0) # check sign of source
10575 bmi.b ld_mone
10576
10577 #
10578 # ld_pone(): return positive one.
10579 #
10580 global ld_pone
10581 ld_pone:
10582 fmov.s &0x3f800000,%fp0 # load +1
10583 clr.b FPSR_CC(%a6)
10584 rts
10585
10586 #
10587 # ld_mone(): return negative one.
10588 #
10589 global ld_mone
10590 ld_mone:
10591 fmov.s &0xbf800000,%fp0 # load -1
10592 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
10593 rts
10594
10595 ppiby2: long 0x3fff0000, 0xc90fdaa2, 0x2168c235
10596 mpiby2: long 0xbfff0000, 0xc90fdaa2, 0x2168c235
10597
10598 #################################################################
10599 # spi_2(): Return signed PI/2 according to sign of src operand. #
10600 #################################################################
10601 global spi_2
10602 spi_2:
10603 tst.b SRC_EX(%a0) # check sign of source
10604 bmi.b ld_mpi2
10605
10606 #
10607 # ld_ppi2(): return positive PI/2.
10608 #
10609 global ld_ppi2
10610 ld_ppi2:
10611 fmov.l %d0,%fpcr
10612 fmov.x ppiby2(%pc),%fp0 # load +pi/2
10613 bra.w t_pinx2 # set INEX2
10614
10615 #
10616 # ld_mpi2(): return negative PI/2.
10617 #
10618 global ld_mpi2
10619 ld_mpi2:
10620 fmov.l %d0,%fpcr
10621 fmov.x mpiby2(%pc),%fp0 # load -pi/2
10622 bra.w t_minx2 # set INEX2
10623
10624 ####################################################
10625 # The following routines give support for fsincos. #
10626 ####################################################
10627
10628 #
10629 # ssincosz(): When the src operand is ZERO, store a one in the
10630 # cosine register and return a ZERO in fp0 w/ the same sign
10631 # as the src operand.
10632 #
10633 global ssincosz
10634 ssincosz:
10635 fmov.s &0x3f800000,%fp1
10636 tst.b SRC_EX(%a0) # test sign
10637 bpl.b sincoszp
10638 fmov.s &0x80000000,%fp0 # return sin result in fp0
10639 mov.b &z_bmask+neg_bmask,FPSR_CC(%a6)
10640 rts
10641 sincoszp:
10642 fmov.s &0x00000000,%fp0 # return sin result in fp0
10643 mov.b &z_bmask,FPSR_CC(%a6)
10644 rts
10645
10646 #
10647 # ssincosi(): When the src operand is INF, store a QNAN in the cosine
10648 # register and jump to the operand error routine for negative
10649 # src operands.
10650 #
10651 global ssincosi
10652 ssincosi:
10653 fmov.x qnan(%pc),%fp1 # load NAN
10654 bra.w t_operr
10655
10656 #
10657 # ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
10658 # register and branch to the src QNAN routine.
10659 #
10660 global ssincosqnan
10661 ssincosqnan:
10662 fmov.x LOCAL_EX(%a0),%fp1
10663 bra.w src_qnan
10664
10665 ########################################################################
10666
10667 global smod_sdnrm
10668 global smod_snorm
10669 smod_sdnrm:
10670 smod_snorm:
10671 mov.b DTAG(%a6),%d1
10672 beq.l smod
10673 cmpi.b %d1,&ZERO
10674 beq.w smod_zro
10675 cmpi.b %d1,&INF
10676 beq.l t_operr
10677 cmpi.b %d1,&DENORM
10678 beq.l smod
10679 bra.l dst_qnan
10680
10681 global smod_szero
10682 smod_szero:
10683 mov.b DTAG(%a6),%d1
10684 beq.l t_operr
10685 cmpi.b %d1,&ZERO
10686 beq.l t_operr
10687 cmpi.b %d1,&INF
10688 beq.l t_operr
10689 cmpi.b %d1,&DENORM
10690 beq.l t_operr
10691 bra.l dst_qnan
10692
10693 global smod_sinf
10694 smod_sinf:
10695 mov.b DTAG(%a6),%d1
10696 beq.l smod_fpn
10697 cmpi.b %d1,&ZERO
10698 beq.l smod_zro
10699 cmpi.b %d1,&INF
10700 beq.l t_operr
10701 cmpi.b %d1,&DENORM
10702 beq.l smod_fpn
10703 bra.l dst_qnan
10704
10705 smod_zro:
10706 srem_zro:
10707 mov.b SRC_EX(%a0),%d1 # get src sign
10708 mov.b DST_EX(%a1),%d0 # get dst sign
10709 eor.b %d0,%d1 # get qbyte sign
10710 andi.b &0x80,%d1
10711 mov.b %d1,FPSR_QBYTE(%a6)
10712 tst.b %d0
10713 bpl.w ld_pzero
10714 bra.w ld_mzero
10715
10716 smod_fpn:
10717 srem_fpn:
10718 clr.b FPSR_QBYTE(%a6)
10719 mov.l %d0,-(%sp)
10720 mov.b SRC_EX(%a0),%d1 # get src sign
10721 mov.b DST_EX(%a1),%d0 # get dst sign
10722 eor.b %d0,%d1 # get qbyte sign
10723 andi.b &0x80,%d1
10724 mov.b %d1,FPSR_QBYTE(%a6)
10725 cmpi.b DTAG(%a6),&DENORM
10726 bne.b smod_nrm
10727 lea DST(%a1),%a0
10728 mov.l (%sp)+,%d0
10729 bra t_resdnrm
10730 smod_nrm:
10731 fmov.l (%sp)+,%fpcr
10732 fmov.x DST(%a1),%fp0
10733 tst.b DST_EX(%a1)
10734 bmi.b smod_nrm_neg
10735 rts
10736
10737 smod_nrm_neg:
10738 mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' code
10739 rts
10740
10741 #########################################################################
10742 global srem_snorm
10743 global srem_sdnrm
10744 srem_sdnrm:
10745 srem_snorm:
10746 mov.b DTAG(%a6),%d1
10747 beq.l srem
10748 cmpi.b %d1,&ZERO
10749 beq.w srem_zro
10750 cmpi.b %d1,&INF
10751 beq.l t_operr
10752 cmpi.b %d1,&DENORM
10753 beq.l srem
10754 bra.l dst_qnan
10755
10756 global srem_szero
10757 srem_szero:
10758 mov.b DTAG(%a6),%d1
10759 beq.l t_operr
10760 cmpi.b %d1,&ZERO
10761 beq.l t_operr
10762 cmpi.b %d1,&INF
10763 beq.l t_operr
10764 cmpi.b %d1,&DENORM
10765 beq.l t_operr
10766 bra.l dst_qnan
10767
10768 global srem_sinf
10769 srem_sinf:
10770 mov.b DTAG(%a6),%d1
10771 beq.w srem_fpn
10772 cmpi.b %d1,&ZERO
10773 beq.w srem_zro
10774 cmpi.b %d1,&INF
10775 beq.l t_operr
10776 cmpi.b %d1,&DENORM
10777 beq.l srem_fpn
10778 bra.l dst_qnan
10779
10780 #########################################################################
10781
10782 global sscale_snorm
10783 global sscale_sdnrm
10784 sscale_snorm:
10785 sscale_sdnrm:
10786 mov.b DTAG(%a6),%d1
10787 beq.l sscale
10788 cmpi.b %d1,&ZERO
10789 beq.l dst_zero
10790 cmpi.b %d1,&INF
10791 beq.l dst_inf
10792 cmpi.b %d1,&DENORM
10793 beq.l sscale
10794 bra.l dst_qnan
10795
10796 global sscale_szero
10797 sscale_szero:
10798 mov.b DTAG(%a6),%d1
10799 beq.l sscale
10800 cmpi.b %d1,&ZERO
10801 beq.l dst_zero
10802 cmpi.b %d1,&INF
10803 beq.l dst_inf
10804 cmpi.b %d1,&DENORM
10805 beq.l sscale
10806 bra.l dst_qnan
10807
10808 global sscale_sinf
10809 sscale_sinf:
10810 mov.b DTAG(%a6),%d1
10811 beq.l t_operr
10812 cmpi.b %d1,&QNAN
10813 beq.l dst_qnan
10814 bra.l t_operr
10815
10816 ########################################################################
10817
10818 global sop_sqnan
10819 sop_sqnan:
10820 mov.b DTAG(%a6),%d1
10821 cmpi.b %d1,&QNAN
10822 beq.l dst_qnan
10823 bra.l src_qnan
10824
10825 #########################################################################
10826 # norm(): normalize the mantissa of an extended precision input. the #
10827 # input operand should not be normalized already. #
10828 # #
10829 # XDEF **************************************************************** #
10830 # norm() #
10831 # #
10832 # XREF **************************************************************** #
10833 # none #
10834 # #
10835 # INPUT *************************************************************** #
10836 # a0 = pointer fp extended precision operand to normalize #
10837 # #
10838 # OUTPUT ************************************************************** #
10839 # d0 = number of bit positions the mantissa was shifted #
10840 # a0 = the input operand's mantissa is normalized; the exponent #
10841 # is unchanged. #
10842 # #
10843 #########################################################################
10844 global norm
10845 norm:
10846 mov.l %d2, -(%sp) # create some temp regs
10847 mov.l %d3, -(%sp)
10848
10849 mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
10850 mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
10851
10852 bfffo %d0{&0:&32}, %d2 # how many places to shift?
10853 beq.b norm_lo # hi(man) is all zeroes!
10854
10855 norm_hi:
10856 lsl.l %d2, %d0 # left shift hi(man)
10857 bfextu %d1{&0:%d2}, %d3 # extract lo bits
10858
10859 or.l %d3, %d0 # create hi(man)
10860 lsl.l %d2, %d1 # create lo(man)
10861
10862 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
10863 mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
10864
10865 mov.l %d2, %d0 # return shift amount
10866
10867 mov.l (%sp)+, %d3 # restore temp regs
10868 mov.l (%sp)+, %d2
10869
10870 rts
10871
10872 norm_lo:
10873 bfffo %d1{&0:&32}, %d2 # how many places to shift?
10874 lsl.l %d2, %d1 # shift lo(man)
10875 add.l &32, %d2 # add 32 to shft amount
10876
10877 mov.l %d1, FTEMP_HI(%a0) # store hi(man)
10878 clr.l FTEMP_LO(%a0) # lo(man) is now zero
10879
10880 mov.l %d2, %d0 # return shift amount
10881
10882 mov.l (%sp)+, %d3 # restore temp regs
10883 mov.l (%sp)+, %d2
10884
10885 rts
10886
10887 #########################################################################
10888 # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
10889 # - returns corresponding optype tag #
10890 # #
10891 # XDEF **************************************************************** #
10892 # unnorm_fix() #
10893 # #
10894 # XREF **************************************************************** #
10895 # norm() - normalize the mantissa #
10896 # #
10897 # INPUT *************************************************************** #
10898 # a0 = pointer to unnormalized extended precision number #
10899 # #
10900 # OUTPUT ************************************************************** #
10901 # d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
10902 # a0 = input operand has been converted to a norm, denorm, or #
10903 # zero; both the exponent and mantissa are changed. #
10904 # #
10905 #########################################################################
10906
10907 global unnorm_fix
10908 unnorm_fix:
10909 bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
10910 bne.b unnorm_shift # hi(man) is not all zeroes
10911
10912 #
10913 # hi(man) is all zeroes so see if any bits in lo(man) are set
10914 #
10915 unnorm_chk_lo:
10916 bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
10917 beq.w unnorm_zero # yes
10918
10919 add.w &32, %d0 # no; fix shift distance
10920
10921 #
10922 # d0 = # shifts needed for complete normalization
10923 #
10924 unnorm_shift:
10925 clr.l %d1 # clear top word
10926 mov.w FTEMP_EX(%a0), %d1 # extract exponent
10927 and.w &0x7fff, %d1 # strip off sgn
10928
10929 cmp.w %d0, %d1 # will denorm push exp < 0?
10930 bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
10931
10932 #
10933 # exponent would not go < 0. therefore, number stays normalized
10934 #
10935 sub.w %d0, %d1 # shift exponent value
10936 mov.w FTEMP_EX(%a0), %d0 # load old exponent
10937 and.w &0x8000, %d0 # save old sign
10938 or.w %d0, %d1 # {sgn,new exp}
10939 mov.w %d1, FTEMP_EX(%a0) # insert new exponent
10940
10941 bsr.l norm # normalize UNNORM
10942
10943 mov.b &NORM, %d0 # return new optype tag
10944 rts
10945
10946 #
10947 # exponent would go < 0, so only denormalize until exp = 0
10948 #
10949 unnorm_nrm_zero:
10950 cmp.b %d1, &32 # is exp <= 32?
10951 bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
10952
10953 bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
10954 mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
10955
10956 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
10957 lsl.l %d1, %d0 # extract new lo(man)
10958 mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
10959
10960 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
10961
10962 mov.b &DENORM, %d0 # return new optype tag
10963 rts
10964
10965 #
10966 # only mantissa bits set are in lo(man)
10967 #
10968 unnorm_nrm_zero_lrg:
10969 sub.w &32, %d1 # adjust shft amt by 32
10970
10971 mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
10972 lsl.l %d1, %d0 # left shift lo(man)
10973
10974 mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
10975 clr.l FTEMP_LO(%a0) # lo(man) = 0
10976
10977 and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
10978
10979 mov.b &DENORM, %d0 # return new optype tag
10980 rts
10981
10982 #
10983 # whole mantissa is zero so this UNNORM is actually a zero
10984 #
10985 unnorm_zero:
10986 and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
10987
10988 mov.b &ZERO, %d0 # fix optype tag
10989 rts
10990