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