|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.