1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1988 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SunOS-4.1 1.8 88/12/06 */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <sys/fpu/fpu_simulator.h> 29*7c478bd9Sstevel@tonic-gate #include <sys/fpu/globals.h> 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate static void 32*7c478bd9Sstevel@tonic-gate true_add(px, py, pz) 33*7c478bd9Sstevel@tonic-gate unpacked *px, *py, *pz; 34*7c478bd9Sstevel@tonic-gate { 35*7c478bd9Sstevel@tonic-gate unsigned c; 36*7c478bd9Sstevel@tonic-gate unpacked *pt; 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate if ((int) px->fpclass <= (int) py->fpclass) { /* Reverse. */ 39*7c478bd9Sstevel@tonic-gate pt = py; 40*7c478bd9Sstevel@tonic-gate py = px; 41*7c478bd9Sstevel@tonic-gate px = pt; 42*7c478bd9Sstevel@tonic-gate } 43*7c478bd9Sstevel@tonic-gate /* Now class(x) >= class(y). */ 44*7c478bd9Sstevel@tonic-gate switch (px->fpclass) { 45*7c478bd9Sstevel@tonic-gate case fp_quiet: /* NaN + x -> NaN */ 46*7c478bd9Sstevel@tonic-gate case fp_signaling: /* NaN + x -> NaN */ 47*7c478bd9Sstevel@tonic-gate case fp_infinity: /* Inf + x -> Inf */ 48*7c478bd9Sstevel@tonic-gate case fp_zero: /* 0 + 0 -> 0 */ 49*7c478bd9Sstevel@tonic-gate *pz = *px; 50*7c478bd9Sstevel@tonic-gate return; 51*7c478bd9Sstevel@tonic-gate default: 52*7c478bd9Sstevel@tonic-gate if (py->fpclass == fp_zero) { 53*7c478bd9Sstevel@tonic-gate *pz = *px; 54*7c478bd9Sstevel@tonic-gate return; 55*7c478bd9Sstevel@tonic-gate } 56*7c478bd9Sstevel@tonic-gate } 57*7c478bd9Sstevel@tonic-gate /* Now z is normal or subnormal. */ 58*7c478bd9Sstevel@tonic-gate /* Now y is normal or subnormal. */ 59*7c478bd9Sstevel@tonic-gate if (px->exponent < py->exponent) { /* Reverse. */ 60*7c478bd9Sstevel@tonic-gate pt = py; 61*7c478bd9Sstevel@tonic-gate py = px; 62*7c478bd9Sstevel@tonic-gate px = pt; 63*7c478bd9Sstevel@tonic-gate } 64*7c478bd9Sstevel@tonic-gate /* Now class(x) >= class(y). */ 65*7c478bd9Sstevel@tonic-gate pz->fpclass = px->fpclass; 66*7c478bd9Sstevel@tonic-gate pz->sign = px->sign; 67*7c478bd9Sstevel@tonic-gate pz->exponent = px->exponent; 68*7c478bd9Sstevel@tonic-gate pz->rounded = pz->sticky = 0; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate if (px->exponent != py->exponent) { /* pre-alignment required */ 71*7c478bd9Sstevel@tonic-gate fpu_rightshift(py, pz->exponent - py->exponent); 72*7c478bd9Sstevel@tonic-gate pz->rounded = py->rounded; 73*7c478bd9Sstevel@tonic-gate pz->sticky = py->sticky; 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate c = 0; 76*7c478bd9Sstevel@tonic-gate c = fpu_add3wc(&(pz->significand[3]), px->significand[3], 77*7c478bd9Sstevel@tonic-gate py->significand[3], c); 78*7c478bd9Sstevel@tonic-gate c = fpu_add3wc(&(pz->significand[2]), px->significand[2], 79*7c478bd9Sstevel@tonic-gate py->significand[2], c); 80*7c478bd9Sstevel@tonic-gate c = fpu_add3wc(&(pz->significand[1]), px->significand[1], 81*7c478bd9Sstevel@tonic-gate py->significand[1], c); 82*7c478bd9Sstevel@tonic-gate c = fpu_add3wc(&(pz->significand[0]), px->significand[0], 83*7c478bd9Sstevel@tonic-gate py->significand[0], c); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* Handle carry out of msb. */ 86*7c478bd9Sstevel@tonic-gate if (pz->significand[0] >= 0x20000) { 87*7c478bd9Sstevel@tonic-gate fpu_rightshift(pz, 1); /* Carried out bit. */ 88*7c478bd9Sstevel@tonic-gate pz->exponent++; /* Renormalize. */ 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static void 93*7c478bd9Sstevel@tonic-gate true_sub(pfpsd, px, py, pz) 94*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd; /* Pointer to simulator data */ 95*7c478bd9Sstevel@tonic-gate unpacked *px, *py, *pz; 96*7c478bd9Sstevel@tonic-gate { 97*7c478bd9Sstevel@tonic-gate unsigned *z, g, s, r, c; 98*7c478bd9Sstevel@tonic-gate unpacked *pt; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate if ((int) px->fpclass <= (int) py->fpclass) { /* Reverse. */ 101*7c478bd9Sstevel@tonic-gate pt = py; 102*7c478bd9Sstevel@tonic-gate py = px; 103*7c478bd9Sstevel@tonic-gate px = pt; 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate /* Now class(x) >= class(y). */ 106*7c478bd9Sstevel@tonic-gate *pz = *px; /* Tentative difference: x. */ 107*7c478bd9Sstevel@tonic-gate switch (pz->fpclass) { 108*7c478bd9Sstevel@tonic-gate case fp_quiet: /* NaN - x -> NaN */ 109*7c478bd9Sstevel@tonic-gate case fp_signaling: /* NaN - x -> NaN */ 110*7c478bd9Sstevel@tonic-gate return; 111*7c478bd9Sstevel@tonic-gate case fp_infinity: /* Inf - x -> Inf */ 112*7c478bd9Sstevel@tonic-gate if (py->fpclass == fp_infinity) { 113*7c478bd9Sstevel@tonic-gate fpu_error_nan(pfpsd, pz); /* Inf - Inf -> NaN */ 114*7c478bd9Sstevel@tonic-gate pz->fpclass = fp_quiet; 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate return; 117*7c478bd9Sstevel@tonic-gate case fp_zero: /* 0 - 0 -> 0 */ 118*7c478bd9Sstevel@tonic-gate pz->sign = (pfpsd->fp_direction == fp_negative); 119*7c478bd9Sstevel@tonic-gate return; 120*7c478bd9Sstevel@tonic-gate default: 121*7c478bd9Sstevel@tonic-gate if (py->fpclass == fp_zero) 122*7c478bd9Sstevel@tonic-gate return; 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate /* x and y are both normal or subnormal. */ 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate if (px->exponent < py->exponent) { /* Reverse. */ 128*7c478bd9Sstevel@tonic-gate pt = py; 129*7c478bd9Sstevel@tonic-gate py = px; 130*7c478bd9Sstevel@tonic-gate px = pt; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate /* Now exp(x) >= exp(y). */ 133*7c478bd9Sstevel@tonic-gate pz->fpclass = px->fpclass; 134*7c478bd9Sstevel@tonic-gate pz->sign = px->sign; 135*7c478bd9Sstevel@tonic-gate pz->exponent = px->exponent; 136*7c478bd9Sstevel@tonic-gate pz->rounded = 0; 137*7c478bd9Sstevel@tonic-gate pz->sticky = 0; 138*7c478bd9Sstevel@tonic-gate z = pz->significand; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate if (px->exponent == py->exponent) { /* no pre-alignment required */ 141*7c478bd9Sstevel@tonic-gate c = 0; 142*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[3], px->significand[3], 143*7c478bd9Sstevel@tonic-gate py->significand[3], c); 144*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[2], px->significand[2], 145*7c478bd9Sstevel@tonic-gate py->significand[2], c); 146*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[1], px->significand[1], 147*7c478bd9Sstevel@tonic-gate py->significand[1], c); 148*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[0], px->significand[0], 149*7c478bd9Sstevel@tonic-gate py->significand[0], c); 150*7c478bd9Sstevel@tonic-gate if ((z[0]|z[1]|z[2]|z[3]) == 0) { /* exact zero result */ 151*7c478bd9Sstevel@tonic-gate pz->sign = (pfpsd->fp_direction == fp_negative); 152*7c478bd9Sstevel@tonic-gate pz->fpclass = fp_zero; 153*7c478bd9Sstevel@tonic-gate return; 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate if (z[0] >= 0x20000) { /* sign reversal occurred */ 156*7c478bd9Sstevel@tonic-gate pz->sign = py->sign; 157*7c478bd9Sstevel@tonic-gate c = 0; 158*7c478bd9Sstevel@tonic-gate c = fpu_neg2wc(&z[3], z[3], c); 159*7c478bd9Sstevel@tonic-gate c = fpu_neg2wc(&z[2], z[2], c); 160*7c478bd9Sstevel@tonic-gate c = fpu_neg2wc(&z[1], z[1], c); 161*7c478bd9Sstevel@tonic-gate c = fpu_neg2wc(&z[0], z[0], c); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate fpu_normalize(pz); 164*7c478bd9Sstevel@tonic-gate return; 165*7c478bd9Sstevel@tonic-gate } else { /* pre-alignment required */ 166*7c478bd9Sstevel@tonic-gate fpu_rightshift(py, pz->exponent - py->exponent - 1); 167*7c478bd9Sstevel@tonic-gate r = py->rounded; /* rounded bit */ 168*7c478bd9Sstevel@tonic-gate s = py->sticky; /* sticky bit */ 169*7c478bd9Sstevel@tonic-gate fpu_rightshift(py, 1); 170*7c478bd9Sstevel@tonic-gate g = py->rounded; /* guard bit */ 171*7c478bd9Sstevel@tonic-gate if (s != 0) r = (r == 0); 172*7c478bd9Sstevel@tonic-gate if ((r|s) != 0) g = (g == 0); /* guard and rounded bits of z */ 173*7c478bd9Sstevel@tonic-gate c = ((g|r|s) != 0); 174*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[3], px->significand[3], 175*7c478bd9Sstevel@tonic-gate py->significand[3], c); 176*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[2], px->significand[2], 177*7c478bd9Sstevel@tonic-gate py->significand[2], c); 178*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[1], px->significand[1], 179*7c478bd9Sstevel@tonic-gate py->significand[1], c); 180*7c478bd9Sstevel@tonic-gate c = fpu_sub3wc(&z[0], px->significand[0], 181*7c478bd9Sstevel@tonic-gate py->significand[0], c); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if (z[0] >= 0x10000) { /* don't need post-shifted */ 184*7c478bd9Sstevel@tonic-gate pz->sticky = s|r; 185*7c478bd9Sstevel@tonic-gate pz->rounded = g; 186*7c478bd9Sstevel@tonic-gate } else { /* post-shifted left 1 bit */ 187*7c478bd9Sstevel@tonic-gate pz->sticky = s; 188*7c478bd9Sstevel@tonic-gate pz->rounded = r; 189*7c478bd9Sstevel@tonic-gate pz->significand[0] = (z[0]<<1)|((z[1]&0x80000000)>>31); 190*7c478bd9Sstevel@tonic-gate pz->significand[1] = (z[1]<<1)|((z[2]&0x80000000)>>31); 191*7c478bd9Sstevel@tonic-gate pz->significand[2] = (z[2]<<1)|((z[3]&0x80000000)>>31); 192*7c478bd9Sstevel@tonic-gate pz->significand[3] = (z[3]<<1)|g; 193*7c478bd9Sstevel@tonic-gate pz->exponent -= 1; 194*7c478bd9Sstevel@tonic-gate if (z[0] < 0x10000) fpu_normalize(pz); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate return; 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate void 201*7c478bd9Sstevel@tonic-gate _fp_add(pfpsd, px, py, pz) 202*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd; 203*7c478bd9Sstevel@tonic-gate unpacked *px, *py, *pz; 204*7c478bd9Sstevel@tonic-gate { 205*7c478bd9Sstevel@tonic-gate if (px->sign == py->sign) 206*7c478bd9Sstevel@tonic-gate true_add(px, py, pz); 207*7c478bd9Sstevel@tonic-gate else 208*7c478bd9Sstevel@tonic-gate true_sub(pfpsd, px, py, pz); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate void 212*7c478bd9Sstevel@tonic-gate _fp_sub(pfpsd, px, py, pz) 213*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd; 214*7c478bd9Sstevel@tonic-gate unpacked *px, *py, *pz; 215*7c478bd9Sstevel@tonic-gate { 216*7c478bd9Sstevel@tonic-gate if (py->fpclass < fp_quiet) py->sign = 1 - py->sign; 217*7c478bd9Sstevel@tonic-gate if (px->sign == py->sign) 218*7c478bd9Sstevel@tonic-gate true_add(px, py, pz); 219*7c478bd9Sstevel@tonic-gate else 220*7c478bd9Sstevel@tonic-gate true_sub(pfpsd, px, py, pz); 221*7c478bd9Sstevel@tonic-gate } 222