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