Annotation of coherent/b/kernel/emulator/wm_sqrt.S, revision 1.1.1.1

1.1       root        1:        .file   "wm_sqrt.S"
                      2: /*---------------------------------------------------------------------------+
                      3:  |  wm_sqrt.S                                                                |
                      4:  |                                                                           |
                      5:  | Fixed point arithmetic square root evaluation.                            |
                      6:  |                                                                           |
                      7:  | Copyright (C) 1992    W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
                      8:  |                       Australia.  E-mail [email protected]    |
                      9:  |                                                                           |
                     10:  | Call from C as:                                                           |
                     11:  |   void wm_sqrt(FPU_REG *n)                                                |
                     12:  |                                                                           |
                     13:  +---------------------------------------------------------------------------*/
                     14: 
                     15: /*---------------------------------------------------------------------------+
                     16:  |  wm_sqrt(FPU_REG *n)                                                      |
                     17:  |    returns the square root of n in n.                                     |
                     18:  |                                                                           |
                     19:  |  Use Newton's method to compute the square root of a number, which must   |
                     20:  |  be in the range  [1.0 .. 4.0),  to 64 bits accuracy.                     |
                     21:  |  Does not check the sign or tag of the argument.                          |
                     22:  |  Sets the exponent, but not the sign or tag of the result.                |
                     23:  |                                                                           |
                     24:  |  The guess is kept in %esi:%edi                                           |
                     25:  +---------------------------------------------------------------------------*/
                     26: 
                     27: #include "exception.h"
                     28: #include "fpu_asm.h"
                     29: 
                     30: 
                     31: .data
                     32: /*
                     33:        Local storage:
                     34:  */
                     35:        .align 4,0
                     36: accum_2:
                     37:        .long   0               // ms word
                     38: accum_1:
                     39:        .long   0
                     40: accum_0:
                     41:        .long   0
                     42: 
                     43: sq_2:
                     44:        .long   0               // ms word
                     45: sq_1:
                     46:        .long   0
                     47: sq_0:
                     48:        .long   0
                     49: 
                     50: .text
                     51:        .align 2,144
                     52: 
                     53: .globl wm_sqrt
                     54: 
                     55: wm_sqrt:
                     56:        pushl   %ebp
                     57:        movl    %esp,%ebp
                     58:        pushl   %esi
                     59:        pushl   %edi
                     60: //     pushl   %ebx
                     61: 
                     62:        movl    PARAM1,%esi
                     63: 
                     64:        movl    SIGH(%esi),%eax
                     65:        movl    SIGL(%esi),%ecx
                     66:        xorl    %edx,%edx
                     67: 
                     68: // We use a rough linear estimate for the first guess..
                     69: 
                     70:        cmpl    EXP_BIAS,EXP(%esi)
                     71:        jnz     L10
                     72: 
                     73:        shrl    $1,%eax                 /* arg is in the range  [1.0 .. 2.0) */
                     74:        rcrl    $1,%ecx
                     75:        rcrl    $1,%edx
                     76: 
                     77: L10:
                     78: // From here on, n is never accessed directly again until it is
                     79: // replaced by the answer.
                     80: 
                     81:        movl    %eax,sq_2               // ms word of n
                     82:        movl    %ecx,sq_1
                     83:        movl    %edx,sq_0
                     84: 
                     85:        shrl    $1,%eax
                     86:        addl    $0x40000000,%eax
                     87:        movl    $0xaaaaaaaa,%ecx
                     88:        mull    %ecx
                     89:        shll    $1,%edx                 /* max result was 7fff... */
                     90:        testl   $0x80000000,%edx        /* but min was 3fff... */
                     91:        jnz     no_adjust
                     92: 
                     93:        movl    $0x80000000,%edx        /* round up */
                     94: 
                     95: no_adjust:
                     96:        movl    %edx,%esi       // Our first guess
                     97: 
                     98: /* We have now computed (approx)   (2 + x) / 3, which forms the basis
                     99:    for a few iterations of Newton's method */
                    100: 
                    101:        movl    sq_2,%ecx       // ms word
                    102: 
                    103: // From our initial estimate, three iterations are enough to get us
                    104: // to 30 bits or so. This will then allow two iterations at better
                    105: // precision to complete the process.
                    106: 
                    107: // Compute  (g + n/g)/2  at each iteration (g is the guess).
                    108:        shrl    $1,%ecx         // Doing this first will prevent a divide
                    109:                                // overflow later.
                    110: 
                    111:        movl    %ecx,%edx
                    112:        divl    %esi
                    113:        shrl    $1,%esi
                    114:        addl    %eax,%esi
                    115: 
                    116:        movl    %ecx,%edx
                    117:        divl    %esi
                    118:        shrl    $1,%esi
                    119:        addl    %eax,%esi
                    120: 
                    121:        movl    %ecx,%edx
                    122:        divl    %esi
                    123:        shrl    $1,%esi
                    124:        addl    %eax,%esi
                    125: 
                    126: // Now that an estimate accurate to about 30 bits has been obtained,
                    127: // we improve it to 60 bits or so.
                    128: 
                    129: // The strategy from now on is to compute new estimates from
                    130: //      guess := guess + (n - guess^2) / (2 * guess)
                    131: 
                    132: // First, find the square of the guess
                    133:        movl    %esi,%eax
                    134:        mull    %esi
                    135: // guess^2 now in %edx:%eax
                    136: 
                    137:        movl    sq_1,%ecx
                    138:        subl    %ecx,%eax
                    139:        movl    sq_2,%ecx       // ms word of normalized n
                    140:        sbbl    %ecx,%edx
                    141:        jnc     l40
                    142: 
                    143: // subtraction gives a negative result
                    144: // negate the reult before division
                    145:        notl    %edx
                    146:        notl    %eax
                    147:        addl    $1,%eax
                    148:        adcl    $0,%edx
                    149: 
                    150:        divl    %esi
                    151:        movl    %eax,%ecx
                    152: 
                    153:        movl    %edx,%eax
                    154:        divl    %esi
                    155:        jmp     l45
                    156: 
                    157: l40:
                    158:        divl    %esi
                    159:        movl    %eax,%ecx
                    160: 
                    161:        movl    %edx,%eax
                    162:        divl    %esi
                    163: 
                    164:        notl    %ecx
                    165:        notl    %eax
                    166:        addl    $1,%eax
                    167:        adcl    $0,%ecx
                    168: 
                    169: l45:
                    170:        sarl    $1,%ecx         // divide by 2
                    171:        rcrl    $1,%eax
                    172: 
                    173:        movl    %eax,%edi
                    174:        addl    %ecx,%esi
                    175: 
                    176: // Now the square root has been computed to better than 60 bits
                    177: 
                    178: // Find the square of the guess
                    179:        movl    %edi,%eax               // ls word of guess
                    180:        mull    %edi
                    181:        movl    %edx,accum_0
                    182: 
                    183:        movl    %esi,%eax
                    184:        mull    %esi
                    185:        movl    %edx,accum_2
                    186:        movl    %eax,accum_1
                    187: 
                    188:        movl    %edi,%eax
                    189:        mull    %esi
                    190:        addl    %eax,accum_0
                    191:        adcl    %edx,accum_1
                    192:        adcl    $0,accum_2
                    193: 
                    194:        movl    %esi,%eax
                    195:        mull    %edi
                    196:        addl    %eax,accum_0
                    197:        adcl    %edx,accum_1
                    198:        adcl    $0,accum_2
                    199: 
                    200: // guess^2 now in accum_2:accum_1:accum_0
                    201: 
                    202:        movl    sq_1,%eax               // get normalized n
                    203:        subl    %eax,accum_1
                    204:        movl    sq_2,%eax               // ms word of normalized n
                    205:        sbbl    %eax,accum_2
                    206:        jnc     l60
                    207: 
                    208: // subtraction gives a negative result
                    209: // negate the reult before division
                    210:        notl    accum_0
                    211:        notl    accum_1
                    212:        notl    accum_2
                    213:        addl    $1,accum_0
                    214:        adcl    $0,accum_1
                    215: 
                    216: #ifdef PARANOID
                    217:        adcl    $0,accum_2      // This must be zero
                    218:        jz      l51
                    219: 
                    220:        pushl   EX_INTERNAL|0x207
                    221:        call    EXCEPTION
                    222: 
                    223: l51:
                    224: #endif PARANOID
                    225: 
                    226:        movl    accum_1,%edx
                    227:        movl    accum_0,%eax
                    228:        divl    %esi
                    229:        movl    %eax,%ecx
                    230: 
                    231:        movl    %edx,%eax
                    232:        divl    %esi
                    233: 
                    234:        sarl    $1,%ecx         // divide by 2
                    235:        rcrl    $1,%eax
                    236: 
                    237:        // round the result
                    238:        addl    $0x80000000,%eax
                    239:        adcl    $0,%ecx
                    240: 
                    241:        addl    %ecx,%edi
                    242:        adcl    $0,%esi
                    243: 
                    244:        jmp     l65
                    245: 
                    246: l60:
                    247:        movl    accum_1,%edx
                    248:        movl    accum_0,%eax
                    249:        divl    %esi
                    250:        movl    %eax,%ecx
                    251: 
                    252:        movl    %edx,%eax
                    253:        divl    %esi
                    254: 
                    255:        sarl    $1,%ecx         // divide by 2
                    256:        rcrl    $1,%eax
                    257: 
                    258:        // round the result
                    259:        addl    $0x80000000,%eax
                    260:        adcl    $0,%ecx
                    261: 
                    262:        subl    %ecx,%edi
                    263:        sbbl    $0,%esi
                    264: 
                    265: l65:
                    266:        movl    PARAM1,%ecx
                    267: 
                    268:        movl    %edi,SIGL(%ecx)
                    269:        movl    %esi,SIGH(%ecx)
                    270: 
                    271:        movl    EXP_BIAS,EXP(%ecx)      /* Result is in  [1.0 .. 2.0) */
                    272: 
                    273: //     popl    %ebx
                    274:        popl    %edi
                    275:        popl    %esi
                    276:        leave
                    277:        ret

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.