1/* d-longdouble.cc -- Software floating-point emulation for the frontend. 2 Copyright (C) 2006-2020 Free Software Foundation, Inc. 3 4GCC is free software; you can redistribute it and/or modify 5it under the terms of the GNU General Public License as published by 6the Free Software Foundation; either version 3, or (at your option) 7any later version. 8 9GCC is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License 15along with GCC; see the file COPYING3. If not see 16<http://www.gnu.org/licenses/>. */ 17 18#include "config.h" 19#include "system.h" 20#include "coretypes.h" 21 22#include "dmd/mtype.h" 23 24#include "tree.h" 25#include "fold-const.h" 26#include "diagnostic.h" 27#include "stor-layout.h" 28 29#include "d-tree.h" 30#include "longdouble.h" 31 32 33/* Constant real values 0, 1, -1 and 0.5. */ 34real_t CTFloat::zero; 35real_t CTFloat::one; 36real_t CTFloat::minusone; 37real_t CTFloat::half; 38 39/* Truncate longdouble to the highest precision supported by target. */ 40 41longdouble 42longdouble::normalize (void) 43{ 44 const machine_mode mode = TYPE_MODE (long_double_type_node); 45 real_convert (&this->rv (), mode, &this->rv ()); 46 return *this; 47} 48 49/* Assign a real_value to a longdouble type. */ 50 51void 52longdouble::set (real_value& d) 53{ 54 real_convert (&this->rv (), TYPE_MODE (long_double_type_node), &d); 55} 56 57/* Conversion routines between longdouble and integer types. */ 58 59void 60longdouble::set (int32_t d) 61{ 62 real_from_integer (&this->rv (), TYPE_MODE (double_type_node), d, SIGNED); 63} 64 65void 66longdouble::set (int64_t d) 67{ 68 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node), d, 69 SIGNED); 70} 71 72int64_t 73longdouble::to_int (void) const 74{ 75 bool overflow; 76 wide_int wi = real_to_integer (&this->rv (), &overflow, 64); 77 return wi.to_shwi (); 78} 79 80/* Unsigned variants of the same conversion routines. */ 81 82void 83longdouble::set (uint32_t d) 84{ 85 real_from_integer (&this->rv (), TYPE_MODE (double_type_node), d, UNSIGNED); 86} 87 88void 89longdouble::set (uint64_t d) 90{ 91 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node), d, 92 UNSIGNED); 93} 94 95uint64_t 96longdouble::to_uint (void) const 97{ 98 bool overflow; 99 wide_int wi = real_to_integer (&this->rv (), &overflow, 64); 100 return wi.to_uhwi (); 101} 102 103/* For conversion between boolean, only need to check if is zero. */ 104 105void 106longdouble::set (bool d) 107{ 108 this->rv () = (d == false) ? dconst0 : dconst1; 109} 110 111bool 112longdouble::to_bool (void) const 113{ 114 return this->rv ().cl != rvc_zero; 115} 116 117/* Overload numeric operators for longdouble types. */ 118 119longdouble 120longdouble::add (const longdouble& r) const 121{ 122 longdouble x; 123 real_arithmetic (&x.rv (), PLUS_EXPR, &this->rv (), &r.rv ()); 124 return x.normalize (); 125} 126 127longdouble 128longdouble::sub (const longdouble& r) const 129{ 130 longdouble x; 131 real_arithmetic (&x.rv (), MINUS_EXPR, &this->rv (), &r.rv ()); 132 return x.normalize (); 133} 134 135longdouble 136longdouble::mul (const longdouble& r) const 137{ 138 longdouble x; 139 real_arithmetic (&x.rv (), MULT_EXPR, &this->rv (), &r.rv ()); 140 return x.normalize (); 141} 142 143longdouble 144longdouble::div (const longdouble& r) const 145{ 146 longdouble x; 147 real_arithmetic (&x.rv (), RDIV_EXPR, &this->rv (), &r.rv ()); 148 return x.normalize (); 149} 150 151longdouble 152longdouble::mod (const longdouble& r) const 153{ 154 longdouble x; 155 real_value q; 156 157 if (r.rv ().cl == rvc_zero || REAL_VALUE_ISINF (this->rv ())) 158 { 159 real_nan (&x.rv (), "", 1, TYPE_MODE (long_double_type_node)); 160 return x; 161 } 162 163 if (this->rv ().cl == rvc_zero) 164 return *this; 165 166 if (REAL_VALUE_ISINF (r.rv ())) 167 return *this; 168 169 /* Need to check for NaN? */ 170 real_arithmetic (&q, RDIV_EXPR, &this->rv (), &r.rv ()); 171 real_arithmetic (&q, FIX_TRUNC_EXPR, &q, NULL); 172 real_arithmetic (&q, MULT_EXPR, &q, &r.rv ()); 173 real_arithmetic (&x.rv (), MINUS_EXPR, &this->rv (), &q); 174 175 return x.normalize (); 176} 177 178longdouble 179longdouble::neg (void) const 180{ 181 longdouble x; 182 real_arithmetic (&x.rv (), NEGATE_EXPR, &this->rv (), NULL); 183 return x.normalize (); 184} 185 186/* Overload equality operators for longdouble types. */ 187 188int 189longdouble::cmp (const longdouble& r) const 190{ 191 if (real_compare (LT_EXPR, &this->rv (), &r.rv ())) 192 return -1; 193 194 if (real_compare (GT_EXPR, &this->rv (), &r.rv ())) 195 return 1; 196 197 return 0; 198} 199 200int 201longdouble::equals (const longdouble& r) const 202{ 203 return real_compare (EQ_EXPR, &this->rv (), &r.rv ()); 204} 205