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

1.1       root        1:        .file   "reg_u_sub.S"
                      2: /*---------------------------------------------------------------------------+
                      3:  |  reg_u_sub.S                                                              |
                      4:  |                                                                           |
                      5:  | Core floating point subtraction routine.                                  |
                      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 reg_u_sub(reg *arg1, reg *arg2, reg *answ)                         |
                     12:  |                                                                           |
                     13:  +---------------------------------------------------------------------------*/
                     14: 
                     15: /*
                     16:  |    Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ).
                     17:  |    Takes two valid reg f.p. numbers (TW_Valid), which are
                     18:  |    treated as unsigned numbers,
                     19:  |    and returns their difference as a TW_Valid or TW_Zero f.p.
                     20:  |    number.
                     21:  |    The first number (arg1) must be the larger.
                     22:  |    The returned number is normalized.
                     23:  |    Basic checks are performed if PARANOID is defined.
                     24:  */
                     25: 
                     26: #include "exception.h"
                     27: #include "fpu_asm.h"
                     28: 
                     29: 
                     30: .text
                     31:        .align 2,144
                     32: .globl reg_u_sub
                     33: reg_u_sub:
                     34:        pushl   %ebp
                     35:        movl    %esp,%ebp
                     36:        pushl   %esi
                     37:        pushl   %edi
                     38:        pushl   %ebx
                     39: 
                     40:        movl    PARAM1,%esi     /* source 1 */
                     41:        movl    PARAM2,%edi     /* source 2 */
                     42: 
                     43: //     xorl    %ecx,%ecx
                     44:        movl    EXP(%esi),%ecx
                     45:        subl    EXP(%edi),%ecx  /* exp1 - exp2 */
                     46: 
                     47: #ifdef PARANOID
                     48:        /* source 2 is always smaller than source 1 */
                     49: //     jc      L_bugged
                     50:        js      L_bugged_1
                     51: 
                     52:        testl   $0x80000000,SIGH(%edi)  /* The args are assumed to be be normalized */
                     53:        je      L_bugged_2
                     54: 
                     55:        testl   $0x80000000,SIGH(%esi)
                     56:        je      L_bugged_2
                     57: #endif PARANOID
                     58: 
                     59: /*--------------------------------------+
                     60:  |     Form a register holding the     |
                     61:  |     smaller number                  |
                     62:  +--------------------------------------*/
                     63:        movl    SIGH(%edi),%eax // register ms word
                     64:        movl    SIGL(%edi),%ebx // register ls word
                     65: 
                     66:        movl    PARAM3,%edi     /* destination */
                     67:        movl    EXP(%esi),%edx
                     68:        movl    %edx,EXP(%edi)  /* Copy exponent to destination */
                     69: 
                     70:        xorl    %edx,%edx       // register extension
                     71: 
                     72: /*--------------------------------------+
                     73:  |     Shift the temporary register    |
                     74:  |      right the required number of   |
                     75:  |     places.                         |
                     76:  +--------------------------------------*/
                     77: L_shift_r:
                     78:        cmpl    $32,%ecx                /* shrd only works for 0..31 bits */
                     79:        jnc     L_more_than_31
                     80: 
                     81: /* less than 32 bits */
                     82:        shrd    %cl,%ebx,%edx
                     83:        shrd    %cl,%eax,%ebx
                     84:        shr     %cl,%eax
                     85:        jmp     L_shift_done
                     86: 
                     87: L_more_than_31:
                     88:        cmpl    $64,%ecx
                     89:        jnc     L_more_than_63
                     90: 
                     91:        subb    $32,%cl
                     92:        shrd    %cl,%eax,%edx
                     93:        movl    %eax,%ebx
                     94:        shr     %cl,%ebx
                     95:        xorl    %eax,%eax
                     96:        jmp     L_shift_done
                     97: 
                     98: L_more_than_63:
                     99:        cmpl    $66,%ecx
                    100:        jnc     L_more_than_65
                    101: 
                    102:        subb    $64,%cl
                    103:        movl    %eax,%edx
                    104:        shr     %cl,%edx
                    105:        xorl    %ebx,%ebx
                    106:        xorl    %eax,%eax
                    107:        jmp     L_shift_done
                    108: 
                    109: L_more_than_65:
                    110:        /* just copy the larger reg to dest */
                    111:        movw    SIGN(%esi),%ax
                    112:        movw    %ax,SIGN(%edi)
                    113:        movl    EXP(%esi),%eax
                    114:        movl    %eax,EXP(%edi)
                    115:        movl    SIGL(%esi),%eax
                    116:        movl    %eax,SIGL(%edi)
                    117:        movl    SIGH(%esi),%eax
                    118:        movl    %eax,SIGH(%edi)
                    119:        jmp     L_exit          // Does not underflow
                    120: 
                    121: L_shift_done:
                    122: L_subtr:
                    123: /*------------------------------+
                    124:  |     Do the subtraction      |
                    125:  +------------------------------*/
                    126:        xorl    %ecx,%ecx
                    127:        subl    %edx,%ecx
                    128:        movl    %ecx,%edx
                    129:        movl    SIGL(%esi),%ecx
                    130:        sbbl    %ebx,%ecx
                    131:        movl    %ecx,%ebx
                    132:        movl    SIGH(%esi),%ecx
                    133:        sbbl    %eax,%ecx
                    134:        movl    %ecx,%eax
                    135: 
                    136: #ifdef PARANOID
                    137:        /* We can never get a borrow */
                    138:        jc      L_bugged
                    139: #endif PARANOID
                    140: 
                    141: /*--------------------------------------+
                    142:  |     Normalize the result            |
                    143:  +--------------------------------------*/
                    144:        testl   $0x80000000,%eax
                    145:        jnz     L_round         /* no shifting needed */
                    146: 
                    147:        orl     %eax,%eax
                    148:        jnz     L_shift_1       /* shift left 1 - 31 bits */
                    149: 
                    150:        orl     %ebx,%ebx
                    151:        jnz     L_shift_32      /* shift left 32 - 63 bits */
                    152: 
                    153: //      A rare case, the only one which is non-zero if we got here
                    154: //         is:           1000000 .... 0000
                    155: //                      -0111111 .... 1111 1
                    156: //                       -------------------- 
                    157: //                       0000000 .... 0000 1 
                    158: 
                    159:        cmpl    $0x80000000,%edx
                    160:        jnz     L_must_be_zero
                    161: 
                    162:        /* Shift left 64 bits */
                    163:        subl    $64,EXP(%edi)
                    164:        movl    %edx,%eax
                    165:        jmp     L_store
                    166: 
                    167: L_must_be_zero:
                    168: #ifdef PARANOID
                    169:        orl     %edx,%edx
                    170:        jnz     L_bugged_3
                    171: #endif PARANOID
                    172: 
                    173:        /* The result is zero */
                    174:        movb    TW_Zero,TAG(%edi)
                    175:        movl    $0,EXP(%edi)            /* exponent */
                    176:        movl    $0,SIGL(%edi)
                    177:        movl    $0,SIGH(%edi)
                    178:        jmp     L_exit          // Does not underflow
                    179: 
                    180: L_shift_32:
                    181:        movl    %ebx,%eax
                    182:        movl    %edx,%ebx
                    183:        movl    $0,%edx
                    184:        subl    $32,EXP(%edi)   /* Can get underflow here */
                    185: 
                    186: /* We need to shift left by 1 - 31 bits */
                    187: L_shift_1:
                    188:        bsrl    %eax,%ecx       /* get the required shift in %ecx */
                    189:        subl    $31,%ecx
                    190:        negl    %ecx
                    191:        shld    %cl,%ebx,%eax
                    192:        shld    %cl,%edx,%ebx
                    193:        shl     %cl,%edx
                    194:        subl    %ecx,EXP(%edi)  /* Can get underflow here */
                    195: 
                    196: L_round:
                    197: /*------------------------------+
                    198:  |     Round the result        |
                    199:  +------------------------------*/
                    200:        cmpl    $0x80000000,%edx
                    201:        jc      L_store
                    202: 
                    203:        jne     L_round_up
                    204: 
                    205:        testb   $1,%dl
                    206:        jz      L_store
                    207: 
                    208: L_round_up:
                    209:        addl    $1,%ebx
                    210:        adcl    $0,%eax
                    211:        jnc     L_store
                    212: 
                    213:        /* We just rounded up to (1) 00 00 */
                    214:        /* This *is* possible, if the subtraction is of the
                    215:           form (1. + x) - (x + y) where x is small and y is
                    216:           very small. */
                    217:        incl    EXP(%edi)
                    218:        movl    $0x80000000,%eax
                    219: 
                    220: L_store:
                    221: /*------------------------------+
                    222:  |     Store the result        |
                    223:  +------------------------------*/
                    224:        movl    %eax,SIGH(%edi)
                    225:        movl    %ebx,SIGL(%edi)
                    226: 
                    227:        movb    TW_Valid,TAG(%edi)              /* Set the tags to TW_Valid */
                    228: 
                    229:        cmpl    EXP_UNDER,EXP(%edi)
                    230:        jle     L_underflow
                    231: 
                    232: L_exit:
                    233:        popl    %ebx
                    234:        popl    %edi
                    235:        popl    %esi
                    236:        leave
                    237:        ret
                    238: 
                    239: 
                    240: L_underflow:
                    241:        push    %edi
                    242:        call    arith_underflow
                    243:        pop     %ebx
                    244:        jmp     L_exit
                    245: 
                    246: 
                    247: #ifdef PARANOID
                    248: L_bugged_1:
                    249:        pushl   EX_INTERNAL|0x206
                    250:        call    EXCEPTION
                    251:        pop     %ebx
                    252:        jmp     L_exit
                    253: 
                    254: L_bugged_2:
                    255:        pushl   EX_INTERNAL|0x209
                    256:        call    EXCEPTION
                    257:        pop     %ebx
                    258:        jmp     L_exit
                    259: 
                    260: L_bugged_3:
                    261:        pushl   EX_INTERNAL|0x210
                    262:        call    EXCEPTION
                    263:        pop     %ebx
                    264:        jmp     L_exit
                    265: 
                    266: L_bugged_4:
                    267:        pushl   EX_INTERNAL|0x211
                    268:        call    EXCEPTION
                    269:        pop     %ebx
                    270:        jmp     L_exit
                    271: 
                    272: L_bugged:
                    273:        pushl   EX_INTERNAL|0x212
                    274:        call    EXCEPTION
                    275:        pop     %ebx
                    276:        jmp     L_exit
                    277: #endif PARANOID

unix.superglobalmegacorp.com

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