Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / cpu / src / N2_Fpu.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: N2_Fpu.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21
22#include "N2_Fpu.h"
23#include "N2_Strand.h"
24
25N2_Fpu::FloatTrapType N2_Fpu::fpu_postprocess( Instr instr, SS_Strand* s, NumberType src_fpop, NumberType src2_fpop, int Er, NumberType rd_fpop, Precision dest_type, uint64_t *rd_dp_value, uint32_t *rd_sp_value ) /*{{{*/
26{
27 int tem; // Trap Enable Mask
28 int fef; // Floating Exception Flags
29 int eft; // Enabled floating traps
30 int cexc = EXC_NONE;
31
32 uint64_t fsr_ns; // floating point status register non-standard
33 uint64_t gsr_im; // GSR register interval arithmetic mode
34
35 FloatTrapType ftt = FTT_NOTRAP;
36 bool rd_sign; // result sign
37 uint64_t rnd_mode = (uint64_t)float_rounding_mode; // rounding mode
38
39 bool guzr = false; // gross underflow zero result
40 bool ur = false; // underflow result
41 bool gor = false; // generated overflow result
42 bool fpop_subnormal = false; // is fp operation need to be subnormally handled
43
44 bool src1_subnorm = false; // source one subnormal
45 bool src2_subnorm = false; // source two subnormal
46 bool rd_subnorm = false; // result subnormal
47 bool rd_positive = false; // sign of the result
48 bool src1_zero = false; // source one zero
49 bool src2_zero = false; // source two zero
50 bool rd_zero = false;
51 bool src1_nan = false;
52 bool src2_nan = false;
53
54 bool rd_small_norm = false;
55
56 int eguf; // exponent gross underflow limit
57 int emax; // maximum exponent value
58
59 fef = float_exception_flags;
60 tem = s->fsr.tem();
61 fsr_ns = s->fsr.ns();
62 gsr_im = s->gsr.im();
63
64 if ( (src_fpop == FP_OP_PSUBNORMAL) || (src_fpop == FP_OP_NSUBNORMAL) )
65 src1_subnorm = true;
66
67 if ( (src2_fpop == FP_OP_PSUBNORMAL) || (src2_fpop == FP_OP_NSUBNORMAL) )
68 src2_subnorm = true;
69
70 if ( (rd_fpop == FP_OP_PZERO) || (rd_fpop == FP_OP_NZERO) )
71 rd_zero = true;
72
73 if ( (rd_fpop == FP_OP_PSUBNORMAL) || (rd_fpop == FP_OP_NSUBNORMAL) ||
74 ( ((fef & EXC_UNDERFLOW) == EXC_UNDERFLOW) &&
75 ((fef & EXC_INEXACT) == EXC_INEXACT) &&
76 (rd_zero) ) )
77 rd_subnorm = true;
78
79 if ( (rd_fpop == FP_OP_PSUBNORMAL) || (rd_fpop == FP_OP_PZERO) )
80 rd_positive = true;
81
82 if ( (src_fpop == FP_OP_PZERO) || (src_fpop == FP_OP_NZERO) )
83 src1_zero = true;
84
85 if ( (src2_fpop == FP_OP_PZERO) || (src2_fpop == FP_OP_NZERO) )
86 src2_zero = true;
87
88 if ( (src_fpop == FP_OP_QNAN) || (src_fpop == FP_OP_SNAN) )
89 src1_nan = true;
90
91 if ( (src2_fpop == FP_OP_QNAN) || (src2_fpop == FP_OP_SNAN) )
92 src2_nan = true;
93
94 if ( (src1_subnorm) || (src2_subnorm) || (rd_subnorm) )
95 fpop_subnormal = true;
96
97 switch (dest_type) {
98
99 case SP_TYPE: emax = SP_EMAX; eguf = SP_EGUF; break;
100 case DP_TYPE: emax = DP_EMAX; eguf = DP_EGUF; break;
101 default:
102 break;
103 }
104
105 if ( fpop_subnormal ) {
106
107 // In Standard Mode deal with the subnormals
108
109 if ((fsr_ns == 0) || (gsr_im == 1)) {
110
111 if ( src1_subnorm || src2_subnorm) {
112
113 switch (instr) {
114 case FADDS:
115 case FADDD:
116 case FSUBS:
117 case FSUBD:
118 if ( (!src1_nan) && (src_fpop != FP_OP_INF) &&
119 (!src2_nan) && (src2_fpop != FP_OP_INF))
120 ftt = FTT_UNFINISHED_FPOP;
121 break;
122
123 case FMULS:
124 case FMULD:
125 if ( (!src1_nan) && (src_fpop != FP_OP_INF) && (src1_zero != true) &&
126 (!src2_nan) && (src2_fpop != FP_OP_INF) && (src2_zero != true) ) {
127
128 // Emax(P) > Er > EGUF(P)
129 // Er <= EGUF(P) & Signr=0 & RND=RP
130 // Er <= EGUF(P) & Signr=1 & RND=RM
131 if (((emax > Er) && (Er > eguf)) ||
132 ( (Er <= eguf) && (rd_positive == true) && (rnd_mode == ROUND_UP) ) ||
133 ( (Er <= eguf) && (rd_positive == false) && (rnd_mode == ROUND_DOWN) ) ) {
134 ftt = FTT_UNFINISHED_FPOP;
135 } else {
136 guzr = true;
137 }
138 }
139 break;
140
141 case FDIVS:
142 case FDIVD:
143 if ( (!src1_nan) && (src_fpop != FP_OP_INF) && (!src1_zero) &&
144 (!src2_nan) && (src2_fpop != FP_OP_INF) && (!src2_zero) ) {
145
146 // Er <= EGUF(P) & Signr=0 & RND=RP
147 // Er <= EGUF(P) & Signr=1 & RND=RM
148 if ( Er < emax ) {
149 if ( ((emax > Er) && (Er > eguf)) ||
150 ( (Er <= eguf) && (rd_positive == true) && (rnd_mode == ROUND_UP) ) ||
151 ( (Er <= eguf) && (rd_positive == false) && (rnd_mode == ROUND_DOWN) ) ) {
152 ftt = FTT_UNFINISHED_FPOP;
153
154 } else {
155 guzr = true;
156 }
157 } else {
158 gor = true;
159 }
160 }
161 break;
162
163 case FSMULD:
164 // if (!(OP_NaN or OP_inf or OP_0))
165 if ( (!src1_nan) && (src_fpop != FP_OP_INF) && (src1_zero != true) &&
166 (!src2_nan) && (src2_fpop != FP_OP_INF) && (src2_zero != true) ) {
167 ftt= FTT_UNFINISHED_FPOP;
168 }
169 break;
170
171 case FSQRTS:
172 case FSQRTD:
173 // if (! (OP_NaN or OP_inf))
174 if ( (!src2_nan) && (src2_fpop != FP_OP_INF) )
175 {
176 if (src2_fpop == FP_OP_NSUBNORMAL)
177 {
178 fef = EXC_INVALID; // set FSR.NV
179
180 if ( (fef & tem & EXC_INVALID) == EXC_INVALID ) {
181 ftt = FTT_IEEE_754_EXCEPTION; // generate invalid exception
182 }
183 (*rd_dp_value) = QNAN_64;
184 (*rd_sp_value) = QNAN_32;
185
186 } else {
187 ftt = FTT_UNFINISHED_FPOP;
188 }
189 }
190 break;
191
192 case FSTOX:
193 case FDTOX:
194 case FSTOI:
195 case FDTOI:
196 case FSTOD:
197 // if (! (OP_NaN or OP_inf))
198 if ( (!src2_nan) && (src2_fpop != FP_OP_INF) ) {
199 ftt= FTT_UNFINISHED_FPOP;
200 }
201 break;
202
203 case FDTOS:
204 if ( (!src2_nan) && (src2_fpop != FP_OP_INF) ) {
205 if ( ( (rd_positive == true) && (rnd_mode == ROUND_UP) ) ||
206 ( (rd_positive == false) && (rnd_mode == ROUND_DOWN) ) ) {
207
208 ftt = FTT_UNFINISHED_FPOP;
209
210 } else {
211 guzr = true;
212 }
213 }
214 break;
215 default:
216 break;
217 }
218 } else if ( ( (src_fpop == FP_OP_NORMAL) && (src2_fpop == FP_OP_NORMAL) ) ||
219 ( (src_fpop == FP_OP_NONE) && (src2_fpop == FP_OP_NORMAL) ) ) {
220
221 switch (instr) {
222 case FADDS:
223 case FADDD:
224 case FSUBS:
225 case FSUBD:
226 ftt = FTT_UNFINISHED_FPOP;
227 break;
228
229 case FMULS:
230 case FMULD:
231 case FDIVS:
232 case FDIVD:
233 {
234 int Erb = 0;
235
236 // Check whether there is a difference between softfloat's underflow and
237 // if a number is subnormal, pzero or nzero
238
239 bool sf_uf = ( (fef & EXC_UNDERFLOW) == EXC_UNDERFLOW);
240 bool fgu_uf = rd_subnorm || (rd_fpop == FP_OP_PZERO) || (rd_fpop == FP_OP_PZERO);
241
242 if (sf_uf == true) {
243 Erb = Er + 1;
244 } else {
245 Erb = Er;
246 }
247
248 if ( Er < emax ) {
249 if ( ( rd_subnorm && (Er > eguf) ) || // (sf_uf && (Er > eguf)) //(1 > Erb) && (Er > EGUF(P))
250 ( (Er <= eguf) &&
251 (rd_positive == true) &&
252 (rnd_mode == ROUND_UP) ) || // Er <= EGUF(P) & Signr=0 & RND=RP
253 ( (Er <= eguf) &&
254 (rd_positive == false) &&
255 (rnd_mode == ROUND_DOWN) ) ) { // Er <= EGUF(P) & Signr=1 & RND=RM
256
257 // generate unfinished trap
258
259 ftt = FTT_UNFINISHED_FPOP;
260
261 } else {
262 // generate gross underflow zero result
263 guzr = true;
264 }
265 } else {
266 // generate gross overflow result
267 gor = true;
268 }
269 break;
270 }
271 case FDTOS:
272 {
273 if ( ( (1 > Er) && (Er > eguf)) || // 1 > Er > EGUF(P)
274 ( (Er <= eguf) &&
275 (rd_positive == true) &&
276 (rnd_mode == ROUND_UP) ) || // Er <= EGUF(P) & Signr=0 & RND=RP
277 ( (Er <= eguf) &&
278 (rd_positive == false) &&
279 (rnd_mode == ROUND_DOWN) ) ) { // Er <= EGUF(P) & Signr=1 & RND=RM
280
281 ftt = FTT_UNFINISHED_FPOP;
282 } else {
283 // generate gross underflow zero result
284 guzr = true;
285 }
286 break;
287 }
288 default:
289 break;
290 }
291 }
292
293 } else if ((fsr_ns == 1) && (gsr_im == 0)) {
294
295 // In Non-standard Mode we flush the subnormals to zero
296
297 // Based on Table 2-29 in Chapter 2.1.10 of the Millennium PRM
298
299 if ( src1_subnorm || src2_subnorm) {
300
301 switch (instr) {
302 case FADDS:
303 case FADDD:
304 case FSUBS:
305 case FSUBD:
306 case FSTOX:
307 case FDTOX:
308 case FSTOI:
309 case FDTOI:
310 case FSTOD:
311 case FDTOS:
312 if ( (!src1_nan) && (src_fpop != FP_OP_INF) && (!src2_nan) && (src2_fpop != FP_OP_INF) ) {
313 // set FSR.NX
314 fef = EXC_INEXACT;
315 }
316 break;
317
318 case FCMPS:
319 case FCMPD:
320 case FCMPES:
321 case FCMPED:
322 break;
323
324 case FMULS:
325 case FMULD:
326 case FSMULD:
327 {
328 // (!(OP_NaN or OP_0))
329
330 if ( (!src1_nan) && (src1_zero != true) && (!src2_nan) && (src2_zero != true) ) {
331
332 if ( (src2_fpop != FP_OP_INF) && (src_fpop != FP_OP_INF) ) {
333
334 fef = EXC_INEXACT; // set FSR.NX
335
336 } else {
337
338 fef = EXC_INVALID; // set FSR.NV
339
340 // return QNaN
341
342 (*rd_dp_value) = QNAN_64;
343 (*rd_sp_value) = QNAN_32;
344 }
345 }
346 break;
347 }
348
349 case FDIVS:
350 case FDIVD:
351 {
352 // !(OP_NaN)
353
354 if ( (!src2_nan) && (!src1_nan) ) {
355
356 if ( (src_fpop != FP_OP_INF) &&
357 (src2_fpop != FP_OP_INF) &&
358 (src1_zero != true) &&
359 (src2_zero != true) ) {
360
361 if ( src1_subnorm && src2_subnorm ) {
362 fef = EXC_INVALID;
363 } else if ( src2_subnorm == true) {
364 fef = EXC_DIVBYZERO;
365 } else {
366 fef = EXC_INEXACT;
367 }
368
369 } else if ( (src_fpop == FP_OP_INF) || (src2_fpop == FP_OP_INF) ) {
370
371 // clear anything?
372
373 } else if ( (src1_zero == true) || (src2_zero == true) ) {
374
375 fef = EXC_INVALID;
376
377 // Clear out FSR.DZ? I don't think it has been set
378 //---->This case overides DZ, so I might need to do something different
379
380 } else {
381 // Could cause FSR.DZ to be set to zero, would be caught above
382 }
383 }
384 break;
385 }
386
387 case FSQRTS:
388 case FSQRTD:
389 {
390 if ( (!src2_nan) && (src2_fpop != FP_OP_INF) ) {
391
392 if (src2_fpop == FP_OP_NSUBNORMAL) {
393 fef = EXC_INEXACT;
394 (*rd_dp_value) = to_nil(*rd_dp_value);
395 (*rd_sp_value) = to_nil(*rd_sp_value);
396 } else if (src2_zero) {
397 fef = EXC_NONE;
398 (*rd_dp_value) = to_nil(*rd_dp_value);
399 (*rd_sp_value) = to_nil(*rd_sp_value);
400 } else {
401 fef = EXC_INEXACT;
402 }
403 }
404 break;
405 }
406 default:
407 break;
408 }
409 } else if ( ( (src_fpop == FP_OP_NORMAL) && (src2_fpop == FP_OP_NORMAL) ) ||
410 ( (src_fpop == FP_OP_NONE) && (src2_fpop == FP_OP_NORMAL) ) ) {
411
412 switch (instr) {
413 case FADDS:
414 case FADDD:
415 case FSUBS:
416 case FSUBD:
417 case FDTOS:
418 guzr = true;
419 break;
420
421 case FMULS:
422 case FMULD:
423 case FDIVS:
424 case FDIVD:
425 {
426 if (Er < emax) { // !(Er >= EMAX(P))
427 guzr = true;
428 } else {
429 gor = true; // generate overflow result
430 }
431 break;
432 }
433 default:
434 break;
435 }
436 }
437 }
438 }
439
440 eft = fef & tem;
441
442 // If there was no subnormal or the subnormals didn't trap, check for other trap conditions
443
444 if (ftt == FTT_NOTRAP)
445 {
446 if ( (fef & EXC_OVERFLOW) == EXC_OVERFLOW )
447 gor = true;
448 else if ( (eft & EXC_DIVBYZERO) == EXC_DIVBYZERO )
449 ftt = FTT_IEEE_754_EXCEPTION;
450 else if ( (eft & EXC_INVALID) == EXC_INVALID )
451 ftt = FTT_IEEE_754_EXCEPTION;
452 else if ( ((fef & EXC_UNDERFLOW) == EXC_UNDERFLOW) && !fpop_subnormal)
453 ur= true;
454 }
455
456 if (((eft & EXC_INEXACT) == EXC_INEXACT) && (guzr != true) && (gor != true) && (ftt == FTT_NOTRAP))
457 {
458 ftt = FTT_IEEE_754_EXCEPTION; // generate underflow trap
459 }
460
461 if ( (guzr == true) || (ur == true) )
462 {
463 ftt = FTT_NOTRAP;
464
465 if (guzr == true)
466 {
467 (*rd_dp_value) = to_nil(*rd_dp_value);
468 (*rd_sp_value) = to_nil(*rd_sp_value);
469 }
470
471 if ( ((tem & EXC_UNDERFLOW) != EXC_UNDERFLOW) && ((tem & EXC_INEXACT) != EXC_INEXACT) )
472 {
473 // if (FSR.UFM=0 && FSR.NXM=0)
474 fef = EXC_UNDERFLOW | EXC_INEXACT;
475 cexc = fef;
476 }
477 else if (((tem & EXC_UNDERFLOW) == EXC_UNDERFLOW) || ((tem & EXC_INEXACT) == EXC_INEXACT) )
478 {
479 // if (FSR.UFM=1 OR FSR.NXM=1)
480 ftt = FTT_IEEE_754_EXCEPTION;
481 fef = EXC_NONE;
482
483 if ( ((tem & EXC_UNDERFLOW) != EXC_UNDERFLOW) && ((tem & EXC_INEXACT) == EXC_INEXACT) )
484 {
485 fef = EXC_INEXACT;
486 }
487 if ((tem & EXC_UNDERFLOW) == EXC_UNDERFLOW)
488 {
489 fef = EXC_UNDERFLOW;
490 }
491 cexc = fef;
492 }
493 }
494 else if ( (gor == true) || ( ((fef & EXC_OVERFLOW) == EXC_OVERFLOW) && (ftt == FTT_NOTRAP) ) )
495 {
496 // (FSR.OFM = 0 && FSR.NXM = 0)
497 if ( ((tem & EXC_OVERFLOW) != EXC_OVERFLOW) && ((tem & EXC_INEXACT) != EXC_INEXACT) )
498 {
499 ftt = FTT_NOTRAP;
500 fef = EXC_OVERFLOW | EXC_INEXACT;
501 }
502 else if ( ((tem & EXC_OVERFLOW) == EXC_OVERFLOW) || ((tem & EXC_INEXACT) == EXC_INEXACT) )
503 { // (FSR.OFM = 1 || FSR.NXM = 1)
504 ftt = FTT_IEEE_754_EXCEPTION;
505 if ( ((tem & EXC_OVERFLOW) != EXC_OVERFLOW) && ((tem & EXC_INEXACT) == EXC_INEXACT) )
506 {
507 fef = EXC_INEXACT;
508 }
509 if ( (tem & EXC_OVERFLOW) == EXC_OVERFLOW )
510 {
511 fef = EXC_OVERFLOW;
512 }
513 }
514 cexc = fef;
515 } else {
516 cexc = fef;
517 }
518
519 assert(cexc == fef);
520 float_exception_flags = cexc;
521
522 return ftt;
523}
524/*}}}*/
525
526SS_Vaddr N2_Fpu::exe_fff( Instr instr, SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
527{
528 uint64_t dp_value[2], dp_result;
529 uint32_t sp_value[2], sp_result;
530 uint64_t orig_dp_value[2];
531 uint32_t orig_sp_value[2];
532 int Er = 0; // Exponent result
533
534 Precision src1_type = UNKNOWN_TYPE;
535 Precision src2_type = UNKNOWN_TYPE;
536 Precision dest_type = UNKNOWN_TYPE;
537 NumberType src1_fptype;
538 NumberType src2_fptype;
539 NumberType dest_fptype;
540
541 if (s->sim_state.fp_disabled())
542 return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);
543
544 s->get_fsr();
545
546 switch (instr)
547 {
548 case FADDS:
549 case FSUBS:
550 case FMULS:
551 case FDIVS:
552 dest_type = src1_type = src2_type = SP_TYPE;
553 sp_value[0] = orig_sp_value[0] = s->get_frf(i->rs1);
554 sp_value[1] = orig_sp_value[1] = s->get_frf(i->rs2);
555 src1_fptype = fpu_optype(sp_value[0]);
556 src2_fptype = fpu_optype(sp_value[1]);
557 break;
558
559 case FSMULD:
560 src1_type = src2_type = SP_TYPE;
561 dest_type = DP_TYPE;
562 sp_value[0] = orig_sp_value[0] = s->get_frf(i->rs1);
563 sp_value[1] = orig_sp_value[1] = s->get_frf(i->rs2);
564 src1_fptype = fpu_optype(sp_value[0]);
565 src2_fptype = fpu_optype(sp_value[1]);
566 break;
567
568 case FADDD:
569 case FSUBD:
570 case FMULD:
571 case FDIVD:
572 dest_type = src1_type = src2_type = DP_TYPE;
573 dp_value[0] = orig_dp_value[0] = s->get_drf(i->rs1);
574 dp_value[1] = orig_dp_value[1] = s->get_drf(i->rs2);
575 src1_fptype = fpu_optype(dp_value[0]);
576 src2_fptype = fpu_optype(dp_value[1]);
577 break;
578
579 default:
580 assert(0);
581 }
582
583 if ((s->fsr.ns() == 1) && (s->gsr.im() == 0))
584 {
585 switch ( instr )
586 {
587 case FADDS:
588 case FSUBS:
589 if (is_sub(sp_value[0]) && !is_nan_or_inf(sp_value[1]))
590 sp_value[0] = to_nil(sp_value[0]);
591 if (is_sub(sp_value[1]) && !is_nan_or_inf(sp_value[0]))
592 sp_value[1] = to_nil(sp_value[1]);
593 break;
594
595 case FADDD:
596 case FSUBD:
597 if (is_sub(dp_value[0]) && !is_nan_or_inf(dp_value[1]))
598 dp_value[0] = to_nil(dp_value[0]);
599 if (is_sub(dp_value[1]) && !is_nan_or_inf(dp_value[0]))
600 dp_value[1] = to_nil(dp_value[1]);
601 break;
602
603 case FDIVS:
604 if (is_sub(sp_value[0]) && !is_nan(sp_value[1]))
605 sp_value[0] = to_nil(sp_value[0]);
606 if (is_sub(sp_value[1]) && !is_nan(sp_value[0]))
607 sp_value[1] = to_nil(sp_value[1]);
608 break;
609
610 case FDIVD:
611 if (is_sub(dp_value[0]) && !is_nan(dp_value[1]))
612 dp_value[0] = to_nil(dp_value[0]);
613 if (is_sub(dp_value[1]) && !is_nan(dp_value[0]))
614 dp_value[1] = to_nil(dp_value[1]);
615 break;
616
617 case FMULS:
618 case FSMULD:
619 if (is_sub(sp_value[0]) && !is_nan_or_inf(sp_value[1]) && !is_nil(sp_value[1]))
620 sp_value[0] = to_nil(sp_value[0]);
621 if (is_sub(sp_value[1]) && !is_nan_or_inf(sp_value[0]) && !is_nil(sp_value[0]))
622 sp_value[1] = to_nil(sp_value[1]);
623 break;
624
625 case FMULD:
626 if (is_sub(dp_value[0]) && !is_nan_or_inf(dp_value[1]) && !is_nil(dp_value[1]))
627 dp_value[0] = to_nil(dp_value[0]);
628 if (is_sub(dp_value[1]) && !is_nan_or_inf(dp_value[0]) && !is_nil(dp_value[0]))
629 dp_value[1] = to_nil(dp_value[1]);
630 break;
631 }
632 }
633
634 float_exception_flags = EXC_NONE;
635 float_rounding_mode = Rounding(s->gsr.im() ? s->gsr.irnd() : s->fsr.rd());
636
637 switch (instr)
638 {
639 case FADDS:
640 sp_result = float32_add( sp_value[0], sp_value[1], false );
641 dest_fptype = fpu_optype(sp_result);
642 break;
643
644 case FADDD:
645 dp_result = float64_add( dp_value[0], dp_value[1], false );
646 dest_fptype = fpu_optype(dp_result);
647 break;
648
649 case FSUBS:
650 sp_result = float32_sub( sp_value[0], sp_value[1], false );
651 dest_fptype = fpu_optype(sp_result);
652 break;
653
654 case FSUBD:
655 dp_result = float64_sub( dp_value[0], dp_value[1], false );
656 dest_fptype = fpu_optype(dp_result);
657 break;
658
659 case FMULS:
660 sp_result = float32_mul( sp_value[0], sp_value[1], false );
661 Er = to_exp(sp_value[0]) + to_exp(sp_value[1]) - SP_BIAS;
662 dest_fptype = fpu_optype(sp_result);
663 break;
664
665 case FMULD:
666 dp_result = float64_mul( dp_value[0], dp_value[1], false );
667 Er = to_exp(dp_value[0]) + to_exp(dp_value[1]) - DP_BIAS;
668 dest_fptype = fpu_optype(dp_result);
669 break;
670
671 case FDIVS:
672 sp_result = float32_div( sp_value[0], sp_value[1] );
673 Er = to_exp(sp_value[0]) - to_exp(sp_value[1]) + SP_BIAS - 1;
674 dest_fptype = fpu_optype(sp_result);
675 break;
676
677 case FDIVD:
678 dp_result = float64_div( dp_value[0], dp_value[1] );
679 Er = to_exp(dp_value[0]) - to_exp(dp_value[1]) + DP_BIAS - 1;
680 dest_fptype = fpu_optype(dp_result);
681 break;
682
683 case FSMULD:
684 dp_result = float64_mul( float32_to_float64( sp_value[0] ), float32_to_float64( sp_value[1] ), false );
685 dest_fptype = fpu_optype(dp_result);
686 break;
687
688 default:
689 assert(0);
690 }
691
692 FloatTrapType ftt = fpu_postprocess(instr,s,src1_fptype,src2_fptype,Er,dest_fptype,dest_type,&dp_result,&sp_result);
693
694 if (ftt == FTT_NOTRAP)
695 {
696 switch(instr)
697 {
698 case FADDS: case FSUBS: case FMULS: case FDIVS:
699 sp_result = nan_postprocess(orig_sp_value[0],orig_sp_value[1],sp_result);
700 s->get_frf(i->rd) = sp_result;
701 break;
702
703 case FADDD: case FSUBD: case FMULD: case FDIVD:
704 dp_result = nan_postprocess(orig_dp_value[0],orig_dp_value[1],dp_result);
705 s->get_drf(i->rd) = dp_result;
706 break;
707
708 case FSMULD:
709 dp_result = nan_postprocess(orig_sp_value[0],orig_sp_value[1],dp_result);
710 s->get_drf(i->rd) = dp_result;
711 break;
712
713 default:
714 assert(0);
715 break;
716 }
717 s->set_fprs(i->rd);
718 }
719
720 return exe_end(pc,npc,s,i,ftt,float_exception_flags);
721}
722/*}}}*/
723SS_Vaddr N2_Fpu::exe_fof( Instr instr, SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
724{
725 uint64_t dp_value;
726 uint32_t sp_value;
727 Precision src2_type = UNKNOWN_TYPE;
728 Precision dest_type = UNKNOWN_TYPE;
729 NumberType src2_fptype;
730 NumberType dest_fptype;
731 int Er = 0; // Exponent result
732
733 if (s->sim_state.fp_disabled())
734 return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);
735
736 s->get_fsr();
737
738 switch (instr)
739 {
740 case FMOVS:
741 case FNEGS:
742 case FABSS:
743 case FSQRTS:
744 case FSTOI:
745 case FITOS:
746 src2_type = SP_TYPE;
747 dest_type = SP_TYPE;
748 sp_value = s->get_frf(i->rs2);
749 src2_fptype = fpu_optype(sp_value);
750 break;
751
752 case FMOVD:
753 case FNEGD:
754 case FABSD:
755 case FSQRTD:
756 case FDTOX:
757 case FXTOD:
758 src2_type = DP_TYPE;
759 dest_type = DP_TYPE;
760 dp_value = s->get_drf(i->rs2);
761 src2_fptype = fpu_optype(dp_value);
762 break;
763
764 case FSTOX:
765 case FSTOD:
766 case FITOD:
767 src2_type = SP_TYPE;
768 dest_type = DP_TYPE;
769 sp_value = s->get_frf(i->rs2);
770 src2_fptype = fpu_optype(sp_value);
771 break;
772
773 case FDTOI:
774 case FDTOS:
775 case FXTOS:
776 src2_type = DP_TYPE;
777 dest_type = SP_TYPE;
778 dp_value = s->get_drf(i->rs2);
779 src2_fptype = fpu_optype(dp_value);
780 break;
781
782 default:
783 assert(0);
784 }
785
786 if ((s->fsr.ns() == 1) && (s->gsr.im() == 0)) // Non-standard Mode
787 {
788 switch ( instr )
789 {
790 case FSTOX:
791 case FSTOI:
792 case FSTOD:
793 case FSQRTS:
794 if (is_sub(sp_value))
795 sp_value = to_nil(sp_value);
796 break;
797
798 case FDTOX:
799 case FDTOI:
800 case FDTOS:
801 case FSQRTD:
802 if (is_sub(dp_value))
803 dp_value = to_nil(dp_value);
804 break;
805 }
806 }
807
808 float_exception_flags = EXC_NONE;
809
810 if ((instr == FSTOX) || (instr == FSTOI) || (instr == FDTOX) || (instr == FDTOI))
811 float_rounding_mode = ROUND_TO_ZERO;
812 else
813 float_rounding_mode = Rounding(s->gsr.im() ? s->gsr.irnd() : s->fsr.rd());
814
815 switch (instr)
816 {
817 case FMOVS:
818 sp_value = sp_value;
819 dest_fptype = fpu_optype(sp_value);
820 break;
821 case FMOVD:
822 dp_value = dp_value;
823 dest_fptype = fpu_optype(dp_value);
824 break;
825 case FNEGS:
826 sp_value = to_neg(sp_value);
827 dest_fptype = fpu_optype(sp_value);
828 break;
829 case FNEGD:
830 dp_value = to_neg(dp_value);
831 dest_fptype = fpu_optype(dp_value);
832 break;
833 case FABSS:
834 sp_value = to_abs(sp_value);
835 dest_fptype = fpu_optype(sp_value);
836 break;
837 case FABSD:
838 dp_value = to_abs(dp_value);
839 dest_fptype = fpu_optype(dp_value);
840 break;
841 case FSTOI:
842 sp_value = float32_to_int32(sp_value);
843 dest_fptype = fpu_optype(sp_value);
844 break;
845 case FSTOX:
846 dp_value = float32_to_int64(sp_value);
847 dest_fptype = fpu_optype(dp_value);
848 break;
849 case FITOS:
850 sp_value = int32_to_float32(sp_value);
851 dest_fptype = fpu_optype(sp_value);
852 break;
853 case FITOD:
854 dp_value = int32_to_float64(sp_value);
855 dest_fptype = fpu_optype(dp_value);
856 break;
857 case FDTOI:
858 sp_value = float64_to_int32(dp_value);
859 dest_fptype = fpu_optype(sp_value);
860 break;
861 case FDTOX:
862 dp_value = float64_to_int64(dp_value);
863 dest_fptype = fpu_optype(dp_value);
864 break;
865 case FXTOS:
866 sp_value = int64_to_float32(dp_value);
867 dest_fptype = fpu_optype(sp_value);
868 break;
869 case FXTOD:
870 dp_value = int64_to_float64(dp_value);
871 dest_fptype = fpu_optype(dp_value);
872 break;
873 case FSTOD:
874 dp_value = float32_to_float64(sp_value);
875 dest_fptype = fpu_optype(dp_value);
876 break;
877 case FSQRTS:
878 Er = to_sgn(sp_value);
879 sp_value = float32_sqrt(sp_value);
880 dest_fptype = fpu_optype(sp_value);
881 break;
882 case FSQRTD:
883 Er = to_sgn(dp_value);
884 dp_value = float64_sqrt(dp_value);
885 dest_fptype = fpu_optype(dp_value);
886 break;
887 case FDTOS:
888 Er = to_exp(dp_value) - DP_BIAS + SP_BIAS;
889 sp_value = float64_to_float32(dp_value);
890 dest_fptype = fpu_optype(sp_value);
891 break;
892 default:
893 assert(0);
894 }
895
896 FloatTrapType ftt = fpu_postprocess(instr,s,FP_OP_NONE,src2_fptype,Er,dest_fptype,dest_type,&dp_value,&sp_value);
897
898 if (ftt == FTT_NOTRAP)
899 {
900 switch (dest_type)
901 {
902 case SP_TYPE: s->get_frf(i->rd) = sp_value; break;
903 case DP_TYPE: s->get_drf(i->rd) = dp_value; break;
904 }
905 s->set_fprs(i->rd);
906 }
907
908 return exe_end(pc,npc,s,i,ftt,float_exception_flags);
909}
910/*}}}*/
911SS_Vaddr N2_Fpu::exe_off( Instr instr, SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
912{
913 int e, l, g;
914
915 if (s->sim_state.fp_disabled())
916 return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);
917
918 s->get_fsr();
919
920 float_exception_flags = EXC_NONE;
921 float_rounding_mode = Rounding(s->gsr.im() ? s->gsr.irnd() : s->fsr.rd());
922
923 switch (instr)
924 {
925 case FCMPS:
926 {
927 uint32_t a = s->get_frf(i->rs1);
928 uint32_t b = s->get_frf(i->rs2);
929 e = float32_eq(a,b);
930 l = float32_lt_quiet(a,b);
931 g = float32_lt_quiet(b,a) && !e;
932 break;
933 }
934 case FCMPES:
935 {
936 uint32_t a = s->get_frf(i->rs1);
937 uint32_t b = s->get_frf(i->rs2);
938 e = float32_eq_signaling(a,b);
939 l = float32_lt(a,b);
940 g = float32_lt(b,a) && !e;
941 break;
942 }
943 case FCMPD:
944 {
945 uint64_t a = s->get_drf(i->rs1);
946 uint64_t b = s->get_drf(i->rs2);
947 e = float64_eq(a,b);
948 l = float64_lt_quiet(a,b);
949 g = float64_lt_quiet(b,a) && !e;
950 break;
951 }
952 case FCMPED:
953 {
954 uint64_t a = s->get_drf(i->rs1);
955 uint64_t b = s->get_drf(i->rs2);
956 e = float64_eq_signaling(a,b);
957 l = float64_lt(a,b);
958 g = float64_lt(b,a) && !e;
959 break;
960 }
961 default:
962 assert(0);
963 }
964
965 FloatTrapType ftt = FTT_NOTRAP;
966 int eft = float_exception_flags & s->fsr.tem();
967
968 if (eft & EXC_INVALID)
969 ftt = FTT_IEEE_754_EXCEPTION;
970 else
971 set_fcc(s->fsr,ConditionField(i->rd),(e ? EQ : (l ? LT : (g ? GT : UN))));
972
973 return exe_end(pc,npc,s,i,ftt,float_exception_flags);
974}
975/*}}}*/
976
977SS_Vaddr n2_exe_fadds( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
978{
979 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FADDS,pc,npc,s,i);
980}
981/*}}}*/
982SS_Vaddr n2_exe_fsubs( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
983{
984 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FSUBS,pc,npc,s,i);
985}
986/*}}}*/
987SS_Vaddr n2_exe_fmuls( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
988{
989 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FMULS,pc,npc,s,i);
990}
991/*}}}*/
992SS_Vaddr n2_exe_fdivs( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
993{
994 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FDIVS,pc,npc,s,i);
995}
996/*}}}*/
997
998SS_Vaddr n2_exe_faddd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
999{
1000 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FADDD,pc,npc,s,i);
1001}
1002/*}}}*/
1003SS_Vaddr n2_exe_fsubd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1004{
1005 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FSUBD,pc,npc,s,i);
1006}
1007/*}}}*/
1008SS_Vaddr n2_exe_fmuld( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1009{
1010 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FMULD,pc,npc,s,i);
1011}
1012/*}}}*/
1013SS_Vaddr n2_exe_fdivd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1014{
1015 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FDIVD,pc,npc,s,i);
1016}
1017/*}}}*/
1018
1019SS_Vaddr n2_exe_fsmuld( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1020{
1021 return ((N2_Strand*)s)->fpu.exe_fff(N2_Fpu::FSMULD,pc,npc,s,i);
1022}
1023/*}}}*/
1024
1025SS_Vaddr n2_exe_fstoi( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1026{
1027 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FSTOI,pc,npc,s,i);
1028}
1029/*}}}*/
1030SS_Vaddr n2_exe_fstox( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1031{
1032 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FSTOX,pc,npc,s,i);
1033}
1034/*}}}*/
1035SS_Vaddr n2_exe_fstod( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1036{
1037 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FSTOD,pc,npc,s,i);
1038}
1039/*}}}*/
1040SS_Vaddr n2_exe_fitos( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1041{
1042 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FITOS,pc,npc,s,i);
1043}
1044/*}}}*/
1045SS_Vaddr n2_exe_fitod( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1046{
1047 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FITOD,pc,npc,s,i);
1048}
1049/*}}}*/
1050SS_Vaddr n2_exe_fdtoi( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1051{
1052 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FDTOI,pc,npc,s,i);
1053}
1054/*}}}*/
1055SS_Vaddr n2_exe_fdtox( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1056{
1057 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FDTOX,pc,npc,s,i);
1058}
1059/*}}}*/
1060SS_Vaddr n2_exe_fdtos( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1061{
1062 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FDTOS,pc,npc,s,i);
1063}
1064/*}}}*/
1065SS_Vaddr n2_exe_fxtos( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1066{
1067 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FXTOS,pc,npc,s,i);
1068}
1069/*}}}*/
1070SS_Vaddr n2_exe_fxtod( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1071{
1072 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FXTOD,pc,npc,s,i);
1073}
1074/*}}}*/
1075
1076SS_Vaddr n2_exe_fmovs( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1077{
1078 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FMOVS,pc,npc,s,i);
1079}
1080/*}}}*/
1081SS_Vaddr n2_exe_fnegs( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1082{
1083 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FNEGS,pc,npc,s,i);
1084}
1085/*}}}*/
1086SS_Vaddr n2_exe_fabss( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1087{
1088 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FABSS,pc,npc,s,i);
1089}
1090/*}}}*/
1091SS_Vaddr n2_exe_fmovd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1092{
1093 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FMOVD,pc,npc,s,i);
1094}
1095/*}}}*/
1096SS_Vaddr n2_exe_fnegd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1097{
1098 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FNEGD,pc,npc,s,i);
1099}
1100/*}}}*/
1101SS_Vaddr n2_exe_fabsd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1102{
1103 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FABSD,pc,npc,s,i);
1104}
1105/*}}}*/
1106
1107SS_Vaddr n2_exe_fsqrts( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1108{
1109 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FSQRTS,pc,npc,s,i);
1110}
1111/*}}}*/
1112SS_Vaddr n2_exe_fsqrtd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1113{
1114 return ((N2_Strand*)s)->fpu.exe_fof(N2_Fpu::FSQRTD,pc,npc,s,i);
1115}
1116/*}}}*/
1117
1118SS_Vaddr n2_exe_fcmps( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1119{
1120 return ((N2_Strand*)s)->fpu.exe_off(N2_Fpu::FCMPS,pc,npc,s,i);
1121}
1122/*}}}*/
1123SS_Vaddr n2_exe_fcmpd( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1124{
1125 return ((N2_Strand*)s)->fpu.exe_off(N2_Fpu::FCMPD,pc,npc,s,i);
1126}
1127/*}}}*/
1128
1129SS_Vaddr n2_exe_fcmpes( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1130{
1131 return ((N2_Strand*)s)->fpu.exe_off(N2_Fpu::FCMPES,pc,npc,s,i);
1132}
1133/*}}}*/
1134SS_Vaddr n2_exe_fcmped( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i )/*{{{*/
1135{
1136 return ((N2_Strand*)s)->fpu.exe_off(N2_Fpu::FCMPED,pc,npc,s,i);
1137}
1138/*}}}*/
1139
1140
1141
1142