Ignore:
Timestamp:
Aug 1, 2003, 8:42:12 AM (22 years ago)
Author:
zap
Message:

See ChangeLog.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/emx/include/386/builtin.h

    • Property cvs2svn:cvs-rev changed from 1.2 to 1.3
    r493 r494  
    8787}
    8888
     89/* Quick routines similar to div() and friends, but inline */
     90
     91static __inline__ long __ldivmod (long num, long den, long *rem)
     92{
     93  long q, r;
     94  __asm__ ("cltd; idivl %2"
     95           : "=a" (q), "=&d" (r)
     96           : "r?m" (den), "a" (num));
     97  *rem = r;
     98  return q;
     99}
     100
     101static __inline__ unsigned long __uldivmod (unsigned long num,
     102  unsigned long den, unsigned long *rem)
     103{
     104  unsigned long q, r;
     105  __asm__ ("xorl %%edx,%%edx; divl %2"
     106           : "=a" (q), "=&d" (r)
     107           : "r?m" (den), "a" (num));
     108  *rem = r;
     109  return q;
     110}
     111
     112/*
     113    Divide a 64-bit integer by a 32-bit one:
     114
     115    A*2^32 + B    A            B + (A mod 32)
     116    ---------- = --- * 2^32 + ----------------
     117        C         C                  C
     118*/
     119static __inline__ long long __lldivmod (long long num, long den, long *rem)
     120{
     121  long long q;
     122  long r;
     123  __asm__ ("    movl    %%eax,%%esi;"
     124           "    movl    %%edx,%%eax;"
     125           "    pushl   %%edx;"
     126           "    cltd;"
     127           "    idivl   %2;"
     128           "    ;"
     129/* Now ensure remainder is smallest of possible two values (negative and
     130   positive). For this we compare the remainder with positive and negative
     131   denominator/2; if it is smaller than one and bigger than another we
     132   consider it optimal, otherwise it can be made smaller by adding or
     133   subtracting denominator to it. This is done to ensure no overflow
     134   will occur at next division. */
     135           "    movl    %2,%%ecx;"
     136           "    sarl    $1,%%ecx;"      /* ecx = den/2 */
     137           "    cmpl    %%ecx,%%edx;"
     138           "    setl    %%bl;"
     139           "    negl    %%ecx;"
     140           "    cmpl    %%ecx,%%edx;"
     141           "    setl    %%bh;"
     142           "    xorb    %%bh,%%bl;"
     143           "    jnz     1f;"            /* Remainder is between -den/2...den/2 */
     144           "    ;"
     145/* If remainder has same sign as denominator, we have to do r -= den; q++;
     146   otherwise we have to do r += den; q--; */
     147           "    movl    %2,%%ebx;"      /* ebx = den */
     148           "    xorl    %%edx,%%ebx;"   /* r ^ den */
     149           "    js      0f;"            /* Different signs */
     150           "    subl    %2,%%edx;"      /* r -= den */
     151           "    addl    $1,%%eax;"      /* q++ */
     152           "    adcl    $0,%%edx;"
     153           "    jmp     1f;"
     154           "    ;"
     155           "0:  addl    %2,%%edx;"      /* r += den */
     156           "    subl    $1,%%eax;"      /* q-- */
     157           "    sbbl    $0,%%edx;"
     158           "    ;"
     159           "1:  xchgl   %%eax,%%esi;"
     160           "    idivl   %2;"
     161           "    ;"
     162           "    movl    %%edx,%1;"
     163           "    cltd;"
     164           "    addl    %%esi,%%edx;"
     165           "    ;"
     166/* Check if numerator has the same sign as remainder; if they have different
     167   sign we should make the remainder have same sign as numerator to comply
     168   with ANSI standard, which says we always should truncate the quotient
     169   towards zero. */
     170           "    popl    %%ebx;"         /* ebx = num >> 32 */
     171           "    xorl    %1,%%ebx;"      /* sign(r) ^ sign(num) */
     172           "    jns     3f;"            /* jump if same sign */
     173           "    ;"
     174/* If remainder has same sign as denominator, we have to do r -= den; q++;
     175   otherwise we have to do r += den; q--; */
     176           "    movl    %2,%%ebx;"
     177           "    xorl    %1,%%ebx;"      /* r ^ den */
     178           "    js      2f;"            /* Different signs */
     179           "    subl    %2,%1;"         /* r -= den */
     180           "    addl    $1,%%eax;"      /* q++ */
     181           "    adcl    $0,%%edx;"
     182           "    jmp     3f;"
     183           "    ;"
     184           "2:  addl    %2,%1;"         /* r += den */
     185           "    subl    $1,%%eax;"      /* q-- */
     186           "    sbbl    $0,%%edx;"
     187           "    ;"
     188           "3:  ;"
     189           : "=A" (q), "=&c" (r)
     190           : "r" (den), "A" (num)
     191           : "ebx", "esi");
     192  *rem = r;
     193  return q;
     194}
     195
     196/*
     197    Same as __lldivmod except that if A < C, we can do just one division
     198    instead of two because the result is always a 32-bit integer.
     199*/
     200static __inline__ unsigned long long __ulldivmod (unsigned long long num,
     201  unsigned long den, unsigned long *rem)
     202{
     203  unsigned long long q;
     204  unsigned long r;
     205  __asm__ ("    movl    %%eax,%1;"
     206           "    movl    %%edx,%%eax;"
     207           "    xorl    %%edx,%%edx;"
     208           "    divl    %2;"
     209           "    xchgl   %%eax,%%ecx;"
     210           "    divl    %2;"
     211           "    xchgl   %%edx,%1;"
     212           : "=A" (q), "=c" (r)
     213           : "r?m" (den), "A" (num));
     214  *rem = r;
     215  return q;
     216}
     217
    89218#if defined (__cplusplus)
    90219}
Note: See TracChangeset for help on using the changeset viewer.