.file "reg_u_add.S"1/*---------------------------------------------------------------------------+2| reg_u_add.S |3| |4| Add two valid (TAG_Valid) FPU_REG numbers, of the same sign, and put the |5| result in a destination FPU_REG. |6| |7| Copyright (C) 1992,1993,1995,1997 |8| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |9| E-mail [email protected] |10| |11| Call from C as: |12| int FPU_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, |13| int control_w) |14| Return value is the tag of the answer, or-ed with FPU_Exception if |15| one was raised, or -1 on internal error. |16| |17+---------------------------------------------------------------------------*/1819/*20| Kernel addition routine FPU_u_add(reg *arg1, reg *arg2, reg *answ).21| Takes two valid reg f.p. numbers (TAG_Valid), which are22| treated as unsigned numbers,23| and returns their sum as a TAG_Valid or TAG_Special f.p. number.24| The returned number is normalized.25| Basic checks are performed if PARANOID is defined.26*/2728#include "exception.h"29#include "fpu_emu.h"30#include "control_w.h"3132.text33ENTRY(FPU_u_add)34pushl %ebp35movl %esp,%ebp36pushl %esi37pushl %edi38pushl %ebx3940movl PARAM1,%esi /* source 1 */41movl PARAM2,%edi /* source 2 */4243movl PARAM6,%ecx44movl %ecx,%edx45subl PARAM7,%ecx /* exp1 - exp2 */46jge L_arg1_larger4748/* num1 is smaller */49movl SIGL(%esi),%ebx50movl SIGH(%esi),%eax5152movl %edi,%esi53movl PARAM7,%edx54negw %cx55jmp L_accum_loaded5657L_arg1_larger:58/* num1 has larger or equal exponent */59movl SIGL(%edi),%ebx60movl SIGH(%edi),%eax6162L_accum_loaded:63movl PARAM3,%edi /* destination */64movw %dx,EXP(%edi) /* Copy exponent to destination */6566xorl %edx,%edx /* clear the extension */6768#ifdef PARANOID69testl $0x80000000,%eax70je L_bugged7172testl $0x80000000,SIGH(%esi)73je L_bugged74#endif /* PARANOID */7576/* The number to be shifted is in %eax:%ebx:%edx */77cmpw $32,%cx /* shrd only works for 0..31 bits */78jnc L_more_than_317980/* less than 32 bits */81shrd %cl,%ebx,%edx82shrd %cl,%eax,%ebx83shr %cl,%eax84jmp L_shift_done8586L_more_than_31:87cmpw $64,%cx88jnc L_more_than_638990subb $32,%cl91jz L_exactly_329293shrd %cl,%eax,%edx94shr %cl,%eax95orl %ebx,%ebx96jz L_more_31_no_low /* none of the lowest bits is set */9798orl $1,%edx /* record the fact in the extension */99100L_more_31_no_low:101movl %eax,%ebx102xorl %eax,%eax103jmp L_shift_done104105L_exactly_32:106movl %ebx,%edx107movl %eax,%ebx108xorl %eax,%eax109jmp L_shift_done110111L_more_than_63:112cmpw $65,%cx113jnc L_more_than_64114115movl %eax,%edx116orl %ebx,%ebx117jz L_more_63_no_low118119orl $1,%edx120jmp L_more_63_no_low121122L_more_than_64:123movl $1,%edx /* The shifted nr always at least one '1' */124125L_more_63_no_low:126xorl %ebx,%ebx127xorl %eax,%eax128129L_shift_done:130/* Now do the addition */131addl SIGL(%esi),%ebx132adcl SIGH(%esi),%eax133jnc L_round_the_result134135/* Overflow, adjust the result */136rcrl $1,%eax137rcrl $1,%ebx138rcrl $1,%edx139jnc L_no_bit_lost140141orl $1,%edx142143L_no_bit_lost:144incw EXP(%edi)145146L_round_the_result:147jmp fpu_reg_round /* Round the result */148149150151#ifdef PARANOID152/* If we ever get here then we have problems! */153L_bugged:154pushl EX_INTERNAL|0x201155call EXCEPTION156pop %ebx157movl $-1,%eax158jmp L_exit159160L_exit:161popl %ebx162popl %edi163popl %esi164leave165ret166#endif /* PARANOID */167168169