home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / general / arith.c < prev    next >
C/C++ Source or Header  |  1996-12-11  |  12KB  |  743 lines

  1. #define ALL
  2.  
  3. #include "common.h"
  4. #include "defs.h"
  5. #include <proto/mathieeedoubbas.h>
  6. #include <proto/mathieeedoubtrans.h>
  7. #include <proto/mathieeesingbas.h>
  8.  
  9. /*  Special patch to work around bug in IEEEDPCmp:
  10.  *  if the first 32 bits of both doubles are equal, and
  11.  *  both doubles are negative, then the result can no longer
  12.  *  be trusted.
  13.  * 
  14.  *  This is the output of a small test program:
  15.  *
  16.  *    test -2.000001 -2.0000009
  17.  *    a = -2.0000009999999996956888, b = -2.0000008999999998593466
  18.  *    (0xc0000000 0x8637bd05, 0xc0000000 0x78cbc3b8)
  19.  *    cmp(a,b) = 0, cmp(b,a) = 1
  20.  *
  21.  *    test -2.0000001 -2.0000002
  22.  *    a = -2.00000009999999983634211, b = -2.0000001999999996726842
  23.  *    (0xc0000000 0xd6bf94d, 0xc0000000 0x1ad7f29a)
  24.  *    cmp(a,b) = 1, cmp(b,a) = 1
  25.  *
  26.  *  As you can see, the results are wrong.
  27.  *
  28.  *  So, we just make both variables positive and exchange them before
  29.  *  passing them to IEEEDPCmp.
  30.  *
  31.  *  This bug was discovered by Bart Van Assche, thanks!
  32.  */
  33.  
  34. static int ieeedpcmp(double a, double b)
  35. {
  36.   if (*((char *)&a) & *((char *)&b) & 0x80)  /* both doubles negative? */
  37.     {
  38.       *((char *)&a) &= 0x7f;    /* yes, make positive */
  39.       *((char *)&b) &= 0x7f;
  40.       return IEEEDPCmp(b, a);   /* pass them to IEEEDPCmp the other way round */
  41.     }
  42.   return IEEEDPCmp(a, b);
  43. }
  44.  
  45. #if defined(L__eqdf2) || defined(ALL)
  46. int __eqdf2 (double a, double b)
  47. {
  48.   return ieeedpcmp (a, b);
  49. }
  50. #endif
  51.  
  52. #if defined(L__eqsf2) || defined(ALL)
  53. int __eqsf2 (FLOAT a, FLOAT b)
  54. {
  55.   return IEEESPCmp (a, b);
  56. }
  57. #endif
  58.  
  59. #if defined(L__fixsfsi) || defined(ALL)
  60. SItype __fixsfsi (FLOAT a)
  61. {
  62.   return IEEESPFix(a);
  63. }
  64. #endif
  65.  
  66. #if defined(L__floatsisf) || defined(ALL)
  67. SFVALUE __floatsisf (SItype a)
  68. {
  69.   return IEEESPFlt(a);
  70. }
  71. #endif
  72.  
  73. #if defined(L__gedf2) || defined(ALL)
  74. int __gedf2 (double a, double b)
  75. {
  76.   return ieeedpcmp (a, b);
  77. }
  78. #endif
  79.  
  80. #if defined(L__gesf2) || defined(ALL)
  81. int __gesf2 (FLOAT a, FLOAT b)
  82. {
  83.   return IEEESPCmp (a, b);
  84. }
  85. #endif
  86.  
  87. #if defined(L__gtdf2) || defined(ALL)
  88. int __gtdf2 (double a, double b)
  89. {
  90.   return ieeedpcmp (a, b);
  91. }
  92. #endif
  93.  
  94. #if defined(L__gtsf2) || defined(ALL)
  95. int __gtsf2 (FLOAT a, FLOAT b)
  96. {
  97.   return IEEESPCmp (a, b);
  98. }
  99. #endif
  100.  
  101. #if defined(L__ledf2) || defined(ALL)
  102. int __ledf2 (double a, double b)
  103. {
  104.   return ieeedpcmp (a, b);
  105. }
  106. #endif
  107.  
  108. #if defined(L__lesf2) || defined(ALL)
  109. int __lesf2 (FLOAT a, FLOAT b)
  110. {
  111.   return IEEESPCmp (a, b);
  112. }
  113. #endif
  114.  
  115. #if defined(L__ltdf2) || defined(ALL)
  116. int __ltdf2 (double a, double b)
  117. {
  118.   return ieeedpcmp (a, b);
  119. }
  120. #endif
  121.  
  122. #if defined(L__ltsf2) || defined(ALL)
  123. int __ltsf2 (FLOAT a, FLOAT b)
  124. {
  125.   return IEEESPCmp (a, b);
  126. }
  127. #endif
  128.  
  129. #if defined(L__nedf2) || defined(ALL)
  130. int __nedf2 (double a, double b)
  131. {
  132.   return !!ieeedpcmp (a, b);
  133. }
  134. #endif
  135.  
  136. #if defined(L__nesf2) || defined(ALL)
  137. int __nesf2 (FLOAT a, FLOAT b)
  138. {
  139.   return !!IEEESPCmp (a, b);
  140. }
  141. #endif
  142.  
  143. /*
  144.  * double frexp(val, eptr)
  145.  * returns: x s.t. val = x * (2 ** n), with n stored in *eptr
  146.  */
  147. #if defined(Lfrexp) || defined(ALL)
  148. double frexp(double value, int *eptr)
  149. {
  150.   union
  151.   {
  152.     double v;
  153.     struct 
  154.     {
  155.       u_int u_sign  :  1;
  156.       u_int u_exp   : 11;
  157.       u_int u_mant1 : 20;
  158.       u_int u_mant2 : 32;
  159.     } s;
  160.   } d;
  161.  
  162.   if (value)
  163.     {
  164.       d.v = value;
  165.       *eptr = d.s.u_exp - 1022;
  166.       d.s.u_exp = 1022;
  167.       return d.v;
  168.     }
  169.   *eptr = 0;
  170.   return 0.0;
  171. }
  172. #endif
  173.  
  174.  
  175.  
  176. #if defined (mc68020) || defined (mc68030) || defined (mc68040) || defined (mc68060)
  177.  
  178. /* int / int */
  179. #if defined(L__divsi3) || defined(ALL)
  180. ENTRY(__divsi3)
  181. asm("
  182.     movel    sp@(4),d0
  183.     divsl    sp@(8),d0
  184.     rts
  185. ");
  186. #endif
  187.  
  188. /* int % int */
  189. #if defined(L__modsi3) || defined(ALL)
  190. ENTRY(__modsi3)
  191. asm("
  192.     movel    sp@(4),d1
  193.     divsll    sp@(8),d0:d1
  194.     rts
  195. ");
  196. #endif
  197.  
  198. /* int * int */
  199. #if defined(L__mulsi3) || defined(ALL)
  200. ENTRY(__mulsi3)
  201. asm("
  202.     movel    sp@(4),d0
  203.     mulsl    sp@(8),d0
  204.     rts
  205. ");
  206. #endif
  207.  
  208. /* unsigned / unsigned */
  209. #if defined(L__udivsi3) || defined(ALL)
  210. ENTRY(__udivsi3)
  211. asm("
  212.     movel    sp@(4),d0
  213.     divul    sp@(8),d0
  214.     rts
  215. ");
  216. #endif
  217.  
  218. /* unsigned % unsigned */
  219. #if defined(L__umodsi3) || defined(ALL)
  220. ENTRY(__umodsi3)
  221. asm("
  222.     movel    sp@(4),d1
  223.     divull    sp@(8),d0:d1
  224.     rts
  225. ");
  226. #endif
  227.  
  228. /* unsigned * unsigned */
  229. #if defined(L__umulsi3) || defined(ALL)
  230. ENTRY(__umulsi3)
  231. asm("
  232.     movel    sp@(4),d0
  233.     mulul    sp@(8),d0
  234.     rts
  235. ");
  236. #endif
  237.  
  238.  
  239. #else
  240.  
  241.  
  242. #if defined(L__divsi3) || defined(ALL)
  243. SItype __divsi3 (SItype a, SItype b)
  244. {
  245.   unsigned SItype q, r;
  246.   int neg = (a < 0) != (b < 0);
  247.  
  248.   if (a < 0) a = -a;
  249.   if (b < 0) b = -b;
  250.  
  251.   divmodu (q, r, a, b);
  252.  
  253.   return neg ? -q : q;
  254. }
  255. #endif
  256.  
  257. #if defined(L__modsi3) || defined(ALL)
  258. SItype __modsi3 (SItype a, SItype b)
  259. {
  260.   unsigned SItype q, r;
  261.   int neg = (a < 0);
  262.  
  263.   if (a < 0) a = -a;
  264.   if (b < 0) b = -b;
  265.  
  266.   divmodu (q, r, a, b);
  267.  
  268.   return neg ? -r : r;
  269. }
  270. #endif
  271.  
  272. #if defined(L__mulsi3) || defined(ALL)
  273. SItype __mulsi3 (SItype a, SItype b)
  274. {
  275.   int neg = (a < 0) != (b < 0);
  276.   SItype res;
  277.  
  278.   if (a < 0) a = -a;
  279.   if (b < 0) b = -b;
  280.   
  281.   res = mulu (a,b);
  282.   return neg ? -res : res;
  283. }
  284. #endif
  285.  
  286. #if defined(L__udivsi3) || defined(ALL)
  287. unsigned SItype __udivsi3 (unsigned SItype a, unsigned SItype b)
  288. {
  289.   unsigned SItype q, r;
  290.   divmodu (q, r, a, b);
  291.   return q;
  292. }
  293. #endif
  294.  
  295. #if defined(L__umodsi3) || defined(ALL)
  296. unsigned SItype __umodsi3 (unsigned SItype a, unsigned SItype b)
  297. {
  298.   unsigned SItype q, r;
  299.   divmodu (q, r, a, b);
  300.   return r;
  301. }
  302. #endif
  303.  
  304. #endif
  305.  
  306. /* -double */
  307. #if defined(L__negdf2) || defined(ALL)
  308. ENTRY(__negdf2)
  309. asm("
  310.     movel    sp@(4),d0
  311.     movel    sp@(8),d1
  312.     bchg    #31,d0
  313.     rts
  314. ");
  315. #endif
  316.  
  317. /* -single */
  318. #if defined(L__negsf2) || defined(ALL)
  319. ENTRY(__negsf2)
  320. asm("
  321.     movel    sp@(4),d0
  322.     bchg    #31,d0
  323.     rts
  324. ");
  325. #endif
  326.  
  327.  
  328.  
  329. #ifdef __HAVE_68881__
  330.  
  331. /* double + double */
  332. #if defined(L__adddf3) || defined(ALL)
  333. ENTRY(__adddf3)
  334. asm("
  335.     fmoved    sp@(4),fp0
  336.     faddd    sp@(12),fp0
  337.     fmoved    fp0,sp@-
  338.     movel    sp@+,d0
  339.     movel    sp@+,d1
  340.     rts
  341. ");
  342. #endif
  343.  
  344. /* single + single */
  345. #if defined(L__addsf3) || defined(ALL)
  346. ENTRY(__addsf3)
  347. asm("
  348.     fmoves    sp@(4),fp0
  349.     fadds    sp@(8),fp0
  350.     fmoves    fp0,d0
  351.     rts
  352. ");
  353. #endif
  354.  
  355. /* double > double: 1 */
  356. /* double < double: -1 */
  357. /* double == double: 0 */
  358. #if defined(L__cmpdf2) || defined(ALL)
  359. ENTRY(__cmpdf2)
  360. asm("
  361.     fmoved    sp@(4),fp0
  362.     fcmpd    sp@(12),fp0
  363.     fbgt    Lagtb1
  364.     fslt    d0
  365.     extbl    d0
  366.     rts
  367. Lagtb1:
  368.     moveq    #1,d0
  369.     rts
  370. ");
  371. #endif
  372.  
  373. /* single > single: 1 */
  374. /* single < single: -1 */
  375. /* single == single: 0 */
  376. #if defined(L__cmpsf2) || defined(ALL)
  377. ENTRY(__cmpsf2)
  378. asm("
  379.     fmoves    sp@(4),fp0
  380.     fcmps    sp@(8),fp0
  381.     fbgt    Lagtb2
  382.     fslt    d0
  383.     extbl    d0
  384.     rts
  385. Lagtb2:
  386.     moveq    #1,d0
  387.     rts
  388. ");
  389. #endif
  390.  
  391. /* double / double */
  392. #if defined(L__divdf3) || defined(ALL)
  393. ENTRY(__divdf3)
  394. asm("
  395.     fmoved    sp@(4),fp0
  396.     fdivd    sp@(12),fp0
  397.     fmoved    fp0,sp@-
  398.     movel    sp@+,d0
  399.     movel    sp@+,d1
  400.     rts
  401. ");
  402. #endif
  403.  
  404. /* single / single */
  405. #if defined(L__divsf3) || defined(ALL)
  406. ENTRY(__divsf3)
  407. asm("
  408.     fmoves    sp@(4),fp0
  409.     fdivs    sp@(8),fp0
  410.     fmoves    fp0,d0
  411.     rts
  412. ");
  413. #endif
  414.  
  415. /* (double) float */
  416. #if defined(L__extendsfdf2) || defined(ALL)
  417. ENTRY(__extendsfdf2)
  418. asm("
  419.     fmoves    sp@(4),fp0
  420.     fmoved    fp0,sp@-
  421.     movel    sp@+,d0
  422.     movel    sp@+,d1
  423.     rts
  424. ");
  425. #endif
  426.  
  427. #if defined(Lfabs) || defined(ALL)
  428. ENTRY(fabs)
  429. asm("
  430.     fmoved    sp@(4),fp0
  431.     fjnlt    L1
  432.     fnegx    fp0
  433. L1:
  434.     fmoved    fp0,sp@-
  435.     movel    sp@+,d0
  436.     movel    sp@+,d1
  437.     rts
  438. ");
  439. #endif
  440.  
  441. /* (int) double */
  442. #if defined(L__fixdfsi) || defined(ALL)
  443. ENTRY(__fixdfsi)
  444. asm("
  445.     fintrzd    sp@(4),fp0
  446.     fmovel    fp0,d0
  447.     rts
  448. ");
  449. #endif
  450.  
  451. /* (double) int */
  452. #if defined(L__floatsidf) || defined(ALL)
  453. ENTRY(__floatsidf)
  454. asm("
  455.     fmovel    sp@(4),fp0
  456.     fmoved    fp0,sp@-
  457.     movel    sp@+,d0
  458.     movel    sp@+,d1
  459.     rts
  460. ");
  461. #endif
  462.  
  463. /*
  464.  * double ldexp(val, exp)
  465.  * returns: val * (2**exp), for integer exp
  466.  */
  467. #if defined(Lldexp) || defined(ALL)
  468. ENTRY(ldexp)
  469. asm("
  470.     fmoved        sp@(4),fp0
  471.     fbeq        Ldone
  472.     ftwotoxl    sp@(12),fp1
  473.     fmulx        fp1,fp0
  474. Ldone:
  475.     fmoved        fp0,sp@-
  476.     movel        sp@+,d0
  477.     movel        sp@+,d1
  478.     rts
  479. ");
  480. #endif
  481.  
  482. /*
  483.  * double modf(val, iptr)
  484.  * returns: xxx and n (in *iptr) where val == n.xxx
  485.  */
  486. #if defined(Lmodf) || defined(ALL)
  487. ENTRY(modf)
  488. asm("
  489.     fmoved    sp@(4),fp0
  490.     movel    sp@(12),a0
  491.     fintrzx    fp0,fp1
  492.     fmoved    fp1,a0@
  493.     fsubx    fp1,fp0
  494.     fmoved    fp0,sp@-
  495.     movel    sp@+,d0
  496.     movel    sp@+,d1
  497.     rts
  498. ");
  499. #endif
  500.  
  501. /* double * double */
  502. #if defined(L__muldf3) || defined(ALL)
  503. ENTRY(__muldf3)
  504. asm("
  505.     fmoved    sp@(4),fp0
  506.     fmuld    sp@(12),fp0
  507.     fmoved    fp0,sp@-
  508.     movel    sp@+,d0
  509.     movel    sp@+,d1
  510.     rts
  511. ");
  512. #endif
  513.  
  514. /* single * single */
  515. #if defined(L__mulsf3) || defined(ALL)
  516. ENTRY(__mulsf3)
  517. asm("
  518.     fmoves    sp@(4),fp0
  519.     fmuls    sp@(8),fp0
  520.     fmoves    fp0,d0
  521.     rts
  522. ");
  523. #endif
  524.  
  525. /* double - double */
  526. #if defined(L__subdf3) || defined(ALL)
  527. ENTRY(__subdf3)
  528. asm("
  529.     fmoved    sp@(4),fp0
  530.     fsubd    sp@(12),fp0
  531.     fmoved    fp0,sp@-
  532.     movel    sp@+,d0
  533.     movel    sp@+,d1
  534.     rts
  535. ");
  536. #endif
  537.  
  538. /* single - single */
  539. #if defined(L__subsf3) || defined(ALL)
  540. ENTRY(__subsf3)
  541. asm("
  542.     fmoves    sp@(4),fp0
  543.     fsubs    sp@(8),fp0
  544.     fmoves    fp0,d0
  545.     rts
  546. ");
  547. #endif
  548.  
  549. /* (float) double */
  550. #if defined(L__truncdfsf2) || defined(ALL)
  551. ENTRY(__truncdfsf2)
  552. asm("
  553.     fmoved    sp@(4),fp0
  554.     fmoves    fp0,d0
  555.     rts
  556. ");
  557. #endif
  558.  
  559. #else /* __HAVE_68881__ */
  560.  
  561. #if defined(L__adddf3) || defined(ALL)
  562. double __adddf3 (double a, double b)
  563. {
  564.   return IEEEDPAdd (a, b);
  565. }
  566. #endif
  567.  
  568. #if defined(L__addsf3) || defined(ALL)
  569. SFVALUE __addsf3 (FLOAT a, FLOAT b)
  570. {
  571.   return IEEESPAdd (a, b);
  572. }
  573. #endif
  574.  
  575. #if defined(L__cmpdf2) || defined(ALL)
  576. int __cmpdf2 (double a, double b)
  577. {
  578.   return ieeedpcmp (a, b);
  579. }
  580. #endif
  581.  
  582. #if defined(L__cmpsf2) || defined(ALL)
  583. int __cmpsf2 (FLOAT a, FLOAT b)
  584. {
  585.   return IEEESPCmp (a, b);
  586. }
  587. #endif
  588.  
  589. #if defined(L__divdf3) || defined(ALL)
  590. double __divdf3 (double a, double b)
  591. {
  592.   return IEEEDPDiv (a, b);
  593. }
  594. #endif
  595.  
  596. #if defined(L__divsf3) || defined(ALL)
  597. SFVALUE __divsf3 (FLOAT a, FLOAT b)
  598. {
  599.   return IEEESPDiv (a, b);
  600. }
  601. #endif
  602.  
  603. #if defined(L__extendsfdf2) || defined(ALL)
  604. double __extendsfdf2 (FLOAT a)
  605. {
  606.   return IEEEDPFieee(a);
  607. }
  608. #endif
  609.  
  610. #if defined(Lfabs) || defined(ALL)
  611. double fabs (double d)
  612. {
  613.   return d < 0.0 ? -d : d;
  614. }
  615. #endif
  616.  
  617. #if defined(L__fixdfsi) || defined(ALL)
  618. SItype __fixdfsi (double a)
  619. {
  620.   return IEEEDPFix (a);
  621. }
  622. #endif
  623.  
  624. #if defined(L__floatsidf) || defined(ALL)
  625. double __floatsidf (SItype a)
  626. {
  627.   return IEEEDPFlt (a);
  628. }
  629. #endif
  630.  
  631. #if defined(Lldexp) || defined(ALL)
  632. /*
  633.  * ldexp returns the quanity "value" * 2 ^ "exp"
  634.  *
  635.  * For the mc68000 using IEEE format the double precision word format is:
  636.  *
  637.  * WORD N   =>    SEEEEEEEEEEEMMMM
  638.  * WORD N+1 =>    MMMMMMMMMMMMMMMM
  639.  * WORD N+2 =>    MMMMMMMMMMMMMMMM
  640.  * WORD N+3 =>    MMMMMMMMMMMMMMMM
  641.  *
  642.  * Where:          S  =>   Sign bit
  643.  *                 E  =>   Exponent
  644.  *                 X  =>   Ignored (set to 0)
  645.  *                 M  =>   Mantissa bit
  646.  *
  647.  * NOTE:  Beware of 0.0; on some machines which use excess 128 notation for the
  648.  * exponent, if the mantissa is zero the exponent is also.
  649.  *
  650.  */
  651.  
  652. #define MANT_MASK 0x800FFFFF    /* Mantissa extraction mask     */
  653. #define ZPOS_MASK 0x3FF00000    /* Positive # mask for exp = 0  */
  654. #define ZNEG_MASK 0x3FF00000    /* Negative # mask for exp = 0  */
  655.  
  656. #define EXP_MASK 0x7FF00000    /* Mask for exponent            */
  657. #define EXP_SHIFTS 20        /* Shifts to get into LSB's     */
  658. #define EXP_BIAS 1023        /* Exponent bias                */
  659.  
  660. union dtol
  661. {
  662.   double dval;
  663.   int ival[2];
  664. };
  665.  
  666. double ldexp (double value, int exp)
  667. {
  668.   union dtol number;
  669.   int *iptr, cexp;
  670.  
  671.   if (value == 0.0)
  672.     return (0.0);
  673.   number.dval = value;
  674.   iptr = &number.ival[0];
  675.   cexp = (((*iptr) & EXP_MASK) >> EXP_SHIFTS) - EXP_BIAS;
  676.   *iptr &= ~EXP_MASK;
  677.   exp += EXP_BIAS;
  678.   *iptr |= ((exp + cexp) << EXP_SHIFTS) & EXP_MASK;
  679.   return (number.dval);
  680. }
  681. #endif
  682.  
  683. /*
  684.  * modf(value, iptr): return fractional part of value, and stores the
  685.  * integral part into iptr (a pointer to double).
  686.  */
  687.  
  688. #if defined(Lmodf) || defined(ALL)
  689. double modf (double value, double *iptr)
  690. {
  691.   /* if value negative */
  692.   if (IEEEDPTst (value) < 0)
  693.     {
  694.       /* in that case, the integer part is calculated by ceil() */
  695.       *iptr = IEEEDPCeil (value);
  696.       return IEEEDPSub (*iptr, value);
  697.     }
  698.   else
  699.     {
  700.       /* if positive, we go for the floor() */
  701.       *iptr = IEEEDPFloor (value);
  702.       return IEEEDPSub (value, *iptr);
  703.     }
  704. }
  705. #endif
  706.  
  707. #if defined(L__muldf3) || defined(ALL)
  708. double __muldf3 (double a, double b)
  709. {
  710.   return IEEEDPMul (a, b);
  711. }
  712. #endif
  713.  
  714. #if defined(L__mulsf3) || defined(ALL)
  715. SFVALUE __mulsf3 (FLOAT a, FLOAT b)
  716. {
  717.   return IEEESPMul (a, b);
  718. }
  719. #endif
  720.  
  721. #if defined(L__subdf3) || defined(ALL)
  722. double __subdf3 (double a, double b)
  723. {
  724.   return IEEEDPSub (a, b);
  725. }
  726. #endif
  727.  
  728. #if defined(L__subsf3) || defined(ALL)
  729. SFVALUE __subsf3 (FLOAT a, FLOAT b)
  730. {
  731.   return IEEESPSub (a, b);
  732. }
  733. #endif
  734.  
  735. #if defined(L__truncdfsf2) || defined(ALL)
  736. SFVALUE __truncdfsf2 (double a)
  737. {
  738.   return IEEEDPTieee(a);
  739. }
  740. #endif
  741.  
  742. #endif /* __HAVE_68881__ */
  743.