1a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 2a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj/* Copyright (C) 2006 Dave Nomura 3a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dcnltc@us.ibm.com 4a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 5a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj This program is free software; you can redistribute it and/or 6a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj modify it under the terms of the GNU General Public License as 7a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj published by the Free Software Foundation; either version 2 of the 8a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj License, or (at your option) any later version. 9a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 10a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj This program is distributed in the hope that it will be useful, but 11a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj WITHOUT ANY WARRANTY; without even the implied warranty of 12a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj General Public License for more details. 14a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 15a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj You should have received a copy of the GNU General Public License 16a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj along with this program; if not, write to the Free Software 17a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 02111-1307, USA. 19a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 20a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj The GNU General Public License is contained in the file COPYING. 21a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj*/ 22a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 23a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#include <stdio.h> 24a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#include <stdlib.h> 25a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#include <limits.h> 26a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 27a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjtypedef enum { FALSE=0, TRUE } bool_t; 28a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 29a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjtypedef enum { 30a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FADDS, FSUBS, FMULS, FDIVS, 31a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FMADDS, FMSUBS, FNMADDS, FNMSUBS, 32a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FADD, FSUB, FMUL, FDIV, FMADD, 33a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FMSUB, FNMADD, FNMSUB, FSQRT 34a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} flt_op_t; 35a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 36a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjtypedef enum { 37a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t; 38a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjchar *round_mode_name[] = { "near", "zero", "+inf", "-inf" }; 39a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 40a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjconst char *flt_op_names[] = { 41a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj "fadds", "fsubs", "fmuls", "fdivs", 42a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj "fmadds", "fmsubs", "fnmadds", "fnmsubs", 43a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj "fadd", "fsub", "fmul", "fdiv", "fmadd", "fmsub", "fnmadd", 44a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj "fnmsub", "fsqrt" 45a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj}; 46a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 47a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjtypedef unsigned int fpscr_t; 48a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 49a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjtypedef union { 50a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float flt; 51a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj struct { 52ee55dc246230e70529b70c4bfb431db66e51525ccarll#if defined(VGP_ppc64le_linux) 53ee55dc246230e70529b70c4bfb431db66e51525ccarll unsigned int frac:23; 54ee55dc246230e70529b70c4bfb431db66e51525ccarll unsigned int exp:8; 55ee55dc246230e70529b70c4bfb431db66e51525ccarll unsigned int sign:1; 56ee55dc246230e70529b70c4bfb431db66e51525ccarll#else 57a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int sign:1; 58a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int exp:8; 59a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int frac:23; 60ee55dc246230e70529b70c4bfb431db66e51525ccarll#endif 61a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } layout; 62a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} flt_overlay; 63a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 64a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjtypedef union { 65a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double dbl; 66a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj struct { 67ee55dc246230e70529b70c4bfb431db66e51525ccarll#if defined(VGP_ppc64le_linux) 68ee55dc246230e70529b70c4bfb431db66e51525ccarll unsigned int frac_lo:32; 69ee55dc246230e70529b70c4bfb431db66e51525ccarll unsigned int frac_hi:20; 70ee55dc246230e70529b70c4bfb431db66e51525ccarll unsigned int exp:11; 71ee55dc246230e70529b70c4bfb431db66e51525ccarll unsigned int sign:1; 72ee55dc246230e70529b70c4bfb431db66e51525ccarll#else 73a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int sign:1; 74a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int exp:11; 75a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int frac_hi:20; 76a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int frac_lo:32; 77ee55dc246230e70529b70c4bfb431db66e51525ccarll#endif 78a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } layout; 79a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj struct { 80a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int hi; 81a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj unsigned int lo; 82a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } dbl_pair; 83a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} dbl_overlay; 84a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 85a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjvoid assert_fail(const char *msg, 86a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj const char* expr, const char* file, int line, const char*fn); 87a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 88a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define STRING(__str) #__str 89a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define assert(msg, expr) \ 90a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ((void) ((expr) ? 0 : \ 91a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (assert_fail (msg, STRING(expr), \ 92a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __FILE__, __LINE__, \ 93a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __PRETTY_FUNCTION__), 0))) 94a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjfloat denorm_small; 95a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjdouble dbl_denorm_small; 96a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjfloat norm_small; 97a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjbool_t debug = FALSE; 98a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjbool_t long_is_64_bits = sizeof(long) == 8; 99a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 100a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjvoid assert_fail (msg, expr, file, line, fn) 101a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjconst char* msg; 102a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjconst char* expr; 103a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjconst char* file; 104a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint line; 105a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjconst char*fn; 106a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 107a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf( "\n%s: %s:%d (%s): Assertion `%s' failed.\n", 108a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj msg, file, line, fn, expr ); 109a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj exit( 1 ); 110a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 111a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjvoid set_rounding_mode(round_mode_t mode) 112a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 113a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(mode) { 114a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_NEAREST: 115a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj asm volatile("mtfsfi 7, 0"); 116a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 117a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_ZERO: 118a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj asm volatile("mtfsfi 7, 1"); 119a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 120a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_PLUS_INFINITY: 121a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj asm volatile("mtfsfi 7, 2"); 122a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 123a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_MINUS_INFINITY: 124a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj asm volatile("mtfsfi 7, 3"); 125a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 126a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 127a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 128a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 129a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjvoid print_double(char *msg, double dbl) 130a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 131a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_overlay D; 132a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj D.dbl = dbl; 133a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 134a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%15s : dbl %-20a = %c(%4d, %05x%08x)\n", 135a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj msg, D.dbl, (D.layout.sign == 0 ? '+' : '-'), 136a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj D.layout.exp, D.layout.frac_hi, D.layout.frac_lo); 137a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 138a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 139a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjvoid print_single(char *msg, float *flt) 140a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 141a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj flt_overlay F; 142a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj F.flt = *flt; 143a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 144a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* NOTE: for the purposes of comparing the fraction of a single with 145a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** a double left shift the .frac so that hex digits are grouped 146a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** from left to right. this is necessary because the size of a 147a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** single mantissa (23) bits is not a multiple of 4 148a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 149a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%15s : flt %-20a = %c(%4d, %06x)\n", 150a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj msg, F.flt, (F.layout.sign == 0 ? '+' : '-'), F.layout.exp, F.layout.frac << 1); 151a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 152a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 153a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint check_dbl_to_flt_round(round_mode_t mode, double dbl, float *expected) 154a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 155a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 156a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj flt_overlay R, E; 157a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj char *result; 158a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 159a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj set_rounding_mode(mode); 160a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 161a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj E.flt = *expected; 162a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj R.flt = (float)dbl; 163a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 164a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if ((R.layout.sign != E.layout.sign) || 165a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.exp != E.layout.exp) || 166a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.frac != E.layout.frac)) { 167a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "FAILED"; 168a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 1; 169a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 170a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "PASSED"; 171a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 0; 172a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 173a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%s:%s:(double)(%-20a) = %20a", 174a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_name[mode], result, R.flt, dbl); 175a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (status) { 176a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_single("\n\texpected", &E.flt); 177a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_single("\n\trounded ", &R.flt); 178a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 179a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj putchar('\n'); 180a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 181a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 182a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 183a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint test_dbl_to_float_convert(char *msg, float *base) 184a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 185a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 186a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double half = (double)denorm_small/2; 187a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double qtr = half/2; 188a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double D_hi = (double)*base + half + qtr; 189a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double D_lo = (double)*base + half - qtr; 190a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float F_lo = *base; 191a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float F_hi = F_lo + denorm_small; 192a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 193a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 194a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 195a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** .....+-----+-----+-----+-----+---.... 196a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** ^F_lo ^ ^ ^ 197a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** D_lo 198a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** D_hi 199a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** F_hi 200a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** F_lo and F_hi are two consecutive single float model numbers 201a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** denorm_small distance apart. D_lo and D_hi are two numbers 202a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** within that range that are not representable as single floats 203a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** and will be rounded to either F_lo or F_hi. 204a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 205a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("-------------------------- %s --------------------------\n", msg); 206a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) { 207a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("D_lo", D_lo); 208a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("D_hi", D_hi); 209a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_single("F_lo", &F_lo); 210a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_single("F_hi", &F_hi); 211a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 212a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 213a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* round to nearest */ 214a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_NEAREST, D_hi, &F_hi); 215a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_NEAREST, D_lo, &F_lo); 216a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 217a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* round to zero */ 218a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_ZERO, D_hi, (D_hi > 0 ? &F_lo : &F_hi)); 219a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_ZERO, D_lo, (D_hi > 0 ? &F_lo : &F_hi)); 220a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 221a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* round to +inf */ 222a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_PLUS_INFINITY, D_hi, &F_hi); 223a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_PLUS_INFINITY, D_lo, &F_hi); 224a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 225a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* round to -inf */ 226a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_MINUS_INFINITY, D_hi, &F_lo); 227a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_dbl_to_flt_round(TO_MINUS_INFINITY, D_lo, &F_lo); 228a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 229a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 230a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 231a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjvoid 232a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjinit() 233a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 234a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj flt_overlay F; 235a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_overlay D; 236a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 237a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* small is the smallest denormalized single float number */ 238a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj F.layout.sign = 0; 239a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj F.layout.exp = 0; 240a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj F.layout.frac = 1; 241a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj denorm_small = F.flt; /* == 2^(-149) */ 242a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) { 243ee55dc246230e70529b70c4bfb431db66e51525ccarll print_single("float small", &F.flt); 244a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 245a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 246a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj D.layout.sign = 0; 247a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj D.layout.exp = 0; 248a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj D.layout.frac_hi = 0; 249a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj D.layout.frac_lo = 1; 250a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_denorm_small = D.dbl; /* == 2^(-1022) */ 251a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) { 252a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("double small", D.dbl); 253a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 254a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 255a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* n_small is the smallest normalized single precision float */ 256a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj F.layout.exp = 1; 257a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj norm_small = F.flt; 258a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 259a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 260a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint check_int_to_flt_round(round_mode_t mode, long L, float *expected) 261a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 262a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 263a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int I = L; 264a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj char *int_name = "int"; 265a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj flt_overlay R, E; 266a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj char *result; 267a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int iter; 268a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 269a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj set_rounding_mode(mode); 270a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj E.flt = *expected; 271a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 272a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (iter = 0; iter < 2; iter++) { 273a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int stat = 0; 274a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj R.flt = (iter == 0 ? (float)I : (float)L); 275a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 276a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if ((R.layout.sign != E.layout.sign) || 277a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.exp != E.layout.exp) || 278a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.frac != E.layout.frac)) { 279a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "FAILED"; 280a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj stat = 1; 281a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 282a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "PASSED"; 283a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj stat = 0; 284a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 285a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%s:%s:(float)(%4s)%9d = %11.1f", 286a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_name[mode], result, int_name, I, R.flt); 287a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (stat) { 288a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_single("\n\texpected: %.1f ", &E.flt); 289a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_single("\n\trounded ", &R.flt); 290a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 291a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj putchar('\n'); 292a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= stat; 293a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 294a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (!long_is_64_bits) break; 295a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int_name = "long"; 296a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 297a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 298a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 299a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 300a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint check_long_to_dbl_round(round_mode_t mode, long L, double *expected) 301a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 302a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 303a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_overlay R, E; 304a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj char *result; 305a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 306a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj set_rounding_mode(mode); 307a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj E.dbl = *expected; 308a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 309a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj R.dbl = (double)L; 310a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 311a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if ((R.layout.sign != E.layout.sign) || 312a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.exp != E.layout.exp) || 313a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.frac_lo != E.layout.frac_lo) || 314a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.frac_hi != E.layout.frac_hi)) { 315a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "FAILED"; 316a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 1; 317a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 318a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "PASSED"; 319a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 0; 320a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 321a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%s:%s:(double)(%18ld) = %20.1f", 322a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_name[mode], result, L, R.dbl); 323a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (status) { 324a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("\n\texpected %.1f : ", E.dbl); 325a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 326a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj putchar('\n'); 327a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 328a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 329a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 330a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint test_int_to_float_convert(char *msg) 331a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 332a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 333a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int int24_hi = 0x03ff0fff; 334a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int int24_lo = 0x03ff0ffd; 335a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float pos_flt_lo = 67047420.0; 336a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float pos_flt_hi = 67047424.0; 337a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float neg_flt_lo = -67047420.0; 338a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float neg_flt_hi = -67047424.0; 339a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 340a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("-------------------------- %s --------------------------\n", msg); 341a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_NEAREST, int24_lo, &pos_flt_lo); 342a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_NEAREST, int24_hi, &pos_flt_hi); 343a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_ZERO, int24_lo, &pos_flt_lo); 344a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_ZERO, int24_hi, &pos_flt_lo); 345a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_PLUS_INFINITY, int24_lo, &pos_flt_hi); 346a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_PLUS_INFINITY, int24_hi, &pos_flt_hi); 347a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_MINUS_INFINITY, int24_lo, &pos_flt_lo); 348a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_MINUS_INFINITY, int24_hi, &pos_flt_lo); 349a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 350a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_NEAREST, -int24_lo, &neg_flt_lo); 351a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_NEAREST, -int24_hi, &neg_flt_hi); 352a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_ZERO, -int24_lo, &neg_flt_lo); 353a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_ZERO, -int24_hi, &neg_flt_lo); 354a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_PLUS_INFINITY, -int24_lo, &neg_flt_lo); 355a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_PLUS_INFINITY, -int24_hi, &neg_flt_lo); 356a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_MINUS_INFINITY, -int24_lo, &neg_flt_hi); 357a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_int_to_flt_round(TO_MINUS_INFINITY, -int24_hi, &neg_flt_hi); 358a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 359a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 360a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 361a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#ifdef __powerpc64__ 362a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint test_long_to_double_convert(char *msg) 363a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 364a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 365a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj long long55_hi = 0x07ff0ffffffffff; 366a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj long long55_lo = 0x07ff0fffffffffd; 367a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double pos_dbl_lo = 36012304344547324.0; 368a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double pos_dbl_hi = 36012304344547328.0; 369a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double neg_dbl_lo = -36012304344547324.0; 370a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double neg_dbl_hi = -36012304344547328.0; 371a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 372a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("-------------------------- %s --------------------------\n", msg); 373a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_NEAREST, long55_lo, &pos_dbl_lo); 374a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_NEAREST, long55_hi, &pos_dbl_hi); 375a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_ZERO, long55_lo, &pos_dbl_lo); 376a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_ZERO, long55_hi, &pos_dbl_lo); 377a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_PLUS_INFINITY, long55_lo, &pos_dbl_hi); 378a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_PLUS_INFINITY, long55_hi, &pos_dbl_hi); 379a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_MINUS_INFINITY, long55_lo, &pos_dbl_lo); 380a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_MINUS_INFINITY, long55_hi, &pos_dbl_lo); 381a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 382a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_NEAREST, -long55_lo, &neg_dbl_lo); 383a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_NEAREST, -long55_hi, &neg_dbl_hi); 384a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_ZERO, -long55_lo, &neg_dbl_lo); 385a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_ZERO, -long55_hi, &neg_dbl_lo); 386a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_PLUS_INFINITY, -long55_lo, &neg_dbl_lo); 387a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_PLUS_INFINITY, -long55_hi, &neg_dbl_lo); 388a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_MINUS_INFINITY, -long55_lo, &neg_dbl_hi); 389a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_long_to_dbl_round(TO_MINUS_INFINITY, -long55_hi, &neg_dbl_hi); 390a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 391a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 392a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#endif 393a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 394a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint check_single_arithmetic_op(flt_op_t op) 395a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 396a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj char *result; 397a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 398a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_overlay R, E; 399a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double qtr, half, fA, fB, fD; 400a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_t mode; 401a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int q, s; 402a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj bool_t two_args = TRUE; 403a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj float whole = denorm_small; 404a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 405a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define BINOP(op) \ 406a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 407a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1, %2\n\t" \ 408a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA) , "f"(fB)); 409a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define UNOP(op) \ 410a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 411a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1\n\t" \ 412a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA)); 413a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 414a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj half = (double)whole/2; 415a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj qtr = half/2; 416a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 417a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) { 418a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("qtr", qtr); 419a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("whole", whole); 420a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("2*whole", 2*whole); 421a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 422a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 423a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (mode = TO_NEAREST; mode <= TO_MINUS_INFINITY; mode++) 424a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (s = -1; s < 2; s += 2) 425a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (q = 1; q < 4; q += 2) { 426a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double expected; 427a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double lo = s*whole; 428a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double hi = s*2*whole; 429a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 430a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(op) { 431a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FADDS: 432a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*whole; 433a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*q*qtr; 434a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 435a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSUBS: 436a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*2*whole; 437a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*(q == 1 ? 3 : 1)*qtr; 438a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 439a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMULS: 440a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = 0.5; 441a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*(4+q)*half; 442a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 443a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FDIVS: 444a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*(4+q)*half; 445a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = 2.0; 446a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 447a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 448a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_single_arithmetic_op: unexpected op", 449a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 450a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 451a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 452a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 453a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(mode) { 454a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_NEAREST: 455a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (q == 1 ? lo : hi); 456a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 457a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_ZERO: 458a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 459a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 460a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_PLUS_INFINITY: 461a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (s == 1 ? hi : lo); 462a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 463a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_MINUS_INFINITY: 464a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (s == 1 ? lo : hi); 465a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 466a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 467a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 468a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj set_rounding_mode(mode); 469a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 470a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 471a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** do the double precision dual operation just for comparison 472a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** when debugging 473a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 474a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(op) { 475a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FADDS: 476a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fadds"); 477a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj R.dbl = fD; 478a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fadd"); 479a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 480a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSUBS: 481a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fsubs"); 482a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj R.dbl = fD; 483a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fsub"); 484a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 485a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMULS: 486a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fmuls"); 487a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj R.dbl = fD; 488a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fmul"); 489a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 490a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FDIVS: 491a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fdivs"); 492a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj R.dbl = fD; 493a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fdiv"); 494a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 495a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 496a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_single_arithmetic_op: unexpected op", 497a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 498a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 499a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 500a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef UNOP 501a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef BINOP 502a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 503a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj E.dbl = expected; 504a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 505a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if ((R.layout.sign != E.layout.sign) || 506a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.exp != E.layout.exp) || 507a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.frac_lo != E.layout.frac_lo) || 508a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (R.layout.frac_hi != E.layout.frac_hi)) { 509a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "FAILED"; 510a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 1; 511a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 512a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "PASSED"; 513a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 0; 514a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 515a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 516a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%s:%s:%s(%-13a", 517a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_name[mode], result, flt_op_names[op], fA); 518a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (two_args) printf(", %-13a", fB); 519a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf(") = %-13a", R.dbl); 520a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (status) printf("\n\texpected %a", E.dbl); 521a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj putchar('\n'); 522a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 523a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) { 524a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("hi", hi); 525a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("lo", lo); 526a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("expected", expected); 527a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("got", R.dbl); 528a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("double result", fD); 529a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 530a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 531a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 532a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 533a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 534a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 535a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint check_single_guarded_arithmetic_op(flt_op_t op) 536a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 537a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj typedef struct { 538a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int num, den, frac; 539a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } fdivs_t; 540a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 541a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj char *result; 542a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 543a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj flt_overlay A, B, Z; 544a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_overlay Res, Exp; 545a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double fA, fB, fC, fD; 546a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_t mode; 547a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int g, s; 548a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int arg_count; 549a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 550a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fdivs_t divs_guard_cases[16] = { 551a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 105, 56, 0x700000 }, /* : 0 */ 552a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 57, 0x608FB8 }, /* : 1 */ 553a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 000, 00, 0x000000 }, /* : X */ 554a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 52, 0x762762 }, /* : 3 */ 555a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 000, 00, 0x000000 }, /* : X */ 556a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 55, 0x68BA2E }, /* : 5 */ 557a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 000, 00, 0x000000 }, /* : X */ 558a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 51, 0x7AFAFA }, /* : 7 */ 559a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 000, 00, 0x000000 }, /* : X */ 560a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 56, 0x649249 }, /* : 9 */ 561a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 000, 00, 0x000000 }, /* : X */ 562a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 54, 0x6D097B }, /* : B */ 563a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 000, 00, 0x000000 }, /* : X */ 564a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 59, 0x58F2FB }, /* : D */ 565a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 000, 00, 0x000000 }, /* : X */ 566a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 101, 52, 0x789D89 } /* : F */ 567a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj }; 568a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 569a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 0x1.00000 00000000p-3 */ 570a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up the invariant fields of B, the arg to cause rounding */ 571a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.flt = 0.0; 572a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.layout.exp = 124; /* -3 */ 573a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 574a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up args so result is always Z = 1.200000000000<g>p+0 */ 575a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.flt = 1.0; 576a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.sign = 0; 577a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 578a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define TERNOP(op) \ 579a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj arg_count = 3; \ 580a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 581a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1, %2, %3\n\t" \ 582a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA) , "f"(fB), "f"(fC)); 583a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define BINOP(op) \ 584a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj arg_count = 2; \ 585a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 586a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1, %2\n\t" \ 587a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA) , "f"(fB)); 588a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define UNOP(op) \ 589a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj arg_count = 1; \ 590a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 591a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1\n\t" \ 592a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA)); 593a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 594a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (mode = TO_NEAREST; mode <= TO_MINUS_INFINITY; mode++) 595a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (s = -1; s < 2; s += 2) 596a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (g = 0; g < 16; g += 1) { 597a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double lo, hi, expected; 598a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int LSB; 599a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int guard = 0; 600a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int z_sign = s; 601a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 602a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 603a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** one argument will have exponent = 0 as will the result (by 604a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** design) so choose the other argument with exponent -3 to 605a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** force a 3 bit shift for scaling leaving us with 3 guard bits 606a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** and the LSB bit at the bottom of the manitssa. 607a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 608a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(op) { 609a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FADDS: 610a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1p+0 + 1.00000<g>p-3 */ 611a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.layout.frac = g; 612a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 613a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*B.flt; 614a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*1.0; 615a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 616a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 617a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 618a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* mask off LSB from resulting guard bits */ 619a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = g & 7; 620a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 621a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac = 0x100000 | (g >> 3); 622a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 623a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSUBS: 624a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1.200002p+0 - 1.000000000000<g>p-3 */ 625a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.flt = 1.125; 626a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* add enough to avoid scaling of the result */ 627a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac |= 0x2; 628a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*A.flt; 629a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 630a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.layout.frac = g; 631a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*B.flt; 632a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 633a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 634a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = (0x10-g); 635a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac = guard>>3; 636a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 637a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* mask off LSB from resulting guard bits */ 638a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard &= 7; 639a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 640a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMULS: 641a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1 + g*2^-23 */ 642a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.flt = 1.0; 643a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac = g; 644a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*A.flt; 645a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = 1.125; 646a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 647a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 648a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.flt = 1.0; 649a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac = 0x100000; 650a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac |= g + (g>>3); 651a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = g & 7; 652a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 653a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FDIVS: 654a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* g >> 3 == LSB, g & 7 == guard bits */ 655a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = g & 7; 656a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if ((guard & 1) == 0) { 657a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* special case: guard bit X = 0 */ 658a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.flt = denorm_small; 659a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac = g; 660a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = A.flt; 661a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*8.0; 662a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.flt = 0.0; 663a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac |= (g >> 3); 664a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 665a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*divs_guard_cases[g].num; 666a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = divs_guard_cases[g].den; 667a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 668a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.flt = 1.0; 669a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac = divs_guard_cases[g].frac; 670a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 671a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 672a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMADDS: 673a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMSUBS: 674a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMADDS: 675a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMSUBS: 676a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1 + g*2^-23 */ 677a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.flt = 1.0; 678a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac = g; 679a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*A.flt; 680a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = 1.125; 681a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 682a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1.000001p-1 */ 683a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.flt = 0.5; 684a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac = 1; 685a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fC = (op == FMADDS || op == FNMADDS ? s : -s)*A.flt; 686a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 687a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 688a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj z_sign = (op == FNMADDS || op == FNMSUBS ? -s : s); 689a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = ((g & 7) + 0x4) & 7; 690a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.flt = 1.0; 691a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac = 0x500000; 692a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac |= g + (g>>3) + ((g & 7)>> 2 ? 1 : 0); 693a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 694a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 695a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_single_arithmetic_op: unexpected op", 696a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 697a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 698a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 699a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 700a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* get LSB for tie breaking */ 701a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj LSB = Z.layout.frac & 1; 702a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 703a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up hi and lo */ 704a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj lo = z_sign*Z.flt; 705a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac += 1; 706a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj hi = z_sign*Z.flt; 707a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 708a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(mode) { 709a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_NEAREST: 710a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* look at 3 guard bits to determine expected rounding */ 711a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(guard) { 712a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 0: 713a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 1: case 2: case 3: 714a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 715a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 716a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 4: /* tie: round to even */ 717a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) printf("tie: LSB = %d\n", LSB); 718a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (LSB == 0 ? lo : hi); 719a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 720a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 5: case 6: case 7: 721a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = hi; 722a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 723a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 724a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_single_guarded_arithmetic_op: unexpected guard", 725a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 726a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 727a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 728a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_ZERO: 729a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 730a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 731a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_PLUS_INFINITY: 732a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (guard == 0) { 733a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* no rounding */ 734a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 735a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 736a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (s == 1 ? hi : lo); 737a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 738a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 739a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_MINUS_INFINITY: 740a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (guard == 0) { 741a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* no rounding */ 742a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 743a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 744a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (s == 1 ? lo : hi); 745a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 746a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 747a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 748a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 749a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj set_rounding_mode(mode); 750a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 751a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 752a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** do the double precision dual operation just for comparison 753a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** when debugging 754a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 755a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(op) { 756a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FADDS: 757a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fadds"); 758a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 759a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 760a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSUBS: 761a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fsubs"); 762a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 763a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 764a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMULS: 765a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fmuls"); 766a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 767a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 768a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FDIVS: 769a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fdivs"); 770a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 771a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 772a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMADDS: 773a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fmadds"); 774a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 775a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 776a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMSUBS: 777a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fmsubs"); 778a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 779a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 780a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMADDS: 781a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fnmadds"); 782a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 783a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 784a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMSUBS: 785a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fnmsubs"); 786a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 787a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 788a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 789a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_single_guarded_arithmetic_op: unexpected op", 790a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 791a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 792a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 793a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef UNOP 794a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef BINOP 795a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef TERNOP 796a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 797a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Exp.dbl = expected; 798a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 799a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if ((Res.layout.sign != Exp.layout.sign) || 800a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (Res.layout.exp != Exp.layout.exp) || 801a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (Res.layout.frac_lo != Exp.layout.frac_lo) || 802a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (Res.layout.frac_hi != Exp.layout.frac_hi)) { 803a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "FAILED"; 804a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 1; 805a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 806a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "PASSED"; 807a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 0; 808a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 809a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 810ee55dc246230e70529b70c4bfb431db66e51525ccarll /* There seems to be some noise in the lower bits. The value 811ee55dc246230e70529b70c4bfb431db66e51525ccarll * on the least significant digit seems to vary when printing 812ee55dc246230e70529b70c4bfb431db66e51525ccarll * based on the rounding mode of the compiler. Just trying 813ee55dc246230e70529b70c4bfb431db66e51525ccarll * to get rid of the noise in the least significant bits when 814ee55dc246230e70529b70c4bfb431db66e51525ccarll * printing the operand. 815ee55dc246230e70529b70c4bfb431db66e51525ccarll */ 816ee55dc246230e70529b70c4bfb431db66e51525ccarll 817ee55dc246230e70529b70c4bfb431db66e51525ccarll fA = ((long int)(fA*10000))/10000.0; 818ee55dc246230e70529b70c4bfb431db66e51525ccarll /* Change -0.0 to a positive 0.0. Some compilers print -0.0 819ee55dc246230e70529b70c4bfb431db66e51525ccarll * others do not. Make it consistent. 820ee55dc246230e70529b70c4bfb431db66e51525ccarll */ 821ee55dc246230e70529b70c4bfb431db66e51525ccarll if (fA == -0.0) 822ee55dc246230e70529b70c4bfb431db66e51525ccarll fA = 0.0; 823ee55dc246230e70529b70c4bfb431db66e51525ccarll 824ee55dc246230e70529b70c4bfb431db66e51525ccarll printf("%s:%s:%s(%-13.6f", 825a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_name[mode], result, flt_op_names[op], fA); 826a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (arg_count > 1) printf(", %-13a", fB); 827a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (arg_count > 2) printf(", %-13a", fC); 828a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf(") = %-13a", Res.dbl); 829a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (status) printf("\n\texpected %a", Exp.dbl); 830a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj putchar('\n'); 831a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 832a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) { 833a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("hi", hi); 834a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("lo", lo); 835a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("expected", expected); 836a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("got", Res.dbl); 837a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 838a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 839a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 840a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 841a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 842a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 843a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint check_double_guarded_arithmetic_op(flt_op_t op) 844a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 845a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj typedef struct { 846a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int num, den, hi, lo; 847a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } fdiv_t; 848a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj typedef struct { 849a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double arg; 850a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int exp, hi, lo; 851a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } fsqrt_t; 852a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 853a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj char *result; 854a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 855a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_overlay A, B, Z; 856a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj dbl_overlay Res, Exp; 857a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double fA, fB, fC, fD; 858a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_t mode; 859a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int g, s; 860a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int arg_count; 861a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fdiv_t div_guard_cases[16] = { 862a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 62, 62, 0x00000, 0x00000000 }, /* 0 */ 863a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 64, 62, 0x08421, 0x08421084 }, /* 1 */ 864a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 66, 62, 0x10842, 0x10842108 }, /* 2 */ 865a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 62, 0x9ce73, 0x9ce739ce }, /* 3 */ 866a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 100, 62, 0x9ce73, 0x9ce739ce }, /* X */ 867a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 102, 62, 0xa5294, 0xa5294a52 }, /* 5 */ 868a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 106, 62, 0xb5ad6, 0xb5ad6b5a }, /* 6 */ 869a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 108, 62, 0xbdef7, 0xbdef7bde }, /* 7 */ 870a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 108, 108, 0x00000, 0x00000000 }, /* 8 */ 871a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 112, 62, 0xce739, 0xce739ce7 }, /* 9 */ 872a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 114, 62, 0xd6b5a, 0xd6b5ad6b }, /* A */ 873a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 116, 62, 0xdef7b, 0xdef7bdef }, /* B */ 874a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 84, 62, 0x5ad6b, 0x5ad6b5ad }, /* X */ 875a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 118, 62, 0xe739c, 0xe739ce73 }, /* D */ 876a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 90, 62, 0x739ce, 0x739ce739 }, /* E */ 877a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj { 92, 62, 0x7bdef, 0x7bdef7bd } /* F */ 878a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj }; 879a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 880a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 881a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fsqrt_t sqrt_guard_cases[16] = { 882e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.08800p0, 0, 0x04371, 0xd9ab72fb}, /* :0 B8.8440 */ 883e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.D2200p0, -1, 0xcfdca, 0xf353049e}, /* :1 A4.6910 */ 884e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.A8220p0, 0, 0x49830, 0x2b49cd6d}, /* :2 E9.D411 */ 885e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.05A20p0, 0, 0x02cd1, 0x3b44f3bf}, /* :3 B7.82D1 */ 886e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.CA820p0, -1, 0xc7607, 0x3cec0937}, /* :4 A1.6541 */ 887e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.DCA20p0, 0, 0x5d4f8, 0xd4e4c2b2}, /* :5 F7.EE51 */ 888e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.02C80p0, 0, 0x01630, 0x9cde7483}, /* :6 B6.8164 */ 889e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.DC800p0, -1, 0xdb2cf, 0xe686fe7c}, /* :7 A8.6E40 */ 890e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.CF920p0, -1, 0xcd089, 0xb6860626}, /* :8 A3.67C9 */ 891e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.1D020p0, 0, 0x0e1d6, 0x2e78ed9d}, /* :9 BF.8E81 */ 892e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.E1C80p0, -1, 0xe0d52, 0x6020fb6b}, /* :A AA.70E4 */ 893e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.C8000p0, -1, 0xc48c6, 0x001f0abf}, /* :B A0.6400 */ 894e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.48520p0, 0, 0x21e9e, 0xd813e2e2}, /* :C CD.A429 */ 895e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.F4C20p0, -1, 0xf4a1b, 0x09bbf0b0}, /* :D B1.7A61 */ 896e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x0.CD080p0, -1, 0xca348, 0x79b907ae}, /* :E A2.6684 */ 897e87dba33a7dc7c42e760b2af34dbf01affcbd330sewardj { 0x1.76B20p0, 0, 0x35b67, 0x81aed827} /* :F DB.BB59 */ 898a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj }; 899a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 900a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 0x1.00000 00000000p-3 */ 901a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up the invariant fields of B, the arg to cause rounding */ 902a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.dbl = 0.0; 903a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.layout.exp = 1020; 904a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 905a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up args so result is always Z = 1.200000000000<g>p+0 */ 906a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.dbl = 1.0; 907a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.sign = 0; 908a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 909a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define TERNOP(op) \ 910a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj arg_count = 3; \ 911a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 912a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1, %2, %3\n\t" \ 913a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA) , "f"(fB), "f"(fC)); 914a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define BINOP(op) \ 915a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj arg_count = 2; \ 916a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 917a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1, %2\n\t" \ 918a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA) , "f"(fB)); 919a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#define UNOP(op) \ 920a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj arg_count = 1; \ 921a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj __asm__ volatile( \ 922a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj op" %0, %1\n\t" \ 923a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj : "=f"(fD) : "f"(fA)); 924a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 925a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (mode = TO_NEAREST; mode <= TO_MINUS_INFINITY; mode++) 926a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (s = (op != FSQRT ? -1 : 1); s < 2; s += 2) 927a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (g = 0; g < 16; g += 1) { 928a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj double lo, hi, expected; 929a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int LSB; 930a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int guard; 931a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int z_sign = s; 932a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 933a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 934a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** one argument will have exponent = 0 as will the result (by 935a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** design) so choose the other argument with exponent -3 to 936a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** force a 3 bit shift for scaling leaving us with 3 guard bits 937a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** and the LSB bit at the bottom of the manitssa. 938a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 939a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(op) { 940a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FADD: 941a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1p+0 + 1.000000000000<g>p-3 */ 942a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.layout.frac_lo = g; 943a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 944a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*B.dbl; 945a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*1.0; 946a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 947a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 948a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 949a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* mask off LSB from resulting guard bits */ 950a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = g & 7; 951a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 952a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_hi = 0x20000; 953a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo = g >> 3; 954a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 955a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 956a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSUB: 957a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1.2000000000002p+0 - 1.000000000000<g>p-3 */ 958a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.dbl = 1.125; 959a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* add enough to avoid scaling of the result */ 960a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac_lo = 0x2; 961a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*A.dbl; 962a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 963a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj B.layout.frac_lo = g; 964a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*B.dbl; 965a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 966a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 967a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = (0x10-g); 968a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_hi = 0x0; 969a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo = guard>>3; 970a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 971a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* mask off LSB from resulting guard bits */ 972a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard &= 7; 973a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 974a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMUL: 975a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1 + g*2^-52 */ 976a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.dbl = 1.0; 977a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac_lo = g; 978a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*A.dbl; 979a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = 1.125; 980a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 981a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 982a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.dbl = 1.0; 983a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_hi = 0x20000; 984a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo = g + (g>>3); 985a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = g & 7; 986a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 987a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMADD: 988a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMSUB: 989a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMADD: 990a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMSUB: 991a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1 + g*2^-52 */ 992a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.dbl = 1.0; 993a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac_lo = g; 994a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*A.dbl; 995a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = 1.125; 996a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 997a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1.0000000000001p-1 */ 998a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.dbl = 0.5; 999a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj A.layout.frac_lo = 1; 1000a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fC = (op == FMADD || op == FNMADD ? s : -s)*A.dbl; 1001a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1002a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up Z to be truncated result */ 1003a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj z_sign = (op == FNMADD || op == FNMSUB ? -s : s); 1004a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = ((g & 7) + 0x4) & 7; 1005a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.dbl = 1.0; 1006a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_hi = 0xa0000; 1007a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo = g + (g>>3) + ((g & 7)>> 2 ? 1 : 0); 1008a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1009a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FDIV: 1010a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* g >> 3 == LSB, g & 7 == guard bits */ 1011a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = g & 7; 1012a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (guard == 0x4) { 1013a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* special case guard bits == 4, inexact tie */ 1014a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = s*2.0; 1015a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.dbl = 0.0; 1016a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (g >> 3) { 1017a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = dbl_denorm_small + 2*dbl_denorm_small; 1018a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo = 0x1; 1019a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 1020a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = dbl_denorm_small; 1021a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1022a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 1023a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*div_guard_cases[g].num; 1024a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fB = div_guard_cases[g].den; 1025a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1026a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%d/%d\n", 1027a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj s*div_guard_cases[g].num, 1028a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj div_guard_cases[g].den); 1029a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.dbl = 1.0; 1030a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_hi = div_guard_cases[g].hi; 1031a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo = div_guard_cases[g].lo; 1032a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1033a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1034a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSQRT: 1035a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj fA = s*sqrt_guard_cases[g].arg; 1036a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.dbl = 1.0; 1037a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.exp = sqrt_guard_cases[g].exp + 1023; 1038a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_hi = sqrt_guard_cases[g].hi; 1039a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo = sqrt_guard_cases[g].lo; 1040a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj guard = g >> 1; 1041a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (g & 1) guard |= 1; 1042a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* don't have test cases for when X bit = 0 */ 1043a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (guard == 0 || guard == 4) continue; 1044a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1045a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 1046a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_double_guarded_arithmetic_op: unexpected op", 1047a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 1048a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1049a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1050a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1051a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* get LSB for tie breaking */ 1052a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj LSB = Z.layout.frac_lo & 1; 1053a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1054a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* set up hi and lo */ 1055a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj lo = z_sign*Z.dbl; 1056a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Z.layout.frac_lo += 1; 1057a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj hi = z_sign*Z.dbl; 1058a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1059a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(mode) { 1060a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_NEAREST: 1061a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* look at 3 guard bits to determine expected rounding */ 1062a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(guard) { 1063a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 0: 1064a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 1: case 2: case 3: 1065a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 1066a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1067a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 4: /* tie: round to even */ 1068a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) printf("tie: LSB = %d\n", LSB); 1069a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (LSB == 0 ? lo : hi); 1070a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1071a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case 5: case 6: case 7: 1072a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = hi; 1073a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1074a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 1075a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_double_guarded_arithmetic_op: unexpected guard", 1076a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 1077a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1078a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1079a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_ZERO: 1080a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 1081a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1082a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_PLUS_INFINITY: 1083a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (guard == 0) { 1084a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* no rounding */ 1085a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 1086a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 1087a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (s == 1 ? hi : lo); 1088a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1089a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1090a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case TO_MINUS_INFINITY: 1091a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (guard == 0) { 1092a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* no rounding */ 1093a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = lo; 1094a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 1095a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj expected = (s == 1 ? lo : hi); 1096a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1097a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1098a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1099a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1100a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj set_rounding_mode(mode); 1101a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1102a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1103a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** do the double precision dual operation just for comparison 1104a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** when debugging 1105a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 1106a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj switch(op) { 1107a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FADD: 1108a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fadd"); 1109a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1110a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1111a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSUB: 1112a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fsub"); 1113a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1114a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1115a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMUL: 1116a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fmul"); 1117a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1118a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1119a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMADD: 1120a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fmadd"); 1121a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1122a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1123a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FMSUB: 1124a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fmsub"); 1125a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1126a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1127a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMADD: 1128a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fnmadd"); 1129a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1130a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1131a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FNMSUB: 1132a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj TERNOP("fnmsub"); 1133a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1134a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1135a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FDIV: 1136a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj BINOP("fdiv"); 1137a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1138a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1139a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj case FSQRT: 1140a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj UNOP("fsqrt"); 1141a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Res.dbl = fD; 1142a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1143a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj default: 1144a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj assert("check_double_guarded_arithmetic_op: unexpected op", 1145a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj FALSE); 1146a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj break; 1147a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1148a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef UNOP 1149a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef BINOP 1150a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#undef TERNOP 1151a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1152a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj Exp.dbl = expected; 1153a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1154a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if ((Res.layout.sign != Exp.layout.sign) || 1155a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (Res.layout.exp != Exp.layout.exp) || 1156a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (Res.layout.frac_lo != Exp.layout.frac_lo) || 1157a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj (Res.layout.frac_hi != Exp.layout.frac_hi)) { 1158a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "FAILED"; 1159a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 1; 1160a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } else { 1161a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj result = "PASSED"; 1162a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status = 0; 1163a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1164a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1165a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("%s:%s:%s(%-13a", 1166a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj round_mode_name[mode], result, flt_op_names[op], fA); 1167a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (arg_count > 1) printf(", %-13a", fB); 1168a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (arg_count > 2) printf(", %-13a", fC); 1169a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf(") = %-13a", Res.dbl); 1170a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (status) printf("\n\texpected %a", Exp.dbl); 1171a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj putchar('\n'); 1172a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1173a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj if (debug) { 1174a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("hi", hi); 1175a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("lo", lo); 1176a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("expected", expected); 1177a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj print_double("got", Res.dbl); 1178a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1179a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1180a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1181a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 1182a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 1183a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1184a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint test_float_arithmetic_ops() 1185a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 1186a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 1187a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj flt_op_t op; 1188a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1189a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj /* 1190a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** choose FP operands whose result should be rounded to either 1191a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj ** lo or hi. 1192a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj */ 1193a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1194a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("-------------------------- %s --------------------------\n", 1195a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj "test rounding of float operators without guard bits"); 1196a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (op = FADDS; op <= FDIVS; op++) { 1197a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_single_arithmetic_op(op); 1198a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1199a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1200a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("-------------------------- %s --------------------------\n", 1201a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj "test rounding of float operators with guard bits"); 1202a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (op = FADDS; op <= FNMSUBS; op++) { 1203a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_single_guarded_arithmetic_op(op); 1204a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1205a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1206a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj printf("-------------------------- %s --------------------------\n", 1207a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj "test rounding of double operators with guard bits"); 1208a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj for (op = FADD; op <= FSQRT; op++) { 1209a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= check_double_guarded_arithmetic_op(op); 1210a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj } 1211a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 1212a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 1213a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1214a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1215a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjint 1216a0d693b676ca016942849cb4243c3bfaae37f9bfsewardjmain() 1217a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj{ 1218a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj int status = 0; 1219a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1220a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj init(); 1221a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1222a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= test_dbl_to_float_convert("test denormalized convert", &denorm_small); 1223a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= test_dbl_to_float_convert("test normalized convert", &norm_small); 1224a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= test_int_to_float_convert("test (float)int convert"); 1225a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= test_int_to_float_convert("test (float)int convert"); 1226a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj 1227a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#ifdef __powerpc64__ 1228a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= test_long_to_double_convert("test (double)long convert"); 1229a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj#endif 1230a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj status |= test_float_arithmetic_ops(); 1231a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj return status; 1232a0d693b676ca016942849cb4243c3bfaae37f9bfsewardj} 1233