Annotation of coherent/b/kernel/emulator/reg_u_sub.S, revision 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.