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