1 1.1 christos /*> cp1.c <*/ 2 1.1 christos /* MIPS Simulator FPU (CoProcessor 1) support. 3 1.11 christos Copyright (C) 2002-2024 Free Software Foundation, Inc. 4 1.1 christos Originally created by Cygnus Solutions. Extensive modifications, 5 1.1 christos including paired-single operation support and MIPS-3D support 6 1.1 christos contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom 7 1.1 christos Corporation (SiByte). 8 1.1 christos 9 1.1 christos This file is part of GDB, the GNU debugger. 10 1.1 christos 11 1.1 christos This program is free software; you can redistribute it and/or modify 12 1.1 christos it under the terms of the GNU General Public License as published by 13 1.1 christos the Free Software Foundation; either version 3 of the License, or 14 1.1 christos (at your option) any later version. 15 1.1 christos 16 1.1 christos This program is distributed in the hope that it will be useful, 17 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 18 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 1.1 christos GNU General Public License for more details. 20 1.1 christos 21 1.1 christos You should have received a copy of the GNU General Public License 22 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 23 1.1 christos 24 1.1 christos /* XXX: The following notice should be removed as soon as is practical: */ 25 1.1 christos /* Floating Point Support for gdb MIPS simulators 26 1.1 christos 27 1.1 christos This file is part of the MIPS sim 28 1.1 christos 29 1.1 christos THIS SOFTWARE IS NOT COPYRIGHTED 30 1.1 christos (by Cygnus.) 31 1.1 christos 32 1.1 christos Cygnus offers the following for use in the public domain. Cygnus 33 1.1 christos makes no warranty with regard to the software or it's performance 34 1.1 christos and the user accepts the software "AS IS" with all faults. 35 1.1 christos 36 1.1 christos CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO 37 1.1 christos THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 38 1.1 christos MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 39 1.1 christos 40 1.1 christos (Originally, this code was in interp.c) 41 1.1 christos */ 42 1.1 christos 43 1.10 christos /* This must come before any other includes. */ 44 1.10 christos #include "defs.h" 45 1.10 christos 46 1.1 christos #include "sim-main.h" 47 1.1 christos 48 1.10 christos #include <stdlib.h> 49 1.10 christos 50 1.1 christos /* Within cp1.c we refer to sim_cpu directly. */ 51 1.1 christos #define CPU cpu 52 1.1 christos #define SD CPU_STATE(cpu) 53 1.1 christos 54 1.1 christos /*-- FPU support routines ---------------------------------------------------*/ 55 1.1 christos 56 1.1 christos /* Numbers are held in normalized form. The SINGLE and DOUBLE binary 57 1.1 christos formats conform to ANSI/IEEE Std 754-1985. 58 1.1 christos 59 1.1 christos SINGLE precision floating: 60 1.1 christos seeeeeeeefffffffffffffffffffffff 61 1.1 christos s = 1bit = sign 62 1.1 christos e = 8bits = exponent 63 1.1 christos f = 23bits = fraction 64 1.1 christos 65 1.1 christos SINGLE precision fixed: 66 1.1 christos siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii 67 1.1 christos s = 1bit = sign 68 1.1 christos i = 31bits = integer 69 1.1 christos 70 1.1 christos DOUBLE precision floating: 71 1.1 christos seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff 72 1.1 christos s = 1bit = sign 73 1.1 christos e = 11bits = exponent 74 1.1 christos f = 52bits = fraction 75 1.1 christos 76 1.1 christos DOUBLE precision fixed: 77 1.1 christos siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii 78 1.1 christos s = 1bit = sign 79 1.1 christos i = 63bits = integer 80 1.1 christos 81 1.1 christos PAIRED SINGLE precision floating: 82 1.1 christos seeeeeeeefffffffffffffffffffffffseeeeeeeefffffffffffffffffffffff 83 1.1 christos | upper || lower | 84 1.1 christos s = 1bit = sign 85 1.1 christos e = 8bits = exponent 86 1.1 christos f = 23bits = fraction 87 1.1 christos Note: upper = [63..32], lower = [31..0] 88 1.1 christos */ 89 1.1 christos 90 1.1 christos /* Extract packed single values: */ 91 1.1 christos #define FP_PS_upper(v) (((v) >> 32) & (unsigned)0xFFFFFFFF) 92 1.1 christos #define FP_PS_lower(v) ((v) & (unsigned)0xFFFFFFFF) 93 1.10 christos #define FP_PS_cat(u,l) (((uint64_t)((u) & (unsigned)0xFFFFFFFF) << 32) \ 94 1.10 christos | (uint64_t)((l) & 0xFFFFFFFF)) 95 1.1 christos 96 1.1 christos /* Explicit QNaN values. */ 97 1.1 christos #define FPQNaN_SINGLE (0x7FBFFFFF) 98 1.1 christos #define FPQNaN_WORD (0x7FFFFFFF) 99 1.1 christos #define FPQNaN_DOUBLE (UNSIGNED64 (0x7FF7FFFFFFFFFFFF)) 100 1.1 christos #define FPQNaN_LONG (UNSIGNED64 (0x7FFFFFFFFFFFFFFF)) 101 1.1 christos #define FPQNaN_PS (FP_PS_cat (FPQNaN_SINGLE, FPQNaN_SINGLE)) 102 1.1 christos 103 1.10 christos static void update_fcsr (sim_cpu *, address_word, sim_fpu_status); 104 1.10 christos 105 1.1 christos static const char *fpu_format_name (FP_formats fmt); 106 1.1 christos #ifdef DEBUG 107 1.1 christos static const char *fpu_rounding_mode_name (int rm); 108 1.1 christos #endif 109 1.1 christos 110 1.1 christos uword64 111 1.1 christos value_fpr (sim_cpu *cpu, 112 1.1 christos address_word cia, 113 1.1 christos int fpr, 114 1.1 christos FP_formats fmt) 115 1.1 christos { 116 1.1 christos uword64 value = 0; 117 1.1 christos int err = 0; 118 1.1 christos 119 1.1 christos /* Treat unused register values, as fixed-point 64bit values. */ 120 1.1 christos if (fmt == fmt_unknown) 121 1.1 christos { 122 1.1 christos #if 1 123 1.1 christos /* If request to read data as "unknown", then use the current 124 1.1 christos encoding: */ 125 1.1 christos fmt = FPR_STATE[fpr]; 126 1.1 christos #else 127 1.1 christos fmt = fmt_long; 128 1.1 christos #endif 129 1.1 christos } 130 1.1 christos 131 1.1 christos /* For values not yet accessed, set to the desired format. */ 132 1.10 christos if (fmt < fmt_uninterpreted && fmt != fmt_dc32) 133 1.1 christos { 134 1.1 christos if (FPR_STATE[fpr] == fmt_uninterpreted) 135 1.1 christos { 136 1.1 christos FPR_STATE[fpr] = fmt; 137 1.1 christos #ifdef DEBUG 138 1.1 christos printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr, 139 1.1 christos fpu_format_name (fmt)); 140 1.1 christos #endif /* DEBUG */ 141 1.1 christos } 142 1.10 christos else if (fmt != FPR_STATE[fpr] 143 1.10 christos && !(fmt == fmt_single 144 1.10 christos && FPR_STATE[fpr] == fmt_double 145 1.10 christos && (FGR[fpr] == 0 || FGR[fpr] == 0xFFFFFFFF))) 146 1.1 christos { 147 1.1 christos sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n", 148 1.1 christos fpr, fpu_format_name (FPR_STATE[fpr]), 149 1.1 christos fpu_format_name (fmt), pr_addr (cia)); 150 1.1 christos FPR_STATE[fpr] = fmt_unknown; 151 1.1 christos } 152 1.1 christos } 153 1.1 christos 154 1.1 christos if (FPR_STATE[fpr] == fmt_unknown) 155 1.1 christos { 156 1.1 christos /* Set QNaN value: */ 157 1.1 christos switch (fmt) 158 1.1 christos { 159 1.1 christos case fmt_single: value = FPQNaN_SINGLE; break; 160 1.1 christos case fmt_double: value = FPQNaN_DOUBLE; break; 161 1.1 christos case fmt_word: value = FPQNaN_WORD; break; 162 1.1 christos case fmt_long: value = FPQNaN_LONG; break; 163 1.1 christos case fmt_ps: value = FPQNaN_PS; break; 164 1.1 christos default: err = -1; break; 165 1.1 christos } 166 1.1 christos } 167 1.1 christos else if (SizeFGR () == 64) 168 1.1 christos { 169 1.1 christos switch (fmt) 170 1.1 christos { 171 1.1 christos case fmt_uninterpreted_32: 172 1.1 christos case fmt_single: 173 1.1 christos case fmt_word: 174 1.10 christos case fmt_dc32: 175 1.1 christos value = (FGR[fpr] & 0xFFFFFFFF); 176 1.1 christos break; 177 1.1 christos 178 1.1 christos case fmt_uninterpreted_64: 179 1.1 christos case fmt_uninterpreted: 180 1.1 christos case fmt_double: 181 1.1 christos case fmt_long: 182 1.1 christos case fmt_ps: 183 1.1 christos value = FGR[fpr]; 184 1.1 christos break; 185 1.1 christos 186 1.1 christos default: 187 1.1 christos err = -1; 188 1.1 christos break; 189 1.1 christos } 190 1.1 christos } 191 1.1 christos else 192 1.1 christos { 193 1.1 christos switch (fmt) 194 1.1 christos { 195 1.1 christos case fmt_uninterpreted_32: 196 1.1 christos case fmt_single: 197 1.1 christos case fmt_word: 198 1.1 christos value = (FGR[fpr] & 0xFFFFFFFF); 199 1.1 christos break; 200 1.1 christos 201 1.1 christos case fmt_uninterpreted_64: 202 1.1 christos case fmt_uninterpreted: 203 1.1 christos case fmt_double: 204 1.1 christos case fmt_long: 205 1.1 christos if ((fpr & 1) == 0) 206 1.1 christos { 207 1.1 christos /* Even register numbers only. */ 208 1.1 christos #ifdef DEBUG 209 1.1 christos printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n", 210 1.1 christos fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]), 211 1.1 christos fpr, pr_uword64 ((uword64) FGR[fpr])); 212 1.1 christos #endif 213 1.1 christos value = ((((uword64) FGR[fpr+1]) << 32) 214 1.1 christos | (FGR[fpr] & 0xFFFFFFFF)); 215 1.1 christos } 216 1.1 christos else 217 1.1 christos { 218 1.1 christos SignalException (ReservedInstruction, 0); 219 1.1 christos } 220 1.1 christos break; 221 1.1 christos 222 1.1 christos case fmt_ps: 223 1.1 christos SignalException (ReservedInstruction, 0); 224 1.1 christos break; 225 1.1 christos 226 1.1 christos default: 227 1.1 christos err = -1; 228 1.1 christos break; 229 1.1 christos } 230 1.1 christos } 231 1.1 christos 232 1.1 christos if (err) 233 1.1 christos SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()"); 234 1.1 christos 235 1.1 christos #ifdef DEBUG 236 1.1 christos printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n", 237 1.1 christos fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia), 238 1.1 christos SizeFGR ()); 239 1.1 christos #endif /* DEBUG */ 240 1.1 christos 241 1.1 christos return (value); 242 1.1 christos } 243 1.1 christos 244 1.1 christos void 245 1.1 christos store_fpr (sim_cpu *cpu, 246 1.1 christos address_word cia, 247 1.1 christos int fpr, 248 1.1 christos FP_formats fmt, 249 1.1 christos uword64 value) 250 1.1 christos { 251 1.1 christos int err = 0; 252 1.1 christos 253 1.1 christos #ifdef DEBUG 254 1.1 christos printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n", 255 1.1 christos fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia), 256 1.1 christos SizeFGR ()); 257 1.1 christos #endif /* DEBUG */ 258 1.1 christos 259 1.1 christos if (SizeFGR () == 64) 260 1.1 christos { 261 1.1 christos switch (fmt) 262 1.1 christos { 263 1.1 christos case fmt_uninterpreted_32: 264 1.1 christos fmt = fmt_uninterpreted; 265 1.11 christos ATTRIBUTE_FALLTHROUGH; 266 1.1 christos case fmt_single: 267 1.1 christos case fmt_word: 268 1.1 christos if (STATE_VERBOSE_P (SD)) 269 1.1 christos sim_io_eprintf (SD, 270 1.1 christos "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n", 271 1.1 christos pr_addr (cia)); 272 1.1 christos FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF)); 273 1.1 christos FPR_STATE[fpr] = fmt; 274 1.1 christos break; 275 1.1 christos 276 1.1 christos case fmt_uninterpreted_64: 277 1.1 christos fmt = fmt_uninterpreted; 278 1.11 christos ATTRIBUTE_FALLTHROUGH; 279 1.1 christos case fmt_uninterpreted: 280 1.1 christos case fmt_double: 281 1.1 christos case fmt_long: 282 1.1 christos case fmt_ps: 283 1.1 christos FGR[fpr] = value; 284 1.1 christos FPR_STATE[fpr] = fmt; 285 1.1 christos break; 286 1.1 christos 287 1.1 christos default: 288 1.1 christos FPR_STATE[fpr] = fmt_unknown; 289 1.1 christos err = -1; 290 1.1 christos break; 291 1.1 christos } 292 1.1 christos } 293 1.1 christos else 294 1.1 christos { 295 1.1 christos switch (fmt) 296 1.1 christos { 297 1.1 christos case fmt_uninterpreted_32: 298 1.1 christos fmt = fmt_uninterpreted; 299 1.11 christos ATTRIBUTE_FALLTHROUGH; 300 1.1 christos case fmt_single: 301 1.1 christos case fmt_word: 302 1.1 christos FGR[fpr] = (value & 0xFFFFFFFF); 303 1.1 christos FPR_STATE[fpr] = fmt; 304 1.1 christos break; 305 1.1 christos 306 1.1 christos case fmt_uninterpreted_64: 307 1.1 christos fmt = fmt_uninterpreted; 308 1.11 christos ATTRIBUTE_FALLTHROUGH; 309 1.1 christos case fmt_uninterpreted: 310 1.1 christos case fmt_double: 311 1.1 christos case fmt_long: 312 1.1 christos if ((fpr & 1) == 0) 313 1.1 christos { 314 1.1 christos /* Even register numbers only. */ 315 1.1 christos FGR[fpr+1] = (value >> 32); 316 1.1 christos FGR[fpr] = (value & 0xFFFFFFFF); 317 1.1 christos FPR_STATE[fpr + 1] = fmt; 318 1.1 christos FPR_STATE[fpr] = fmt; 319 1.1 christos } 320 1.1 christos else 321 1.1 christos { 322 1.1 christos FPR_STATE[fpr] = fmt_unknown; 323 1.1 christos FPR_STATE[fpr ^ 1] = fmt_unknown; 324 1.1 christos SignalException (ReservedInstruction, 0); 325 1.1 christos } 326 1.1 christos break; 327 1.1 christos 328 1.1 christos case fmt_ps: 329 1.1 christos FPR_STATE[fpr] = fmt_unknown; 330 1.1 christos SignalException (ReservedInstruction, 0); 331 1.1 christos break; 332 1.1 christos 333 1.1 christos default: 334 1.1 christos FPR_STATE[fpr] = fmt_unknown; 335 1.1 christos err = -1; 336 1.1 christos break; 337 1.1 christos } 338 1.1 christos } 339 1.1 christos 340 1.1 christos if (err) 341 1.1 christos SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()"); 342 1.1 christos 343 1.1 christos #ifdef DEBUG 344 1.1 christos printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n", 345 1.1 christos fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt)); 346 1.1 christos #endif /* DEBUG */ 347 1.1 christos 348 1.1 christos return; 349 1.1 christos } 350 1.1 christos 351 1.1 christos 352 1.1 christos /* CP1 control/status register access functions. */ 353 1.1 christos 354 1.1 christos void 355 1.1 christos test_fcsr (sim_cpu *cpu, 356 1.1 christos address_word cia) 357 1.1 christos { 358 1.1 christos unsigned int cause; 359 1.1 christos 360 1.1 christos cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift; 361 1.1 christos if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0 362 1.1 christos || (cause & (1 << UO))) 363 1.1 christos { 364 1.1 christos SignalExceptionFPE(); 365 1.1 christos } 366 1.1 christos } 367 1.1 christos 368 1.1 christos unsigned_word 369 1.1 christos value_fcr(sim_cpu *cpu, 370 1.1 christos address_word cia, 371 1.1 christos int fcr) 372 1.1 christos { 373 1.10 christos uint32_t value = 0; 374 1.1 christos 375 1.1 christos switch (fcr) 376 1.1 christos { 377 1.1 christos case 0: /* FP Implementation and Revision Register. */ 378 1.1 christos value = FCR0; 379 1.1 christos break; 380 1.1 christos case 25: /* FP Condition Codes Register (derived from FCSR). */ 381 1.1 christos value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift; 382 1.1 christos value = (value & 0x1) | (value >> 1); /* Close FCC gap. */ 383 1.1 christos break; 384 1.1 christos case 26: /* FP Exceptions Register (derived from FCSR). */ 385 1.1 christos value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask); 386 1.1 christos break; 387 1.1 christos case 28: /* FP Enables Register (derived from FCSR). */ 388 1.1 christos value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask); 389 1.1 christos if ((FCR31 & fcsr_FS) != 0) 390 1.1 christos value |= fenr_FS; 391 1.1 christos break; 392 1.1 christos case 31: /* FP Control/Status Register (FCSR). */ 393 1.1 christos value = FCR31 & ~fcsr_ZERO_mask; 394 1.1 christos break; 395 1.1 christos } 396 1.1 christos 397 1.1 christos return (EXTEND32 (value)); 398 1.1 christos } 399 1.1 christos 400 1.1 christos void 401 1.1 christos store_fcr(sim_cpu *cpu, 402 1.1 christos address_word cia, 403 1.1 christos int fcr, 404 1.1 christos unsigned_word value) 405 1.1 christos { 406 1.10 christos uint32_t v; 407 1.1 christos 408 1.1 christos v = VL4_8(value); 409 1.1 christos switch (fcr) 410 1.1 christos { 411 1.1 christos case 25: /* FP Condition Codes Register (stored into FCSR). */ 412 1.1 christos v = (v << 1) | (v & 0x1); /* Adjust for FCC gap. */ 413 1.1 christos FCR31 &= ~fcsr_FCC_mask; 414 1.1 christos FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask); 415 1.1 christos break; 416 1.1 christos case 26: /* FP Exceptions Register (stored into FCSR). */ 417 1.1 christos FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask); 418 1.1 christos FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask)); 419 1.1 christos test_fcsr(cpu, cia); 420 1.1 christos break; 421 1.1 christos case 28: /* FP Enables Register (stored into FCSR). */ 422 1.1 christos if ((v & fenr_FS) != 0) 423 1.1 christos v |= fcsr_FS; 424 1.1 christos else 425 1.1 christos v &= ~fcsr_FS; 426 1.1 christos FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask); 427 1.1 christos FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask)); 428 1.1 christos test_fcsr(cpu, cia); 429 1.1 christos break; 430 1.1 christos case 31: /* FP Control/Status Register (FCSR). */ 431 1.1 christos FCR31 = v & ~fcsr_ZERO_mask; 432 1.1 christos test_fcsr(cpu, cia); 433 1.1 christos break; 434 1.1 christos } 435 1.1 christos } 436 1.1 christos 437 1.10 christos static void 438 1.1 christos update_fcsr (sim_cpu *cpu, 439 1.1 christos address_word cia, 440 1.1 christos sim_fpu_status status) 441 1.1 christos { 442 1.1 christos FCSR &= ~fcsr_CAUSE_mask; 443 1.1 christos 444 1.1 christos if (status != 0) 445 1.1 christos { 446 1.1 christos unsigned int cause = 0; 447 1.1 christos 448 1.1 christos /* map between sim_fpu codes and MIPS FCSR */ 449 1.1 christos if (status & (sim_fpu_status_invalid_snan 450 1.1 christos | sim_fpu_status_invalid_isi 451 1.1 christos | sim_fpu_status_invalid_idi 452 1.1 christos | sim_fpu_status_invalid_zdz 453 1.1 christos | sim_fpu_status_invalid_imz 454 1.1 christos | sim_fpu_status_invalid_cmp 455 1.1 christos | sim_fpu_status_invalid_sqrt 456 1.1 christos | sim_fpu_status_invalid_cvi)) 457 1.1 christos cause |= (1 << IO); 458 1.1 christos if (status & sim_fpu_status_invalid_div0) 459 1.1 christos cause |= (1 << DZ); 460 1.1 christos if (status & sim_fpu_status_overflow) 461 1.1 christos cause |= (1 << OF); 462 1.1 christos if (status & sim_fpu_status_underflow) 463 1.1 christos cause |= (1 << UF); 464 1.1 christos if (status & sim_fpu_status_inexact) 465 1.1 christos cause |= (1 << IR); 466 1.1 christos #if 0 /* Not yet. */ 467 1.1 christos /* Implicit clearing of other bits by unimplemented done by callers. */ 468 1.1 christos if (status & sim_fpu_status_unimplemented) 469 1.1 christos cause |= (1 << UO); 470 1.1 christos #endif 471 1.1 christos 472 1.1 christos FCSR |= (cause << fcsr_CAUSE_shift); 473 1.1 christos test_fcsr (cpu, cia); 474 1.1 christos FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift); 475 1.1 christos } 476 1.1 christos return; 477 1.1 christos } 478 1.1 christos 479 1.1 christos static sim_fpu_round 480 1.1 christos rounding_mode(int rm) 481 1.1 christos { 482 1.1 christos sim_fpu_round round; 483 1.1 christos 484 1.1 christos switch (rm) 485 1.1 christos { 486 1.1 christos case FP_RM_NEAREST: 487 1.1 christos /* Round result to nearest representable value. When two 488 1.1 christos representable values are equally near, round to the value 489 1.1 christos that has a least significant bit of zero (i.e. is even). */ 490 1.1 christos round = sim_fpu_round_near; 491 1.1 christos break; 492 1.1 christos case FP_RM_TOZERO: 493 1.1 christos /* Round result to the value closest to, and not greater in 494 1.1 christos magnitude than, the result. */ 495 1.1 christos round = sim_fpu_round_zero; 496 1.1 christos break; 497 1.1 christos case FP_RM_TOPINF: 498 1.1 christos /* Round result to the value closest to, and not less than, 499 1.1 christos the result. */ 500 1.1 christos round = sim_fpu_round_up; 501 1.1 christos break; 502 1.1 christos case FP_RM_TOMINF: 503 1.1 christos /* Round result to the value closest to, and not greater than, 504 1.1 christos the result. */ 505 1.1 christos round = sim_fpu_round_down; 506 1.1 christos break; 507 1.1 christos default: 508 1.1 christos round = 0; 509 1.1 christos fprintf (stderr, "Bad switch\n"); 510 1.1 christos abort (); 511 1.1 christos } 512 1.1 christos return round; 513 1.1 christos } 514 1.1 christos 515 1.1 christos /* When the FS bit is set, MIPS processors return zero for 516 1.1 christos denormalized results and optionally replace denormalized inputs 517 1.1 christos with zero. When FS is clear, some implementation trap on input 518 1.1 christos and/or output, while other perform the operation in hardware. */ 519 1.1 christos static sim_fpu_denorm 520 1.1 christos denorm_mode(sim_cpu *cpu) 521 1.1 christos { 522 1.1 christos sim_fpu_denorm denorm; 523 1.1 christos 524 1.1 christos /* XXX: FIXME: Eventually should be CPU model dependent. */ 525 1.1 christos if (GETFS()) 526 1.1 christos denorm = sim_fpu_denorm_zero; 527 1.1 christos else 528 1.1 christos denorm = 0; 529 1.1 christos return denorm; 530 1.1 christos } 531 1.1 christos 532 1.1 christos 533 1.1 christos /* Comparison operations. */ 534 1.1 christos 535 1.1 christos static sim_fpu_status 536 1.10 christos fp_test(uint64_t op1, 537 1.10 christos uint64_t op2, 538 1.1 christos FP_formats fmt, 539 1.1 christos int abs, 540 1.1 christos int cond, 541 1.1 christos int *condition) 542 1.1 christos { 543 1.1 christos sim_fpu wop1; 544 1.1 christos sim_fpu wop2; 545 1.1 christos sim_fpu_status status = 0; 546 1.1 christos int less, equal, unordered; 547 1.1 christos 548 1.1 christos /* The format type has already been checked: */ 549 1.1 christos switch (fmt) 550 1.1 christos { 551 1.1 christos case fmt_single: 552 1.1 christos { 553 1.1 christos sim_fpu_32to (&wop1, op1); 554 1.1 christos sim_fpu_32to (&wop2, op2); 555 1.1 christos break; 556 1.1 christos } 557 1.1 christos case fmt_double: 558 1.1 christos { 559 1.1 christos sim_fpu_64to (&wop1, op1); 560 1.1 christos sim_fpu_64to (&wop2, op2); 561 1.1 christos break; 562 1.1 christos } 563 1.1 christos default: 564 1.1 christos fprintf (stderr, "Bad switch\n"); 565 1.1 christos abort (); 566 1.1 christos } 567 1.1 christos 568 1.1 christos if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2)) 569 1.1 christos { 570 1.10 christos if ((cond & (1 << 3)) 571 1.10 christos || sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2)) 572 1.1 christos status = sim_fpu_status_invalid_snan; 573 1.1 christos less = 0; 574 1.1 christos equal = 0; 575 1.1 christos unordered = 1; 576 1.1 christos } 577 1.1 christos else 578 1.1 christos { 579 1.1 christos if (abs) 580 1.1 christos { 581 1.1 christos status |= sim_fpu_abs (&wop1, &wop1); 582 1.1 christos status |= sim_fpu_abs (&wop2, &wop2); 583 1.1 christos } 584 1.1 christos equal = sim_fpu_is_eq (&wop1, &wop2); 585 1.1 christos less = !equal && sim_fpu_is_lt (&wop1, &wop2); 586 1.1 christos unordered = 0; 587 1.1 christos } 588 1.1 christos *condition = (((cond & (1 << 2)) && less) 589 1.1 christos || ((cond & (1 << 1)) && equal) 590 1.1 christos || ((cond & (1 << 0)) && unordered)); 591 1.1 christos return status; 592 1.1 christos } 593 1.1 christos 594 1.10 christos static const int sim_fpu_class_mips_mapping[] = { 595 1.10 christos FP_R6CLASS_SNAN, /* SIM_FPU_IS_SNAN = 1, Noisy not-a-number */ 596 1.10 christos FP_R6CLASS_QNAN, /* SIM_FPU_IS_QNAN = 2, Quiet not-a-number */ 597 1.10 christos FP_R6CLASS_NEGINF, /* SIM_FPU_IS_NINF = 3, -infinity */ 598 1.10 christos FP_R6CLASS_POSINF, /* SIM_FPU_IS_PINF = 4, +infinity */ 599 1.10 christos FP_R6CLASS_NEGNORM, /* SIM_FPU_IS_NNUMBER = 5, -num - [-MAX .. -MIN] */ 600 1.10 christos FP_R6CLASS_POSNORM, /* SIM_FPU_IS_PNUMBER = 6, +num - [+MIN .. +MAX] */ 601 1.10 christos FP_R6CLASS_NEGSUB, /* SIM_FPU_IS_NDENORM = 7, -denorm - (MIN .. 0) */ 602 1.10 christos FP_R6CLASS_POSSUB, /* SIM_FPU_IS_PDENORM = 8, +denorm - (0 .. MIN) */ 603 1.10 christos FP_R6CLASS_NEGZERO, /* SIM_FPU_IS_NZERO = 9, -0 */ 604 1.10 christos FP_R6CLASS_POSZERO /* SIM_FPU_IS_PZERO = 10, +0 */ 605 1.10 christos }; 606 1.10 christos 607 1.10 christos uint64_t 608 1.10 christos fp_classify (sim_cpu *cpu, 609 1.10 christos address_word cia, 610 1.10 christos uint64_t op, 611 1.10 christos FP_formats fmt) 612 1.10 christos { 613 1.10 christos sim_fpu wop; 614 1.10 christos 615 1.10 christos switch (fmt) 616 1.10 christos { 617 1.10 christos case fmt_single: 618 1.10 christos sim_fpu_32to (&wop, op); 619 1.10 christos break; 620 1.10 christos case fmt_double: 621 1.10 christos sim_fpu_64to (&wop, op); 622 1.10 christos break; 623 1.10 christos default: 624 1.10 christos sim_io_error (SD, "Bad switch\n"); 625 1.10 christos } 626 1.10 christos return sim_fpu_class_mips_mapping[sim_fpu_classify (&wop) - 1]; 627 1.10 christos } 628 1.10 christos 629 1.10 christos int 630 1.10 christos fp_rint (sim_cpu *cpu, 631 1.10 christos address_word cia, 632 1.10 christos uint64_t op, 633 1.10 christos uint64_t *ans, 634 1.10 christos FP_formats fmt) 635 1.10 christos { 636 1.10 christos sim_fpu wop = {0}, wtemp = {0}, wmagic = {0}, wans = {0}; 637 1.10 christos int status = 0; 638 1.10 christos sim_fpu_round round = rounding_mode (GETRM()); 639 1.10 christos 640 1.10 christos switch (fmt) 641 1.10 christos { 642 1.10 christos case fmt_single: 643 1.10 christos sim_fpu_32to (&wop, op); 644 1.10 christos sim_fpu_32to (&wmagic, 0x4b000000); 645 1.10 christos break; 646 1.10 christos case fmt_double: 647 1.10 christos sim_fpu_64to (&wop, op); 648 1.10 christos sim_fpu_64to (&wmagic, 0x4330000000000000); 649 1.10 christos break; 650 1.10 christos default: 651 1.10 christos sim_io_error (SD, "Bad switch\n"); 652 1.10 christos } 653 1.10 christos 654 1.10 christos if (sim_fpu_is_nan (&wop) || sim_fpu_is_infinity (&wop)) 655 1.10 christos { 656 1.10 christos status = sim_fpu_status_invalid_cvi; 657 1.10 christos update_fcsr (cpu, cia, status); 658 1.10 christos return status; 659 1.10 christos } 660 1.10 christos 661 1.10 christos switch (fmt) 662 1.10 christos { 663 1.10 christos case fmt_single: 664 1.10 christos if (sim_fpu_is_ge (&wop, &wmagic)) 665 1.10 christos wans = wop; 666 1.10 christos else 667 1.10 christos { 668 1.10 christos sim_fpu_add (&wtemp, &wop, &wmagic); 669 1.10 christos sim_fpu_round_32 (&wtemp, round, sim_fpu_denorm_default); 670 1.10 christos sim_fpu_sub (&wans, &wtemp, &wmagic); 671 1.10 christos } 672 1.10 christos sim_fpu_to32 ((uint32_t *) ans, &wans); 673 1.10 christos break; 674 1.10 christos case fmt_double: 675 1.10 christos if (sim_fpu_is_ge (&wop, &wmagic)) 676 1.10 christos wans = wop; 677 1.10 christos else 678 1.10 christos { 679 1.10 christos sim_fpu_add (&wtemp, &wop, &wmagic); 680 1.10 christos sim_fpu_round_64 (&wtemp, round, sim_fpu_denorm_default); 681 1.10 christos sim_fpu_sub (&wans, &wtemp, &wmagic); 682 1.10 christos } 683 1.10 christos sim_fpu_to64 (ans, &wans); 684 1.10 christos break; 685 1.10 christos default: 686 1.10 christos sim_io_error (SD, "Bad switch\n"); 687 1.10 christos } 688 1.10 christos 689 1.10 christos if (*ans != op && status == 0) 690 1.10 christos status = sim_fpu_status_inexact; 691 1.10 christos 692 1.10 christos update_fcsr (cpu, cia, status); 693 1.10 christos return status; 694 1.10 christos } 695 1.10 christos 696 1.1 christos void 697 1.1 christos fp_cmp(sim_cpu *cpu, 698 1.1 christos address_word cia, 699 1.10 christos uint64_t op1, 700 1.10 christos uint64_t op2, 701 1.1 christos FP_formats fmt, 702 1.1 christos int abs, 703 1.1 christos int cond, 704 1.1 christos int cc) 705 1.1 christos { 706 1.1 christos sim_fpu_status status = 0; 707 1.1 christos 708 1.1 christos /* The format type should already have been checked. The FCSR is 709 1.1 christos updated before the condition codes so that any exceptions will 710 1.1 christos be signalled before the condition codes are changed. */ 711 1.1 christos switch (fmt) 712 1.1 christos { 713 1.1 christos case fmt_single: 714 1.1 christos case fmt_double: 715 1.1 christos { 716 1.1 christos int result; 717 1.1 christos status = fp_test(op1, op2, fmt, abs, cond, &result); 718 1.1 christos update_fcsr (cpu, cia, status); 719 1.1 christos SETFCC (cc, result); 720 1.1 christos break; 721 1.1 christos } 722 1.1 christos case fmt_ps: 723 1.1 christos { 724 1.1 christos int result0, result1; 725 1.1 christos status = fp_test(FP_PS_lower (op1), FP_PS_lower (op2), fmt_single, 726 1.1 christos abs, cond, &result0); 727 1.1 christos status |= fp_test(FP_PS_upper (op1), FP_PS_upper (op2), fmt_single, 728 1.1 christos abs, cond, &result1); 729 1.1 christos update_fcsr (cpu, cia, status); 730 1.1 christos SETFCC (cc, result0); 731 1.1 christos SETFCC (cc+1, result1); 732 1.1 christos break; 733 1.1 christos } 734 1.1 christos default: 735 1.10 christos sim_io_error (SD, "Bad switch\n"); 736 1.1 christos } 737 1.1 christos } 738 1.1 christos 739 1.10 christos uint64_t 740 1.10 christos fp_r6_cmp (sim_cpu *cpu, 741 1.10 christos address_word cia, 742 1.10 christos uint64_t op1, 743 1.10 christos uint64_t op2, 744 1.10 christos FP_formats fmt, 745 1.10 christos int cond) 746 1.10 christos { 747 1.10 christos sim_fpu wop1, wop2; 748 1.10 christos int result = 0; 749 1.10 christos 750 1.10 christos switch (fmt) 751 1.10 christos { 752 1.10 christos case fmt_single: 753 1.10 christos sim_fpu_32to (&wop1, op1); 754 1.10 christos sim_fpu_32to (&wop2, op2); 755 1.10 christos break; 756 1.10 christos case fmt_double: 757 1.10 christos sim_fpu_64to (&wop1, op1); 758 1.10 christos sim_fpu_64to (&wop2, op2); 759 1.10 christos break; 760 1.10 christos default: 761 1.10 christos sim_io_error (SD, "Bad switch\n"); 762 1.10 christos } 763 1.10 christos 764 1.10 christos switch (cond) 765 1.10 christos { 766 1.10 christos case FP_R6CMP_AF: 767 1.10 christos result = 0; 768 1.10 christos break; 769 1.10 christos case FP_R6CMP_UN: 770 1.10 christos result = sim_fpu_is_un (&wop1, &wop2); 771 1.10 christos break; 772 1.10 christos case FP_R6CMP_OR: 773 1.10 christos result = sim_fpu_is_or (&wop1, &wop2); 774 1.10 christos break; 775 1.10 christos case FP_R6CMP_EQ: 776 1.10 christos result = sim_fpu_is_eq (&wop1, &wop2); 777 1.10 christos break; 778 1.10 christos case FP_R6CMP_NE: 779 1.10 christos result = sim_fpu_is_ne (&wop1, &wop2); 780 1.10 christos break; 781 1.10 christos case FP_R6CMP_LT: 782 1.10 christos result = sim_fpu_is_lt (&wop1, &wop2); 783 1.10 christos break; 784 1.10 christos case FP_R6CMP_LE: 785 1.10 christos result = sim_fpu_is_le (&wop1, &wop2); 786 1.10 christos break; 787 1.10 christos case FP_R6CMP_UEQ: 788 1.10 christos result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_eq (&wop1, &wop2); 789 1.10 christos break; 790 1.10 christos case FP_R6CMP_UNE: 791 1.10 christos result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_ne (&wop1, &wop2); 792 1.10 christos break; 793 1.10 christos case FP_R6CMP_ULT: 794 1.10 christos result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_lt (&wop1, &wop2); 795 1.10 christos break; 796 1.10 christos case FP_R6CMP_ULE: 797 1.10 christos result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_le (&wop1, &wop2); 798 1.10 christos break; 799 1.10 christos default: 800 1.10 christos update_fcsr (cpu, cia, sim_fpu_status_invalid_cmp); 801 1.10 christos break; 802 1.10 christos } 803 1.10 christos 804 1.10 christos if (result) 805 1.10 christos { 806 1.10 christos switch (fmt) 807 1.10 christos { 808 1.10 christos case fmt_single: 809 1.10 christos return 0xFFFFFFFF; 810 1.10 christos case fmt_double: 811 1.10 christos return 0xFFFFFFFFFFFFFFFF; 812 1.10 christos default: 813 1.10 christos sim_io_error (SD, "Bad switch\n"); 814 1.10 christos } 815 1.10 christos } 816 1.10 christos else 817 1.10 christos return 0; 818 1.10 christos } 819 1.1 christos 820 1.1 christos /* Basic arithmetic operations. */ 821 1.1 christos 822 1.10 christos static uint64_t 823 1.1 christos fp_unary(sim_cpu *cpu, 824 1.1 christos address_word cia, 825 1.1 christos int (*sim_fpu_op)(sim_fpu *, const sim_fpu *), 826 1.10 christos uint64_t op, 827 1.1 christos FP_formats fmt) 828 1.1 christos { 829 1.10 christos sim_fpu wop = {0}; 830 1.1 christos sim_fpu ans; 831 1.1 christos sim_fpu_round round = rounding_mode (GETRM()); 832 1.1 christos sim_fpu_denorm denorm = denorm_mode (cpu); 833 1.1 christos sim_fpu_status status = 0; 834 1.10 christos uint64_t result = 0; 835 1.1 christos 836 1.1 christos /* The format type has already been checked: */ 837 1.1 christos switch (fmt) 838 1.1 christos { 839 1.1 christos case fmt_single: 840 1.1 christos { 841 1.10 christos uint32_t res; 842 1.1 christos sim_fpu_32to (&wop, op); 843 1.1 christos status |= (*sim_fpu_op) (&ans, &wop); 844 1.1 christos status |= sim_fpu_round_32 (&ans, round, denorm); 845 1.1 christos sim_fpu_to32 (&res, &ans); 846 1.1 christos result = res; 847 1.1 christos break; 848 1.1 christos } 849 1.1 christos case fmt_double: 850 1.1 christos { 851 1.10 christos uint64_t res; 852 1.1 christos sim_fpu_64to (&wop, op); 853 1.1 christos status |= (*sim_fpu_op) (&ans, &wop); 854 1.1 christos status |= sim_fpu_round_64 (&ans, round, denorm); 855 1.1 christos sim_fpu_to64 (&res, &ans); 856 1.1 christos result = res; 857 1.1 christos break; 858 1.1 christos } 859 1.1 christos case fmt_ps: 860 1.1 christos { 861 1.1 christos int status_u = 0, status_l = 0; 862 1.10 christos uint32_t res_u, res_l; 863 1.1 christos sim_fpu_32to (&wop, FP_PS_upper(op)); 864 1.1 christos status_u |= (*sim_fpu_op) (&ans, &wop); 865 1.1 christos sim_fpu_to32 (&res_u, &ans); 866 1.1 christos sim_fpu_32to (&wop, FP_PS_lower(op)); 867 1.1 christos status_l |= (*sim_fpu_op) (&ans, &wop); 868 1.1 christos sim_fpu_to32 (&res_l, &ans); 869 1.1 christos result = FP_PS_cat(res_u, res_l); 870 1.1 christos status = status_u | status_l; 871 1.1 christos break; 872 1.1 christos } 873 1.1 christos default: 874 1.10 christos sim_io_error (SD, "Bad switch\n"); 875 1.1 christos } 876 1.1 christos 877 1.1 christos update_fcsr (cpu, cia, status); 878 1.1 christos return result; 879 1.1 christos } 880 1.1 christos 881 1.10 christos static uint64_t 882 1.1 christos fp_binary(sim_cpu *cpu, 883 1.1 christos address_word cia, 884 1.1 christos int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *), 885 1.10 christos uint64_t op1, 886 1.10 christos uint64_t op2, 887 1.1 christos FP_formats fmt) 888 1.1 christos { 889 1.10 christos sim_fpu wop1 = {0}; 890 1.10 christos sim_fpu wop2 = {0}; 891 1.10 christos sim_fpu ans = {0}; 892 1.1 christos sim_fpu_round round = rounding_mode (GETRM()); 893 1.1 christos sim_fpu_denorm denorm = denorm_mode (cpu); 894 1.1 christos sim_fpu_status status = 0; 895 1.10 christos uint64_t result = 0; 896 1.1 christos 897 1.1 christos /* The format type has already been checked: */ 898 1.1 christos switch (fmt) 899 1.1 christos { 900 1.1 christos case fmt_single: 901 1.1 christos { 902 1.10 christos uint32_t res; 903 1.1 christos sim_fpu_32to (&wop1, op1); 904 1.1 christos sim_fpu_32to (&wop2, op2); 905 1.1 christos status |= (*sim_fpu_op) (&ans, &wop1, &wop2); 906 1.1 christos status |= sim_fpu_round_32 (&ans, round, denorm); 907 1.1 christos sim_fpu_to32 (&res, &ans); 908 1.1 christos result = res; 909 1.1 christos break; 910 1.1 christos } 911 1.1 christos case fmt_double: 912 1.1 christos { 913 1.10 christos uint64_t res; 914 1.1 christos sim_fpu_64to (&wop1, op1); 915 1.1 christos sim_fpu_64to (&wop2, op2); 916 1.1 christos status |= (*sim_fpu_op) (&ans, &wop1, &wop2); 917 1.1 christos status |= sim_fpu_round_64 (&ans, round, denorm); 918 1.1 christos sim_fpu_to64 (&res, &ans); 919 1.1 christos result = res; 920 1.1 christos break; 921 1.1 christos } 922 1.1 christos case fmt_ps: 923 1.1 christos { 924 1.1 christos int status_u = 0, status_l = 0; 925 1.10 christos uint32_t res_u, res_l; 926 1.1 christos sim_fpu_32to (&wop1, FP_PS_upper(op1)); 927 1.1 christos sim_fpu_32to (&wop2, FP_PS_upper(op2)); 928 1.1 christos status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2); 929 1.1 christos sim_fpu_to32 (&res_u, &ans); 930 1.1 christos sim_fpu_32to (&wop1, FP_PS_lower(op1)); 931 1.1 christos sim_fpu_32to (&wop2, FP_PS_lower(op2)); 932 1.1 christos status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2); 933 1.1 christos sim_fpu_to32 (&res_l, &ans); 934 1.1 christos result = FP_PS_cat(res_u, res_l); 935 1.1 christos status = status_u | status_l; 936 1.1 christos break; 937 1.1 christos } 938 1.1 christos default: 939 1.10 christos sim_io_error (SD, "Bad switch\n"); 940 1.1 christos } 941 1.1 christos 942 1.1 christos update_fcsr (cpu, cia, status); 943 1.1 christos return result; 944 1.1 christos } 945 1.1 christos 946 1.1 christos /* Common MAC code for single operands (.s or .d), defers setting FCSR. */ 947 1.1 christos static sim_fpu_status 948 1.1 christos inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *), 949 1.10 christos uint64_t op1, 950 1.10 christos uint64_t op2, 951 1.10 christos uint64_t op3, 952 1.1 christos int scale, 953 1.1 christos int negate, 954 1.1 christos FP_formats fmt, 955 1.1 christos sim_fpu_round round, 956 1.1 christos sim_fpu_denorm denorm, 957 1.10 christos uint64_t *result) 958 1.1 christos { 959 1.1 christos sim_fpu wop1; 960 1.1 christos sim_fpu wop2; 961 1.1 christos sim_fpu ans; 962 1.1 christos sim_fpu_status status = 0; 963 1.1 christos sim_fpu_status op_status; 964 1.10 christos uint64_t temp = 0; 965 1.1 christos 966 1.1 christos switch (fmt) 967 1.1 christos { 968 1.1 christos case fmt_single: 969 1.1 christos { 970 1.10 christos uint32_t res; 971 1.1 christos sim_fpu_32to (&wop1, op1); 972 1.1 christos sim_fpu_32to (&wop2, op2); 973 1.1 christos status |= sim_fpu_mul (&ans, &wop1, &wop2); 974 1.1 christos if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */ 975 1.1 christos ans.normal_exp += scale; 976 1.1 christos status |= sim_fpu_round_32 (&ans, round, denorm); 977 1.1 christos wop1 = ans; 978 1.10 christos op_status = 0; 979 1.1 christos sim_fpu_32to (&wop2, op3); 980 1.1 christos op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2); 981 1.1 christos op_status |= sim_fpu_round_32 (&ans, round, denorm); 982 1.1 christos status |= op_status; 983 1.1 christos if (negate) 984 1.1 christos { 985 1.1 christos wop1 = ans; 986 1.1 christos op_status = sim_fpu_neg (&ans, &wop1); 987 1.1 christos op_status |= sim_fpu_round_32 (&ans, round, denorm); 988 1.1 christos status |= op_status; 989 1.1 christos } 990 1.1 christos sim_fpu_to32 (&res, &ans); 991 1.1 christos temp = res; 992 1.1 christos break; 993 1.1 christos } 994 1.1 christos case fmt_double: 995 1.1 christos { 996 1.10 christos uint64_t res; 997 1.1 christos sim_fpu_64to (&wop1, op1); 998 1.1 christos sim_fpu_64to (&wop2, op2); 999 1.1 christos status |= sim_fpu_mul (&ans, &wop1, &wop2); 1000 1.1 christos if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */ 1001 1.1 christos ans.normal_exp += scale; 1002 1.1 christos status |= sim_fpu_round_64 (&ans, round, denorm); 1003 1.1 christos wop1 = ans; 1004 1.10 christos op_status = 0; 1005 1.1 christos sim_fpu_64to (&wop2, op3); 1006 1.1 christos op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2); 1007 1.1 christos op_status |= sim_fpu_round_64 (&ans, round, denorm); 1008 1.1 christos status |= op_status; 1009 1.1 christos if (negate) 1010 1.1 christos { 1011 1.1 christos wop1 = ans; 1012 1.1 christos op_status = sim_fpu_neg (&ans, &wop1); 1013 1.1 christos op_status |= sim_fpu_round_64 (&ans, round, denorm); 1014 1.1 christos status |= op_status; 1015 1.1 christos } 1016 1.1 christos sim_fpu_to64 (&res, &ans); 1017 1.1 christos temp = res; 1018 1.1 christos break; 1019 1.1 christos } 1020 1.1 christos default: 1021 1.1 christos fprintf (stderr, "Bad switch\n"); 1022 1.1 christos abort (); 1023 1.1 christos } 1024 1.1 christos *result = temp; 1025 1.1 christos return status; 1026 1.1 christos } 1027 1.1 christos 1028 1.1 christos /* Common implementation of madd, nmadd, msub, nmsub that does 1029 1.1 christos intermediate rounding per spec. Also used for recip2 and rsqrt2, 1030 1.1 christos which are transformed into equivalent nmsub operations. The scale 1031 1.1 christos argument is an adjustment to the exponent of the intermediate 1032 1.1 christos product op1*op2. It is currently non-zero for rsqrt2 (-1), which 1033 1.1 christos requires an effective division by 2. */ 1034 1.10 christos static uint64_t 1035 1.1 christos fp_mac(sim_cpu *cpu, 1036 1.1 christos address_word cia, 1037 1.1 christos int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *), 1038 1.10 christos uint64_t op1, 1039 1.10 christos uint64_t op2, 1040 1.10 christos uint64_t op3, 1041 1.1 christos int scale, 1042 1.1 christos int negate, 1043 1.1 christos FP_formats fmt) 1044 1.1 christos { 1045 1.1 christos sim_fpu_round round = rounding_mode (GETRM()); 1046 1.1 christos sim_fpu_denorm denorm = denorm_mode (cpu); 1047 1.1 christos sim_fpu_status status = 0; 1048 1.10 christos uint64_t result = 0; 1049 1.1 christos 1050 1.1 christos /* The format type has already been checked: */ 1051 1.1 christos switch (fmt) 1052 1.1 christos { 1053 1.1 christos case fmt_single: 1054 1.1 christos case fmt_double: 1055 1.1 christos status = inner_mac(sim_fpu_op, op1, op2, op3, scale, 1056 1.1 christos negate, fmt, round, denorm, &result); 1057 1.1 christos break; 1058 1.1 christos case fmt_ps: 1059 1.1 christos { 1060 1.1 christos int status_u, status_l; 1061 1.10 christos uint64_t result_u, result_l; 1062 1.1 christos status_u = inner_mac(sim_fpu_op, FP_PS_upper(op1), FP_PS_upper(op2), 1063 1.1 christos FP_PS_upper(op3), scale, negate, fmt_single, 1064 1.1 christos round, denorm, &result_u); 1065 1.1 christos status_l = inner_mac(sim_fpu_op, FP_PS_lower(op1), FP_PS_lower(op2), 1066 1.1 christos FP_PS_lower(op3), scale, negate, fmt_single, 1067 1.1 christos round, denorm, &result_l); 1068 1.1 christos result = FP_PS_cat(result_u, result_l); 1069 1.1 christos status = status_u | status_l; 1070 1.1 christos break; 1071 1.1 christos } 1072 1.1 christos default: 1073 1.10 christos sim_io_error (SD, "Bad switch\n"); 1074 1.10 christos } 1075 1.10 christos 1076 1.10 christos update_fcsr (cpu, cia, status); 1077 1.10 christos return result; 1078 1.10 christos } 1079 1.10 christos 1080 1.10 christos /* Common FMAC code for .s, .d. Defers setting FCSR to caller. */ 1081 1.10 christos static sim_fpu_status 1082 1.10 christos inner_fmac (sim_cpu *cpu, 1083 1.10 christos int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *), 1084 1.10 christos uint64_t op1, 1085 1.10 christos uint64_t op2, 1086 1.10 christos uint64_t op3, 1087 1.10 christos sim_fpu_round round, 1088 1.10 christos sim_fpu_denorm denorm, 1089 1.10 christos FP_formats fmt, 1090 1.10 christos uint64_t *result) 1091 1.10 christos { 1092 1.10 christos sim_fpu wop1, wop2, ans; 1093 1.10 christos sim_fpu_status status = 0; 1094 1.10 christos sim_fpu_status op_status; 1095 1.10 christos uint32_t t32 = 0; 1096 1.10 christos uint64_t t64 = 0; 1097 1.10 christos 1098 1.10 christos switch (fmt) 1099 1.10 christos { 1100 1.10 christos case fmt_single: 1101 1.10 christos sim_fpu_32to (&wop1, op1); 1102 1.10 christos sim_fpu_32to (&wop2, op2); 1103 1.10 christos status |= sim_fpu_mul (&ans, &wop1, &wop2); 1104 1.10 christos wop1 = ans; 1105 1.10 christos op_status = 0; 1106 1.10 christos sim_fpu_32to (&wop2, op3); 1107 1.10 christos op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1); 1108 1.10 christos op_status |= sim_fpu_round_32 (&ans, round, denorm); 1109 1.10 christos status |= op_status; 1110 1.10 christos sim_fpu_to32 (&t32, &ans); 1111 1.10 christos t64 = t32; 1112 1.10 christos break; 1113 1.10 christos case fmt_double: 1114 1.10 christos sim_fpu_64to (&wop1, op1); 1115 1.10 christos sim_fpu_64to (&wop2, op2); 1116 1.10 christos status |= sim_fpu_mul (&ans, &wop1, &wop2); 1117 1.10 christos wop1 = ans; 1118 1.10 christos op_status = 0; 1119 1.10 christos sim_fpu_64to (&wop2, op3); 1120 1.10 christos op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1); 1121 1.10 christos op_status |= sim_fpu_round_64 (&ans, round, denorm); 1122 1.10 christos status |= op_status; 1123 1.10 christos sim_fpu_to64 (&t64, &ans); 1124 1.10 christos break; 1125 1.10 christos default: 1126 1.10 christos sim_io_error (SD, "Bad switch\n"); 1127 1.10 christos } 1128 1.10 christos 1129 1.10 christos *result = t64; 1130 1.10 christos return status; 1131 1.10 christos } 1132 1.10 christos 1133 1.10 christos static uint64_t 1134 1.10 christos fp_fmac (sim_cpu *cpu, 1135 1.10 christos address_word cia, 1136 1.10 christos int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *), 1137 1.10 christos uint64_t op1, 1138 1.10 christos uint64_t op2, 1139 1.10 christos uint64_t op3, 1140 1.10 christos FP_formats fmt) 1141 1.10 christos { 1142 1.10 christos sim_fpu_round round = rounding_mode (GETRM()); 1143 1.10 christos sim_fpu_denorm denorm = denorm_mode (cpu); 1144 1.10 christos sim_fpu_status status = 0; 1145 1.10 christos uint64_t result = 0; 1146 1.10 christos 1147 1.10 christos switch (fmt) 1148 1.10 christos { 1149 1.10 christos case fmt_single: 1150 1.10 christos case fmt_double: 1151 1.10 christos status = inner_fmac (cpu, sim_fpu_op, op1, op2, op3, 1152 1.10 christos round, denorm, fmt, &result); 1153 1.10 christos break; 1154 1.10 christos default: 1155 1.10 christos sim_io_error (SD, "Bad switch\n"); 1156 1.1 christos } 1157 1.1 christos 1158 1.1 christos update_fcsr (cpu, cia, status); 1159 1.1 christos return result; 1160 1.1 christos } 1161 1.1 christos 1162 1.1 christos /* Common rsqrt code for single operands (.s or .d), intermediate rounding. */ 1163 1.1 christos static sim_fpu_status 1164 1.10 christos inner_rsqrt(uint64_t op1, 1165 1.1 christos FP_formats fmt, 1166 1.1 christos sim_fpu_round round, 1167 1.1 christos sim_fpu_denorm denorm, 1168 1.10 christos uint64_t *result) 1169 1.1 christos { 1170 1.1 christos sim_fpu wop1; 1171 1.1 christos sim_fpu ans; 1172 1.1 christos sim_fpu_status status = 0; 1173 1.1 christos sim_fpu_status op_status; 1174 1.10 christos uint64_t temp = 0; 1175 1.1 christos 1176 1.1 christos switch (fmt) 1177 1.1 christos { 1178 1.1 christos case fmt_single: 1179 1.1 christos { 1180 1.10 christos uint32_t res; 1181 1.1 christos sim_fpu_32to (&wop1, op1); 1182 1.1 christos status |= sim_fpu_sqrt (&ans, &wop1); 1183 1.11 christos status |= sim_fpu_round_32 (&ans, round, denorm); 1184 1.1 christos wop1 = ans; 1185 1.1 christos op_status = sim_fpu_inv (&ans, &wop1); 1186 1.1 christos op_status |= sim_fpu_round_32 (&ans, round, denorm); 1187 1.1 christos sim_fpu_to32 (&res, &ans); 1188 1.1 christos temp = res; 1189 1.1 christos status |= op_status; 1190 1.1 christos break; 1191 1.1 christos } 1192 1.1 christos case fmt_double: 1193 1.1 christos { 1194 1.10 christos uint64_t res; 1195 1.1 christos sim_fpu_64to (&wop1, op1); 1196 1.1 christos status |= sim_fpu_sqrt (&ans, &wop1); 1197 1.1 christos status |= sim_fpu_round_64 (&ans, round, denorm); 1198 1.1 christos wop1 = ans; 1199 1.1 christos op_status = sim_fpu_inv (&ans, &wop1); 1200 1.1 christos op_status |= sim_fpu_round_64 (&ans, round, denorm); 1201 1.1 christos sim_fpu_to64 (&res, &ans); 1202 1.1 christos temp = res; 1203 1.1 christos status |= op_status; 1204 1.1 christos break; 1205 1.1 christos } 1206 1.1 christos default: 1207 1.1 christos fprintf (stderr, "Bad switch\n"); 1208 1.1 christos abort (); 1209 1.1 christos } 1210 1.1 christos *result = temp; 1211 1.1 christos return status; 1212 1.1 christos } 1213 1.1 christos 1214 1.10 christos static uint64_t 1215 1.1 christos fp_inv_sqrt(sim_cpu *cpu, 1216 1.1 christos address_word cia, 1217 1.10 christos uint64_t op1, 1218 1.1 christos FP_formats fmt) 1219 1.1 christos { 1220 1.1 christos sim_fpu_round round = rounding_mode (GETRM()); 1221 1.11 christos sim_fpu_denorm denorm = denorm_mode (cpu); 1222 1.1 christos sim_fpu_status status = 0; 1223 1.10 christos uint64_t result = 0; 1224 1.1 christos 1225 1.1 christos /* The format type has already been checked: */ 1226 1.1 christos switch (fmt) 1227 1.1 christos { 1228 1.1 christos case fmt_single: 1229 1.1 christos case fmt_double: 1230 1.1 christos status = inner_rsqrt (op1, fmt, round, denorm, &result); 1231 1.1 christos break; 1232 1.1 christos case fmt_ps: 1233 1.1 christos { 1234 1.1 christos int status_u, status_l; 1235 1.10 christos uint64_t result_u, result_l; 1236 1.1 christos status_u = inner_rsqrt (FP_PS_upper(op1), fmt_single, round, denorm, 1237 1.1 christos &result_u); 1238 1.1 christos status_l = inner_rsqrt (FP_PS_lower(op1), fmt_single, round, denorm, 1239 1.1 christos &result_l); 1240 1.1 christos result = FP_PS_cat(result_u, result_l); 1241 1.1 christos status = status_u | status_l; 1242 1.1 christos break; 1243 1.1 christos } 1244 1.1 christos default: 1245 1.10 christos sim_io_error (SD, "Bad switch\n"); 1246 1.1 christos } 1247 1.1 christos 1248 1.1 christos update_fcsr (cpu, cia, status); 1249 1.1 christos return result; 1250 1.1 christos } 1251 1.1 christos 1252 1.1 christos 1253 1.10 christos uint64_t 1254 1.1 christos fp_abs(sim_cpu *cpu, 1255 1.1 christos address_word cia, 1256 1.10 christos uint64_t op, 1257 1.1 christos FP_formats fmt) 1258 1.1 christos { 1259 1.1 christos return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt); 1260 1.1 christos } 1261 1.1 christos 1262 1.10 christos uint64_t 1263 1.1 christos fp_neg(sim_cpu *cpu, 1264 1.1 christos address_word cia, 1265 1.10 christos uint64_t op, 1266 1.1 christos FP_formats fmt) 1267 1.1 christos { 1268 1.1 christos return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt); 1269 1.1 christos } 1270 1.1 christos 1271 1.10 christos uint64_t 1272 1.1 christos fp_add(sim_cpu *cpu, 1273 1.1 christos address_word cia, 1274 1.10 christos uint64_t op1, 1275 1.10 christos uint64_t op2, 1276 1.1 christos FP_formats fmt) 1277 1.1 christos { 1278 1.1 christos return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt); 1279 1.1 christos } 1280 1.1 christos 1281 1.10 christos uint64_t 1282 1.1 christos fp_sub(sim_cpu *cpu, 1283 1.1 christos address_word cia, 1284 1.10 christos uint64_t op1, 1285 1.10 christos uint64_t op2, 1286 1.1 christos FP_formats fmt) 1287 1.1 christos { 1288 1.1 christos return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt); 1289 1.1 christos } 1290 1.1 christos 1291 1.10 christos uint64_t 1292 1.1 christos fp_mul(sim_cpu *cpu, 1293 1.1 christos address_word cia, 1294 1.10 christos uint64_t op1, 1295 1.10 christos uint64_t op2, 1296 1.1 christos FP_formats fmt) 1297 1.1 christos { 1298 1.1 christos return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt); 1299 1.1 christos } 1300 1.1 christos 1301 1.10 christos uint64_t 1302 1.1 christos fp_div(sim_cpu *cpu, 1303 1.1 christos address_word cia, 1304 1.10 christos uint64_t op1, 1305 1.10 christos uint64_t op2, 1306 1.1 christos FP_formats fmt) 1307 1.1 christos { 1308 1.1 christos return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt); 1309 1.1 christos } 1310 1.1 christos 1311 1.10 christos uint64_t 1312 1.10 christos fp_min (sim_cpu *cpu, 1313 1.10 christos address_word cia, 1314 1.10 christos uint64_t op1, 1315 1.10 christos uint64_t op2, 1316 1.10 christos FP_formats fmt) 1317 1.10 christos { 1318 1.10 christos return fp_binary (cpu, cia, &sim_fpu_min, op1, op2, fmt); 1319 1.10 christos } 1320 1.10 christos 1321 1.10 christos uint64_t 1322 1.10 christos fp_max (sim_cpu *cpu, 1323 1.10 christos address_word cia, 1324 1.10 christos uint64_t op1, 1325 1.10 christos uint64_t op2, 1326 1.10 christos FP_formats fmt) 1327 1.10 christos { 1328 1.10 christos return fp_binary (cpu, cia, &sim_fpu_max, op1, op2, fmt); 1329 1.10 christos } 1330 1.10 christos 1331 1.10 christos uint64_t 1332 1.10 christos fp_mina (sim_cpu *cpu, 1333 1.10 christos address_word cia, 1334 1.10 christos uint64_t op1, 1335 1.10 christos uint64_t op2, 1336 1.10 christos FP_formats fmt) 1337 1.10 christos { 1338 1.10 christos uint64_t ret; 1339 1.10 christos sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans; 1340 1.10 christos sim_fpu_status status = 0; 1341 1.10 christos 1342 1.10 christos switch (fmt) 1343 1.10 christos { 1344 1.10 christos case fmt_single: 1345 1.10 christos sim_fpu_32to (&wop1, op1); 1346 1.10 christos sim_fpu_32to (&wop2, op2); 1347 1.10 christos break; 1348 1.10 christos case fmt_double: 1349 1.10 christos sim_fpu_64to (&wop1, op1); 1350 1.10 christos sim_fpu_64to (&wop2, op2); 1351 1.10 christos break; 1352 1.10 christos default: 1353 1.10 christos sim_io_error (SD, "Bad switch\n"); 1354 1.10 christos } 1355 1.10 christos 1356 1.10 christos status |= sim_fpu_abs (&waop1, &wop1); 1357 1.10 christos status |= sim_fpu_abs (&waop2, &wop2); 1358 1.10 christos status |= sim_fpu_min (&wans, &waop1, &waop2); 1359 1.10 christos ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2; 1360 1.10 christos 1361 1.10 christos update_fcsr (cpu, cia, status); 1362 1.10 christos return ret; 1363 1.10 christos } 1364 1.10 christos 1365 1.10 christos uint64_t 1366 1.10 christos fp_maxa (sim_cpu *cpu, 1367 1.10 christos address_word cia, 1368 1.10 christos uint64_t op1, 1369 1.10 christos uint64_t op2, 1370 1.10 christos FP_formats fmt) 1371 1.10 christos { 1372 1.10 christos uint64_t ret; 1373 1.10 christos sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans; 1374 1.10 christos sim_fpu_status status = 0; 1375 1.10 christos 1376 1.10 christos switch (fmt) 1377 1.10 christos { 1378 1.10 christos case fmt_single: 1379 1.10 christos sim_fpu_32to (&wop1, op1); 1380 1.10 christos sim_fpu_32to (&wop2, op2); 1381 1.10 christos break; 1382 1.10 christos case fmt_double: 1383 1.10 christos sim_fpu_64to (&wop1, op1); 1384 1.10 christos sim_fpu_64to (&wop2, op2); 1385 1.10 christos break; 1386 1.10 christos default: 1387 1.10 christos sim_io_error (SD, "Bad switch\n"); 1388 1.10 christos } 1389 1.10 christos 1390 1.10 christos status |= sim_fpu_abs (&waop1, &wop1); 1391 1.10 christos status |= sim_fpu_abs (&waop2, &wop2); 1392 1.10 christos status |= sim_fpu_max (&wans, &waop1, &waop2); 1393 1.10 christos ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2; 1394 1.10 christos 1395 1.10 christos update_fcsr (cpu, cia, status); 1396 1.10 christos return ret; 1397 1.10 christos } 1398 1.10 christos 1399 1.10 christos uint64_t 1400 1.1 christos fp_recip(sim_cpu *cpu, 1401 1.1 christos address_word cia, 1402 1.10 christos uint64_t op, 1403 1.1 christos FP_formats fmt) 1404 1.1 christos { 1405 1.1 christos return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt); 1406 1.1 christos } 1407 1.1 christos 1408 1.10 christos uint64_t 1409 1.1 christos fp_sqrt(sim_cpu *cpu, 1410 1.1 christos address_word cia, 1411 1.10 christos uint64_t op, 1412 1.1 christos FP_formats fmt) 1413 1.1 christos { 1414 1.1 christos return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt); 1415 1.1 christos } 1416 1.1 christos 1417 1.10 christos uint64_t 1418 1.1 christos fp_rsqrt(sim_cpu *cpu, 1419 1.1 christos address_word cia, 1420 1.10 christos uint64_t op, 1421 1.1 christos FP_formats fmt) 1422 1.1 christos { 1423 1.1 christos return fp_inv_sqrt(cpu, cia, op, fmt); 1424 1.1 christos } 1425 1.1 christos 1426 1.10 christos uint64_t 1427 1.1 christos fp_madd(sim_cpu *cpu, 1428 1.1 christos address_word cia, 1429 1.10 christos uint64_t op1, 1430 1.10 christos uint64_t op2, 1431 1.10 christos uint64_t op3, 1432 1.1 christos FP_formats fmt) 1433 1.1 christos { 1434 1.1 christos return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt); 1435 1.1 christos } 1436 1.1 christos 1437 1.10 christos uint64_t 1438 1.1 christos fp_msub(sim_cpu *cpu, 1439 1.1 christos address_word cia, 1440 1.10 christos uint64_t op1, 1441 1.10 christos uint64_t op2, 1442 1.10 christos uint64_t op3, 1443 1.1 christos FP_formats fmt) 1444 1.1 christos { 1445 1.1 christos return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt); 1446 1.1 christos } 1447 1.1 christos 1448 1.10 christos uint64_t 1449 1.10 christos fp_fmadd (sim_cpu *cpu, 1450 1.10 christos address_word cia, 1451 1.10 christos uint64_t op1, 1452 1.10 christos uint64_t op2, 1453 1.10 christos uint64_t op3, 1454 1.10 christos FP_formats fmt) 1455 1.10 christos { 1456 1.10 christos return fp_fmac (cpu, cia, &sim_fpu_add, op1, op2, op3, fmt); 1457 1.10 christos } 1458 1.10 christos 1459 1.10 christos uint64_t 1460 1.10 christos fp_fmsub (sim_cpu *cpu, 1461 1.10 christos address_word cia, 1462 1.10 christos uint64_t op1, 1463 1.10 christos uint64_t op2, 1464 1.10 christos uint64_t op3, 1465 1.10 christos FP_formats fmt) 1466 1.10 christos { 1467 1.10 christos return fp_fmac (cpu, cia, &sim_fpu_sub, op1, op2, op3, fmt); 1468 1.10 christos } 1469 1.10 christos 1470 1.10 christos uint64_t 1471 1.1 christos fp_nmadd(sim_cpu *cpu, 1472 1.1 christos address_word cia, 1473 1.10 christos uint64_t op1, 1474 1.10 christos uint64_t op2, 1475 1.10 christos uint64_t op3, 1476 1.1 christos FP_formats fmt) 1477 1.1 christos { 1478 1.1 christos return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 1, fmt); 1479 1.1 christos } 1480 1.1 christos 1481 1.10 christos uint64_t 1482 1.1 christos fp_nmsub(sim_cpu *cpu, 1483 1.1 christos address_word cia, 1484 1.10 christos uint64_t op1, 1485 1.10 christos uint64_t op2, 1486 1.10 christos uint64_t op3, 1487 1.1 christos FP_formats fmt) 1488 1.1 christos { 1489 1.1 christos return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 1, fmt); 1490 1.1 christos } 1491 1.1 christos 1492 1.1 christos 1493 1.1 christos /* MIPS-3D ASE operations. */ 1494 1.1 christos 1495 1.1 christos /* Variant of fp_binary for *r.ps MIPS-3D operations. */ 1496 1.10 christos static uint64_t 1497 1.1 christos fp_binary_r(sim_cpu *cpu, 1498 1.1 christos address_word cia, 1499 1.1 christos int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *), 1500 1.10 christos uint64_t op1, 1501 1.10 christos uint64_t op2) 1502 1.1 christos { 1503 1.1 christos sim_fpu wop1; 1504 1.1 christos sim_fpu wop2; 1505 1.1 christos sim_fpu ans; 1506 1.1 christos sim_fpu_round round = rounding_mode (GETRM ()); 1507 1.1 christos sim_fpu_denorm denorm = denorm_mode (cpu); 1508 1.1 christos sim_fpu_status status_u, status_l; 1509 1.10 christos uint64_t result; 1510 1.10 christos uint32_t res_u, res_l; 1511 1.1 christos 1512 1.1 christos /* The format must be fmt_ps. */ 1513 1.1 christos status_u = 0; 1514 1.1 christos sim_fpu_32to (&wop1, FP_PS_upper (op1)); 1515 1.1 christos sim_fpu_32to (&wop2, FP_PS_lower (op1)); 1516 1.1 christos status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2); 1517 1.1 christos status_u |= sim_fpu_round_32 (&ans, round, denorm); 1518 1.1 christos sim_fpu_to32 (&res_u, &ans); 1519 1.1 christos status_l = 0; 1520 1.1 christos sim_fpu_32to (&wop1, FP_PS_upper (op2)); 1521 1.1 christos sim_fpu_32to (&wop2, FP_PS_lower (op2)); 1522 1.1 christos status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2); 1523 1.1 christos status_l |= sim_fpu_round_32 (&ans, round, denorm); 1524 1.1 christos sim_fpu_to32 (&res_l, &ans); 1525 1.1 christos result = FP_PS_cat (res_u, res_l); 1526 1.1 christos 1527 1.1 christos update_fcsr (cpu, cia, status_u | status_l); 1528 1.1 christos return result; 1529 1.1 christos } 1530 1.1 christos 1531 1.10 christos uint64_t 1532 1.1 christos fp_add_r(sim_cpu *cpu, 1533 1.1 christos address_word cia, 1534 1.10 christos uint64_t op1, 1535 1.10 christos uint64_t op2, 1536 1.1 christos FP_formats fmt) 1537 1.1 christos { 1538 1.1 christos return fp_binary_r (cpu, cia, &sim_fpu_add, op1, op2); 1539 1.1 christos } 1540 1.1 christos 1541 1.10 christos uint64_t 1542 1.1 christos fp_mul_r(sim_cpu *cpu, 1543 1.1 christos address_word cia, 1544 1.10 christos uint64_t op1, 1545 1.10 christos uint64_t op2, 1546 1.1 christos FP_formats fmt) 1547 1.1 christos { 1548 1.1 christos return fp_binary_r (cpu, cia, &sim_fpu_mul, op1, op2); 1549 1.1 christos } 1550 1.1 christos 1551 1.1 christos #define NR_FRAC_GUARD (60) 1552 1.1 christos #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD) 1553 1.1 christos 1554 1.1 christos static int 1555 1.1 christos fpu_inv1(sim_fpu *f, const sim_fpu *l) 1556 1.1 christos { 1557 1.1 christos static const sim_fpu sim_fpu_one = { 1558 1.1 christos sim_fpu_class_number, 0, IMPLICIT_1, 0 1559 1.1 christos }; 1560 1.1 christos int status = 0; 1561 1.1 christos 1562 1.1 christos if (sim_fpu_is_zero (l)) 1563 1.1 christos { 1564 1.1 christos *f = sim_fpu_maxfp; 1565 1.1 christos f->sign = l->sign; 1566 1.1 christos return sim_fpu_status_invalid_div0; 1567 1.1 christos } 1568 1.1 christos if (sim_fpu_is_infinity (l)) 1569 1.1 christos { 1570 1.1 christos *f = sim_fpu_zero; 1571 1.1 christos f->sign = l->sign; 1572 1.1 christos return status; 1573 1.1 christos } 1574 1.1 christos status |= sim_fpu_div (f, &sim_fpu_one, l); 1575 1.1 christos return status; 1576 1.1 christos } 1577 1.1 christos 1578 1.1 christos static int 1579 1.1 christos fpu_inv1_32(sim_fpu *f, const sim_fpu *l) 1580 1.1 christos { 1581 1.1 christos if (sim_fpu_is_zero (l)) 1582 1.1 christos { 1583 1.1 christos *f = sim_fpu_max32; 1584 1.1 christos f->sign = l->sign; 1585 1.1 christos return sim_fpu_status_invalid_div0; 1586 1.1 christos } 1587 1.1 christos return fpu_inv1 (f, l); 1588 1.1 christos } 1589 1.1 christos 1590 1.1 christos static int 1591 1.1 christos fpu_inv1_64(sim_fpu *f, const sim_fpu *l) 1592 1.1 christos { 1593 1.1 christos if (sim_fpu_is_zero (l)) 1594 1.1 christos { 1595 1.1 christos *f = sim_fpu_max64; 1596 1.1 christos f->sign = l->sign; 1597 1.1 christos return sim_fpu_status_invalid_div0; 1598 1.1 christos } 1599 1.1 christos return fpu_inv1 (f, l); 1600 1.1 christos } 1601 1.1 christos 1602 1.10 christos uint64_t 1603 1.1 christos fp_recip1(sim_cpu *cpu, 1604 1.1 christos address_word cia, 1605 1.10 christos uint64_t op, 1606 1.1 christos FP_formats fmt) 1607 1.1 christos { 1608 1.1 christos switch (fmt) 1609 1.1 christos { 1610 1.1 christos case fmt_single: 1611 1.1 christos case fmt_ps: 1612 1.1 christos return fp_unary (cpu, cia, &fpu_inv1_32, op, fmt); 1613 1.1 christos case fmt_double: 1614 1.1 christos return fp_unary (cpu, cia, &fpu_inv1_64, op, fmt); 1615 1.1 christos } 1616 1.1 christos return 0; 1617 1.1 christos } 1618 1.1 christos 1619 1.10 christos uint64_t 1620 1.1 christos fp_recip2(sim_cpu *cpu, 1621 1.1 christos address_word cia, 1622 1.10 christos uint64_t op1, 1623 1.10 christos uint64_t op2, 1624 1.1 christos FP_formats fmt) 1625 1.1 christos { 1626 1.10 christos static const uint64_t one_single = UNSIGNED64 (0x3F800000); 1627 1.10 christos static const uint64_t one_double = UNSIGNED64 (0x3FF0000000000000); 1628 1.10 christos static const uint64_t one_ps = (UNSIGNED64 (0x3F800000) << 32 | UNSIGNED64 (0x3F800000)); 1629 1.10 christos uint64_t one; 1630 1.1 christos 1631 1.1 christos /* Implemented as nmsub fd, 1, fs, ft. */ 1632 1.1 christos switch (fmt) 1633 1.1 christos { 1634 1.1 christos case fmt_single: one = one_single; break; 1635 1.1 christos case fmt_double: one = one_double; break; 1636 1.1 christos case fmt_ps: one = one_ps; break; 1637 1.1 christos default: one = 0; abort (); 1638 1.1 christos } 1639 1.1 christos return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, one, 0, 1, fmt); 1640 1.1 christos } 1641 1.1 christos 1642 1.1 christos static int 1643 1.1 christos fpu_inv_sqrt1(sim_fpu *f, const sim_fpu *l) 1644 1.1 christos { 1645 1.1 christos static const sim_fpu sim_fpu_one = { 1646 1.1 christos sim_fpu_class_number, 0, IMPLICIT_1, 0 1647 1.1 christos }; 1648 1.1 christos int status = 0; 1649 1.1 christos sim_fpu t; 1650 1.1 christos 1651 1.1 christos if (sim_fpu_is_zero (l)) 1652 1.1 christos { 1653 1.1 christos *f = sim_fpu_maxfp; 1654 1.1 christos f->sign = l->sign; 1655 1.1 christos return sim_fpu_status_invalid_div0; 1656 1.1 christos } 1657 1.1 christos if (sim_fpu_is_infinity (l)) 1658 1.1 christos { 1659 1.1 christos if (!l->sign) 1660 1.1 christos { 1661 1.1 christos f->class = sim_fpu_class_zero; 1662 1.1 christos f->sign = 0; 1663 1.1 christos } 1664 1.1 christos else 1665 1.1 christos { 1666 1.1 christos *f = sim_fpu_qnan; 1667 1.1 christos status = sim_fpu_status_invalid_sqrt; 1668 1.1 christos } 1669 1.1 christos return status; 1670 1.1 christos } 1671 1.1 christos status |= sim_fpu_sqrt (&t, l); 1672 1.1 christos status |= sim_fpu_div (f, &sim_fpu_one, &t); 1673 1.1 christos return status; 1674 1.1 christos } 1675 1.1 christos 1676 1.1 christos static int 1677 1.1 christos fpu_inv_sqrt1_32(sim_fpu *f, const sim_fpu *l) 1678 1.1 christos { 1679 1.1 christos if (sim_fpu_is_zero (l)) 1680 1.1 christos { 1681 1.1 christos *f = sim_fpu_max32; 1682 1.1 christos f->sign = l->sign; 1683 1.1 christos return sim_fpu_status_invalid_div0; 1684 1.1 christos } 1685 1.1 christos return fpu_inv_sqrt1 (f, l); 1686 1.1 christos } 1687 1.1 christos 1688 1.1 christos static int 1689 1.1 christos fpu_inv_sqrt1_64(sim_fpu *f, const sim_fpu *l) 1690 1.1 christos { 1691 1.1 christos if (sim_fpu_is_zero (l)) 1692 1.1 christos { 1693 1.1 christos *f = sim_fpu_max64; 1694 1.1 christos f->sign = l->sign; 1695 1.1 christos return sim_fpu_status_invalid_div0; 1696 1.1 christos } 1697 1.1 christos return fpu_inv_sqrt1 (f, l); 1698 1.1 christos } 1699 1.1 christos 1700 1.10 christos uint64_t 1701 1.1 christos fp_rsqrt1(sim_cpu *cpu, 1702 1.1 christos address_word cia, 1703 1.10 christos uint64_t op, 1704 1.1 christos FP_formats fmt) 1705 1.1 christos { 1706 1.1 christos switch (fmt) 1707 1.1 christos { 1708 1.1 christos case fmt_single: 1709 1.1 christos case fmt_ps: 1710 1.1 christos return fp_unary (cpu, cia, &fpu_inv_sqrt1_32, op, fmt); 1711 1.1 christos case fmt_double: 1712 1.1 christos return fp_unary (cpu, cia, &fpu_inv_sqrt1_64, op, fmt); 1713 1.1 christos } 1714 1.1 christos return 0; 1715 1.1 christos } 1716 1.1 christos 1717 1.10 christos uint64_t 1718 1.1 christos fp_rsqrt2(sim_cpu *cpu, 1719 1.1 christos address_word cia, 1720 1.10 christos uint64_t op1, 1721 1.10 christos uint64_t op2, 1722 1.1 christos FP_formats fmt) 1723 1.1 christos { 1724 1.10 christos static const uint64_t half_single = UNSIGNED64 (0x3F000000); 1725 1.10 christos static const uint64_t half_double = UNSIGNED64 (0x3FE0000000000000); 1726 1.10 christos static const uint64_t half_ps = (UNSIGNED64 (0x3F000000) << 32 | UNSIGNED64 (0x3F000000)); 1727 1.10 christos uint64_t half; 1728 1.1 christos 1729 1.1 christos /* Implemented as (nmsub fd, 0.5, fs, ft)/2, where the divide is 1730 1.1 christos done by scaling the exponent during multiply. */ 1731 1.1 christos switch (fmt) 1732 1.1 christos { 1733 1.1 christos case fmt_single: half = half_single; break; 1734 1.1 christos case fmt_double: half = half_double; break; 1735 1.1 christos case fmt_ps: half = half_ps; break; 1736 1.1 christos default: half = 0; abort (); 1737 1.1 christos } 1738 1.1 christos return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, half, -1, 1, fmt); 1739 1.1 christos } 1740 1.1 christos 1741 1.1 christos 1742 1.1 christos /* Conversion operations. */ 1743 1.1 christos 1744 1.1 christos uword64 1745 1.1 christos convert (sim_cpu *cpu, 1746 1.1 christos address_word cia, 1747 1.1 christos int rm, 1748 1.1 christos uword64 op, 1749 1.1 christos FP_formats from, 1750 1.1 christos FP_formats to) 1751 1.1 christos { 1752 1.1 christos sim_fpu wop; 1753 1.1 christos sim_fpu_round round = rounding_mode (rm); 1754 1.1 christos sim_fpu_denorm denorm = denorm_mode (cpu); 1755 1.10 christos uint32_t result32; 1756 1.10 christos uint64_t result64; 1757 1.1 christos sim_fpu_status status = 0; 1758 1.1 christos 1759 1.1 christos /* Convert the input to sim_fpu internal format */ 1760 1.1 christos switch (from) 1761 1.1 christos { 1762 1.1 christos case fmt_double: 1763 1.1 christos sim_fpu_64to (&wop, op); 1764 1.1 christos break; 1765 1.1 christos case fmt_single: 1766 1.1 christos sim_fpu_32to (&wop, op); 1767 1.1 christos break; 1768 1.1 christos case fmt_word: 1769 1.1 christos status = sim_fpu_i32to (&wop, op, round); 1770 1.1 christos break; 1771 1.1 christos case fmt_long: 1772 1.1 christos status = sim_fpu_i64to (&wop, op, round); 1773 1.1 christos break; 1774 1.1 christos default: 1775 1.10 christos sim_io_error (SD, "Bad switch\n"); 1776 1.1 christos } 1777 1.1 christos 1778 1.1 christos /* Convert sim_fpu format into the output */ 1779 1.1 christos /* The value WOP is converted to the destination format, rounding 1780 1.1 christos using mode RM. When the destination is a fixed-point format, then 1781 1.1 christos a source value of Infinity, NaN or one which would round to an 1782 1.1 christos integer outside the fixed point range then an IEEE Invalid Operation 1783 1.1 christos condition is raised. Not used if destination format is PS. */ 1784 1.1 christos switch (to) 1785 1.1 christos { 1786 1.1 christos case fmt_single: 1787 1.1 christos status |= sim_fpu_round_32 (&wop, round, denorm); 1788 1.1 christos /* For a NaN, normalize mantissa bits (cvt.s.d can't preserve them) */ 1789 1.1 christos if (sim_fpu_is_qnan (&wop)) 1790 1.1 christos wop = sim_fpu_qnan; 1791 1.1 christos sim_fpu_to32 (&result32, &wop); 1792 1.1 christos result64 = result32; 1793 1.1 christos break; 1794 1.1 christos case fmt_double: 1795 1.1 christos status |= sim_fpu_round_64 (&wop, round, denorm); 1796 1.1 christos /* For a NaN, normalize mantissa bits (make cvt.d.s consistent) */ 1797 1.1 christos if (sim_fpu_is_qnan (&wop)) 1798 1.1 christos wop = sim_fpu_qnan; 1799 1.1 christos sim_fpu_to64 (&result64, &wop); 1800 1.1 christos break; 1801 1.1 christos case fmt_word: 1802 1.10 christos status |= sim_fpu_to32u (&result32, &wop, round); 1803 1.1 christos result64 = result32; 1804 1.1 christos break; 1805 1.1 christos case fmt_long: 1806 1.10 christos status |= sim_fpu_to64u (&result64, &wop, round); 1807 1.1 christos break; 1808 1.1 christos default: 1809 1.1 christos result64 = 0; 1810 1.10 christos sim_io_error (SD, "Bad switch\n"); 1811 1.1 christos } 1812 1.1 christos 1813 1.1 christos update_fcsr (cpu, cia, status); 1814 1.1 christos return result64; 1815 1.1 christos } 1816 1.1 christos 1817 1.10 christos uint64_t 1818 1.1 christos ps_lower(sim_cpu *cpu, 1819 1.1 christos address_word cia, 1820 1.10 christos uint64_t op) 1821 1.1 christos { 1822 1.1 christos return FP_PS_lower (op); 1823 1.1 christos } 1824 1.1 christos 1825 1.10 christos uint64_t 1826 1.1 christos ps_upper(sim_cpu *cpu, 1827 1.1 christos address_word cia, 1828 1.10 christos uint64_t op) 1829 1.1 christos { 1830 1.1 christos return FP_PS_upper(op); 1831 1.1 christos } 1832 1.1 christos 1833 1.10 christos uint64_t 1834 1.1 christos pack_ps(sim_cpu *cpu, 1835 1.1 christos address_word cia, 1836 1.10 christos uint64_t op1, 1837 1.10 christos uint64_t op2, 1838 1.1 christos FP_formats fmt) 1839 1.1 christos { 1840 1.10 christos uint64_t result = 0; 1841 1.1 christos 1842 1.1 christos /* The registers must specify FPRs valid for operands of type 1843 1.1 christos "fmt". If they are not valid, the result is undefined. */ 1844 1.1 christos 1845 1.1 christos /* The format type should already have been checked: */ 1846 1.1 christos switch (fmt) 1847 1.1 christos { 1848 1.1 christos case fmt_single: 1849 1.1 christos { 1850 1.1 christos sim_fpu wop; 1851 1.10 christos uint32_t res_u, res_l; 1852 1.1 christos sim_fpu_32to (&wop, op1); 1853 1.1 christos sim_fpu_to32 (&res_u, &wop); 1854 1.1 christos sim_fpu_32to (&wop, op2); 1855 1.1 christos sim_fpu_to32 (&res_l, &wop); 1856 1.1 christos result = FP_PS_cat(res_u, res_l); 1857 1.1 christos break; 1858 1.1 christos } 1859 1.1 christos default: 1860 1.10 christos sim_io_error (SD, "Bad switch\n"); 1861 1.1 christos } 1862 1.1 christos 1863 1.1 christos return result; 1864 1.1 christos } 1865 1.1 christos 1866 1.10 christos uint64_t 1867 1.1 christos convert_ps (sim_cpu *cpu, 1868 1.1 christos address_word cia, 1869 1.1 christos int rm, 1870 1.10 christos uint64_t op, 1871 1.1 christos FP_formats from, 1872 1.1 christos FP_formats to) 1873 1.1 christos { 1874 1.1 christos sim_fpu wop_u, wop_l; 1875 1.1 christos sim_fpu_round round = rounding_mode (rm); 1876 1.1 christos sim_fpu_denorm denorm = denorm_mode (cpu); 1877 1.10 christos uint32_t res_u, res_l; 1878 1.10 christos uint64_t result; 1879 1.1 christos sim_fpu_status status_u = 0, status_l = 0; 1880 1.1 christos 1881 1.1 christos /* As convert, but used only for paired values (formats PS, PW) */ 1882 1.1 christos 1883 1.1 christos /* Convert the input to sim_fpu internal format */ 1884 1.1 christos switch (from) 1885 1.1 christos { 1886 1.1 christos case fmt_word: /* fmt_pw */ 1887 1.1 christos sim_fpu_i32to (&wop_u, (op >> 32) & (unsigned)0xFFFFFFFF, round); 1888 1.1 christos sim_fpu_i32to (&wop_l, op & (unsigned)0xFFFFFFFF, round); 1889 1.1 christos break; 1890 1.1 christos case fmt_ps: 1891 1.1 christos sim_fpu_32to (&wop_u, FP_PS_upper(op)); 1892 1.1 christos sim_fpu_32to (&wop_l, FP_PS_lower(op)); 1893 1.1 christos break; 1894 1.1 christos default: 1895 1.10 christos sim_io_error (SD, "Bad switch\n"); 1896 1.1 christos } 1897 1.1 christos 1898 1.1 christos /* Convert sim_fpu format into the output */ 1899 1.1 christos switch (to) 1900 1.1 christos { 1901 1.1 christos case fmt_word: /* fmt_pw */ 1902 1.10 christos status_u |= sim_fpu_to32u (&res_u, &wop_u, round); 1903 1.10 christos status_l |= sim_fpu_to32u (&res_l, &wop_l, round); 1904 1.10 christos result = (((uint64_t)res_u) << 32) | (uint64_t)res_l; 1905 1.1 christos break; 1906 1.1 christos case fmt_ps: 1907 1.11 christos status_u |= sim_fpu_round_32 (&wop_u, round, denorm); 1908 1.11 christos status_l |= sim_fpu_round_32 (&wop_l, round, denorm); 1909 1.1 christos sim_fpu_to32 (&res_u, &wop_u); 1910 1.1 christos sim_fpu_to32 (&res_l, &wop_l); 1911 1.1 christos result = FP_PS_cat(res_u, res_l); 1912 1.1 christos break; 1913 1.1 christos default: 1914 1.1 christos result = 0; 1915 1.10 christos sim_io_error (SD, "Bad switch\n"); 1916 1.1 christos } 1917 1.1 christos 1918 1.1 christos update_fcsr (cpu, cia, status_u | status_l); 1919 1.1 christos return result; 1920 1.1 christos } 1921 1.1 christos 1922 1.1 christos static const char * 1923 1.1 christos fpu_format_name (FP_formats fmt) 1924 1.1 christos { 1925 1.1 christos switch (fmt) 1926 1.1 christos { 1927 1.1 christos case fmt_single: 1928 1.1 christos return "single"; 1929 1.1 christos case fmt_double: 1930 1.1 christos return "double"; 1931 1.1 christos case fmt_word: 1932 1.1 christos return "word"; 1933 1.1 christos case fmt_long: 1934 1.1 christos return "long"; 1935 1.1 christos case fmt_ps: 1936 1.1 christos return "ps"; 1937 1.1 christos case fmt_unknown: 1938 1.1 christos return "<unknown>"; 1939 1.1 christos case fmt_uninterpreted: 1940 1.1 christos return "<uninterpreted>"; 1941 1.1 christos case fmt_uninterpreted_32: 1942 1.1 christos return "<uninterpreted_32>"; 1943 1.1 christos case fmt_uninterpreted_64: 1944 1.1 christos return "<uninterpreted_64>"; 1945 1.1 christos default: 1946 1.1 christos return "<format error>"; 1947 1.1 christos } 1948 1.1 christos } 1949 1.1 christos 1950 1.1 christos #ifdef DEBUG 1951 1.1 christos static const char * 1952 1.1 christos fpu_rounding_mode_name (int rm) 1953 1.1 christos { 1954 1.1 christos switch (rm) 1955 1.1 christos { 1956 1.1 christos case FP_RM_NEAREST: 1957 1.1 christos return "Round"; 1958 1.1 christos case FP_RM_TOZERO: 1959 1.1 christos return "Trunc"; 1960 1.1 christos case FP_RM_TOPINF: 1961 1.1 christos return "Ceil"; 1962 1.1 christos case FP_RM_TOMINF: 1963 1.1 christos return "Floor"; 1964 1.1 christos default: 1965 1.1 christos return "<rounding mode error>"; 1966 1.1 christos } 1967 1.1 christos } 1968 1.1 christos #endif /* DEBUG */ 1969