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