Annotation of coherent/b/kernel/emulator/reg_u_add.S, revision 1.1

1.1     ! root        1:        .file   "reg_u_add.S"
        !             2: /*---------------------------------------------------------------------------+
        !             3:  |  reg_u_add.S                                                              |
        !             4:  |                                                                           |
        !             5:  | Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the   |
        !             6:  |   result in a destination FPU_REG.                                        |
        !             7:  |                                                                           |
        !             8:  | Copyright (C) 1992    W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
        !             9:  |                       Australia.  E-mail [email protected]    |
        !            10:  |                                                                           |
        !            11:  | Call from C as:                                                           |
        !            12:  |   void reg_u_add(reg *arg1, reg *arg2, reg *answ)                         |
        !            13:  |                                                                           |
        !            14:  +---------------------------------------------------------------------------*/
        !            15: 
        !            16: /*
        !            17:  |    Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ).
        !            18:  |    Takes two valid reg f.p. numbers (TW_Valid), which are
        !            19:  |    treated as unsigned numbers,
        !            20:  |    and returns their sum as a TW_Valid or TW_S f.p. number.
        !            21:  |    The returned number is normalized.
        !            22:  |    Basic checks are performed if PARANOID is defined.
        !            23:  */
        !            24: 
        !            25: #include "exception.h"
        !            26: #include "fpu_asm.h"
        !            27: 
        !            28: .text
        !            29:        .align 2,144
        !            30: .globl reg_u_add
        !            31: reg_u_add:
        !            32:        pushl   %ebp
        !            33:        movl    %esp,%ebp
        !            34: //     subl    $16,%esp
        !            35:        pushl   %esi
        !            36:        pushl   %edi
        !            37:        pushl   %ebx
        !            38: 
        !            39:        movl    PARAM1,%esi             /* source 1 */
        !            40:        movl    PARAM2,%edi             /* source 2 */
        !            41: 
        !            42:        xorl    %ecx,%ecx
        !            43:        movl    EXP(%esi),%ecx
        !            44:        subl    EXP(%edi),%ecx          /* exp1 - exp2 */
        !            45: //     jnc     L_arg1_larger
        !            46:        jge     L_arg1_larger
        !            47: 
        !            48:        /* num1 is smaller */
        !            49:        movl    SIGL(%esi),%ebx
        !            50:        movl    SIGH(%esi),%eax
        !            51: 
        !            52:        movl    %edi,%esi
        !            53:        negw    %cx
        !            54:        jmp     L_accum_loaded
        !            55: 
        !            56: L_arg1_larger:
        !            57:        /* num1 has larger or equal exponent */
        !            58:        movl    SIGL(%edi),%ebx
        !            59:        movl    SIGH(%edi),%eax
        !            60: 
        !            61: L_accum_loaded:
        !            62:        movl    16(%ebp),%edi   /* destination */
        !            63: 
        !            64:        movl    EXP(%esi),%edx
        !            65:        movl    %edx,EXP(%edi)  /* Copy exponent to destination */
        !            66: 
        !            67:        xorl    %edx,%edx               /* clear the extension */
        !            68: 
        !            69: #ifdef PARANOID
        !            70:        testl   $0x80000000,%eax
        !            71:        je      L_bugged
        !            72: 
        !            73:        testl   $0x80000000,SIGH(%esi)
        !            74:        je      L_bugged
        !            75: #endif PARANOID
        !            76: 
        !            77:        cmpw    $32,%cx         /* shrd only works for 0..31 bits */
        !            78:        jnc     L_more_than_31
        !            79: 
        !            80: /* less than 32 bits */
        !            81:        shrd    %cl,%ebx,%edx
        !            82:        shrd    %cl,%eax,%ebx
        !            83:        shr     %cl,%eax
        !            84:        jmp     L_shift_done
        !            85: 
        !            86: L_more_than_31:
        !            87:        cmpw    $64,%cx
        !            88:        jnc     L_more_than_63
        !            89: 
        !            90:        subb    $32,%cl
        !            91:        shrd    %cl,%eax,%edx
        !            92:        shr     %cl,%eax
        !            93:        movl    %eax,%ebx
        !            94:        xorl    %eax,%eax
        !            95:        jmp     L_shift_done
        !            96: 
        !            97: L_more_than_63:
        !            98:        cmpw    $66,%cx
        !            99:        jnc     L_more_than_65
        !           100: 
        !           101:        subb    $64,%cl
        !           102:        movl    %eax,%edx
        !           103:        shr     %cl,%edx
        !           104:        xorl    %ebx,%ebx
        !           105:        xorl    %eax,%eax
        !           106:        jmp     L_shift_done
        !           107: 
        !           108: L_more_than_65:
        !           109:        /* just copy the larger reg to dest */
        !           110:        movw    SIGN(%esi),%ax
        !           111:        movw    %ax,SIGN(%edi)
        !           112:        movl    SIGL(%esi),%eax
        !           113:        movl    %eax,SIGL(%edi)
        !           114:        movl    SIGH(%esi),%eax
        !           115:        movl    %eax,SIGH(%edi)
        !           116:        jmp     L_exit          // Does not overflow
        !           117: 
        !           118: L_shift_done:
        !           119:        /* Now do the addition */
        !           120:        addl    SIGL(%esi),%ebx
        !           121:        adcl    SIGH(%esi),%eax
        !           122:        jnc     L_round_the_result
        !           123: 
        !           124:        /* Overflow, adjust the result */
        !           125:        rcrl    $1,%eax
        !           126:        rcrl    $1,%ebx
        !           127:        rcrl    $1,%edx
        !           128: 
        !           129:        incl    EXP(%edi)
        !           130:        
        !           131: L_round_the_result:
        !           132:        /* Round the result */
        !           133:        cmpl    $0x80000000,%edx
        !           134:        jc      L_no_round_up
        !           135: 
        !           136:        jne     L_do_round_up
        !           137: 
        !           138:        /* Now test for round-to-even */
        !           139:        test    $1,%ebx
        !           140:        jz      L_no_round_up
        !           141: 
        !           142: L_do_round_up:
        !           143:        addl    $1,%ebx
        !           144:        adcl    $0,%eax
        !           145:        jnc     L_no_round_up           /* Rounding done, no overflow */
        !           146: 
        !           147:        /* Overflow, adjust the result */
        !           148:        rcrl    $1,%eax
        !           149:        rcrl    $1,%ebx
        !           150:        incl    EXP(%edi)
        !           151: 
        !           152: L_no_round_up:
        !           153:        /* store the result */
        !           154:        movl    %eax,SIGH(%edi)
        !           155:        movl    %ebx,SIGL(%edi)
        !           156: 
        !           157:        movb    TW_Valid,TAG(%edi)              /* Set the tags to TW_Valid */
        !           158:        movb    SIGN(%esi),%al
        !           159:        movb    %al,SIGN(%edi)          /* Copy the sign from the first arg */
        !           160: 
        !           161:        // The number may have overflowed
        !           162:        cmpl    EXP_OVER,EXP(%edi)
        !           163:        jge     L_overflow
        !           164: 
        !           165: L_exit:
        !           166:        popl    %ebx
        !           167:        popl    %edi
        !           168:        popl    %esi
        !           169:        leave
        !           170:        ret
        !           171: 
        !           172: /* The addition resulted in a number too large to represent */
        !           173: L_overflow:
        !           174:        push    %edi
        !           175:        call    arith_overflow
        !           176:        pop     %ebx
        !           177:        jmp     L_exit
        !           178: 
        !           179: 
        !           180: #ifdef PARANOID
        !           181: /* If we ever get here then we have problems! */
        !           182: L_bugged:
        !           183:        pushl   EX_INTERNAL|0x201
        !           184:        call    EXCEPTION
        !           185:        pop     %ebx
        !           186:        jmp     L_exit
        !           187: #endif PARANOID

unix.superglobalmegacorp.com

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