18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Floating-point emulation code 68c2ecf20Sopenharmony_ci * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * BEGIN_DESC 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * File: 128c2ecf20Sopenharmony_ci * @(#) pa/spmath/fmpyfadd.c $Revision: 1.1 $ 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Purpose: 158c2ecf20Sopenharmony_ci * Double Floating-point Multiply Fused Add 168c2ecf20Sopenharmony_ci * Double Floating-point Multiply Negate Fused Add 178c2ecf20Sopenharmony_ci * Single Floating-point Multiply Fused Add 188c2ecf20Sopenharmony_ci * Single Floating-point Multiply Negate Fused Add 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * External Interfaces: 218c2ecf20Sopenharmony_ci * dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) 228c2ecf20Sopenharmony_ci * dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) 238c2ecf20Sopenharmony_ci * sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) 248c2ecf20Sopenharmony_ci * sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * Internal Interfaces: 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * Theory: 298c2ecf20Sopenharmony_ci * <<please update with a overview of the operation of this file>> 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * END_DESC 328c2ecf20Sopenharmony_ci*/ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include "float.h" 368c2ecf20Sopenharmony_ci#include "sgl_float.h" 378c2ecf20Sopenharmony_ci#include "dbl_float.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * Double Floating-point Multiply Fused Add 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ciint 458c2ecf20Sopenharmony_cidbl_fmpyfadd( 468c2ecf20Sopenharmony_ci dbl_floating_point *src1ptr, 478c2ecf20Sopenharmony_ci dbl_floating_point *src2ptr, 488c2ecf20Sopenharmony_ci dbl_floating_point *src3ptr, 498c2ecf20Sopenharmony_ci unsigned int *status, 508c2ecf20Sopenharmony_ci dbl_floating_point *dstptr) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; 538c2ecf20Sopenharmony_ci register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; 548c2ecf20Sopenharmony_ci unsigned int rightp1, rightp2, rightp3, rightp4; 558c2ecf20Sopenharmony_ci unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; 568c2ecf20Sopenharmony_ci register int mpy_exponent, add_exponent, count; 578c2ecf20Sopenharmony_ci boolean inexact = FALSE, is_tiny = FALSE; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci unsigned int signlessleft1, signlessright1, save; 608c2ecf20Sopenharmony_ci register int result_exponent, diff_exponent; 618c2ecf20Sopenharmony_ci int sign_save, jumpsize; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); 648c2ecf20Sopenharmony_ci Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); 658c2ecf20Sopenharmony_ci Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* 688c2ecf20Sopenharmony_ci * set sign bit of result of multiply 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ci if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 718c2ecf20Sopenharmony_ci Dbl_setnegativezerop1(resultp1); 728c2ecf20Sopenharmony_ci else Dbl_setzerop1(resultp1); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* 758c2ecf20Sopenharmony_ci * Generate multiply exponent 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* 808c2ecf20Sopenharmony_ci * check first operand for NaN's or infinity 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci if (Dbl_isinfinity_exponent(opnd1p1)) { 838c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { 848c2ecf20Sopenharmony_ci if (Dbl_isnotnan(opnd2p1,opnd2p2) && 858c2ecf20Sopenharmony_ci Dbl_isnotnan(opnd3p1,opnd3p2)) { 868c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { 878c2ecf20Sopenharmony_ci /* 888c2ecf20Sopenharmony_ci * invalid since operands are infinity 898c2ecf20Sopenharmony_ci * and zero 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 928c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 938c2ecf20Sopenharmony_ci Set_invalidflag(); 948c2ecf20Sopenharmony_ci Dbl_makequietnan(resultp1,resultp2); 958c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 968c2ecf20Sopenharmony_ci return(NOEXCEPTION); 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci /* 998c2ecf20Sopenharmony_ci * Check third operand for infinity with a 1008c2ecf20Sopenharmony_ci * sign opposite of the multiply result 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_ci if (Dbl_isinfinity(opnd3p1,opnd3p2) && 1038c2ecf20Sopenharmony_ci (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { 1048c2ecf20Sopenharmony_ci /* 1058c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 1068c2ecf20Sopenharmony_ci * subtraction of infinities 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 1098c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 1108c2ecf20Sopenharmony_ci Set_invalidflag(); 1118c2ecf20Sopenharmony_ci Dbl_makequietnan(resultp1,resultp2); 1128c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 1138c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* 1178c2ecf20Sopenharmony_ci * return infinity 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 1208c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 1218c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci else { 1258c2ecf20Sopenharmony_ci /* 1268c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(opnd1p1)) { 1298c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 1308c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 1318c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 1328c2ecf20Sopenharmony_ci /* make NaN quiet */ 1338c2ecf20Sopenharmony_ci Set_invalidflag(); 1348c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd1p1); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci /* 1378c2ecf20Sopenharmony_ci * is second operand a signaling NaN? 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci else if (Dbl_is_signalingnan(opnd2p1)) { 1408c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 1418c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 1428c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 1438c2ecf20Sopenharmony_ci /* make NaN quiet */ 1448c2ecf20Sopenharmony_ci Set_invalidflag(); 1458c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd2p1); 1468c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 1478c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci /* 1508c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_ci else if (Dbl_is_signalingnan(opnd3p1)) { 1538c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 1548c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 1558c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 1568c2ecf20Sopenharmony_ci /* make NaN quiet */ 1578c2ecf20Sopenharmony_ci Set_invalidflag(); 1588c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd3p1); 1598c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 1608c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci /* 1638c2ecf20Sopenharmony_ci * return quiet NaN 1648c2ecf20Sopenharmony_ci */ 1658c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); 1668c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* 1718c2ecf20Sopenharmony_ci * check second operand for NaN's or infinity 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci if (Dbl_isinfinity_exponent(opnd2p1)) { 1748c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { 1758c2ecf20Sopenharmony_ci if (Dbl_isnotnan(opnd3p1,opnd3p2)) { 1768c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { 1778c2ecf20Sopenharmony_ci /* 1788c2ecf20Sopenharmony_ci * invalid since multiply operands are 1798c2ecf20Sopenharmony_ci * zero & infinity 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 1828c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 1838c2ecf20Sopenharmony_ci Set_invalidflag(); 1848c2ecf20Sopenharmony_ci Dbl_makequietnan(opnd2p1,opnd2p2); 1858c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 1868c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* 1908c2ecf20Sopenharmony_ci * Check third operand for infinity with a 1918c2ecf20Sopenharmony_ci * sign opposite of the multiply result 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_ci if (Dbl_isinfinity(opnd3p1,opnd3p2) && 1948c2ecf20Sopenharmony_ci (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { 1958c2ecf20Sopenharmony_ci /* 1968c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 1978c2ecf20Sopenharmony_ci * subtraction of infinities 1988c2ecf20Sopenharmony_ci */ 1998c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 2008c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 2018c2ecf20Sopenharmony_ci Set_invalidflag(); 2028c2ecf20Sopenharmony_ci Dbl_makequietnan(resultp1,resultp2); 2038c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 2048c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* 2088c2ecf20Sopenharmony_ci * return infinity 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_ci Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 2118c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 2128c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci else { 2168c2ecf20Sopenharmony_ci /* 2178c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(opnd2p1)) { 2208c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 2218c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 2228c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 2238c2ecf20Sopenharmony_ci /* make NaN quiet */ 2248c2ecf20Sopenharmony_ci Set_invalidflag(); 2258c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd2p1); 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci /* 2288c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_ci else if (Dbl_is_signalingnan(opnd3p1)) { 2318c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 2328c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 2338c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 2348c2ecf20Sopenharmony_ci /* make NaN quiet */ 2358c2ecf20Sopenharmony_ci Set_invalidflag(); 2368c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd3p1); 2378c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 2388c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci /* 2418c2ecf20Sopenharmony_ci * return quiet NaN 2428c2ecf20Sopenharmony_ci */ 2438c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 2448c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* 2498c2ecf20Sopenharmony_ci * check third operand for NaN's or infinity 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_ci if (Dbl_isinfinity_exponent(opnd3p1)) { 2528c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { 2538c2ecf20Sopenharmony_ci /* return infinity */ 2548c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 2558c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2568c2ecf20Sopenharmony_ci } else { 2578c2ecf20Sopenharmony_ci /* 2588c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(opnd3p1)) { 2618c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 2628c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 2638c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 2648c2ecf20Sopenharmony_ci /* make NaN quiet */ 2658c2ecf20Sopenharmony_ci Set_invalidflag(); 2668c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd3p1); 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci /* 2698c2ecf20Sopenharmony_ci * return quiet NaN 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 2728c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* 2778c2ecf20Sopenharmony_ci * Generate multiply mantissa 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci if (Dbl_isnotzero_exponent(opnd1p1)) { 2808c2ecf20Sopenharmony_ci /* set hidden bit */ 2818c2ecf20Sopenharmony_ci Dbl_clear_signexponent_set_hidden(opnd1p1); 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci else { 2848c2ecf20Sopenharmony_ci /* check for zero */ 2858c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { 2868c2ecf20Sopenharmony_ci /* 2878c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { 2908c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 2918c2ecf20Sopenharmony_ci Dbl_or_signs(opnd3p1,resultp1); 2928c2ecf20Sopenharmony_ci } else { 2938c2ecf20Sopenharmony_ci Dbl_and_signs(opnd3p1,resultp1); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci /* 2978c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_ci else if (Dbl_iszero_exponent(opnd3p1) && 3008c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 3018c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 3028c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(opnd3p1); 3038c2ecf20Sopenharmony_ci result_exponent = 0; 3048c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd3p1,opnd3p2); 3058c2ecf20Sopenharmony_ci Dbl_normalize(opnd3p1,opnd3p2,result_exponent); 3068c2ecf20Sopenharmony_ci Dbl_set_sign(opnd3p1,/*using*/sign_save); 3078c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(opnd3p1,result_exponent, 3088c2ecf20Sopenharmony_ci unfl); 3098c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 3108c2ecf20Sopenharmony_ci /* inexact = FALSE */ 3118c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 3148c2ecf20Sopenharmony_ci return(NOEXCEPTION); 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci /* is denormalized, adjust exponent */ 3178c2ecf20Sopenharmony_ci Dbl_clear_signexponent(opnd1p1); 3188c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd1p1,opnd1p2); 3198c2ecf20Sopenharmony_ci Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci /* opnd2 needs to have hidden bit set with msb in hidden bit */ 3228c2ecf20Sopenharmony_ci if (Dbl_isnotzero_exponent(opnd2p1)) { 3238c2ecf20Sopenharmony_ci Dbl_clear_signexponent_set_hidden(opnd2p1); 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci else { 3268c2ecf20Sopenharmony_ci /* check for zero */ 3278c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { 3288c2ecf20Sopenharmony_ci /* 3298c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 3308c2ecf20Sopenharmony_ci */ 3318c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { 3328c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 3338c2ecf20Sopenharmony_ci Dbl_or_signs(opnd3p1,resultp1); 3348c2ecf20Sopenharmony_ci } else { 3358c2ecf20Sopenharmony_ci Dbl_and_signs(opnd3p1,resultp1); 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci /* 3398c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 3408c2ecf20Sopenharmony_ci */ 3418c2ecf20Sopenharmony_ci else if (Dbl_iszero_exponent(opnd3p1) && 3428c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 3438c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 3448c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(opnd3p1); 3458c2ecf20Sopenharmony_ci result_exponent = 0; 3468c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd3p1,opnd3p2); 3478c2ecf20Sopenharmony_ci Dbl_normalize(opnd3p1,opnd3p2,result_exponent); 3488c2ecf20Sopenharmony_ci Dbl_set_sign(opnd3p1,/*using*/sign_save); 3498c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(opnd3p1,result_exponent, 3508c2ecf20Sopenharmony_ci unfl); 3518c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 3528c2ecf20Sopenharmony_ci /* inexact = FALSE */ 3538c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 3568c2ecf20Sopenharmony_ci return(NOEXCEPTION); 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci /* is denormalized; want to normalize */ 3598c2ecf20Sopenharmony_ci Dbl_clear_signexponent(opnd2p1); 3608c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd2p1,opnd2p2); 3618c2ecf20Sopenharmony_ci Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* Multiply the first two source mantissas together */ 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /* 3678c2ecf20Sopenharmony_ci * The intermediate result will be kept in tmpres, 3688c2ecf20Sopenharmony_ci * which needs enough room for 106 bits of mantissa, 3698c2ecf20Sopenharmony_ci * so lets call it a Double extended. 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_ci Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* 3748c2ecf20Sopenharmony_ci * Four bits at a time are inspected in each loop, and a 3758c2ecf20Sopenharmony_ci * simple shift and add multiply algorithm is used. 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_ci for (count = DBL_P-1; count >= 0; count -= 4) { 3788c2ecf20Sopenharmony_ci Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); 3798c2ecf20Sopenharmony_ci if (Dbit28p2(opnd1p2)) { 3808c2ecf20Sopenharmony_ci /* Fourword_add should be an ADD followed by 3 ADDC's */ 3818c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 3828c2ecf20Sopenharmony_ci opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci if (Dbit29p2(opnd1p2)) { 3858c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 3868c2ecf20Sopenharmony_ci opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci if (Dbit30p2(opnd1p2)) { 3898c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 3908c2ecf20Sopenharmony_ci opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci if (Dbit31p2(opnd1p2)) { 3938c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 3948c2ecf20Sopenharmony_ci opnd2p1, opnd2p2, 0, 0); 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci Dbl_rightshiftby4(opnd1p1,opnd1p2); 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci if (Is_dexthiddenoverflow(tmpresp1)) { 3998c2ecf20Sopenharmony_ci /* result mantissa >= 2 (mantissa overflow) */ 4008c2ecf20Sopenharmony_ci mpy_exponent++; 4018c2ecf20Sopenharmony_ci Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* 4058c2ecf20Sopenharmony_ci * Restore the sign of the mpy result which was saved in resultp1. 4068c2ecf20Sopenharmony_ci * The exponent will continue to be kept in mpy_exponent. 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* 4118c2ecf20Sopenharmony_ci * No rounding is required, since the result of the multiply 4128c2ecf20Sopenharmony_ci * is exact in the extended format. 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* 4168c2ecf20Sopenharmony_ci * Now we are ready to perform the add portion of the operation. 4178c2ecf20Sopenharmony_ci * 4188c2ecf20Sopenharmony_ci * The exponents need to be kept as integers for now, since the 4198c2ecf20Sopenharmony_ci * multiply result might not fit into the exponent field. We 4208c2ecf20Sopenharmony_ci * can't overflow or underflow because of this yet, since the 4218c2ecf20Sopenharmony_ci * add could bring the final result back into range. 4228c2ecf20Sopenharmony_ci */ 4238c2ecf20Sopenharmony_ci add_exponent = Dbl_exponent(opnd3p1); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* 4268c2ecf20Sopenharmony_ci * Check for denormalized or zero add operand. 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_ci if (add_exponent == 0) { 4298c2ecf20Sopenharmony_ci /* check for zero */ 4308c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { 4318c2ecf20Sopenharmony_ci /* right is zero */ 4328c2ecf20Sopenharmony_ci /* Left can't be zero and must be result. 4338c2ecf20Sopenharmony_ci * 4348c2ecf20Sopenharmony_ci * The final result is now in tmpres and mpy_exponent, 4358c2ecf20Sopenharmony_ci * and needs to be rounded and squeezed back into 4368c2ecf20Sopenharmony_ci * double precision format from double extended. 4378c2ecf20Sopenharmony_ci */ 4388c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 4398c2ecf20Sopenharmony_ci Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, 4408c2ecf20Sopenharmony_ci resultp1,resultp2,resultp3,resultp4); 4418c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ 4428c2ecf20Sopenharmony_ci goto round; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* 4468c2ecf20Sopenharmony_ci * Neither are zeroes. 4478c2ecf20Sopenharmony_ci * Adjust exponent and normalize add operand. 4488c2ecf20Sopenharmony_ci */ 4498c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ 4508c2ecf20Sopenharmony_ci Dbl_clear_signexponent(opnd3p1); 4518c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd3p1,opnd3p2); 4528c2ecf20Sopenharmony_ci Dbl_normalize(opnd3p1,opnd3p2,add_exponent); 4538c2ecf20Sopenharmony_ci Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ 4548c2ecf20Sopenharmony_ci } else { 4558c2ecf20Sopenharmony_ci Dbl_clear_exponent_set_hidden(opnd3p1); 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci /* 4588c2ecf20Sopenharmony_ci * Copy opnd3 to the double extended variable called right. 4598c2ecf20Sopenharmony_ci */ 4608c2ecf20Sopenharmony_ci Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* 4638c2ecf20Sopenharmony_ci * A zero "save" helps discover equal operands (for later), 4648c2ecf20Sopenharmony_ci * and is used in swapping operands (if needed). 4658c2ecf20Sopenharmony_ci */ 4668c2ecf20Sopenharmony_ci Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci /* 4698c2ecf20Sopenharmony_ci * Compare magnitude of operands. 4708c2ecf20Sopenharmony_ci */ 4718c2ecf20Sopenharmony_ci Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); 4728c2ecf20Sopenharmony_ci Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); 4738c2ecf20Sopenharmony_ci if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && 4748c2ecf20Sopenharmony_ci Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ 4758c2ecf20Sopenharmony_ci /* 4768c2ecf20Sopenharmony_ci * Set the left operand to the larger one by XOR swap. 4778c2ecf20Sopenharmony_ci * First finish the first word "save". 4788c2ecf20Sopenharmony_ci */ 4798c2ecf20Sopenharmony_ci Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); 4808c2ecf20Sopenharmony_ci Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); 4818c2ecf20Sopenharmony_ci Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, 4828c2ecf20Sopenharmony_ci rightp2,rightp3,rightp4); 4838c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 4848c2ecf20Sopenharmony_ci diff_exponent = add_exponent - mpy_exponent; 4858c2ecf20Sopenharmony_ci result_exponent = add_exponent; 4868c2ecf20Sopenharmony_ci } else { 4878c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 4888c2ecf20Sopenharmony_ci diff_exponent = mpy_exponent - add_exponent; 4898c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci /* Invariant: left is not smaller than right. */ 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci /* 4948c2ecf20Sopenharmony_ci * Special case alignment of operands that would force alignment 4958c2ecf20Sopenharmony_ci * beyond the extent of the extension. A further optimization 4968c2ecf20Sopenharmony_ci * could special case this but only reduces the path length for 4978c2ecf20Sopenharmony_ci * this infrequent case. 4988c2ecf20Sopenharmony_ci */ 4998c2ecf20Sopenharmony_ci if (diff_exponent > DBLEXT_THRESHOLD) { 5008c2ecf20Sopenharmony_ci diff_exponent = DBLEXT_THRESHOLD; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci /* Align right operand by shifting it to the right */ 5048c2ecf20Sopenharmony_ci Dblext_clear_sign(rightp1); 5058c2ecf20Sopenharmony_ci Dblext_right_align(rightp1,rightp2,rightp3,rightp4, 5068c2ecf20Sopenharmony_ci /*shifted by*/diff_exponent); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci /* Treat sum and difference of the operands separately. */ 5098c2ecf20Sopenharmony_ci if ((int)save < 0) { 5108c2ecf20Sopenharmony_ci /* 5118c2ecf20Sopenharmony_ci * Difference of the two operands. Overflow can occur if the 5128c2ecf20Sopenharmony_ci * multiply overflowed. A borrow can occur out of the hidden 5138c2ecf20Sopenharmony_ci * bit and force a post normalization phase. 5148c2ecf20Sopenharmony_ci */ 5158c2ecf20Sopenharmony_ci Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, 5168c2ecf20Sopenharmony_ci rightp1,rightp2,rightp3,rightp4, 5178c2ecf20Sopenharmony_ci resultp1,resultp2,resultp3,resultp4); 5188c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(resultp1); 5198c2ecf20Sopenharmony_ci if (Dbl_iszero_hidden(resultp1)) { 5208c2ecf20Sopenharmony_ci /* Handle normalization */ 5218c2ecf20Sopenharmony_ci /* A straightforward algorithm would now shift the 5228c2ecf20Sopenharmony_ci * result and extension left until the hidden bit 5238c2ecf20Sopenharmony_ci * becomes one. Not all of the extension bits need 5248c2ecf20Sopenharmony_ci * participate in the shift. Only the two most 5258c2ecf20Sopenharmony_ci * significant bits (round and guard) are needed. 5268c2ecf20Sopenharmony_ci * If only a single shift is needed then the guard 5278c2ecf20Sopenharmony_ci * bit becomes a significant low order bit and the 5288c2ecf20Sopenharmony_ci * extension must participate in the rounding. 5298c2ecf20Sopenharmony_ci * If more than a single shift is needed, then all 5308c2ecf20Sopenharmony_ci * bits to the right of the guard bit are zeros, 5318c2ecf20Sopenharmony_ci * and the guard bit may or may not be zero. */ 5328c2ecf20Sopenharmony_ci Dblext_leftshiftby1(resultp1,resultp2,resultp3, 5338c2ecf20Sopenharmony_ci resultp4); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Need to check for a zero result. The sign and 5368c2ecf20Sopenharmony_ci * exponent fields have already been zeroed. The more 5378c2ecf20Sopenharmony_ci * efficient test of the full object can be used. 5388c2ecf20Sopenharmony_ci */ 5398c2ecf20Sopenharmony_ci if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){ 5408c2ecf20Sopenharmony_ci /* Must have been "x-x" or "x+(-x)". */ 5418c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) 5428c2ecf20Sopenharmony_ci Dbl_setone_sign(resultp1); 5438c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 5448c2ecf20Sopenharmony_ci return(NOEXCEPTION); 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci result_exponent--; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* Look to see if normalization is finished. */ 5498c2ecf20Sopenharmony_ci if (Dbl_isone_hidden(resultp1)) { 5508c2ecf20Sopenharmony_ci /* No further normalization is needed */ 5518c2ecf20Sopenharmony_ci goto round; 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* Discover first one bit to determine shift amount. 5558c2ecf20Sopenharmony_ci * Use a modified binary search. We have already 5568c2ecf20Sopenharmony_ci * shifted the result one position right and still 5578c2ecf20Sopenharmony_ci * not found a one so the remainder of the extension 5588c2ecf20Sopenharmony_ci * must be zero and simplifies rounding. */ 5598c2ecf20Sopenharmony_ci /* Scan bytes */ 5608c2ecf20Sopenharmony_ci while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { 5618c2ecf20Sopenharmony_ci Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); 5628c2ecf20Sopenharmony_ci result_exponent -= 8; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci /* Now narrow it down to the nibble */ 5658c2ecf20Sopenharmony_ci if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { 5668c2ecf20Sopenharmony_ci /* The lower nibble contains the 5678c2ecf20Sopenharmony_ci * normalizing one */ 5688c2ecf20Sopenharmony_ci Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); 5698c2ecf20Sopenharmony_ci result_exponent -= 4; 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci /* Select case where first bit is set (already 5728c2ecf20Sopenharmony_ci * normalized) otherwise select the proper shift. */ 5738c2ecf20Sopenharmony_ci jumpsize = Dbl_hiddenhigh3mantissa(resultp1); 5748c2ecf20Sopenharmony_ci if (jumpsize <= 7) switch(jumpsize) { 5758c2ecf20Sopenharmony_ci case 1: 5768c2ecf20Sopenharmony_ci Dblext_leftshiftby3(resultp1,resultp2,resultp3, 5778c2ecf20Sopenharmony_ci resultp4); 5788c2ecf20Sopenharmony_ci result_exponent -= 3; 5798c2ecf20Sopenharmony_ci break; 5808c2ecf20Sopenharmony_ci case 2: 5818c2ecf20Sopenharmony_ci case 3: 5828c2ecf20Sopenharmony_ci Dblext_leftshiftby2(resultp1,resultp2,resultp3, 5838c2ecf20Sopenharmony_ci resultp4); 5848c2ecf20Sopenharmony_ci result_exponent -= 2; 5858c2ecf20Sopenharmony_ci break; 5868c2ecf20Sopenharmony_ci case 4: 5878c2ecf20Sopenharmony_ci case 5: 5888c2ecf20Sopenharmony_ci case 6: 5898c2ecf20Sopenharmony_ci case 7: 5908c2ecf20Sopenharmony_ci Dblext_leftshiftby1(resultp1,resultp2,resultp3, 5918c2ecf20Sopenharmony_ci resultp4); 5928c2ecf20Sopenharmony_ci result_exponent -= 1; 5938c2ecf20Sopenharmony_ci break; 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci } /* end if (hidden...)... */ 5968c2ecf20Sopenharmony_ci /* Fall through and round */ 5978c2ecf20Sopenharmony_ci } /* end if (save < 0)... */ 5988c2ecf20Sopenharmony_ci else { 5998c2ecf20Sopenharmony_ci /* Add magnitudes */ 6008c2ecf20Sopenharmony_ci Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, 6018c2ecf20Sopenharmony_ci rightp1,rightp2,rightp3,rightp4, 6028c2ecf20Sopenharmony_ci /*to*/resultp1,resultp2,resultp3,resultp4); 6038c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(resultp1); 6048c2ecf20Sopenharmony_ci if (Dbl_isone_hiddenoverflow(resultp1)) { 6058c2ecf20Sopenharmony_ci /* Prenormalization required. */ 6068c2ecf20Sopenharmony_ci Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, 6078c2ecf20Sopenharmony_ci resultp4); 6088c2ecf20Sopenharmony_ci result_exponent++; 6098c2ecf20Sopenharmony_ci } /* end if hiddenoverflow... */ 6108c2ecf20Sopenharmony_ci } /* end else ...add magnitudes... */ 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* Round the result. If the extension and lower two words are 6138c2ecf20Sopenharmony_ci * all zeros, then the result is exact. Otherwise round in the 6148c2ecf20Sopenharmony_ci * correct direction. Underflow is possible. If a postnormalization 6158c2ecf20Sopenharmony_ci * is necessary, then the mantissa is all zeros so no shift is needed. 6168c2ecf20Sopenharmony_ci */ 6178c2ecf20Sopenharmony_ci round: 6188c2ecf20Sopenharmony_ci if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { 6198c2ecf20Sopenharmony_ci Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, 6208c2ecf20Sopenharmony_ci result_exponent,is_tiny); 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci Dbl_set_sign(resultp1,/*using*/sign_save); 6238c2ecf20Sopenharmony_ci if (Dblext_isnotzero_mantissap3(resultp3) || 6248c2ecf20Sopenharmony_ci Dblext_isnotzero_mantissap4(resultp4)) { 6258c2ecf20Sopenharmony_ci inexact = TRUE; 6268c2ecf20Sopenharmony_ci switch(Rounding_mode()) { 6278c2ecf20Sopenharmony_ci case ROUNDNEAREST: /* The default. */ 6288c2ecf20Sopenharmony_ci if (Dblext_isone_highp3(resultp3)) { 6298c2ecf20Sopenharmony_ci /* at least 1/2 ulp */ 6308c2ecf20Sopenharmony_ci if (Dblext_isnotzero_low31p3(resultp3) || 6318c2ecf20Sopenharmony_ci Dblext_isnotzero_mantissap4(resultp4) || 6328c2ecf20Sopenharmony_ci Dblext_isone_lowp2(resultp2)) { 6338c2ecf20Sopenharmony_ci /* either exactly half way and odd or 6348c2ecf20Sopenharmony_ci * more than 1/2ulp */ 6358c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci break; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci case ROUNDPLUS: 6418c2ecf20Sopenharmony_ci if (Dbl_iszero_sign(resultp1)) { 6428c2ecf20Sopenharmony_ci /* Round up positive results */ 6438c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 6448c2ecf20Sopenharmony_ci } 6458c2ecf20Sopenharmony_ci break; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci case ROUNDMINUS: 6488c2ecf20Sopenharmony_ci if (Dbl_isone_sign(resultp1)) { 6498c2ecf20Sopenharmony_ci /* Round down negative results */ 6508c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci case ROUNDZERO:; 6548c2ecf20Sopenharmony_ci /* truncate is simple */ 6558c2ecf20Sopenharmony_ci } /* end switch... */ 6568c2ecf20Sopenharmony_ci if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci if (result_exponent >= DBL_INFINITY_EXPONENT) { 6598c2ecf20Sopenharmony_ci /* trap if OVERFLOWTRAP enabled */ 6608c2ecf20Sopenharmony_ci if (Is_overflowtrap_enabled()) { 6618c2ecf20Sopenharmony_ci /* 6628c2ecf20Sopenharmony_ci * Adjust bias of result 6638c2ecf20Sopenharmony_ci */ 6648c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); 6658c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 6668c2ecf20Sopenharmony_ci if (inexact) 6678c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 6688c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION | 6698c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 6708c2ecf20Sopenharmony_ci else Set_inexactflag(); 6718c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION); 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci inexact = TRUE; 6748c2ecf20Sopenharmony_ci Set_overflowflag(); 6758c2ecf20Sopenharmony_ci /* set result to infinity or largest number */ 6768c2ecf20Sopenharmony_ci Dbl_setoverflow(resultp1,resultp2); 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci } else if (result_exponent <= 0) { /* underflow case */ 6798c2ecf20Sopenharmony_ci if (Is_underflowtrap_enabled()) { 6808c2ecf20Sopenharmony_ci /* 6818c2ecf20Sopenharmony_ci * Adjust bias of result 6828c2ecf20Sopenharmony_ci */ 6838c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); 6848c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 6858c2ecf20Sopenharmony_ci if (inexact) 6868c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 6878c2ecf20Sopenharmony_ci return (OPC_2E_UNDERFLOWEXCEPTION | 6888c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 6898c2ecf20Sopenharmony_ci else Set_inexactflag(); 6908c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci else if (inexact && is_tiny) Set_underflowflag(); 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci else Dbl_set_exponent(resultp1,result_exponent); 6958c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 6968c2ecf20Sopenharmony_ci if (inexact) 6978c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); 6988c2ecf20Sopenharmony_ci else Set_inexactflag(); 6998c2ecf20Sopenharmony_ci return(NOEXCEPTION); 7008c2ecf20Sopenharmony_ci} 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci/* 7038c2ecf20Sopenharmony_ci * Double Floating-point Multiply Negate Fused Add 7048c2ecf20Sopenharmony_ci */ 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cidbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cidbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; 7098c2ecf20Sopenharmony_ciunsigned int *status; 7108c2ecf20Sopenharmony_ci{ 7118c2ecf20Sopenharmony_ci unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; 7128c2ecf20Sopenharmony_ci register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; 7138c2ecf20Sopenharmony_ci unsigned int rightp1, rightp2, rightp3, rightp4; 7148c2ecf20Sopenharmony_ci unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; 7158c2ecf20Sopenharmony_ci register int mpy_exponent, add_exponent, count; 7168c2ecf20Sopenharmony_ci boolean inexact = FALSE, is_tiny = FALSE; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci unsigned int signlessleft1, signlessright1, save; 7198c2ecf20Sopenharmony_ci register int result_exponent, diff_exponent; 7208c2ecf20Sopenharmony_ci int sign_save, jumpsize; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); 7238c2ecf20Sopenharmony_ci Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); 7248c2ecf20Sopenharmony_ci Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /* 7278c2ecf20Sopenharmony_ci * set sign bit of result of multiply 7288c2ecf20Sopenharmony_ci */ 7298c2ecf20Sopenharmony_ci if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 7308c2ecf20Sopenharmony_ci Dbl_setzerop1(resultp1); 7318c2ecf20Sopenharmony_ci else 7328c2ecf20Sopenharmony_ci Dbl_setnegativezerop1(resultp1); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci /* 7358c2ecf20Sopenharmony_ci * Generate multiply exponent 7368c2ecf20Sopenharmony_ci */ 7378c2ecf20Sopenharmony_ci mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* 7408c2ecf20Sopenharmony_ci * check first operand for NaN's or infinity 7418c2ecf20Sopenharmony_ci */ 7428c2ecf20Sopenharmony_ci if (Dbl_isinfinity_exponent(opnd1p1)) { 7438c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { 7448c2ecf20Sopenharmony_ci if (Dbl_isnotnan(opnd2p1,opnd2p2) && 7458c2ecf20Sopenharmony_ci Dbl_isnotnan(opnd3p1,opnd3p2)) { 7468c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { 7478c2ecf20Sopenharmony_ci /* 7488c2ecf20Sopenharmony_ci * invalid since operands are infinity 7498c2ecf20Sopenharmony_ci * and zero 7508c2ecf20Sopenharmony_ci */ 7518c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 7528c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 7538c2ecf20Sopenharmony_ci Set_invalidflag(); 7548c2ecf20Sopenharmony_ci Dbl_makequietnan(resultp1,resultp2); 7558c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 7568c2ecf20Sopenharmony_ci return(NOEXCEPTION); 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci /* 7598c2ecf20Sopenharmony_ci * Check third operand for infinity with a 7608c2ecf20Sopenharmony_ci * sign opposite of the multiply result 7618c2ecf20Sopenharmony_ci */ 7628c2ecf20Sopenharmony_ci if (Dbl_isinfinity(opnd3p1,opnd3p2) && 7638c2ecf20Sopenharmony_ci (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { 7648c2ecf20Sopenharmony_ci /* 7658c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 7668c2ecf20Sopenharmony_ci * subtraction of infinities 7678c2ecf20Sopenharmony_ci */ 7688c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 7698c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 7708c2ecf20Sopenharmony_ci Set_invalidflag(); 7718c2ecf20Sopenharmony_ci Dbl_makequietnan(resultp1,resultp2); 7728c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 7738c2ecf20Sopenharmony_ci return(NOEXCEPTION); 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci /* 7778c2ecf20Sopenharmony_ci * return infinity 7788c2ecf20Sopenharmony_ci */ 7798c2ecf20Sopenharmony_ci Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 7808c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 7818c2ecf20Sopenharmony_ci return(NOEXCEPTION); 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci else { 7858c2ecf20Sopenharmony_ci /* 7868c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 7878c2ecf20Sopenharmony_ci */ 7888c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(opnd1p1)) { 7898c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 7908c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 7918c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 7928c2ecf20Sopenharmony_ci /* make NaN quiet */ 7938c2ecf20Sopenharmony_ci Set_invalidflag(); 7948c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd1p1); 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci /* 7978c2ecf20Sopenharmony_ci * is second operand a signaling NaN? 7988c2ecf20Sopenharmony_ci */ 7998c2ecf20Sopenharmony_ci else if (Dbl_is_signalingnan(opnd2p1)) { 8008c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 8018c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 8028c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 8038c2ecf20Sopenharmony_ci /* make NaN quiet */ 8048c2ecf20Sopenharmony_ci Set_invalidflag(); 8058c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd2p1); 8068c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 8078c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci /* 8108c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 8118c2ecf20Sopenharmony_ci */ 8128c2ecf20Sopenharmony_ci else if (Dbl_is_signalingnan(opnd3p1)) { 8138c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 8148c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 8158c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 8168c2ecf20Sopenharmony_ci /* make NaN quiet */ 8178c2ecf20Sopenharmony_ci Set_invalidflag(); 8188c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd3p1); 8198c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 8208c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci /* 8238c2ecf20Sopenharmony_ci * return quiet NaN 8248c2ecf20Sopenharmony_ci */ 8258c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); 8268c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci /* 8318c2ecf20Sopenharmony_ci * check second operand for NaN's or infinity 8328c2ecf20Sopenharmony_ci */ 8338c2ecf20Sopenharmony_ci if (Dbl_isinfinity_exponent(opnd2p1)) { 8348c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { 8358c2ecf20Sopenharmony_ci if (Dbl_isnotnan(opnd3p1,opnd3p2)) { 8368c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { 8378c2ecf20Sopenharmony_ci /* 8388c2ecf20Sopenharmony_ci * invalid since multiply operands are 8398c2ecf20Sopenharmony_ci * zero & infinity 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 8428c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 8438c2ecf20Sopenharmony_ci Set_invalidflag(); 8448c2ecf20Sopenharmony_ci Dbl_makequietnan(opnd2p1,opnd2p2); 8458c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 8468c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci /* 8508c2ecf20Sopenharmony_ci * Check third operand for infinity with a 8518c2ecf20Sopenharmony_ci * sign opposite of the multiply result 8528c2ecf20Sopenharmony_ci */ 8538c2ecf20Sopenharmony_ci if (Dbl_isinfinity(opnd3p1,opnd3p2) && 8548c2ecf20Sopenharmony_ci (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { 8558c2ecf20Sopenharmony_ci /* 8568c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 8578c2ecf20Sopenharmony_ci * subtraction of infinities 8588c2ecf20Sopenharmony_ci */ 8598c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 8608c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 8618c2ecf20Sopenharmony_ci Set_invalidflag(); 8628c2ecf20Sopenharmony_ci Dbl_makequietnan(resultp1,resultp2); 8638c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 8648c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8658c2ecf20Sopenharmony_ci } 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci /* 8688c2ecf20Sopenharmony_ci * return infinity 8698c2ecf20Sopenharmony_ci */ 8708c2ecf20Sopenharmony_ci Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 8718c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 8728c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8738c2ecf20Sopenharmony_ci } 8748c2ecf20Sopenharmony_ci } 8758c2ecf20Sopenharmony_ci else { 8768c2ecf20Sopenharmony_ci /* 8778c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 8788c2ecf20Sopenharmony_ci */ 8798c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(opnd2p1)) { 8808c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 8818c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 8828c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 8838c2ecf20Sopenharmony_ci /* make NaN quiet */ 8848c2ecf20Sopenharmony_ci Set_invalidflag(); 8858c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd2p1); 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci /* 8888c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 8898c2ecf20Sopenharmony_ci */ 8908c2ecf20Sopenharmony_ci else if (Dbl_is_signalingnan(opnd3p1)) { 8918c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 8928c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 8938c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 8948c2ecf20Sopenharmony_ci /* make NaN quiet */ 8958c2ecf20Sopenharmony_ci Set_invalidflag(); 8968c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd3p1); 8978c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 8988c2ecf20Sopenharmony_ci return(NOEXCEPTION); 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci /* 9018c2ecf20Sopenharmony_ci * return quiet NaN 9028c2ecf20Sopenharmony_ci */ 9038c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 9048c2ecf20Sopenharmony_ci return(NOEXCEPTION); 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* 9098c2ecf20Sopenharmony_ci * check third operand for NaN's or infinity 9108c2ecf20Sopenharmony_ci */ 9118c2ecf20Sopenharmony_ci if (Dbl_isinfinity_exponent(opnd3p1)) { 9128c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { 9138c2ecf20Sopenharmony_ci /* return infinity */ 9148c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 9158c2ecf20Sopenharmony_ci return(NOEXCEPTION); 9168c2ecf20Sopenharmony_ci } else { 9178c2ecf20Sopenharmony_ci /* 9188c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 9198c2ecf20Sopenharmony_ci */ 9208c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(opnd3p1)) { 9218c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 9228c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 9238c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 9248c2ecf20Sopenharmony_ci /* make NaN quiet */ 9258c2ecf20Sopenharmony_ci Set_invalidflag(); 9268c2ecf20Sopenharmony_ci Dbl_set_quiet(opnd3p1); 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci /* 9298c2ecf20Sopenharmony_ci * return quiet NaN 9308c2ecf20Sopenharmony_ci */ 9318c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 9328c2ecf20Sopenharmony_ci return(NOEXCEPTION); 9338c2ecf20Sopenharmony_ci } 9348c2ecf20Sopenharmony_ci } 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* 9378c2ecf20Sopenharmony_ci * Generate multiply mantissa 9388c2ecf20Sopenharmony_ci */ 9398c2ecf20Sopenharmony_ci if (Dbl_isnotzero_exponent(opnd1p1)) { 9408c2ecf20Sopenharmony_ci /* set hidden bit */ 9418c2ecf20Sopenharmony_ci Dbl_clear_signexponent_set_hidden(opnd1p1); 9428c2ecf20Sopenharmony_ci } 9438c2ecf20Sopenharmony_ci else { 9448c2ecf20Sopenharmony_ci /* check for zero */ 9458c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { 9468c2ecf20Sopenharmony_ci /* 9478c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 9488c2ecf20Sopenharmony_ci */ 9498c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { 9508c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 9518c2ecf20Sopenharmony_ci Dbl_or_signs(opnd3p1,resultp1); 9528c2ecf20Sopenharmony_ci } else { 9538c2ecf20Sopenharmony_ci Dbl_and_signs(opnd3p1,resultp1); 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci /* 9578c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 9588c2ecf20Sopenharmony_ci */ 9598c2ecf20Sopenharmony_ci else if (Dbl_iszero_exponent(opnd3p1) && 9608c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 9618c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 9628c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(opnd3p1); 9638c2ecf20Sopenharmony_ci result_exponent = 0; 9648c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd3p1,opnd3p2); 9658c2ecf20Sopenharmony_ci Dbl_normalize(opnd3p1,opnd3p2,result_exponent); 9668c2ecf20Sopenharmony_ci Dbl_set_sign(opnd3p1,/*using*/sign_save); 9678c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(opnd3p1,result_exponent, 9688c2ecf20Sopenharmony_ci unfl); 9698c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 9708c2ecf20Sopenharmony_ci /* inexact = FALSE */ 9718c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 9748c2ecf20Sopenharmony_ci return(NOEXCEPTION); 9758c2ecf20Sopenharmony_ci } 9768c2ecf20Sopenharmony_ci /* is denormalized, adjust exponent */ 9778c2ecf20Sopenharmony_ci Dbl_clear_signexponent(opnd1p1); 9788c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd1p1,opnd1p2); 9798c2ecf20Sopenharmony_ci Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci /* opnd2 needs to have hidden bit set with msb in hidden bit */ 9828c2ecf20Sopenharmony_ci if (Dbl_isnotzero_exponent(opnd2p1)) { 9838c2ecf20Sopenharmony_ci Dbl_clear_signexponent_set_hidden(opnd2p1); 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci else { 9868c2ecf20Sopenharmony_ci /* check for zero */ 9878c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { 9888c2ecf20Sopenharmony_ci /* 9898c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 9908c2ecf20Sopenharmony_ci */ 9918c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { 9928c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 9938c2ecf20Sopenharmony_ci Dbl_or_signs(opnd3p1,resultp1); 9948c2ecf20Sopenharmony_ci } else { 9958c2ecf20Sopenharmony_ci Dbl_and_signs(opnd3p1,resultp1); 9968c2ecf20Sopenharmony_ci } 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci /* 9998c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 10008c2ecf20Sopenharmony_ci */ 10018c2ecf20Sopenharmony_ci else if (Dbl_iszero_exponent(opnd3p1) && 10028c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 10038c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 10048c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(opnd3p1); 10058c2ecf20Sopenharmony_ci result_exponent = 0; 10068c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd3p1,opnd3p2); 10078c2ecf20Sopenharmony_ci Dbl_normalize(opnd3p1,opnd3p2,result_exponent); 10088c2ecf20Sopenharmony_ci Dbl_set_sign(opnd3p1,/*using*/sign_save); 10098c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(opnd3p1,result_exponent, 10108c2ecf20Sopenharmony_ci unfl); 10118c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 10128c2ecf20Sopenharmony_ci /* inexact = FALSE */ 10138c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); 10168c2ecf20Sopenharmony_ci return(NOEXCEPTION); 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci /* is denormalized; want to normalize */ 10198c2ecf20Sopenharmony_ci Dbl_clear_signexponent(opnd2p1); 10208c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd2p1,opnd2p2); 10218c2ecf20Sopenharmony_ci Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci /* Multiply the first two source mantissas together */ 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci /* 10278c2ecf20Sopenharmony_ci * The intermediate result will be kept in tmpres, 10288c2ecf20Sopenharmony_ci * which needs enough room for 106 bits of mantissa, 10298c2ecf20Sopenharmony_ci * so lets call it a Double extended. 10308c2ecf20Sopenharmony_ci */ 10318c2ecf20Sopenharmony_ci Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci /* 10348c2ecf20Sopenharmony_ci * Four bits at a time are inspected in each loop, and a 10358c2ecf20Sopenharmony_ci * simple shift and add multiply algorithm is used. 10368c2ecf20Sopenharmony_ci */ 10378c2ecf20Sopenharmony_ci for (count = DBL_P-1; count >= 0; count -= 4) { 10388c2ecf20Sopenharmony_ci Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); 10398c2ecf20Sopenharmony_ci if (Dbit28p2(opnd1p2)) { 10408c2ecf20Sopenharmony_ci /* Fourword_add should be an ADD followed by 3 ADDC's */ 10418c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 10428c2ecf20Sopenharmony_ci opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); 10438c2ecf20Sopenharmony_ci } 10448c2ecf20Sopenharmony_ci if (Dbit29p2(opnd1p2)) { 10458c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 10468c2ecf20Sopenharmony_ci opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); 10478c2ecf20Sopenharmony_ci } 10488c2ecf20Sopenharmony_ci if (Dbit30p2(opnd1p2)) { 10498c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 10508c2ecf20Sopenharmony_ci opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci if (Dbit31p2(opnd1p2)) { 10538c2ecf20Sopenharmony_ci Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 10548c2ecf20Sopenharmony_ci opnd2p1, opnd2p2, 0, 0); 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci Dbl_rightshiftby4(opnd1p1,opnd1p2); 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci if (Is_dexthiddenoverflow(tmpresp1)) { 10598c2ecf20Sopenharmony_ci /* result mantissa >= 2 (mantissa overflow) */ 10608c2ecf20Sopenharmony_ci mpy_exponent++; 10618c2ecf20Sopenharmony_ci Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); 10628c2ecf20Sopenharmony_ci } 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci /* 10658c2ecf20Sopenharmony_ci * Restore the sign of the mpy result which was saved in resultp1. 10668c2ecf20Sopenharmony_ci * The exponent will continue to be kept in mpy_exponent. 10678c2ecf20Sopenharmony_ci */ 10688c2ecf20Sopenharmony_ci Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci /* 10718c2ecf20Sopenharmony_ci * No rounding is required, since the result of the multiply 10728c2ecf20Sopenharmony_ci * is exact in the extended format. 10738c2ecf20Sopenharmony_ci */ 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci /* 10768c2ecf20Sopenharmony_ci * Now we are ready to perform the add portion of the operation. 10778c2ecf20Sopenharmony_ci * 10788c2ecf20Sopenharmony_ci * The exponents need to be kept as integers for now, since the 10798c2ecf20Sopenharmony_ci * multiply result might not fit into the exponent field. We 10808c2ecf20Sopenharmony_ci * can't overflow or underflow because of this yet, since the 10818c2ecf20Sopenharmony_ci * add could bring the final result back into range. 10828c2ecf20Sopenharmony_ci */ 10838c2ecf20Sopenharmony_ci add_exponent = Dbl_exponent(opnd3p1); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci /* 10868c2ecf20Sopenharmony_ci * Check for denormalized or zero add operand. 10878c2ecf20Sopenharmony_ci */ 10888c2ecf20Sopenharmony_ci if (add_exponent == 0) { 10898c2ecf20Sopenharmony_ci /* check for zero */ 10908c2ecf20Sopenharmony_ci if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { 10918c2ecf20Sopenharmony_ci /* right is zero */ 10928c2ecf20Sopenharmony_ci /* Left can't be zero and must be result. 10938c2ecf20Sopenharmony_ci * 10948c2ecf20Sopenharmony_ci * The final result is now in tmpres and mpy_exponent, 10958c2ecf20Sopenharmony_ci * and needs to be rounded and squeezed back into 10968c2ecf20Sopenharmony_ci * double precision format from double extended. 10978c2ecf20Sopenharmony_ci */ 10988c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 10998c2ecf20Sopenharmony_ci Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, 11008c2ecf20Sopenharmony_ci resultp1,resultp2,resultp3,resultp4); 11018c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ 11028c2ecf20Sopenharmony_ci goto round; 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci /* 11068c2ecf20Sopenharmony_ci * Neither are zeroes. 11078c2ecf20Sopenharmony_ci * Adjust exponent and normalize add operand. 11088c2ecf20Sopenharmony_ci */ 11098c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ 11108c2ecf20Sopenharmony_ci Dbl_clear_signexponent(opnd3p1); 11118c2ecf20Sopenharmony_ci Dbl_leftshiftby1(opnd3p1,opnd3p2); 11128c2ecf20Sopenharmony_ci Dbl_normalize(opnd3p1,opnd3p2,add_exponent); 11138c2ecf20Sopenharmony_ci Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ 11148c2ecf20Sopenharmony_ci } else { 11158c2ecf20Sopenharmony_ci Dbl_clear_exponent_set_hidden(opnd3p1); 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci /* 11188c2ecf20Sopenharmony_ci * Copy opnd3 to the double extended variable called right. 11198c2ecf20Sopenharmony_ci */ 11208c2ecf20Sopenharmony_ci Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* 11238c2ecf20Sopenharmony_ci * A zero "save" helps discover equal operands (for later), 11248c2ecf20Sopenharmony_ci * and is used in swapping operands (if needed). 11258c2ecf20Sopenharmony_ci */ 11268c2ecf20Sopenharmony_ci Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci /* 11298c2ecf20Sopenharmony_ci * Compare magnitude of operands. 11308c2ecf20Sopenharmony_ci */ 11318c2ecf20Sopenharmony_ci Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); 11328c2ecf20Sopenharmony_ci Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); 11338c2ecf20Sopenharmony_ci if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && 11348c2ecf20Sopenharmony_ci Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ 11358c2ecf20Sopenharmony_ci /* 11368c2ecf20Sopenharmony_ci * Set the left operand to the larger one by XOR swap. 11378c2ecf20Sopenharmony_ci * First finish the first word "save". 11388c2ecf20Sopenharmony_ci */ 11398c2ecf20Sopenharmony_ci Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); 11408c2ecf20Sopenharmony_ci Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); 11418c2ecf20Sopenharmony_ci Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, 11428c2ecf20Sopenharmony_ci rightp2,rightp3,rightp4); 11438c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 11448c2ecf20Sopenharmony_ci diff_exponent = add_exponent - mpy_exponent; 11458c2ecf20Sopenharmony_ci result_exponent = add_exponent; 11468c2ecf20Sopenharmony_ci } else { 11478c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 11488c2ecf20Sopenharmony_ci diff_exponent = mpy_exponent - add_exponent; 11498c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci /* Invariant: left is not smaller than right. */ 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci /* 11548c2ecf20Sopenharmony_ci * Special case alignment of operands that would force alignment 11558c2ecf20Sopenharmony_ci * beyond the extent of the extension. A further optimization 11568c2ecf20Sopenharmony_ci * could special case this but only reduces the path length for 11578c2ecf20Sopenharmony_ci * this infrequent case. 11588c2ecf20Sopenharmony_ci */ 11598c2ecf20Sopenharmony_ci if (diff_exponent > DBLEXT_THRESHOLD) { 11608c2ecf20Sopenharmony_ci diff_exponent = DBLEXT_THRESHOLD; 11618c2ecf20Sopenharmony_ci } 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci /* Align right operand by shifting it to the right */ 11648c2ecf20Sopenharmony_ci Dblext_clear_sign(rightp1); 11658c2ecf20Sopenharmony_ci Dblext_right_align(rightp1,rightp2,rightp3,rightp4, 11668c2ecf20Sopenharmony_ci /*shifted by*/diff_exponent); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci /* Treat sum and difference of the operands separately. */ 11698c2ecf20Sopenharmony_ci if ((int)save < 0) { 11708c2ecf20Sopenharmony_ci /* 11718c2ecf20Sopenharmony_ci * Difference of the two operands. Overflow can occur if the 11728c2ecf20Sopenharmony_ci * multiply overflowed. A borrow can occur out of the hidden 11738c2ecf20Sopenharmony_ci * bit and force a post normalization phase. 11748c2ecf20Sopenharmony_ci */ 11758c2ecf20Sopenharmony_ci Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, 11768c2ecf20Sopenharmony_ci rightp1,rightp2,rightp3,rightp4, 11778c2ecf20Sopenharmony_ci resultp1,resultp2,resultp3,resultp4); 11788c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(resultp1); 11798c2ecf20Sopenharmony_ci if (Dbl_iszero_hidden(resultp1)) { 11808c2ecf20Sopenharmony_ci /* Handle normalization */ 11818c2ecf20Sopenharmony_ci /* A straightforward algorithm would now shift the 11828c2ecf20Sopenharmony_ci * result and extension left until the hidden bit 11838c2ecf20Sopenharmony_ci * becomes one. Not all of the extension bits need 11848c2ecf20Sopenharmony_ci * participate in the shift. Only the two most 11858c2ecf20Sopenharmony_ci * significant bits (round and guard) are needed. 11868c2ecf20Sopenharmony_ci * If only a single shift is needed then the guard 11878c2ecf20Sopenharmony_ci * bit becomes a significant low order bit and the 11888c2ecf20Sopenharmony_ci * extension must participate in the rounding. 11898c2ecf20Sopenharmony_ci * If more than a single shift is needed, then all 11908c2ecf20Sopenharmony_ci * bits to the right of the guard bit are zeros, 11918c2ecf20Sopenharmony_ci * and the guard bit may or may not be zero. */ 11928c2ecf20Sopenharmony_ci Dblext_leftshiftby1(resultp1,resultp2,resultp3, 11938c2ecf20Sopenharmony_ci resultp4); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci /* Need to check for a zero result. The sign and 11968c2ecf20Sopenharmony_ci * exponent fields have already been zeroed. The more 11978c2ecf20Sopenharmony_ci * efficient test of the full object can be used. 11988c2ecf20Sopenharmony_ci */ 11998c2ecf20Sopenharmony_ci if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) { 12008c2ecf20Sopenharmony_ci /* Must have been "x-x" or "x+(-x)". */ 12018c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) 12028c2ecf20Sopenharmony_ci Dbl_setone_sign(resultp1); 12038c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 12048c2ecf20Sopenharmony_ci return(NOEXCEPTION); 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci result_exponent--; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci /* Look to see if normalization is finished. */ 12098c2ecf20Sopenharmony_ci if (Dbl_isone_hidden(resultp1)) { 12108c2ecf20Sopenharmony_ci /* No further normalization is needed */ 12118c2ecf20Sopenharmony_ci goto round; 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci /* Discover first one bit to determine shift amount. 12158c2ecf20Sopenharmony_ci * Use a modified binary search. We have already 12168c2ecf20Sopenharmony_ci * shifted the result one position right and still 12178c2ecf20Sopenharmony_ci * not found a one so the remainder of the extension 12188c2ecf20Sopenharmony_ci * must be zero and simplifies rounding. */ 12198c2ecf20Sopenharmony_ci /* Scan bytes */ 12208c2ecf20Sopenharmony_ci while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { 12218c2ecf20Sopenharmony_ci Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); 12228c2ecf20Sopenharmony_ci result_exponent -= 8; 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci /* Now narrow it down to the nibble */ 12258c2ecf20Sopenharmony_ci if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { 12268c2ecf20Sopenharmony_ci /* The lower nibble contains the 12278c2ecf20Sopenharmony_ci * normalizing one */ 12288c2ecf20Sopenharmony_ci Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); 12298c2ecf20Sopenharmony_ci result_exponent -= 4; 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci /* Select case where first bit is set (already 12328c2ecf20Sopenharmony_ci * normalized) otherwise select the proper shift. */ 12338c2ecf20Sopenharmony_ci jumpsize = Dbl_hiddenhigh3mantissa(resultp1); 12348c2ecf20Sopenharmony_ci if (jumpsize <= 7) switch(jumpsize) { 12358c2ecf20Sopenharmony_ci case 1: 12368c2ecf20Sopenharmony_ci Dblext_leftshiftby3(resultp1,resultp2,resultp3, 12378c2ecf20Sopenharmony_ci resultp4); 12388c2ecf20Sopenharmony_ci result_exponent -= 3; 12398c2ecf20Sopenharmony_ci break; 12408c2ecf20Sopenharmony_ci case 2: 12418c2ecf20Sopenharmony_ci case 3: 12428c2ecf20Sopenharmony_ci Dblext_leftshiftby2(resultp1,resultp2,resultp3, 12438c2ecf20Sopenharmony_ci resultp4); 12448c2ecf20Sopenharmony_ci result_exponent -= 2; 12458c2ecf20Sopenharmony_ci break; 12468c2ecf20Sopenharmony_ci case 4: 12478c2ecf20Sopenharmony_ci case 5: 12488c2ecf20Sopenharmony_ci case 6: 12498c2ecf20Sopenharmony_ci case 7: 12508c2ecf20Sopenharmony_ci Dblext_leftshiftby1(resultp1,resultp2,resultp3, 12518c2ecf20Sopenharmony_ci resultp4); 12528c2ecf20Sopenharmony_ci result_exponent -= 1; 12538c2ecf20Sopenharmony_ci break; 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci } /* end if (hidden...)... */ 12568c2ecf20Sopenharmony_ci /* Fall through and round */ 12578c2ecf20Sopenharmony_ci } /* end if (save < 0)... */ 12588c2ecf20Sopenharmony_ci else { 12598c2ecf20Sopenharmony_ci /* Add magnitudes */ 12608c2ecf20Sopenharmony_ci Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, 12618c2ecf20Sopenharmony_ci rightp1,rightp2,rightp3,rightp4, 12628c2ecf20Sopenharmony_ci /*to*/resultp1,resultp2,resultp3,resultp4); 12638c2ecf20Sopenharmony_ci sign_save = Dbl_signextendedsign(resultp1); 12648c2ecf20Sopenharmony_ci if (Dbl_isone_hiddenoverflow(resultp1)) { 12658c2ecf20Sopenharmony_ci /* Prenormalization required. */ 12668c2ecf20Sopenharmony_ci Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, 12678c2ecf20Sopenharmony_ci resultp4); 12688c2ecf20Sopenharmony_ci result_exponent++; 12698c2ecf20Sopenharmony_ci } /* end if hiddenoverflow... */ 12708c2ecf20Sopenharmony_ci } /* end else ...add magnitudes... */ 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci /* Round the result. If the extension and lower two words are 12738c2ecf20Sopenharmony_ci * all zeros, then the result is exact. Otherwise round in the 12748c2ecf20Sopenharmony_ci * correct direction. Underflow is possible. If a postnormalization 12758c2ecf20Sopenharmony_ci * is necessary, then the mantissa is all zeros so no shift is needed. 12768c2ecf20Sopenharmony_ci */ 12778c2ecf20Sopenharmony_ci round: 12788c2ecf20Sopenharmony_ci if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { 12798c2ecf20Sopenharmony_ci Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, 12808c2ecf20Sopenharmony_ci result_exponent,is_tiny); 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci Dbl_set_sign(resultp1,/*using*/sign_save); 12838c2ecf20Sopenharmony_ci if (Dblext_isnotzero_mantissap3(resultp3) || 12848c2ecf20Sopenharmony_ci Dblext_isnotzero_mantissap4(resultp4)) { 12858c2ecf20Sopenharmony_ci inexact = TRUE; 12868c2ecf20Sopenharmony_ci switch(Rounding_mode()) { 12878c2ecf20Sopenharmony_ci case ROUNDNEAREST: /* The default. */ 12888c2ecf20Sopenharmony_ci if (Dblext_isone_highp3(resultp3)) { 12898c2ecf20Sopenharmony_ci /* at least 1/2 ulp */ 12908c2ecf20Sopenharmony_ci if (Dblext_isnotzero_low31p3(resultp3) || 12918c2ecf20Sopenharmony_ci Dblext_isnotzero_mantissap4(resultp4) || 12928c2ecf20Sopenharmony_ci Dblext_isone_lowp2(resultp2)) { 12938c2ecf20Sopenharmony_ci /* either exactly half way and odd or 12948c2ecf20Sopenharmony_ci * more than 1/2ulp */ 12958c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci break; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci case ROUNDPLUS: 13018c2ecf20Sopenharmony_ci if (Dbl_iszero_sign(resultp1)) { 13028c2ecf20Sopenharmony_ci /* Round up positive results */ 13038c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci break; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci case ROUNDMINUS: 13088c2ecf20Sopenharmony_ci if (Dbl_isone_sign(resultp1)) { 13098c2ecf20Sopenharmony_ci /* Round down negative results */ 13108c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci case ROUNDZERO:; 13148c2ecf20Sopenharmony_ci /* truncate is simple */ 13158c2ecf20Sopenharmony_ci } /* end switch... */ 13168c2ecf20Sopenharmony_ci if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; 13178c2ecf20Sopenharmony_ci } 13188c2ecf20Sopenharmony_ci if (result_exponent >= DBL_INFINITY_EXPONENT) { 13198c2ecf20Sopenharmony_ci /* Overflow */ 13208c2ecf20Sopenharmony_ci if (Is_overflowtrap_enabled()) { 13218c2ecf20Sopenharmony_ci /* 13228c2ecf20Sopenharmony_ci * Adjust bias of result 13238c2ecf20Sopenharmony_ci */ 13248c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); 13258c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 13268c2ecf20Sopenharmony_ci if (inexact) 13278c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 13288c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION | 13298c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 13308c2ecf20Sopenharmony_ci else Set_inexactflag(); 13318c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION); 13328c2ecf20Sopenharmony_ci } 13338c2ecf20Sopenharmony_ci inexact = TRUE; 13348c2ecf20Sopenharmony_ci Set_overflowflag(); 13358c2ecf20Sopenharmony_ci Dbl_setoverflow(resultp1,resultp2); 13368c2ecf20Sopenharmony_ci } else if (result_exponent <= 0) { /* underflow case */ 13378c2ecf20Sopenharmony_ci if (Is_underflowtrap_enabled()) { 13388c2ecf20Sopenharmony_ci /* 13398c2ecf20Sopenharmony_ci * Adjust bias of result 13408c2ecf20Sopenharmony_ci */ 13418c2ecf20Sopenharmony_ci Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); 13428c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 13438c2ecf20Sopenharmony_ci if (inexact) 13448c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 13458c2ecf20Sopenharmony_ci return (OPC_2E_UNDERFLOWEXCEPTION | 13468c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 13478c2ecf20Sopenharmony_ci else Set_inexactflag(); 13488c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci else if (inexact && is_tiny) Set_underflowflag(); 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci else Dbl_set_exponent(resultp1,result_exponent); 13538c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 13548c2ecf20Sopenharmony_ci if (inexact) 13558c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); 13568c2ecf20Sopenharmony_ci else Set_inexactflag(); 13578c2ecf20Sopenharmony_ci return(NOEXCEPTION); 13588c2ecf20Sopenharmony_ci} 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci/* 13618c2ecf20Sopenharmony_ci * Single Floating-point Multiply Fused Add 13628c2ecf20Sopenharmony_ci */ 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_cisgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_cisgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; 13678c2ecf20Sopenharmony_ciunsigned int *status; 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci unsigned int opnd1, opnd2, opnd3; 13708c2ecf20Sopenharmony_ci register unsigned int tmpresp1, tmpresp2; 13718c2ecf20Sopenharmony_ci unsigned int rightp1, rightp2; 13728c2ecf20Sopenharmony_ci unsigned int resultp1, resultp2 = 0; 13738c2ecf20Sopenharmony_ci register int mpy_exponent, add_exponent, count; 13748c2ecf20Sopenharmony_ci boolean inexact = FALSE, is_tiny = FALSE; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci unsigned int signlessleft1, signlessright1, save; 13778c2ecf20Sopenharmony_ci register int result_exponent, diff_exponent; 13788c2ecf20Sopenharmony_ci int sign_save, jumpsize; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci Sgl_copyfromptr(src1ptr,opnd1); 13818c2ecf20Sopenharmony_ci Sgl_copyfromptr(src2ptr,opnd2); 13828c2ecf20Sopenharmony_ci Sgl_copyfromptr(src3ptr,opnd3); 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci /* 13858c2ecf20Sopenharmony_ci * set sign bit of result of multiply 13868c2ecf20Sopenharmony_ci */ 13878c2ecf20Sopenharmony_ci if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) 13888c2ecf20Sopenharmony_ci Sgl_setnegativezero(resultp1); 13898c2ecf20Sopenharmony_ci else Sgl_setzero(resultp1); 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci /* 13928c2ecf20Sopenharmony_ci * Generate multiply exponent 13938c2ecf20Sopenharmony_ci */ 13948c2ecf20Sopenharmony_ci mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci /* 13978c2ecf20Sopenharmony_ci * check first operand for NaN's or infinity 13988c2ecf20Sopenharmony_ci */ 13998c2ecf20Sopenharmony_ci if (Sgl_isinfinity_exponent(opnd1)) { 14008c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd1)) { 14018c2ecf20Sopenharmony_ci if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { 14028c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd2)) { 14038c2ecf20Sopenharmony_ci /* 14048c2ecf20Sopenharmony_ci * invalid since operands are infinity 14058c2ecf20Sopenharmony_ci * and zero 14068c2ecf20Sopenharmony_ci */ 14078c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 14088c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 14098c2ecf20Sopenharmony_ci Set_invalidflag(); 14108c2ecf20Sopenharmony_ci Sgl_makequietnan(resultp1); 14118c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 14128c2ecf20Sopenharmony_ci return(NOEXCEPTION); 14138c2ecf20Sopenharmony_ci } 14148c2ecf20Sopenharmony_ci /* 14158c2ecf20Sopenharmony_ci * Check third operand for infinity with a 14168c2ecf20Sopenharmony_ci * sign opposite of the multiply result 14178c2ecf20Sopenharmony_ci */ 14188c2ecf20Sopenharmony_ci if (Sgl_isinfinity(opnd3) && 14198c2ecf20Sopenharmony_ci (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { 14208c2ecf20Sopenharmony_ci /* 14218c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 14228c2ecf20Sopenharmony_ci * subtraction of infinities 14238c2ecf20Sopenharmony_ci */ 14248c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 14258c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 14268c2ecf20Sopenharmony_ci Set_invalidflag(); 14278c2ecf20Sopenharmony_ci Sgl_makequietnan(resultp1); 14288c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 14298c2ecf20Sopenharmony_ci return(NOEXCEPTION); 14308c2ecf20Sopenharmony_ci } 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci /* 14338c2ecf20Sopenharmony_ci * return infinity 14348c2ecf20Sopenharmony_ci */ 14358c2ecf20Sopenharmony_ci Sgl_setinfinity_exponentmantissa(resultp1); 14368c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 14378c2ecf20Sopenharmony_ci return(NOEXCEPTION); 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci } 14408c2ecf20Sopenharmony_ci else { 14418c2ecf20Sopenharmony_ci /* 14428c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 14438c2ecf20Sopenharmony_ci */ 14448c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(opnd1)) { 14458c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 14468c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 14478c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 14488c2ecf20Sopenharmony_ci /* make NaN quiet */ 14498c2ecf20Sopenharmony_ci Set_invalidflag(); 14508c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd1); 14518c2ecf20Sopenharmony_ci } 14528c2ecf20Sopenharmony_ci /* 14538c2ecf20Sopenharmony_ci * is second operand a signaling NaN? 14548c2ecf20Sopenharmony_ci */ 14558c2ecf20Sopenharmony_ci else if (Sgl_is_signalingnan(opnd2)) { 14568c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 14578c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 14588c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 14598c2ecf20Sopenharmony_ci /* make NaN quiet */ 14608c2ecf20Sopenharmony_ci Set_invalidflag(); 14618c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd2); 14628c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd2,dstptr); 14638c2ecf20Sopenharmony_ci return(NOEXCEPTION); 14648c2ecf20Sopenharmony_ci } 14658c2ecf20Sopenharmony_ci /* 14668c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 14678c2ecf20Sopenharmony_ci */ 14688c2ecf20Sopenharmony_ci else if (Sgl_is_signalingnan(opnd3)) { 14698c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 14708c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 14718c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 14728c2ecf20Sopenharmony_ci /* make NaN quiet */ 14738c2ecf20Sopenharmony_ci Set_invalidflag(); 14748c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd3); 14758c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 14768c2ecf20Sopenharmony_ci return(NOEXCEPTION); 14778c2ecf20Sopenharmony_ci } 14788c2ecf20Sopenharmony_ci /* 14798c2ecf20Sopenharmony_ci * return quiet NaN 14808c2ecf20Sopenharmony_ci */ 14818c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd1,dstptr); 14828c2ecf20Sopenharmony_ci return(NOEXCEPTION); 14838c2ecf20Sopenharmony_ci } 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci /* 14878c2ecf20Sopenharmony_ci * check second operand for NaN's or infinity 14888c2ecf20Sopenharmony_ci */ 14898c2ecf20Sopenharmony_ci if (Sgl_isinfinity_exponent(opnd2)) { 14908c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd2)) { 14918c2ecf20Sopenharmony_ci if (Sgl_isnotnan(opnd3)) { 14928c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd1)) { 14938c2ecf20Sopenharmony_ci /* 14948c2ecf20Sopenharmony_ci * invalid since multiply operands are 14958c2ecf20Sopenharmony_ci * zero & infinity 14968c2ecf20Sopenharmony_ci */ 14978c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 14988c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 14998c2ecf20Sopenharmony_ci Set_invalidflag(); 15008c2ecf20Sopenharmony_ci Sgl_makequietnan(opnd2); 15018c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd2,dstptr); 15028c2ecf20Sopenharmony_ci return(NOEXCEPTION); 15038c2ecf20Sopenharmony_ci } 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci /* 15068c2ecf20Sopenharmony_ci * Check third operand for infinity with a 15078c2ecf20Sopenharmony_ci * sign opposite of the multiply result 15088c2ecf20Sopenharmony_ci */ 15098c2ecf20Sopenharmony_ci if (Sgl_isinfinity(opnd3) && 15108c2ecf20Sopenharmony_ci (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { 15118c2ecf20Sopenharmony_ci /* 15128c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 15138c2ecf20Sopenharmony_ci * subtraction of infinities 15148c2ecf20Sopenharmony_ci */ 15158c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 15168c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 15178c2ecf20Sopenharmony_ci Set_invalidflag(); 15188c2ecf20Sopenharmony_ci Sgl_makequietnan(resultp1); 15198c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 15208c2ecf20Sopenharmony_ci return(NOEXCEPTION); 15218c2ecf20Sopenharmony_ci } 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci /* 15248c2ecf20Sopenharmony_ci * return infinity 15258c2ecf20Sopenharmony_ci */ 15268c2ecf20Sopenharmony_ci Sgl_setinfinity_exponentmantissa(resultp1); 15278c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 15288c2ecf20Sopenharmony_ci return(NOEXCEPTION); 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci else { 15328c2ecf20Sopenharmony_ci /* 15338c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 15348c2ecf20Sopenharmony_ci */ 15358c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(opnd2)) { 15368c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 15378c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 15388c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 15398c2ecf20Sopenharmony_ci /* make NaN quiet */ 15408c2ecf20Sopenharmony_ci Set_invalidflag(); 15418c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd2); 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci /* 15448c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 15458c2ecf20Sopenharmony_ci */ 15468c2ecf20Sopenharmony_ci else if (Sgl_is_signalingnan(opnd3)) { 15478c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 15488c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 15498c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 15508c2ecf20Sopenharmony_ci /* make NaN quiet */ 15518c2ecf20Sopenharmony_ci Set_invalidflag(); 15528c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd3); 15538c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 15548c2ecf20Sopenharmony_ci return(NOEXCEPTION); 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci /* 15578c2ecf20Sopenharmony_ci * return quiet NaN 15588c2ecf20Sopenharmony_ci */ 15598c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd2,dstptr); 15608c2ecf20Sopenharmony_ci return(NOEXCEPTION); 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci } 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci /* 15658c2ecf20Sopenharmony_ci * check third operand for NaN's or infinity 15668c2ecf20Sopenharmony_ci */ 15678c2ecf20Sopenharmony_ci if (Sgl_isinfinity_exponent(opnd3)) { 15688c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd3)) { 15698c2ecf20Sopenharmony_ci /* return infinity */ 15708c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 15718c2ecf20Sopenharmony_ci return(NOEXCEPTION); 15728c2ecf20Sopenharmony_ci } else { 15738c2ecf20Sopenharmony_ci /* 15748c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 15758c2ecf20Sopenharmony_ci */ 15768c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(opnd3)) { 15778c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 15788c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 15798c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 15808c2ecf20Sopenharmony_ci /* make NaN quiet */ 15818c2ecf20Sopenharmony_ci Set_invalidflag(); 15828c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd3); 15838c2ecf20Sopenharmony_ci } 15848c2ecf20Sopenharmony_ci /* 15858c2ecf20Sopenharmony_ci * return quiet NaN 15868c2ecf20Sopenharmony_ci */ 15878c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 15888c2ecf20Sopenharmony_ci return(NOEXCEPTION); 15898c2ecf20Sopenharmony_ci } 15908c2ecf20Sopenharmony_ci } 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci /* 15938c2ecf20Sopenharmony_ci * Generate multiply mantissa 15948c2ecf20Sopenharmony_ci */ 15958c2ecf20Sopenharmony_ci if (Sgl_isnotzero_exponent(opnd1)) { 15968c2ecf20Sopenharmony_ci /* set hidden bit */ 15978c2ecf20Sopenharmony_ci Sgl_clear_signexponent_set_hidden(opnd1); 15988c2ecf20Sopenharmony_ci } 15998c2ecf20Sopenharmony_ci else { 16008c2ecf20Sopenharmony_ci /* check for zero */ 16018c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd1)) { 16028c2ecf20Sopenharmony_ci /* 16038c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 16048c2ecf20Sopenharmony_ci */ 16058c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd3)) { 16068c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 16078c2ecf20Sopenharmony_ci Sgl_or_signs(opnd3,resultp1); 16088c2ecf20Sopenharmony_ci } else { 16098c2ecf20Sopenharmony_ci Sgl_and_signs(opnd3,resultp1); 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci /* 16138c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 16148c2ecf20Sopenharmony_ci */ 16158c2ecf20Sopenharmony_ci else if (Sgl_iszero_exponent(opnd3) && 16168c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 16178c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 16188c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(opnd3); 16198c2ecf20Sopenharmony_ci result_exponent = 0; 16208c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd3); 16218c2ecf20Sopenharmony_ci Sgl_normalize(opnd3,result_exponent); 16228c2ecf20Sopenharmony_ci Sgl_set_sign(opnd3,/*using*/sign_save); 16238c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(opnd3,result_exponent, 16248c2ecf20Sopenharmony_ci unfl); 16258c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 16268c2ecf20Sopenharmony_ci /* inexact = FALSE */ 16278c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 16288c2ecf20Sopenharmony_ci } 16298c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 16308c2ecf20Sopenharmony_ci return(NOEXCEPTION); 16318c2ecf20Sopenharmony_ci } 16328c2ecf20Sopenharmony_ci /* is denormalized, adjust exponent */ 16338c2ecf20Sopenharmony_ci Sgl_clear_signexponent(opnd1); 16348c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd1); 16358c2ecf20Sopenharmony_ci Sgl_normalize(opnd1,mpy_exponent); 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci /* opnd2 needs to have hidden bit set with msb in hidden bit */ 16388c2ecf20Sopenharmony_ci if (Sgl_isnotzero_exponent(opnd2)) { 16398c2ecf20Sopenharmony_ci Sgl_clear_signexponent_set_hidden(opnd2); 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci else { 16428c2ecf20Sopenharmony_ci /* check for zero */ 16438c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd2)) { 16448c2ecf20Sopenharmony_ci /* 16458c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 16468c2ecf20Sopenharmony_ci */ 16478c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd3)) { 16488c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 16498c2ecf20Sopenharmony_ci Sgl_or_signs(opnd3,resultp1); 16508c2ecf20Sopenharmony_ci } else { 16518c2ecf20Sopenharmony_ci Sgl_and_signs(opnd3,resultp1); 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci /* 16558c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 16568c2ecf20Sopenharmony_ci */ 16578c2ecf20Sopenharmony_ci else if (Sgl_iszero_exponent(opnd3) && 16588c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 16598c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 16608c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(opnd3); 16618c2ecf20Sopenharmony_ci result_exponent = 0; 16628c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd3); 16638c2ecf20Sopenharmony_ci Sgl_normalize(opnd3,result_exponent); 16648c2ecf20Sopenharmony_ci Sgl_set_sign(opnd3,/*using*/sign_save); 16658c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(opnd3,result_exponent, 16668c2ecf20Sopenharmony_ci unfl); 16678c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 16688c2ecf20Sopenharmony_ci /* inexact = FALSE */ 16698c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 16708c2ecf20Sopenharmony_ci } 16718c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 16728c2ecf20Sopenharmony_ci return(NOEXCEPTION); 16738c2ecf20Sopenharmony_ci } 16748c2ecf20Sopenharmony_ci /* is denormalized; want to normalize */ 16758c2ecf20Sopenharmony_ci Sgl_clear_signexponent(opnd2); 16768c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd2); 16778c2ecf20Sopenharmony_ci Sgl_normalize(opnd2,mpy_exponent); 16788c2ecf20Sopenharmony_ci } 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci /* Multiply the first two source mantissas together */ 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci /* 16838c2ecf20Sopenharmony_ci * The intermediate result will be kept in tmpres, 16848c2ecf20Sopenharmony_ci * which needs enough room for 106 bits of mantissa, 16858c2ecf20Sopenharmony_ci * so lets call it a Double extended. 16868c2ecf20Sopenharmony_ci */ 16878c2ecf20Sopenharmony_ci Sglext_setzero(tmpresp1,tmpresp2); 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci /* 16908c2ecf20Sopenharmony_ci * Four bits at a time are inspected in each loop, and a 16918c2ecf20Sopenharmony_ci * simple shift and add multiply algorithm is used. 16928c2ecf20Sopenharmony_ci */ 16938c2ecf20Sopenharmony_ci for (count = SGL_P-1; count >= 0; count -= 4) { 16948c2ecf20Sopenharmony_ci Sglext_rightshiftby4(tmpresp1,tmpresp2); 16958c2ecf20Sopenharmony_ci if (Sbit28(opnd1)) { 16968c2ecf20Sopenharmony_ci /* Twoword_add should be an ADD followed by 2 ADDC's */ 16978c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); 16988c2ecf20Sopenharmony_ci } 16998c2ecf20Sopenharmony_ci if (Sbit29(opnd1)) { 17008c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); 17018c2ecf20Sopenharmony_ci } 17028c2ecf20Sopenharmony_ci if (Sbit30(opnd1)) { 17038c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); 17048c2ecf20Sopenharmony_ci } 17058c2ecf20Sopenharmony_ci if (Sbit31(opnd1)) { 17068c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2, 0); 17078c2ecf20Sopenharmony_ci } 17088c2ecf20Sopenharmony_ci Sgl_rightshiftby4(opnd1); 17098c2ecf20Sopenharmony_ci } 17108c2ecf20Sopenharmony_ci if (Is_sexthiddenoverflow(tmpresp1)) { 17118c2ecf20Sopenharmony_ci /* result mantissa >= 2 (mantissa overflow) */ 17128c2ecf20Sopenharmony_ci mpy_exponent++; 17138c2ecf20Sopenharmony_ci Sglext_rightshiftby4(tmpresp1,tmpresp2); 17148c2ecf20Sopenharmony_ci } else { 17158c2ecf20Sopenharmony_ci Sglext_rightshiftby3(tmpresp1,tmpresp2); 17168c2ecf20Sopenharmony_ci } 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci /* 17198c2ecf20Sopenharmony_ci * Restore the sign of the mpy result which was saved in resultp1. 17208c2ecf20Sopenharmony_ci * The exponent will continue to be kept in mpy_exponent. 17218c2ecf20Sopenharmony_ci */ 17228c2ecf20Sopenharmony_ci Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci /* 17258c2ecf20Sopenharmony_ci * No rounding is required, since the result of the multiply 17268c2ecf20Sopenharmony_ci * is exact in the extended format. 17278c2ecf20Sopenharmony_ci */ 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci /* 17308c2ecf20Sopenharmony_ci * Now we are ready to perform the add portion of the operation. 17318c2ecf20Sopenharmony_ci * 17328c2ecf20Sopenharmony_ci * The exponents need to be kept as integers for now, since the 17338c2ecf20Sopenharmony_ci * multiply result might not fit into the exponent field. We 17348c2ecf20Sopenharmony_ci * can't overflow or underflow because of this yet, since the 17358c2ecf20Sopenharmony_ci * add could bring the final result back into range. 17368c2ecf20Sopenharmony_ci */ 17378c2ecf20Sopenharmony_ci add_exponent = Sgl_exponent(opnd3); 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci /* 17408c2ecf20Sopenharmony_ci * Check for denormalized or zero add operand. 17418c2ecf20Sopenharmony_ci */ 17428c2ecf20Sopenharmony_ci if (add_exponent == 0) { 17438c2ecf20Sopenharmony_ci /* check for zero */ 17448c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd3)) { 17458c2ecf20Sopenharmony_ci /* right is zero */ 17468c2ecf20Sopenharmony_ci /* Left can't be zero and must be result. 17478c2ecf20Sopenharmony_ci * 17488c2ecf20Sopenharmony_ci * The final result is now in tmpres and mpy_exponent, 17498c2ecf20Sopenharmony_ci * and needs to be rounded and squeezed back into 17508c2ecf20Sopenharmony_ci * double precision format from double extended. 17518c2ecf20Sopenharmony_ci */ 17528c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 17538c2ecf20Sopenharmony_ci Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); 17548c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ 17558c2ecf20Sopenharmony_ci goto round; 17568c2ecf20Sopenharmony_ci } 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci /* 17598c2ecf20Sopenharmony_ci * Neither are zeroes. 17608c2ecf20Sopenharmony_ci * Adjust exponent and normalize add operand. 17618c2ecf20Sopenharmony_ci */ 17628c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(opnd3); /* save sign */ 17638c2ecf20Sopenharmony_ci Sgl_clear_signexponent(opnd3); 17648c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd3); 17658c2ecf20Sopenharmony_ci Sgl_normalize(opnd3,add_exponent); 17668c2ecf20Sopenharmony_ci Sgl_set_sign(opnd3,sign_save); /* restore sign */ 17678c2ecf20Sopenharmony_ci } else { 17688c2ecf20Sopenharmony_ci Sgl_clear_exponent_set_hidden(opnd3); 17698c2ecf20Sopenharmony_ci } 17708c2ecf20Sopenharmony_ci /* 17718c2ecf20Sopenharmony_ci * Copy opnd3 to the double extended variable called right. 17728c2ecf20Sopenharmony_ci */ 17738c2ecf20Sopenharmony_ci Sgl_copyto_sglext(opnd3,rightp1,rightp2); 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci /* 17768c2ecf20Sopenharmony_ci * A zero "save" helps discover equal operands (for later), 17778c2ecf20Sopenharmony_ci * and is used in swapping operands (if needed). 17788c2ecf20Sopenharmony_ci */ 17798c2ecf20Sopenharmony_ci Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci /* 17828c2ecf20Sopenharmony_ci * Compare magnitude of operands. 17838c2ecf20Sopenharmony_ci */ 17848c2ecf20Sopenharmony_ci Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); 17858c2ecf20Sopenharmony_ci Sglext_copytoint_exponentmantissa(rightp1,signlessright1); 17868c2ecf20Sopenharmony_ci if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && 17878c2ecf20Sopenharmony_ci Sglext_ismagnitudeless(signlessleft1,signlessright1)) { 17888c2ecf20Sopenharmony_ci /* 17898c2ecf20Sopenharmony_ci * Set the left operand to the larger one by XOR swap. 17908c2ecf20Sopenharmony_ci * First finish the first word "save". 17918c2ecf20Sopenharmony_ci */ 17928c2ecf20Sopenharmony_ci Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); 17938c2ecf20Sopenharmony_ci Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); 17948c2ecf20Sopenharmony_ci Sglext_swap_lower(tmpresp2,rightp2); 17958c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 17968c2ecf20Sopenharmony_ci diff_exponent = add_exponent - mpy_exponent; 17978c2ecf20Sopenharmony_ci result_exponent = add_exponent; 17988c2ecf20Sopenharmony_ci } else { 17998c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 18008c2ecf20Sopenharmony_ci diff_exponent = mpy_exponent - add_exponent; 18018c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 18028c2ecf20Sopenharmony_ci } 18038c2ecf20Sopenharmony_ci /* Invariant: left is not smaller than right. */ 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci /* 18068c2ecf20Sopenharmony_ci * Special case alignment of operands that would force alignment 18078c2ecf20Sopenharmony_ci * beyond the extent of the extension. A further optimization 18088c2ecf20Sopenharmony_ci * could special case this but only reduces the path length for 18098c2ecf20Sopenharmony_ci * this infrequent case. 18108c2ecf20Sopenharmony_ci */ 18118c2ecf20Sopenharmony_ci if (diff_exponent > SGLEXT_THRESHOLD) { 18128c2ecf20Sopenharmony_ci diff_exponent = SGLEXT_THRESHOLD; 18138c2ecf20Sopenharmony_ci } 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci /* Align right operand by shifting it to the right */ 18168c2ecf20Sopenharmony_ci Sglext_clear_sign(rightp1); 18178c2ecf20Sopenharmony_ci Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci /* Treat sum and difference of the operands separately. */ 18208c2ecf20Sopenharmony_ci if ((int)save < 0) { 18218c2ecf20Sopenharmony_ci /* 18228c2ecf20Sopenharmony_ci * Difference of the two operands. Overflow can occur if the 18238c2ecf20Sopenharmony_ci * multiply overflowed. A borrow can occur out of the hidden 18248c2ecf20Sopenharmony_ci * bit and force a post normalization phase. 18258c2ecf20Sopenharmony_ci */ 18268c2ecf20Sopenharmony_ci Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, 18278c2ecf20Sopenharmony_ci resultp1,resultp2); 18288c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(resultp1); 18298c2ecf20Sopenharmony_ci if (Sgl_iszero_hidden(resultp1)) { 18308c2ecf20Sopenharmony_ci /* Handle normalization */ 18318c2ecf20Sopenharmony_ci /* A straightforward algorithm would now shift the 18328c2ecf20Sopenharmony_ci * result and extension left until the hidden bit 18338c2ecf20Sopenharmony_ci * becomes one. Not all of the extension bits need 18348c2ecf20Sopenharmony_ci * participate in the shift. Only the two most 18358c2ecf20Sopenharmony_ci * significant bits (round and guard) are needed. 18368c2ecf20Sopenharmony_ci * If only a single shift is needed then the guard 18378c2ecf20Sopenharmony_ci * bit becomes a significant low order bit and the 18388c2ecf20Sopenharmony_ci * extension must participate in the rounding. 18398c2ecf20Sopenharmony_ci * If more than a single shift is needed, then all 18408c2ecf20Sopenharmony_ci * bits to the right of the guard bit are zeros, 18418c2ecf20Sopenharmony_ci * and the guard bit may or may not be zero. */ 18428c2ecf20Sopenharmony_ci Sglext_leftshiftby1(resultp1,resultp2); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci /* Need to check for a zero result. The sign and 18458c2ecf20Sopenharmony_ci * exponent fields have already been zeroed. The more 18468c2ecf20Sopenharmony_ci * efficient test of the full object can be used. 18478c2ecf20Sopenharmony_ci */ 18488c2ecf20Sopenharmony_ci if (Sglext_iszero(resultp1,resultp2)) { 18498c2ecf20Sopenharmony_ci /* Must have been "x-x" or "x+(-x)". */ 18508c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) 18518c2ecf20Sopenharmony_ci Sgl_setone_sign(resultp1); 18528c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 18538c2ecf20Sopenharmony_ci return(NOEXCEPTION); 18548c2ecf20Sopenharmony_ci } 18558c2ecf20Sopenharmony_ci result_exponent--; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci /* Look to see if normalization is finished. */ 18588c2ecf20Sopenharmony_ci if (Sgl_isone_hidden(resultp1)) { 18598c2ecf20Sopenharmony_ci /* No further normalization is needed */ 18608c2ecf20Sopenharmony_ci goto round; 18618c2ecf20Sopenharmony_ci } 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci /* Discover first one bit to determine shift amount. 18648c2ecf20Sopenharmony_ci * Use a modified binary search. We have already 18658c2ecf20Sopenharmony_ci * shifted the result one position right and still 18668c2ecf20Sopenharmony_ci * not found a one so the remainder of the extension 18678c2ecf20Sopenharmony_ci * must be zero and simplifies rounding. */ 18688c2ecf20Sopenharmony_ci /* Scan bytes */ 18698c2ecf20Sopenharmony_ci while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { 18708c2ecf20Sopenharmony_ci Sglext_leftshiftby8(resultp1,resultp2); 18718c2ecf20Sopenharmony_ci result_exponent -= 8; 18728c2ecf20Sopenharmony_ci } 18738c2ecf20Sopenharmony_ci /* Now narrow it down to the nibble */ 18748c2ecf20Sopenharmony_ci if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { 18758c2ecf20Sopenharmony_ci /* The lower nibble contains the 18768c2ecf20Sopenharmony_ci * normalizing one */ 18778c2ecf20Sopenharmony_ci Sglext_leftshiftby4(resultp1,resultp2); 18788c2ecf20Sopenharmony_ci result_exponent -= 4; 18798c2ecf20Sopenharmony_ci } 18808c2ecf20Sopenharmony_ci /* Select case where first bit is set (already 18818c2ecf20Sopenharmony_ci * normalized) otherwise select the proper shift. */ 18828c2ecf20Sopenharmony_ci jumpsize = Sgl_hiddenhigh3mantissa(resultp1); 18838c2ecf20Sopenharmony_ci if (jumpsize <= 7) switch(jumpsize) { 18848c2ecf20Sopenharmony_ci case 1: 18858c2ecf20Sopenharmony_ci Sglext_leftshiftby3(resultp1,resultp2); 18868c2ecf20Sopenharmony_ci result_exponent -= 3; 18878c2ecf20Sopenharmony_ci break; 18888c2ecf20Sopenharmony_ci case 2: 18898c2ecf20Sopenharmony_ci case 3: 18908c2ecf20Sopenharmony_ci Sglext_leftshiftby2(resultp1,resultp2); 18918c2ecf20Sopenharmony_ci result_exponent -= 2; 18928c2ecf20Sopenharmony_ci break; 18938c2ecf20Sopenharmony_ci case 4: 18948c2ecf20Sopenharmony_ci case 5: 18958c2ecf20Sopenharmony_ci case 6: 18968c2ecf20Sopenharmony_ci case 7: 18978c2ecf20Sopenharmony_ci Sglext_leftshiftby1(resultp1,resultp2); 18988c2ecf20Sopenharmony_ci result_exponent -= 1; 18998c2ecf20Sopenharmony_ci break; 19008c2ecf20Sopenharmony_ci } 19018c2ecf20Sopenharmony_ci } /* end if (hidden...)... */ 19028c2ecf20Sopenharmony_ci /* Fall through and round */ 19038c2ecf20Sopenharmony_ci } /* end if (save < 0)... */ 19048c2ecf20Sopenharmony_ci else { 19058c2ecf20Sopenharmony_ci /* Add magnitudes */ 19068c2ecf20Sopenharmony_ci Sglext_addition(tmpresp1,tmpresp2, 19078c2ecf20Sopenharmony_ci rightp1,rightp2, /*to*/resultp1,resultp2); 19088c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(resultp1); 19098c2ecf20Sopenharmony_ci if (Sgl_isone_hiddenoverflow(resultp1)) { 19108c2ecf20Sopenharmony_ci /* Prenormalization required. */ 19118c2ecf20Sopenharmony_ci Sglext_arithrightshiftby1(resultp1,resultp2); 19128c2ecf20Sopenharmony_ci result_exponent++; 19138c2ecf20Sopenharmony_ci } /* end if hiddenoverflow... */ 19148c2ecf20Sopenharmony_ci } /* end else ...add magnitudes... */ 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci /* Round the result. If the extension and lower two words are 19178c2ecf20Sopenharmony_ci * all zeros, then the result is exact. Otherwise round in the 19188c2ecf20Sopenharmony_ci * correct direction. Underflow is possible. If a postnormalization 19198c2ecf20Sopenharmony_ci * is necessary, then the mantissa is all zeros so no shift is needed. 19208c2ecf20Sopenharmony_ci */ 19218c2ecf20Sopenharmony_ci round: 19228c2ecf20Sopenharmony_ci if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { 19238c2ecf20Sopenharmony_ci Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); 19248c2ecf20Sopenharmony_ci } 19258c2ecf20Sopenharmony_ci Sgl_set_sign(resultp1,/*using*/sign_save); 19268c2ecf20Sopenharmony_ci if (Sglext_isnotzero_mantissap2(resultp2)) { 19278c2ecf20Sopenharmony_ci inexact = TRUE; 19288c2ecf20Sopenharmony_ci switch(Rounding_mode()) { 19298c2ecf20Sopenharmony_ci case ROUNDNEAREST: /* The default. */ 19308c2ecf20Sopenharmony_ci if (Sglext_isone_highp2(resultp2)) { 19318c2ecf20Sopenharmony_ci /* at least 1/2 ulp */ 19328c2ecf20Sopenharmony_ci if (Sglext_isnotzero_low31p2(resultp2) || 19338c2ecf20Sopenharmony_ci Sglext_isone_lowp1(resultp1)) { 19348c2ecf20Sopenharmony_ci /* either exactly half way and odd or 19358c2ecf20Sopenharmony_ci * more than 1/2ulp */ 19368c2ecf20Sopenharmony_ci Sgl_increment(resultp1); 19378c2ecf20Sopenharmony_ci } 19388c2ecf20Sopenharmony_ci } 19398c2ecf20Sopenharmony_ci break; 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci case ROUNDPLUS: 19428c2ecf20Sopenharmony_ci if (Sgl_iszero_sign(resultp1)) { 19438c2ecf20Sopenharmony_ci /* Round up positive results */ 19448c2ecf20Sopenharmony_ci Sgl_increment(resultp1); 19458c2ecf20Sopenharmony_ci } 19468c2ecf20Sopenharmony_ci break; 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci case ROUNDMINUS: 19498c2ecf20Sopenharmony_ci if (Sgl_isone_sign(resultp1)) { 19508c2ecf20Sopenharmony_ci /* Round down negative results */ 19518c2ecf20Sopenharmony_ci Sgl_increment(resultp1); 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci case ROUNDZERO:; 19558c2ecf20Sopenharmony_ci /* truncate is simple */ 19568c2ecf20Sopenharmony_ci } /* end switch... */ 19578c2ecf20Sopenharmony_ci if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; 19588c2ecf20Sopenharmony_ci } 19598c2ecf20Sopenharmony_ci if (result_exponent >= SGL_INFINITY_EXPONENT) { 19608c2ecf20Sopenharmony_ci /* Overflow */ 19618c2ecf20Sopenharmony_ci if (Is_overflowtrap_enabled()) { 19628c2ecf20Sopenharmony_ci /* 19638c2ecf20Sopenharmony_ci * Adjust bias of result 19648c2ecf20Sopenharmony_ci */ 19658c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); 19668c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 19678c2ecf20Sopenharmony_ci if (inexact) 19688c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 19698c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION | 19708c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 19718c2ecf20Sopenharmony_ci else Set_inexactflag(); 19728c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION); 19738c2ecf20Sopenharmony_ci } 19748c2ecf20Sopenharmony_ci inexact = TRUE; 19758c2ecf20Sopenharmony_ci Set_overflowflag(); 19768c2ecf20Sopenharmony_ci Sgl_setoverflow(resultp1); 19778c2ecf20Sopenharmony_ci } else if (result_exponent <= 0) { /* underflow case */ 19788c2ecf20Sopenharmony_ci if (Is_underflowtrap_enabled()) { 19798c2ecf20Sopenharmony_ci /* 19808c2ecf20Sopenharmony_ci * Adjust bias of result 19818c2ecf20Sopenharmony_ci */ 19828c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); 19838c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 19848c2ecf20Sopenharmony_ci if (inexact) 19858c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 19868c2ecf20Sopenharmony_ci return (OPC_2E_UNDERFLOWEXCEPTION | 19878c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 19888c2ecf20Sopenharmony_ci else Set_inexactflag(); 19898c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 19908c2ecf20Sopenharmony_ci } 19918c2ecf20Sopenharmony_ci else if (inexact && is_tiny) Set_underflowflag(); 19928c2ecf20Sopenharmony_ci } 19938c2ecf20Sopenharmony_ci else Sgl_set_exponent(resultp1,result_exponent); 19948c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 19958c2ecf20Sopenharmony_ci if (inexact) 19968c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); 19978c2ecf20Sopenharmony_ci else Set_inexactflag(); 19988c2ecf20Sopenharmony_ci return(NOEXCEPTION); 19998c2ecf20Sopenharmony_ci} 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci/* 20028c2ecf20Sopenharmony_ci * Single Floating-point Multiply Negate Fused Add 20038c2ecf20Sopenharmony_ci */ 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_cisgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_cisgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; 20088c2ecf20Sopenharmony_ciunsigned int *status; 20098c2ecf20Sopenharmony_ci{ 20108c2ecf20Sopenharmony_ci unsigned int opnd1, opnd2, opnd3; 20118c2ecf20Sopenharmony_ci register unsigned int tmpresp1, tmpresp2; 20128c2ecf20Sopenharmony_ci unsigned int rightp1, rightp2; 20138c2ecf20Sopenharmony_ci unsigned int resultp1, resultp2 = 0; 20148c2ecf20Sopenharmony_ci register int mpy_exponent, add_exponent, count; 20158c2ecf20Sopenharmony_ci boolean inexact = FALSE, is_tiny = FALSE; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci unsigned int signlessleft1, signlessright1, save; 20188c2ecf20Sopenharmony_ci register int result_exponent, diff_exponent; 20198c2ecf20Sopenharmony_ci int sign_save, jumpsize; 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci Sgl_copyfromptr(src1ptr,opnd1); 20228c2ecf20Sopenharmony_ci Sgl_copyfromptr(src2ptr,opnd2); 20238c2ecf20Sopenharmony_ci Sgl_copyfromptr(src3ptr,opnd3); 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci /* 20268c2ecf20Sopenharmony_ci * set sign bit of result of multiply 20278c2ecf20Sopenharmony_ci */ 20288c2ecf20Sopenharmony_ci if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) 20298c2ecf20Sopenharmony_ci Sgl_setzero(resultp1); 20308c2ecf20Sopenharmony_ci else 20318c2ecf20Sopenharmony_ci Sgl_setnegativezero(resultp1); 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_ci /* 20348c2ecf20Sopenharmony_ci * Generate multiply exponent 20358c2ecf20Sopenharmony_ci */ 20368c2ecf20Sopenharmony_ci mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci /* 20398c2ecf20Sopenharmony_ci * check first operand for NaN's or infinity 20408c2ecf20Sopenharmony_ci */ 20418c2ecf20Sopenharmony_ci if (Sgl_isinfinity_exponent(opnd1)) { 20428c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd1)) { 20438c2ecf20Sopenharmony_ci if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { 20448c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd2)) { 20458c2ecf20Sopenharmony_ci /* 20468c2ecf20Sopenharmony_ci * invalid since operands are infinity 20478c2ecf20Sopenharmony_ci * and zero 20488c2ecf20Sopenharmony_ci */ 20498c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 20508c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 20518c2ecf20Sopenharmony_ci Set_invalidflag(); 20528c2ecf20Sopenharmony_ci Sgl_makequietnan(resultp1); 20538c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 20548c2ecf20Sopenharmony_ci return(NOEXCEPTION); 20558c2ecf20Sopenharmony_ci } 20568c2ecf20Sopenharmony_ci /* 20578c2ecf20Sopenharmony_ci * Check third operand for infinity with a 20588c2ecf20Sopenharmony_ci * sign opposite of the multiply result 20598c2ecf20Sopenharmony_ci */ 20608c2ecf20Sopenharmony_ci if (Sgl_isinfinity(opnd3) && 20618c2ecf20Sopenharmony_ci (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { 20628c2ecf20Sopenharmony_ci /* 20638c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 20648c2ecf20Sopenharmony_ci * subtraction of infinities 20658c2ecf20Sopenharmony_ci */ 20668c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 20678c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 20688c2ecf20Sopenharmony_ci Set_invalidflag(); 20698c2ecf20Sopenharmony_ci Sgl_makequietnan(resultp1); 20708c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 20718c2ecf20Sopenharmony_ci return(NOEXCEPTION); 20728c2ecf20Sopenharmony_ci } 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci /* 20758c2ecf20Sopenharmony_ci * return infinity 20768c2ecf20Sopenharmony_ci */ 20778c2ecf20Sopenharmony_ci Sgl_setinfinity_exponentmantissa(resultp1); 20788c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 20798c2ecf20Sopenharmony_ci return(NOEXCEPTION); 20808c2ecf20Sopenharmony_ci } 20818c2ecf20Sopenharmony_ci } 20828c2ecf20Sopenharmony_ci else { 20838c2ecf20Sopenharmony_ci /* 20848c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 20858c2ecf20Sopenharmony_ci */ 20868c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(opnd1)) { 20878c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 20888c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 20898c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 20908c2ecf20Sopenharmony_ci /* make NaN quiet */ 20918c2ecf20Sopenharmony_ci Set_invalidflag(); 20928c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd1); 20938c2ecf20Sopenharmony_ci } 20948c2ecf20Sopenharmony_ci /* 20958c2ecf20Sopenharmony_ci * is second operand a signaling NaN? 20968c2ecf20Sopenharmony_ci */ 20978c2ecf20Sopenharmony_ci else if (Sgl_is_signalingnan(opnd2)) { 20988c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 20998c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 21008c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 21018c2ecf20Sopenharmony_ci /* make NaN quiet */ 21028c2ecf20Sopenharmony_ci Set_invalidflag(); 21038c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd2); 21048c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd2,dstptr); 21058c2ecf20Sopenharmony_ci return(NOEXCEPTION); 21068c2ecf20Sopenharmony_ci } 21078c2ecf20Sopenharmony_ci /* 21088c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 21098c2ecf20Sopenharmony_ci */ 21108c2ecf20Sopenharmony_ci else if (Sgl_is_signalingnan(opnd3)) { 21118c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 21128c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 21138c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 21148c2ecf20Sopenharmony_ci /* make NaN quiet */ 21158c2ecf20Sopenharmony_ci Set_invalidflag(); 21168c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd3); 21178c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 21188c2ecf20Sopenharmony_ci return(NOEXCEPTION); 21198c2ecf20Sopenharmony_ci } 21208c2ecf20Sopenharmony_ci /* 21218c2ecf20Sopenharmony_ci * return quiet NaN 21228c2ecf20Sopenharmony_ci */ 21238c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd1,dstptr); 21248c2ecf20Sopenharmony_ci return(NOEXCEPTION); 21258c2ecf20Sopenharmony_ci } 21268c2ecf20Sopenharmony_ci } 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci /* 21298c2ecf20Sopenharmony_ci * check second operand for NaN's or infinity 21308c2ecf20Sopenharmony_ci */ 21318c2ecf20Sopenharmony_ci if (Sgl_isinfinity_exponent(opnd2)) { 21328c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd2)) { 21338c2ecf20Sopenharmony_ci if (Sgl_isnotnan(opnd3)) { 21348c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd1)) { 21358c2ecf20Sopenharmony_ci /* 21368c2ecf20Sopenharmony_ci * invalid since multiply operands are 21378c2ecf20Sopenharmony_ci * zero & infinity 21388c2ecf20Sopenharmony_ci */ 21398c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 21408c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 21418c2ecf20Sopenharmony_ci Set_invalidflag(); 21428c2ecf20Sopenharmony_ci Sgl_makequietnan(opnd2); 21438c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd2,dstptr); 21448c2ecf20Sopenharmony_ci return(NOEXCEPTION); 21458c2ecf20Sopenharmony_ci } 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci /* 21488c2ecf20Sopenharmony_ci * Check third operand for infinity with a 21498c2ecf20Sopenharmony_ci * sign opposite of the multiply result 21508c2ecf20Sopenharmony_ci */ 21518c2ecf20Sopenharmony_ci if (Sgl_isinfinity(opnd3) && 21528c2ecf20Sopenharmony_ci (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { 21538c2ecf20Sopenharmony_ci /* 21548c2ecf20Sopenharmony_ci * invalid since attempting a magnitude 21558c2ecf20Sopenharmony_ci * subtraction of infinities 21568c2ecf20Sopenharmony_ci */ 21578c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 21588c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 21598c2ecf20Sopenharmony_ci Set_invalidflag(); 21608c2ecf20Sopenharmony_ci Sgl_makequietnan(resultp1); 21618c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 21628c2ecf20Sopenharmony_ci return(NOEXCEPTION); 21638c2ecf20Sopenharmony_ci } 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci /* 21668c2ecf20Sopenharmony_ci * return infinity 21678c2ecf20Sopenharmony_ci */ 21688c2ecf20Sopenharmony_ci Sgl_setinfinity_exponentmantissa(resultp1); 21698c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 21708c2ecf20Sopenharmony_ci return(NOEXCEPTION); 21718c2ecf20Sopenharmony_ci } 21728c2ecf20Sopenharmony_ci } 21738c2ecf20Sopenharmony_ci else { 21748c2ecf20Sopenharmony_ci /* 21758c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 21768c2ecf20Sopenharmony_ci */ 21778c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(opnd2)) { 21788c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 21798c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 21808c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 21818c2ecf20Sopenharmony_ci /* make NaN quiet */ 21828c2ecf20Sopenharmony_ci Set_invalidflag(); 21838c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd2); 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci /* 21868c2ecf20Sopenharmony_ci * is third operand a signaling NaN? 21878c2ecf20Sopenharmony_ci */ 21888c2ecf20Sopenharmony_ci else if (Sgl_is_signalingnan(opnd3)) { 21898c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 21908c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 21918c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 21928c2ecf20Sopenharmony_ci /* make NaN quiet */ 21938c2ecf20Sopenharmony_ci Set_invalidflag(); 21948c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd3); 21958c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 21968c2ecf20Sopenharmony_ci return(NOEXCEPTION); 21978c2ecf20Sopenharmony_ci } 21988c2ecf20Sopenharmony_ci /* 21998c2ecf20Sopenharmony_ci * return quiet NaN 22008c2ecf20Sopenharmony_ci */ 22018c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd2,dstptr); 22028c2ecf20Sopenharmony_ci return(NOEXCEPTION); 22038c2ecf20Sopenharmony_ci } 22048c2ecf20Sopenharmony_ci } 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci /* 22078c2ecf20Sopenharmony_ci * check third operand for NaN's or infinity 22088c2ecf20Sopenharmony_ci */ 22098c2ecf20Sopenharmony_ci if (Sgl_isinfinity_exponent(opnd3)) { 22108c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd3)) { 22118c2ecf20Sopenharmony_ci /* return infinity */ 22128c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 22138c2ecf20Sopenharmony_ci return(NOEXCEPTION); 22148c2ecf20Sopenharmony_ci } else { 22158c2ecf20Sopenharmony_ci /* 22168c2ecf20Sopenharmony_ci * is NaN; signaling or quiet? 22178c2ecf20Sopenharmony_ci */ 22188c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(opnd3)) { 22198c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 22208c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) 22218c2ecf20Sopenharmony_ci return(OPC_2E_INVALIDEXCEPTION); 22228c2ecf20Sopenharmony_ci /* make NaN quiet */ 22238c2ecf20Sopenharmony_ci Set_invalidflag(); 22248c2ecf20Sopenharmony_ci Sgl_set_quiet(opnd3); 22258c2ecf20Sopenharmony_ci } 22268c2ecf20Sopenharmony_ci /* 22278c2ecf20Sopenharmony_ci * return quiet NaN 22288c2ecf20Sopenharmony_ci */ 22298c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 22308c2ecf20Sopenharmony_ci return(NOEXCEPTION); 22318c2ecf20Sopenharmony_ci } 22328c2ecf20Sopenharmony_ci } 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci /* 22358c2ecf20Sopenharmony_ci * Generate multiply mantissa 22368c2ecf20Sopenharmony_ci */ 22378c2ecf20Sopenharmony_ci if (Sgl_isnotzero_exponent(opnd1)) { 22388c2ecf20Sopenharmony_ci /* set hidden bit */ 22398c2ecf20Sopenharmony_ci Sgl_clear_signexponent_set_hidden(opnd1); 22408c2ecf20Sopenharmony_ci } 22418c2ecf20Sopenharmony_ci else { 22428c2ecf20Sopenharmony_ci /* check for zero */ 22438c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd1)) { 22448c2ecf20Sopenharmony_ci /* 22458c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 22468c2ecf20Sopenharmony_ci */ 22478c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd3)) { 22488c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 22498c2ecf20Sopenharmony_ci Sgl_or_signs(opnd3,resultp1); 22508c2ecf20Sopenharmony_ci } else { 22518c2ecf20Sopenharmony_ci Sgl_and_signs(opnd3,resultp1); 22528c2ecf20Sopenharmony_ci } 22538c2ecf20Sopenharmony_ci } 22548c2ecf20Sopenharmony_ci /* 22558c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 22568c2ecf20Sopenharmony_ci */ 22578c2ecf20Sopenharmony_ci else if (Sgl_iszero_exponent(opnd3) && 22588c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 22598c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 22608c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(opnd3); 22618c2ecf20Sopenharmony_ci result_exponent = 0; 22628c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd3); 22638c2ecf20Sopenharmony_ci Sgl_normalize(opnd3,result_exponent); 22648c2ecf20Sopenharmony_ci Sgl_set_sign(opnd3,/*using*/sign_save); 22658c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(opnd3,result_exponent, 22668c2ecf20Sopenharmony_ci unfl); 22678c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 22688c2ecf20Sopenharmony_ci /* inexact = FALSE */ 22698c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 22708c2ecf20Sopenharmony_ci } 22718c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 22728c2ecf20Sopenharmony_ci return(NOEXCEPTION); 22738c2ecf20Sopenharmony_ci } 22748c2ecf20Sopenharmony_ci /* is denormalized, adjust exponent */ 22758c2ecf20Sopenharmony_ci Sgl_clear_signexponent(opnd1); 22768c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd1); 22778c2ecf20Sopenharmony_ci Sgl_normalize(opnd1,mpy_exponent); 22788c2ecf20Sopenharmony_ci } 22798c2ecf20Sopenharmony_ci /* opnd2 needs to have hidden bit set with msb in hidden bit */ 22808c2ecf20Sopenharmony_ci if (Sgl_isnotzero_exponent(opnd2)) { 22818c2ecf20Sopenharmony_ci Sgl_clear_signexponent_set_hidden(opnd2); 22828c2ecf20Sopenharmony_ci } 22838c2ecf20Sopenharmony_ci else { 22848c2ecf20Sopenharmony_ci /* check for zero */ 22858c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd2)) { 22868c2ecf20Sopenharmony_ci /* 22878c2ecf20Sopenharmony_ci * Perform the add opnd3 with zero here. 22888c2ecf20Sopenharmony_ci */ 22898c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(opnd3)) { 22908c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) { 22918c2ecf20Sopenharmony_ci Sgl_or_signs(opnd3,resultp1); 22928c2ecf20Sopenharmony_ci } else { 22938c2ecf20Sopenharmony_ci Sgl_and_signs(opnd3,resultp1); 22948c2ecf20Sopenharmony_ci } 22958c2ecf20Sopenharmony_ci } 22968c2ecf20Sopenharmony_ci /* 22978c2ecf20Sopenharmony_ci * Now let's check for trapped underflow case. 22988c2ecf20Sopenharmony_ci */ 22998c2ecf20Sopenharmony_ci else if (Sgl_iszero_exponent(opnd3) && 23008c2ecf20Sopenharmony_ci Is_underflowtrap_enabled()) { 23018c2ecf20Sopenharmony_ci /* need to normalize results mantissa */ 23028c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(opnd3); 23038c2ecf20Sopenharmony_ci result_exponent = 0; 23048c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd3); 23058c2ecf20Sopenharmony_ci Sgl_normalize(opnd3,result_exponent); 23068c2ecf20Sopenharmony_ci Sgl_set_sign(opnd3,/*using*/sign_save); 23078c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(opnd3,result_exponent, 23088c2ecf20Sopenharmony_ci unfl); 23098c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 23108c2ecf20Sopenharmony_ci /* inexact = FALSE */ 23118c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 23128c2ecf20Sopenharmony_ci } 23138c2ecf20Sopenharmony_ci Sgl_copytoptr(opnd3,dstptr); 23148c2ecf20Sopenharmony_ci return(NOEXCEPTION); 23158c2ecf20Sopenharmony_ci } 23168c2ecf20Sopenharmony_ci /* is denormalized; want to normalize */ 23178c2ecf20Sopenharmony_ci Sgl_clear_signexponent(opnd2); 23188c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd2); 23198c2ecf20Sopenharmony_ci Sgl_normalize(opnd2,mpy_exponent); 23208c2ecf20Sopenharmony_ci } 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci /* Multiply the first two source mantissas together */ 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_ci /* 23258c2ecf20Sopenharmony_ci * The intermediate result will be kept in tmpres, 23268c2ecf20Sopenharmony_ci * which needs enough room for 106 bits of mantissa, 23278c2ecf20Sopenharmony_ci * so lets call it a Double extended. 23288c2ecf20Sopenharmony_ci */ 23298c2ecf20Sopenharmony_ci Sglext_setzero(tmpresp1,tmpresp2); 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci /* 23328c2ecf20Sopenharmony_ci * Four bits at a time are inspected in each loop, and a 23338c2ecf20Sopenharmony_ci * simple shift and add multiply algorithm is used. 23348c2ecf20Sopenharmony_ci */ 23358c2ecf20Sopenharmony_ci for (count = SGL_P-1; count >= 0; count -= 4) { 23368c2ecf20Sopenharmony_ci Sglext_rightshiftby4(tmpresp1,tmpresp2); 23378c2ecf20Sopenharmony_ci if (Sbit28(opnd1)) { 23388c2ecf20Sopenharmony_ci /* Twoword_add should be an ADD followed by 2 ADDC's */ 23398c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); 23408c2ecf20Sopenharmony_ci } 23418c2ecf20Sopenharmony_ci if (Sbit29(opnd1)) { 23428c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); 23438c2ecf20Sopenharmony_ci } 23448c2ecf20Sopenharmony_ci if (Sbit30(opnd1)) { 23458c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); 23468c2ecf20Sopenharmony_ci } 23478c2ecf20Sopenharmony_ci if (Sbit31(opnd1)) { 23488c2ecf20Sopenharmony_ci Twoword_add(tmpresp1, tmpresp2, opnd2, 0); 23498c2ecf20Sopenharmony_ci } 23508c2ecf20Sopenharmony_ci Sgl_rightshiftby4(opnd1); 23518c2ecf20Sopenharmony_ci } 23528c2ecf20Sopenharmony_ci if (Is_sexthiddenoverflow(tmpresp1)) { 23538c2ecf20Sopenharmony_ci /* result mantissa >= 2 (mantissa overflow) */ 23548c2ecf20Sopenharmony_ci mpy_exponent++; 23558c2ecf20Sopenharmony_ci Sglext_rightshiftby4(tmpresp1,tmpresp2); 23568c2ecf20Sopenharmony_ci } else { 23578c2ecf20Sopenharmony_ci Sglext_rightshiftby3(tmpresp1,tmpresp2); 23588c2ecf20Sopenharmony_ci } 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci /* 23618c2ecf20Sopenharmony_ci * Restore the sign of the mpy result which was saved in resultp1. 23628c2ecf20Sopenharmony_ci * The exponent will continue to be kept in mpy_exponent. 23638c2ecf20Sopenharmony_ci */ 23648c2ecf20Sopenharmony_ci Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci /* 23678c2ecf20Sopenharmony_ci * No rounding is required, since the result of the multiply 23688c2ecf20Sopenharmony_ci * is exact in the extended format. 23698c2ecf20Sopenharmony_ci */ 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci /* 23728c2ecf20Sopenharmony_ci * Now we are ready to perform the add portion of the operation. 23738c2ecf20Sopenharmony_ci * 23748c2ecf20Sopenharmony_ci * The exponents need to be kept as integers for now, since the 23758c2ecf20Sopenharmony_ci * multiply result might not fit into the exponent field. We 23768c2ecf20Sopenharmony_ci * can't overflow or underflow because of this yet, since the 23778c2ecf20Sopenharmony_ci * add could bring the final result back into range. 23788c2ecf20Sopenharmony_ci */ 23798c2ecf20Sopenharmony_ci add_exponent = Sgl_exponent(opnd3); 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci /* 23828c2ecf20Sopenharmony_ci * Check for denormalized or zero add operand. 23838c2ecf20Sopenharmony_ci */ 23848c2ecf20Sopenharmony_ci if (add_exponent == 0) { 23858c2ecf20Sopenharmony_ci /* check for zero */ 23868c2ecf20Sopenharmony_ci if (Sgl_iszero_mantissa(opnd3)) { 23878c2ecf20Sopenharmony_ci /* right is zero */ 23888c2ecf20Sopenharmony_ci /* Left can't be zero and must be result. 23898c2ecf20Sopenharmony_ci * 23908c2ecf20Sopenharmony_ci * The final result is now in tmpres and mpy_exponent, 23918c2ecf20Sopenharmony_ci * and needs to be rounded and squeezed back into 23928c2ecf20Sopenharmony_ci * double precision format from double extended. 23938c2ecf20Sopenharmony_ci */ 23948c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 23958c2ecf20Sopenharmony_ci Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); 23968c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ 23978c2ecf20Sopenharmony_ci goto round; 23988c2ecf20Sopenharmony_ci } 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_ci /* 24018c2ecf20Sopenharmony_ci * Neither are zeroes. 24028c2ecf20Sopenharmony_ci * Adjust exponent and normalize add operand. 24038c2ecf20Sopenharmony_ci */ 24048c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(opnd3); /* save sign */ 24058c2ecf20Sopenharmony_ci Sgl_clear_signexponent(opnd3); 24068c2ecf20Sopenharmony_ci Sgl_leftshiftby1(opnd3); 24078c2ecf20Sopenharmony_ci Sgl_normalize(opnd3,add_exponent); 24088c2ecf20Sopenharmony_ci Sgl_set_sign(opnd3,sign_save); /* restore sign */ 24098c2ecf20Sopenharmony_ci } else { 24108c2ecf20Sopenharmony_ci Sgl_clear_exponent_set_hidden(opnd3); 24118c2ecf20Sopenharmony_ci } 24128c2ecf20Sopenharmony_ci /* 24138c2ecf20Sopenharmony_ci * Copy opnd3 to the double extended variable called right. 24148c2ecf20Sopenharmony_ci */ 24158c2ecf20Sopenharmony_ci Sgl_copyto_sglext(opnd3,rightp1,rightp2); 24168c2ecf20Sopenharmony_ci 24178c2ecf20Sopenharmony_ci /* 24188c2ecf20Sopenharmony_ci * A zero "save" helps discover equal operands (for later), 24198c2ecf20Sopenharmony_ci * and is used in swapping operands (if needed). 24208c2ecf20Sopenharmony_ci */ 24218c2ecf20Sopenharmony_ci Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); 24228c2ecf20Sopenharmony_ci 24238c2ecf20Sopenharmony_ci /* 24248c2ecf20Sopenharmony_ci * Compare magnitude of operands. 24258c2ecf20Sopenharmony_ci */ 24268c2ecf20Sopenharmony_ci Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); 24278c2ecf20Sopenharmony_ci Sglext_copytoint_exponentmantissa(rightp1,signlessright1); 24288c2ecf20Sopenharmony_ci if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && 24298c2ecf20Sopenharmony_ci Sglext_ismagnitudeless(signlessleft1,signlessright1)) { 24308c2ecf20Sopenharmony_ci /* 24318c2ecf20Sopenharmony_ci * Set the left operand to the larger one by XOR swap. 24328c2ecf20Sopenharmony_ci * First finish the first word "save". 24338c2ecf20Sopenharmony_ci */ 24348c2ecf20Sopenharmony_ci Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); 24358c2ecf20Sopenharmony_ci Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); 24368c2ecf20Sopenharmony_ci Sglext_swap_lower(tmpresp2,rightp2); 24378c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 24388c2ecf20Sopenharmony_ci diff_exponent = add_exponent - mpy_exponent; 24398c2ecf20Sopenharmony_ci result_exponent = add_exponent; 24408c2ecf20Sopenharmony_ci } else { 24418c2ecf20Sopenharmony_ci /* also setup exponents used in rest of routine */ 24428c2ecf20Sopenharmony_ci diff_exponent = mpy_exponent - add_exponent; 24438c2ecf20Sopenharmony_ci result_exponent = mpy_exponent; 24448c2ecf20Sopenharmony_ci } 24458c2ecf20Sopenharmony_ci /* Invariant: left is not smaller than right. */ 24468c2ecf20Sopenharmony_ci 24478c2ecf20Sopenharmony_ci /* 24488c2ecf20Sopenharmony_ci * Special case alignment of operands that would force alignment 24498c2ecf20Sopenharmony_ci * beyond the extent of the extension. A further optimization 24508c2ecf20Sopenharmony_ci * could special case this but only reduces the path length for 24518c2ecf20Sopenharmony_ci * this infrequent case. 24528c2ecf20Sopenharmony_ci */ 24538c2ecf20Sopenharmony_ci if (diff_exponent > SGLEXT_THRESHOLD) { 24548c2ecf20Sopenharmony_ci diff_exponent = SGLEXT_THRESHOLD; 24558c2ecf20Sopenharmony_ci } 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci /* Align right operand by shifting it to the right */ 24588c2ecf20Sopenharmony_ci Sglext_clear_sign(rightp1); 24598c2ecf20Sopenharmony_ci Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_ci /* Treat sum and difference of the operands separately. */ 24628c2ecf20Sopenharmony_ci if ((int)save < 0) { 24638c2ecf20Sopenharmony_ci /* 24648c2ecf20Sopenharmony_ci * Difference of the two operands. Overflow can occur if the 24658c2ecf20Sopenharmony_ci * multiply overflowed. A borrow can occur out of the hidden 24668c2ecf20Sopenharmony_ci * bit and force a post normalization phase. 24678c2ecf20Sopenharmony_ci */ 24688c2ecf20Sopenharmony_ci Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, 24698c2ecf20Sopenharmony_ci resultp1,resultp2); 24708c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(resultp1); 24718c2ecf20Sopenharmony_ci if (Sgl_iszero_hidden(resultp1)) { 24728c2ecf20Sopenharmony_ci /* Handle normalization */ 24738c2ecf20Sopenharmony_ci /* A straightforward algorithm would now shift the 24748c2ecf20Sopenharmony_ci * result and extension left until the hidden bit 24758c2ecf20Sopenharmony_ci * becomes one. Not all of the extension bits need 24768c2ecf20Sopenharmony_ci * participate in the shift. Only the two most 24778c2ecf20Sopenharmony_ci * significant bits (round and guard) are needed. 24788c2ecf20Sopenharmony_ci * If only a single shift is needed then the guard 24798c2ecf20Sopenharmony_ci * bit becomes a significant low order bit and the 24808c2ecf20Sopenharmony_ci * extension must participate in the rounding. 24818c2ecf20Sopenharmony_ci * If more than a single shift is needed, then all 24828c2ecf20Sopenharmony_ci * bits to the right of the guard bit are zeros, 24838c2ecf20Sopenharmony_ci * and the guard bit may or may not be zero. */ 24848c2ecf20Sopenharmony_ci Sglext_leftshiftby1(resultp1,resultp2); 24858c2ecf20Sopenharmony_ci 24868c2ecf20Sopenharmony_ci /* Need to check for a zero result. The sign and 24878c2ecf20Sopenharmony_ci * exponent fields have already been zeroed. The more 24888c2ecf20Sopenharmony_ci * efficient test of the full object can be used. 24898c2ecf20Sopenharmony_ci */ 24908c2ecf20Sopenharmony_ci if (Sglext_iszero(resultp1,resultp2)) { 24918c2ecf20Sopenharmony_ci /* Must have been "x-x" or "x+(-x)". */ 24928c2ecf20Sopenharmony_ci if (Is_rounding_mode(ROUNDMINUS)) 24938c2ecf20Sopenharmony_ci Sgl_setone_sign(resultp1); 24948c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 24958c2ecf20Sopenharmony_ci return(NOEXCEPTION); 24968c2ecf20Sopenharmony_ci } 24978c2ecf20Sopenharmony_ci result_exponent--; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci /* Look to see if normalization is finished. */ 25008c2ecf20Sopenharmony_ci if (Sgl_isone_hidden(resultp1)) { 25018c2ecf20Sopenharmony_ci /* No further normalization is needed */ 25028c2ecf20Sopenharmony_ci goto round; 25038c2ecf20Sopenharmony_ci } 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_ci /* Discover first one bit to determine shift amount. 25068c2ecf20Sopenharmony_ci * Use a modified binary search. We have already 25078c2ecf20Sopenharmony_ci * shifted the result one position right and still 25088c2ecf20Sopenharmony_ci * not found a one so the remainder of the extension 25098c2ecf20Sopenharmony_ci * must be zero and simplifies rounding. */ 25108c2ecf20Sopenharmony_ci /* Scan bytes */ 25118c2ecf20Sopenharmony_ci while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { 25128c2ecf20Sopenharmony_ci Sglext_leftshiftby8(resultp1,resultp2); 25138c2ecf20Sopenharmony_ci result_exponent -= 8; 25148c2ecf20Sopenharmony_ci } 25158c2ecf20Sopenharmony_ci /* Now narrow it down to the nibble */ 25168c2ecf20Sopenharmony_ci if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { 25178c2ecf20Sopenharmony_ci /* The lower nibble contains the 25188c2ecf20Sopenharmony_ci * normalizing one */ 25198c2ecf20Sopenharmony_ci Sglext_leftshiftby4(resultp1,resultp2); 25208c2ecf20Sopenharmony_ci result_exponent -= 4; 25218c2ecf20Sopenharmony_ci } 25228c2ecf20Sopenharmony_ci /* Select case where first bit is set (already 25238c2ecf20Sopenharmony_ci * normalized) otherwise select the proper shift. */ 25248c2ecf20Sopenharmony_ci jumpsize = Sgl_hiddenhigh3mantissa(resultp1); 25258c2ecf20Sopenharmony_ci if (jumpsize <= 7) switch(jumpsize) { 25268c2ecf20Sopenharmony_ci case 1: 25278c2ecf20Sopenharmony_ci Sglext_leftshiftby3(resultp1,resultp2); 25288c2ecf20Sopenharmony_ci result_exponent -= 3; 25298c2ecf20Sopenharmony_ci break; 25308c2ecf20Sopenharmony_ci case 2: 25318c2ecf20Sopenharmony_ci case 3: 25328c2ecf20Sopenharmony_ci Sglext_leftshiftby2(resultp1,resultp2); 25338c2ecf20Sopenharmony_ci result_exponent -= 2; 25348c2ecf20Sopenharmony_ci break; 25358c2ecf20Sopenharmony_ci case 4: 25368c2ecf20Sopenharmony_ci case 5: 25378c2ecf20Sopenharmony_ci case 6: 25388c2ecf20Sopenharmony_ci case 7: 25398c2ecf20Sopenharmony_ci Sglext_leftshiftby1(resultp1,resultp2); 25408c2ecf20Sopenharmony_ci result_exponent -= 1; 25418c2ecf20Sopenharmony_ci break; 25428c2ecf20Sopenharmony_ci } 25438c2ecf20Sopenharmony_ci } /* end if (hidden...)... */ 25448c2ecf20Sopenharmony_ci /* Fall through and round */ 25458c2ecf20Sopenharmony_ci } /* end if (save < 0)... */ 25468c2ecf20Sopenharmony_ci else { 25478c2ecf20Sopenharmony_ci /* Add magnitudes */ 25488c2ecf20Sopenharmony_ci Sglext_addition(tmpresp1,tmpresp2, 25498c2ecf20Sopenharmony_ci rightp1,rightp2, /*to*/resultp1,resultp2); 25508c2ecf20Sopenharmony_ci sign_save = Sgl_signextendedsign(resultp1); 25518c2ecf20Sopenharmony_ci if (Sgl_isone_hiddenoverflow(resultp1)) { 25528c2ecf20Sopenharmony_ci /* Prenormalization required. */ 25538c2ecf20Sopenharmony_ci Sglext_arithrightshiftby1(resultp1,resultp2); 25548c2ecf20Sopenharmony_ci result_exponent++; 25558c2ecf20Sopenharmony_ci } /* end if hiddenoverflow... */ 25568c2ecf20Sopenharmony_ci } /* end else ...add magnitudes... */ 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci /* Round the result. If the extension and lower two words are 25598c2ecf20Sopenharmony_ci * all zeros, then the result is exact. Otherwise round in the 25608c2ecf20Sopenharmony_ci * correct direction. Underflow is possible. If a postnormalization 25618c2ecf20Sopenharmony_ci * is necessary, then the mantissa is all zeros so no shift is needed. 25628c2ecf20Sopenharmony_ci */ 25638c2ecf20Sopenharmony_ci round: 25648c2ecf20Sopenharmony_ci if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { 25658c2ecf20Sopenharmony_ci Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); 25668c2ecf20Sopenharmony_ci } 25678c2ecf20Sopenharmony_ci Sgl_set_sign(resultp1,/*using*/sign_save); 25688c2ecf20Sopenharmony_ci if (Sglext_isnotzero_mantissap2(resultp2)) { 25698c2ecf20Sopenharmony_ci inexact = TRUE; 25708c2ecf20Sopenharmony_ci switch(Rounding_mode()) { 25718c2ecf20Sopenharmony_ci case ROUNDNEAREST: /* The default. */ 25728c2ecf20Sopenharmony_ci if (Sglext_isone_highp2(resultp2)) { 25738c2ecf20Sopenharmony_ci /* at least 1/2 ulp */ 25748c2ecf20Sopenharmony_ci if (Sglext_isnotzero_low31p2(resultp2) || 25758c2ecf20Sopenharmony_ci Sglext_isone_lowp1(resultp1)) { 25768c2ecf20Sopenharmony_ci /* either exactly half way and odd or 25778c2ecf20Sopenharmony_ci * more than 1/2ulp */ 25788c2ecf20Sopenharmony_ci Sgl_increment(resultp1); 25798c2ecf20Sopenharmony_ci } 25808c2ecf20Sopenharmony_ci } 25818c2ecf20Sopenharmony_ci break; 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci case ROUNDPLUS: 25848c2ecf20Sopenharmony_ci if (Sgl_iszero_sign(resultp1)) { 25858c2ecf20Sopenharmony_ci /* Round up positive results */ 25868c2ecf20Sopenharmony_ci Sgl_increment(resultp1); 25878c2ecf20Sopenharmony_ci } 25888c2ecf20Sopenharmony_ci break; 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci case ROUNDMINUS: 25918c2ecf20Sopenharmony_ci if (Sgl_isone_sign(resultp1)) { 25928c2ecf20Sopenharmony_ci /* Round down negative results */ 25938c2ecf20Sopenharmony_ci Sgl_increment(resultp1); 25948c2ecf20Sopenharmony_ci } 25958c2ecf20Sopenharmony_ci 25968c2ecf20Sopenharmony_ci case ROUNDZERO:; 25978c2ecf20Sopenharmony_ci /* truncate is simple */ 25988c2ecf20Sopenharmony_ci } /* end switch... */ 25998c2ecf20Sopenharmony_ci if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; 26008c2ecf20Sopenharmony_ci } 26018c2ecf20Sopenharmony_ci if (result_exponent >= SGL_INFINITY_EXPONENT) { 26028c2ecf20Sopenharmony_ci /* Overflow */ 26038c2ecf20Sopenharmony_ci if (Is_overflowtrap_enabled()) { 26048c2ecf20Sopenharmony_ci /* 26058c2ecf20Sopenharmony_ci * Adjust bias of result 26068c2ecf20Sopenharmony_ci */ 26078c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); 26088c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 26098c2ecf20Sopenharmony_ci if (inexact) 26108c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 26118c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION | 26128c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 26138c2ecf20Sopenharmony_ci else Set_inexactflag(); 26148c2ecf20Sopenharmony_ci return (OPC_2E_OVERFLOWEXCEPTION); 26158c2ecf20Sopenharmony_ci } 26168c2ecf20Sopenharmony_ci inexact = TRUE; 26178c2ecf20Sopenharmony_ci Set_overflowflag(); 26188c2ecf20Sopenharmony_ci Sgl_setoverflow(resultp1); 26198c2ecf20Sopenharmony_ci } else if (result_exponent <= 0) { /* underflow case */ 26208c2ecf20Sopenharmony_ci if (Is_underflowtrap_enabled()) { 26218c2ecf20Sopenharmony_ci /* 26228c2ecf20Sopenharmony_ci * Adjust bias of result 26238c2ecf20Sopenharmony_ci */ 26248c2ecf20Sopenharmony_ci Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); 26258c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 26268c2ecf20Sopenharmony_ci if (inexact) 26278c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) 26288c2ecf20Sopenharmony_ci return (OPC_2E_UNDERFLOWEXCEPTION | 26298c2ecf20Sopenharmony_ci OPC_2E_INEXACTEXCEPTION); 26308c2ecf20Sopenharmony_ci else Set_inexactflag(); 26318c2ecf20Sopenharmony_ci return(OPC_2E_UNDERFLOWEXCEPTION); 26328c2ecf20Sopenharmony_ci } 26338c2ecf20Sopenharmony_ci else if (inexact && is_tiny) Set_underflowflag(); 26348c2ecf20Sopenharmony_ci } 26358c2ecf20Sopenharmony_ci else Sgl_set_exponent(resultp1,result_exponent); 26368c2ecf20Sopenharmony_ci Sgl_copytoptr(resultp1,dstptr); 26378c2ecf20Sopenharmony_ci if (inexact) 26388c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); 26398c2ecf20Sopenharmony_ci else Set_inexactflag(); 26408c2ecf20Sopenharmony_ci return(NOEXCEPTION); 26418c2ecf20Sopenharmony_ci} 26428c2ecf20Sopenharmony_ci 2643