/* SPDX-License-Identifier: GPL-2.0 */1.file "reg_u_add.S"2/*---------------------------------------------------------------------------+3| reg_u_add.S |4| |5| Add two valid (TAG_Valid) FPU_REG numbers, of the same sign, and put the |6| result in a destination FPU_REG. |7| |8| Copyright (C) 1992,1993,1995,1997 |9| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |10| E-mail [email protected] |11| |12| Call from C as: |13| int FPU_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, |14| int control_w) |15| Return value is the tag of the answer, or-ed with FPU_Exception if |16| one was raised, or -1 on internal error. |17| |18+---------------------------------------------------------------------------*/1920/*21| Kernel addition routine FPU_u_add(reg *arg1, reg *arg2, reg *answ).22| Takes two valid reg f.p. numbers (TAG_Valid), which are23| treated as unsigned numbers,24| and returns their sum as a TAG_Valid or TAG_Special f.p. number.25| The returned number is normalized.26| Basic checks are performed if PARANOID is defined.27*/2829#include "exception.h"30#include "fpu_emu.h"31#include "control_w.h"3233.text34SYM_FUNC_START(FPU_u_add)35pushl %ebp36movl %esp,%ebp37pushl %esi38pushl %edi39pushl %ebx4041movl PARAM1,%esi /* source 1 */42movl PARAM2,%edi /* source 2 */4344movl PARAM6,%ecx45movl %ecx,%edx46subl PARAM7,%ecx /* exp1 - exp2 */47jge L_arg1_larger4849/* num1 is smaller */50movl SIGL(%esi),%ebx51movl SIGH(%esi),%eax5253movl %edi,%esi54movl PARAM7,%edx55negw %cx56jmp L_accum_loaded5758L_arg1_larger:59/* num1 has larger or equal exponent */60movl SIGL(%edi),%ebx61movl SIGH(%edi),%eax6263L_accum_loaded:64movl PARAM3,%edi /* destination */65movw %dx,EXP(%edi) /* Copy exponent to destination */6667xorl %edx,%edx /* clear the extension */6869#ifdef PARANOID70testl $0x80000000,%eax71je L_bugged7273testl $0x80000000,SIGH(%esi)74je L_bugged75#endif /* PARANOID */7677/* The number to be shifted is in %eax:%ebx:%edx */78cmpw $32,%cx /* shrd only works for 0..31 bits */79jnc L_more_than_318081/* less than 32 bits */82shrd %cl,%ebx,%edx83shrd %cl,%eax,%ebx84shr %cl,%eax85jmp L_shift_done8687L_more_than_31:88cmpw $64,%cx89jnc L_more_than_639091subb $32,%cl92jz L_exactly_329394shrd %cl,%eax,%edx95shr %cl,%eax96orl %ebx,%ebx97jz L_more_31_no_low /* none of the lowest bits is set */9899orl $1,%edx /* record the fact in the extension */100101L_more_31_no_low:102movl %eax,%ebx103xorl %eax,%eax104jmp L_shift_done105106L_exactly_32:107movl %ebx,%edx108movl %eax,%ebx109xorl %eax,%eax110jmp L_shift_done111112L_more_than_63:113cmpw $65,%cx114jnc L_more_than_64115116movl %eax,%edx117orl %ebx,%ebx118jz L_more_63_no_low119120orl $1,%edx121jmp L_more_63_no_low122123L_more_than_64:124movl $1,%edx /* The shifted nr always at least one '1' */125126L_more_63_no_low:127xorl %ebx,%ebx128xorl %eax,%eax129130L_shift_done:131/* Now do the addition */132addl SIGL(%esi),%ebx133adcl SIGH(%esi),%eax134jnc L_round_the_result135136/* Overflow, adjust the result */137rcrl $1,%eax138rcrl $1,%ebx139rcrl $1,%edx140jnc L_no_bit_lost141142orl $1,%edx143144L_no_bit_lost:145incw EXP(%edi)146147L_round_the_result:148jmp fpu_reg_round /* Round the result */149150151152#ifdef PARANOID153/* If we ever get here then we have problems! */154L_bugged:155pushl EX_INTERNAL|0x201156call EXCEPTION157pop %ebx158movl $-1,%eax159jmp L_exit160161L_exit:162popl %ebx163popl %edi164popl %esi165leave166RET167#endif /* PARANOID */168SYM_FUNC_END(FPU_u_add)169170171