1 /*
2 * Copyright (c) 2007-2013 Michael Mondy
3 * Copyright (c) 2012-2016 Harry Reed
4 * Copyright (c) 2013-2016 Charles Anthony
5 * Copyright (c) 2016 Michal Tomek
6 * Copyright (c) 2021 The DPS8M Development Team
7 *
8 * All rights reserved.
9 *
10 * This software is made available under the terms of the ICU
11 * License, version 1.8.1 or later. For more details, see the
12 * LICENSE.md file at the top-level directory of this distribution.
13 */
14
15 #include <stdio.h>
16 #include <math.h>
17
18 #include "dps8.h"
19 #include "dps8_sys.h"
20 #include "dps8_faults.h"
21 #include "dps8_scu.h"
22 #include "dps8_iom.h"
23 #include "dps8_cable.h"
24 #include "dps8_cpu.h"
25 #include "dps8_ins.h"
26 #include "dps8_math.h"
27 #include "dps8_utils.h"
28
29 #define DBG_CTR cpu.cycleCnt
30
31 #if defined(__CYGWIN__) || defined(__DragonFly__)
ldexpl(long double x,int n)32 long double ldexpl(long double x, int n) {
33 return __builtin_ldexpl(x, n);
34 }
35
exp2l(long double e)36 long double exp2l (long double e) {
37 return __builtin_exp2l(e);
38 }
39 #endif
40
41 /*!
42 * convert floating point quantity in C(EAQ) to a IEEE long double ...
43 */
EAQToIEEElongdouble(void)44 long double EAQToIEEElongdouble(void)
45 {
46 // mantissa
47 word72 Mant = convert_to_word72 (cpu.rA, cpu.rQ);
48 #ifdef NEED_128
49
50 if (iszero_128 (Mant))
51 return 0;
52
53 bool S = isnonzero_128 (and_128 (Mant, SIGN72)); // sign of mantissa
54 if (S)
55 Mant = and_128 (negate_128 (Mant), MASK71); // 71 bits (not 72!)
56 #else
57
58 if (Mant == 0)
59 return 0;
60
61 bool S = Mant & SIGN72; // sign of mantissa
62 if (S)
63 Mant = (-Mant) & MASK71; // 71 bits (not 72!)
64 #endif
65 long double m = 0; // mantissa value;
66 int e = SIGNEXT8_int (cpu . rE & MASK8); // make signed
67
68 #ifdef NEED_128
69 if (S && iszero_128 (Mant))// denormalized -1.0*2^e
70 return -exp2l(e);
71 #else
72 if (S && Mant == 0) // denormalized -1.0*2^e
73 return -exp2l(e);
74 #endif
75
76 long double v = 0.5;
77 for(int n = 70 ; n >= 0 ; n -= 1) // this also normalizes the mantissa
78 {
79 #ifdef NEED_128
80 if (isnonzero_128 (and_128 (Mant, lshift_128 (construct_128 (0, 1), (unsigned int) n))))
81 {
82 m += v;
83 }
84 #else
85 if (Mant & ((word72)1 << n))
86 {
87 m += v;
88 }
89 #endif
90 v /= 2.0;
91 }
92
93 /*if (m == 0 && e == -128) // special case - normalized 0
94 return 0;
95 if (m == 0)
96 return (S ? -1 : 1) * exp2l(e); */
97
98 return (S ? -1 : 1) * ldexpl(m, e);
99 }
100
101 #if defined(__MINGW32__) || defined(__MINGW64__)
102
103 // MINGW doesn't have long double support, convert to IEEE double instead
EAQToIEEEdouble(void)104 double EAQToIEEEdouble(void)
105 {
106 // mantissa
107 word72 Mant = convert_to_word72 (cpu.rA, cpu.rQ);
108
109 # ifdef NEED_128
110 if (iszero_128 (Mant))
111 return 0;
112
113 bool S = isnonzero_128 (and_128 (Mant, SIGN72)); // sign of mantissa
114 if (S)
115 Mant = and_128 (negate_128 (Mant), MASK71); // 71 bits (not 72!)
116 # else
117 if (Mant == 0)
118 return 0;
119
120 bool S = Mant & SIGN72; // sign of mantissa
121 if (S)
122 Mant = (-Mant) & MASK71; // 71 bits (not 72!)
123 # endif
124
125 double m = 0; // mantissa value
126 int e = SIGNEXT8_int (cpu . rE & MASK8); // make signed
127
128 # ifdef NEED_128
129 if (S && iszero_128 (Mant))// denormalized -1.0*2^e
130 return -exp2(e);
131 # else
132 if (S && Mant == 0) // denormalized -1.0*2^e
133 return -exp2(e);
134 # endif
135 double v = 0.5;
136 for(int n = 70 ; n >= 0 ; n -= 1) // this also normalizes the mantissa
137 {
138 # ifdef NEED_128
139 if (isnonzero_128 (and_128 (Mant, lshift_128 (construct_128 (0, 1), (unsigned int) n))))
140 {
141 m += v;
142 }
143 # else
144 if (Mant & ((word72)1 << n))
145 {
146 m += v;
147 }
148 # endif
149 v /= 2.0;
150 }
151
152 return (S ? -1 : 1) * ldexp(m, e);
153 }
154 #endif
155
156 #ifndef QUIET_UNUSED
157 /*!
158 * return normalized dps8 representation of IEEE double f0 ...
159 */
IEEElongdoubleToFloat72(long double f0)160 float72 IEEElongdoubleToFloat72(long double f0)
161 {
162 if (f0 == 0)
163 return (float72)((float72)0400000000000LL << 36);
164
165 bool sign = f0 < 0 ? true : false;
166 long double f = fabsl(f0);
167
168 int exp;
169 long double mant = frexpl(f, &exp);
170 //sim_printf (sign=%d f0=%Lf mant=%Lf exp=%d\n", sign, f0, mant, exp);
171
172 word72 result = 0;
173
174 // now let's examine the mantissa and assign bits as necessary...
175
176 if (sign && mant == 0.5)
177 {
178 //result = bitfieldInsert72(result, 1, 63, 1);
179 putbits72 (& result, 71-62, 1, 1);
180 exp -= 1;
181 mant -= 0.5;
182 }
183
184 long double bitval = 0.5; ///< start at 1/2 and go down .....
185 for(int n = 62 ; n >= 0 && mant > 0; n -= 1)
186 {
187 if (mant >= bitval)
188 {
189 //result = bitfieldInsert72(result, 1, n, 1);
190 putbits72 (& result, 71-n, 1, 1);
191 mant -= bitval;
192 //sim_printf ("Inserting a bit @ %d %012"PRIo64" %012"PRIo64"\n", n , (word36)((result >> 36) & DMASK), (word36)(result & DMASK));
193 }
194 bitval /= 2.0;
195 }
196 //sim_printf ("n=%d mant=%f\n", n, mant);
197 //sim_printf ("result=%012"PRIo64" %012"PRIo64"\n", (word36)((result >> 36) & DMASK), (word36)(result & DMASK));
198
199 // if f is < 0 then take 2-comp of result ...
200 if (sign)
201 {
202 result = -result & (((word72)1 << 64) - 1);
203 //sim_printf ("-result=%012"PRIo64" %012"PRIo64"\n", (word36)((result >> 36) & DMASK), (word36)(result & DMASK));
204 }
205 //! insert exponent ...
206 int e = (int)exp;
207 //result = bitfieldInsert72(result, e & 0377, 64, 8); ///< & 0777777777777LL;
208 putbits72 (& result, 71-64, 8, e & 0377);
209
210 // XXX TODO test for exp under/overflow ...
211
212 return result;
213 }
214 #endif
215
216 #ifndef QUIET_UNUSED
MYfrexpl(long double x,int * exp)217 static long double MYfrexpl(long double x, int *exp)
218 {
219 long double exponents[20], *next;
220 int exponent, bit;
221
222 /* Check for zero, nan and infinity. */
223 if (x != x || x + x == x )
224 {
225 *exp = 0;
226 return x;
227 }
228
229 if (x < 0)
230 return -MYfrexpl(-x, exp);
231
232 exponent = 0;
233 if (x > 1.0)
234 {
235 for (next = exponents, exponents[0] = 2.0L, bit = 1;
236 *next <= x + x;
237 bit <<= 1, next[1] = next[0] * next[0], next++);
238
239 for (; next >= exponents; bit >>= 1, next--)
240 if (x + x >= *next)
241 {
242 x /= *next;
243 exponent |= bit;
244 }
245
246 }
247
248 else if (x < 0.5)
249 {
250 for (next = exponents, exponents[0] = 0.5L, bit = 1;
251 *next > x;
252 bit <<= 1, next[1] = next[0] * next[0], next++);
253
254 for (; next >= exponents; bit >>= 1, next--)
255 if (x < *next)
256 {
257 x /= *next;
258 exponent |= bit;
259 }
260
261 exponent = -exponent;
262 }
263
264 *exp = exponent;
265 return x;
266 }
267 #endif
268
269 #ifndef QUIET_UNUSED
270 /*!
271 * Store EAQ with normalized dps8 representation of IEEE double f0 ...
272 */
IEEElongdoubleToEAQ(long double f0)273 void IEEElongdoubleToEAQ(long double f0)
274 {
275 if (f0 == 0)
276 {
277 cpu . rA = 0;
278 # ifdef TESTING
279 HDBGRegAW ("IEEEld2EAQ");
280 # endif
281 cpu . rQ = 0;
282 cpu . rE = 0200U; /*-128*/
283 return;
284 }
285
286 bool sign = f0 < 0 ? true : false;
287 long double f = fabsl(f0);
288 int exp;
289 long double mant = MYfrexpl(f, &exp);
290 word72 result = 0;
291
292 // now let's examine the mantissa and assign bits as necessary...
293 if (sign && mant == 0.5)
294 {
295 //result = bitfieldInsert72(result, 1, 63, 1);
296 result = putbits72 (& result, 71-63, 1, 1);
297 exp -= 1;
298 mant -= 0.5;
299 }
300
301 long double bitval = 0.5; ///< start at 1/2 and go down .....
302 for(int n = 70 ; n >= 0 && mant > 0; n -= 1)
303 {
304 if (mant >= bitval)
305 {
306 //result = bitfieldInsert72(result, 1, n, 1);
307 putbits72 (& result 71-n, 1, 1);
308 mant -= bitval;
309 //sim_printf ("Inserting a bit @ %d %012"PRIo64" %012"PRIo64"\n", n , (word36)((result >> 36) & DMASK), (word36)(result & DMASK));
310 }
311 bitval /= 2.0;
312 }
313
314 // if f is < 0 then take 2-comp of result ...
315 if (sign)
316 result = -result & (((word72)1 << 72) - 1);
317
318 cpu . rE = exp & MASK8;
319 cpu . rA = (result >> 36) & MASK36;
320 # ifdef TESTING
321 HDBGRegAW ("IEEEld2EAQ");
322 # endif
323 cpu . rQ = result & MASK36;
324 }
325 #endif
326
327 #if 0
328 /*!
329 * return IEEE double version dps8 single-precision number ...
330 */
331 static double float36ToIEEEdouble(word36 f36)
332 {
333 unsigned char E; ///< exponent
334 uint64 Mant; ///< mantissa
335 E = (f36 >> 28) & 0xff;
336 Mant = f36 & 01777777777LL;
337 if (Mant == 0)
338 return 0;
339
340 bool S = Mant & 01000000000LL; ///< sign of mantissa
341 if (S)
342 Mant = (-Mant) & 0777777777; // 27 bits (not 28!)
343
344 double m = 0; ///< mantissa value;
345 int e = (char)E; ///< make signed
346
347 if (S && Mant == 0) // denormalized -1.0*2^e
348 return -exp2(e);
349
350 double v = 0.5;
351 for(int n = 26 ; n >= 0 ; n -= 1) // this also normalizes the mantissa
352 {
353 if (Mant & ((uint64)1 << n))
354 {
355 m += v;
356 } //else
357 v /= 2.0;
358 }
359
360 return (S ? -1 : 1) * ldexp(m, e);
361 }
362 #endif
363
364 #if 0
365 /*!
366 * return normalized dps8 representation of IEEE double f0 ...
367 */
368 float36 IEEEdoubleTofloat36(double f0)
369 {
370 if (f0 == 0)
371 return 0400000000000LL;
372
373 double f = f0;
374 bool sign = f0 < 0 ? true : false;
375 if (sign)
376 f = fabs(f0);
377
378 int exp;
379 double mant = frexp(f, &exp);
380
381 //sim_printf (sign=%d f0=%f mant=%f exp=%d\n", sign, f0, mant, exp);
382
383 word36 result = 0;
384
385 // now let's examine the mantissa and assign bits as necessary...
386
387 double bitval = 0.5; ///< start at 1/2 and go down .....
388 for(int n = 26 ; n >= 0 && mant > 0; n -= 1)
389 {
390 if (mant >= bitval)
391 {
392 //result = bitfieldInsert36(result, 1, n, 1);
393 setbits36_1 (& result, 35-n, 1);
394 mant -= bitval;
395 //sim_printf ("Inserting a bit @ %d result=%012"PRIo64"\n", n, result);
396 }
397 bitval /= 2.0;
398 }
399 //sim_printf ("result=%012"PRIo64"\n", result);
400
401 // if f is < 0 then take 2-comp of result ...
402 if (sign)
403 {
404 result = -result & 001777777777LL;
405 //sim_printf ("-result=%012"PRIo64"\n", result);
406 }
407 // insert exponent ...
408 int e = (int)exp;
409 //result = bitfieldInsert36(result, e, 28, 8) & 0777777777777LL;
410 putbits36_8 (& result, 0, e);
411
412 // XXX TODO test for exp under/overflow ...
413
414 return result;
415 }
416 #endif
417
418 /*
419 * single-precision arithmetic routines ...
420 */
421
422 #ifdef HEX_MODE
423 //#define HEX_SIGN (SIGN72 | BIT71 | BIT70 | BIT69 | BIT68)
424 //#define HEX_MSB ( BIT71 | BIT70 | BIT69 | BIT68)
425 # ifdef NEED_128
426 # define HEX_SIGN construct_128 (0xF0, 0)
427 # define HEX_MSB consturct_128 (0x70, 0)
428 # define HEX_NORM construct_128 (0x78, 0)
429 # else
430 # define HEX_SIGN (SIGN72 | BIT71 | BIT70 | BIT69)
431 # define HEX_MSB ( BIT71 | BIT70 | BIT69)
432 # define HEX_NORM ( BIT71 | BIT70 | BIT69 | BIT68)
433 # endif
434
isHex(void)435 static inline bool isHex (void)
436 {
437 return (!!cpu.MR.hexfp) && (!!TST_I_HEX);
438 }
439 #endif
440
441 /*!
442 * unnormalized floating single-precision add
443 */
ufa(bool sub)444 void ufa (bool sub)
445 {
446 // C(EAQ) + C(Y) → C(EAQ)
447 // The ufa instruction is executed as follows:
448 //
449 // The mantissas are aligned by shifting the mantissa of the operand having
450 // the algebraically smaller exponent to the right the number of places
451 // equal to the absolute value of the difference in the two exponents. Bits
452 // shifted beyond the bit position equivalent to AQ71 are lost.
453 //
454 // The algebraically larger exponent replaces C(E). The sum of the
455 // mantissas replaces C(AQ).
456 //
457 // If an overflow occurs during addition, then;
458 // * C(AQ) are shifted one place to the right.
459 // * C(AQ)0 is inverted to restore the sign.
460 // * C(E) is increased by one.
461
462 CPTUR (cptUseE);
463 #ifdef HEX_MODE
464 uint shift_amt = isHex() ? 4 : 1;
465 //uint shift_msk = isHex() ? 017 : 1;
466 //word72 sign_msk = isHex() ? HEX_SIGN : SIGN72;
467 //word72 sign_msb = isHex() ? HEX_MSB : BIT71;
468 #endif
469 word72 m1 = convert_to_word72 (cpu.rA, cpu.rQ);
470 #ifdef NEED_128
471 // 28-bit mantissa (incl sign)
472 word72 m2 = lshift_128 (construct_128 (0, (uint64_t) getbits36_28 (cpu.CY, 8)), 44u); // 28-bit mantissa (incl sign)
473 #else
474 // 28-bit mantissa (incl sign)
475 word72 m2 = ((word72) getbits36_28 (cpu.CY, 8)) << 44; // 28-bit mantissa (incl sign)
476 #endif
477
478 int e1 = SIGNEXT8_int (cpu . rE & MASK8);
479 int e2 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
480
481 // RJ78: The two's complement of the subtrahend is first taken and the
482 // smaller value is then right-shifted to equalize it (i.e. ufa).
483
484 int m2zero = 0;
485 if (sub) {
486 // ISOLTS-735 08i asserts no carry for (-1.0*2^96)-(-1.0*2^2) but 08g
487 // asserts carry for -0.5079365*2^78-0.0
488 // I assume zero subtrahend is handled in a special way.
489
490 #ifdef NEED_128
491 if (iszero_128 (m2))
492 m2zero = 1;
493 if (iseq_128 (m2, SIGN72)) { // -1.0 -> 0.5, increase exponent, ISOLTS-735 08i,j
494 # ifdef HEX_MODE
495 m2 = rshift_128 (m2, shift_amt);
496 e2 += 1;
497 # else // ! HEX_MODE
498 m2 = rshift_128 (m2, 1);
499 e2 += 1;
500 # endif // ! HEX_MODE
501 } else
502 m2 = and_128 (negate_128 (m2), MASK72);
503 }
504 #else // ! NEED_128
505 if (m2 == 0)
506 m2zero = 1;
507 if (m2 == SIGN72) { // -1.0 -> 0.5, increase exponent, ISOLTS-735 08i,j
508 # ifdef HEX_MODE
509 m2 >>= shift_amt;
510 e2 += 1;
511 # else // ! HEX_MODE
512 m2 >>= 1;
513 e2 += 1;
514 # endif // ! HEX_MODE
515 } else
516 m2 = (-m2) & MASK72;
517 }
518
519 #endif // ! NEED_128
520
521 int e3 = -1;
522
523 // which exponent is smaller?
524 #ifdef L68
525 cpu.ou.cycle |= ou_GOE;
526 #endif
527 int shift_count = -1;
528 word1 allones = 1;
529 word1 notallzeros = 0;
530 //word1 last = 0;
531 (void)allones;
532 if (e1 == e2)
533 {
534 shift_count = 0;
535 e3 = e1;
536 }
537 else if (e1 < e2)
538 {
539 #ifdef HEX_MODE
540 shift_count = abs(e2 - e1) * (int) shift_amt;
541 #else
542 shift_count = abs(e2 - e1);
543 #endif
544 #ifdef NEED_128
545 bool sign = isnonzero_128 (and_128 (m1, SIGN72)); // mantissa negative?
546 for(int n = 0 ; n < shift_count ; n += 1)
547 {
548 //last = m1.l & 1;
549 allones &= m1.l & 1;
550 notallzeros |= m1.l & 1;
551 m1 = rshift_128 (m1, 1);
552 if (sign)
553 m1 = or_128 (m1, SIGN72);
554 }
555 # ifdef HEX_MODE
556 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
557 m1 = construct_128 (0, 0);
558 # else
559 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count > 71)
560 m1 = construct_128 (0, 0);
561 # endif
562 m1 = and_128 (m1, MASK72);
563 e3 = e2;
564 #else
565 bool sign = m1 & SIGN72; // mantissa negative?
566 for(int n = 0 ; n < shift_count ; n += 1)
567 {
568 //last = m1 & 1;
569 allones &= m1 & 1;
570 notallzeros |= m1 & 1;
571 m1 >>= 1;
572 if (sign)
573 m1 |= SIGN72;
574 }
575
576 # ifdef HEX_MODE
577 if (m1 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
578 m1 = 0;
579 # else
580 if (m1 == MASK72 && notallzeros == 1 && shift_count > 71)
581 m1 = 0;
582 # endif
583 m1 &= MASK72;
584 e3 = e2;
585 #endif // NEED_128
586 }
587 else
588 {
589 // e2 < e1;
590 #ifdef HEX_MODE
591 shift_count = abs(e1 - e2) * (int) shift_amt;
592 #else
593 shift_count = abs(e1 - e2);
594 #endif
595 #ifdef NEED_128
596 bool sign = isnonzero_128 (and_128 (m2, SIGN72)); // mantissa negative?
597 for(int n = 0 ; n < shift_count ; n += 1)
598 {
599 //last = m2.l & 1;
600 allones &= m2.l & 1;
601 notallzeros |= m2.l & 1;
602 m2 = rshift_128 (m2, 1);
603 if (sign)
604 m2 = or_128 (m2, SIGN72);
605 }
606 # ifdef HEX_MODE
607 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
608 m2 = construct_128 (0, 0);
609 # else
610 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count > 71)
611 m2 = construct_128 (0, 0);
612 # endif
613 m2 = and_128 (m2, MASK72);
614 e3 = e1;
615 #else
616 bool sign = m2 & SIGN72; // mantissa negative?
617 for(int n = 0 ; n < shift_count ; n += 1)
618 {
619 //last = m2 & 1;
620 allones &= m2 & 1;
621 notallzeros |= m2 & 1;
622 m2 >>= 1;
623 if (sign)
624 m2 |= SIGN72;
625 }
626 # ifdef HEX_MODE
627 if (m2 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
628 m2 = 0;
629 # else
630 if (m2 == MASK72 && notallzeros == 1 && shift_count > 71)
631 m2 = 0;
632 # endif
633 m2 &= MASK72;
634 e3 = e1;
635 #endif // NEED_128
636 }
637
638 bool ovf;
639 word72 m3;
640 m3 = Add72b (m1, m2, 0, I_CARRY, & cpu.cu.IR, & ovf);
641 // ISOLTS-735 08g
642 // if 2's complement carried, OR it in now.
643 if (m2zero)
644 SET_I_CARRY;
645
646 if (ovf)
647 {
648 #ifdef NEED_128
649 # ifdef HEX_MODE
650 // word72 signbit = m3 & sign_msk;
651 // m3 >>= shift_amt;
652 // m3 = (m3 & MASK71) | signbit;
653 // m3 ^= SIGN72; // C(AQ)0 is inverted to restore the sign
654 // e3 += 1;
655 word72 s = and_128 (m3, SIGN72); // save the sign bit
656 if (isHex ())
657 {
658 m3 = rshift_128 (m3, shift_amt); // renormalize the mantissa
659 if (isnonzero_128 (s))
660 // Sign is set, number should be positive; clear the sign bit and the 3 MSBs
661 m3 = and_128 (m3, MASK68);
662 else
663 // Sign is clr, number should be negative; set the sign bit and the 3 MSBs
664 m3 = or_128 (m3, HEX_SIGN);
665 }
666 else
667 {
668 word72 signbit = and_128 (m3, SIGN72);
669 m3 = rshift_128 (m3, 1);
670 m3 = and_128 (m3, MASK71);
671 m3 = or_128 (m3, signbit);
672 m3 = xor_128 (m3, SIGN72); // C(AQ)0 is inverted to restore the sign
673 }
674 e3 += 1;
675 # else
676 word72 signbit = and_128 (m3, SIGN72);
677 m3 = rshift_128 (m3, 1);
678 m3 = and_128 (m3, MASK71);
679 m3 = or_128 (m3, signbit);
680 m3 = xor_128 (m3, SIGN72); // C(AQ)0 is inverted to restore the sign
681 e3 += 1;
682 # endif
683 #else // NEED_128
684 # ifdef HEX_MODE
685 // word72 signbit = m3 & sign_msk;
686 // m3 >>= shift_amt;
687 // m3 = (m3 & MASK71) | signbit;
688 // m3 ^= SIGN72; // C(AQ)0 is inverted to restore the sign
689 // e3 += 1;
690 word72 s = m3 & SIGN72; // save the sign bit
691 if (isHex ())
692 {
693 m3 >>= shift_amt; // renormalize the mantissa
694 if (s)
695 // Sign is set, number should be positive; clear the sign bit and the 3 MSBs
696 m3 &= MASK68;
697 else
698 // Sign is clr, number should be negative; set the sign bit and the 3 MSBs
699 m3 |= HEX_SIGN;
700 }
701 else
702 {
703 word72 signbit = m3 & SIGN72;
704 m3 >>= 1;
705 m3 = (m3 & MASK71) | signbit;
706 m3 ^= SIGN72; // C(AQ)0 is inverted to restore the sign
707 }
708 e3 += 1;
709 # else
710 word72 signbit = m3 & SIGN72;
711 m3 >>= 1;
712 m3 = (m3 & MASK71) | signbit;
713 m3 ^= SIGN72; // C(AQ)0 is inverted to restore the sign
714 e3 += 1;
715 # endif
716 #endif // NEED_128
717 }
718
719 convert_to_word36 (m3, & cpu.rA, & cpu.rQ);
720 #ifdef TESTING
721 HDBGRegAW ("ufa");
722 #endif
723 cpu . rE = e3 & 0377;
724
725 SC_I_NEG (cpu.rA & SIGN36); // Do this here instead of in Add72b because
726 // of ovf handling above
727 if (cpu.rA == 0 && cpu.rQ == 0)
728 {
729 SET_I_ZERO;
730 cpu . rE = 0200U; /*-128*/
731 }
732 else
733 {
734 CLR_I_ZERO;
735 }
736
737 // EOFL: If exponent is greater than +127, then ON
738 if (e3 > 127)
739 {
740 SET_I_EOFL;
741 if (tstOVFfault ())
742 dlyDoFault (FAULT_OFL, fst_zero, "ufa exp overflow fault");
743 }
744
745 // EUFL: If exponent is less than -128, then ON
746 if(e3 < -128)
747 {
748 SET_I_EUFL;
749 if (tstOVFfault ())
750 dlyDoFault (FAULT_OFL, fst_zero, "ufa exp underflow fault");
751 }
752 }
753
754 /*
755 * floating normalize ...
756 */
757
fno(word8 * E,word36 * A,word36 * Q)758 void fno (word8 * E, word36 * A, word36 * Q)
759 {
760 // The fno instruction normalizes the number in C(EAQ) if C(AQ) ≠ 0 and the
761 // overflow indicator is OFF.
762 //
763 // A normalized floating number is defined as one whose mantissa lies in
764 // the interval [0.5,1.0) such that
765 // 0.5<= |C(AQ)| <1.0 which, in turn, requires that C(AQ)0 ≠ C(AQ)1.
766 //
767 // If the overflow indicator is ON, then C(AQ) is shifted one place to the
768 // right, C(AQ)0 is inverted to reconstitute the actual sign, and the
769 // overflow indicator is set OFF. This action makes the fno instruction
770 // useful in correcting overflows that occur with fixed point numbers.
771 //
772 // Normalization is performed by shifting C(AQ)1,71 one place to the left
773 // and reducing C(E) by 1, repeatedly, until the conditions for C(AQ)0 and
774 // C(AQ)1 are met. Bits shifted out of AQ1 are lost.
775 //
776 // If C(AQ) = 0, then C(E) is set to -128 and the zero indicator is set ON.
777
778 #ifdef L68
779 cpu.ou.cycle |= ou_GON;
780 #endif
781 #ifdef HEX_MODE
782 uint shift_amt = isHex() ? 4 : 1;
783 //uint shift_msk = isHex() ? 017 : 1;
784 //word72 sign_msk = isHex() ? HEX_SIGN : SIGN72;
785 //word72 sign_msb = isHex() ? HEX_NORM : BIT71;
786 #endif
787 *A &= DMASK;
788 *Q &= DMASK;
789 float72 m = convert_to_word72 (* A, * Q);
790 if (TST_I_OFLOW)
791 {
792 CLR_I_OFLOW;
793 #ifdef NEED_128
794 word72 s = and_128 (m, SIGN72); // save the sign bit
795 # ifdef HEX_MODE
796 if (isHex ())
797 {
798 m = rshift_128 (m, shift_amt); // renormalize the mantissa
799 if (isnonzero_128 (s)) // sign of mantissa
800 // Sign is set, number should be positive; clear the sign bit and the 3 MSBs
801 m = and_128 (m, MASK68);
802 else
803 // Sign is clr, number should be negative; set the sign bit and the 3 MSBs
804 m = or_128 (m, HEX_SIGN);
805 }
806 else
807 {
808 m = rshift_128 (m, 1); // renormalize the mantissa
809 m = or_128 (m, SIGN72); // set the sign bit
810 m = xor_128 (m, s); // if the was 0, leave it 1; if it was 1, make it 0
811 }
812 # else
813 m = rshift_128 (m, 1); // renormalize the mantissa
814 m = or_128 (m, SIGN72); // set the sign bit
815 m = xor_128 (m, s); // if the was 0, leave it 1; if it was 1, make it 0
816 # endif
817
818 // Zero: If C(AQ) = floating point 0, then ON; otherwise OFF
819 if (iszero_128 (m))
820 {
821 *E = 0200U; /*-128*/
822 SET_I_ZERO;
823 }
824 else
825 {
826 CLR_I_ZERO;
827 if (*E == 127)
828 {
829 SET_I_EOFL;
830 if (tstOVFfault ())
831 dlyDoFault (FAULT_OFL, fst_zero, "fno exp overflow fault");
832 }
833 (*E) ++;
834 *E &= MASK8;
835 }
836 #else
837 word72 s = m & SIGN72; // save the sign bit
838 # ifdef HEX_MODE
839 if (isHex ())
840 {
841 m >>= shift_amt; // renormalize the mantissa
842 if (s)
843 // Sign is set, number should be positive; clear the sign bit and the 3 MSBs
844 m &= MASK68;
845 else
846 // Sign is clr, number should be negative; set the sign bit and the 3 MSBs
847 m |= HEX_SIGN;
848 }
849 else
850 {
851 m >>= 1; // renormalize the mantissa
852 m |= SIGN72; // set the sign bit
853 m ^= s; // if the was 0, leave it 1; if it was 1, make it 0
854 }
855 # else
856 m >>= 1; // renormalize the mantissa
857 m |= SIGN72; // set the sign bit
858 m ^= s; // if the was 0, leave it 1; if it was 1, make it 0
859 # endif
860
861 // Zero: If C(AQ) = floating point 0, then ON; otherwise OFF
862 if (m == 0)
863 {
864 *E = 0200U; /*-128*/
865 SET_I_ZERO;
866 }
867 else
868 {
869 CLR_I_ZERO;
870 if (*E == 127)
871 {
872 SET_I_EOFL;
873 if (tstOVFfault ())
874 dlyDoFault (FAULT_OFL, fst_zero, "fno exp overflow fault");
875 }
876 (*E) ++;
877 *E &= MASK8;
878 }
879 #endif // NEED_128
880 convert_to_word36 (m, A, Q);
881 SC_I_NEG ((*A) & SIGN36);
882
883 return;
884 }
885
886 // only normalize C(EAQ) if C(AQ) ≠ 0 and the overflow indicator is OFF
887 #ifdef NEED_128
888 if (iszero_128 (m)) /// C(AQ) == 0.
889 #else
890 if (m == 0) // C(AQ) == 0.
891 #endif
892 {
893 //*A = (m >> 36) & MASK36;
894 //*Q = m & MASK36;
895 *E = 0200U; /*-128*/
896 SET_I_ZERO;
897 CLR_I_NEG;
898 return;
899 }
900
901 int e = SIGNEXT8_int ((*E) & MASK8);
902 #ifdef NEED_128
903 bool s = isnonzero_128 (and_128 (m, SIGN72));
904 #else
905 bool s = (m & SIGN72) != (word72)0; ///< save sign bit
906 #endif
907
908 #ifdef HEX_MODE
909 // Normalized in Hex Mode: If sign is 0, bits 1-4 != 0; if sign is 1,
910 // bits 1-4 != 017.
911 if (isHex ())
912 {
913 if (s)
914 {
915 // Negative
916 // Until bits 1-4 != 014
917 // Termination guarantee: Zeros are being shifted into the right
918 // end, so the loop will terminate when the first shifted
919 // zero enters bits 1-4.
920 # ifdef NEED_128
921 while (iseq_128 (and_128 (m, HEX_NORM), HEX_NORM))
922 {
923 //if (m == 0) // XXX: necessary??
924 // break;
925 m = lshift_128 (m, 4);
926 e -= 1;
927 }
928 m = and_128 (m, MASK71);
929 m = or_128 (m, SIGN72);
930 # else
931 while ((m & HEX_NORM) == HEX_NORM)
932 {
933 //if (m == 0) // XXX: necessary??
934 // break;
935 m <<= 4;
936 e -= 1;
937 }
938 m &= MASK71;
939 m |= SIGN72;
940 # endif
941 }
942 else
943 {
944 # ifdef NEED_128
945 // Positive
946 // Until bits 1-4 != 0
947 // Termination guarantee: m is known to be non-zero; a non-zero
948 // bit will eventually be shifted into bits 1-4.
949 while (iszero_128 (and_128 (m, HEX_NORM)))
950 {
951 m = lshift_128 (m, 4);
952 e -= 1;
953 }
954 m = and_128 (m, MASK71);
955 # else
956 // Positive
957 // Until bits 1-4 != 0
958 // Termination guarantee: m is known to be non-zero; a non-zero
959 // bit will eventually be shifted into bits 1-4.
960 while ((m & HEX_NORM) == 0)
961 {
962 m <<= 4;
963 e -= 1;
964 }
965 m &= MASK71;
966 # endif
967 }
968 }
969 else
970 {
971 # ifdef NEED_128
972 while (s == isnonzero_128 (and_128 (m, BIT71))) // until C(AQ)0 != C(AQ)1?
973 {
974 m = lshift_128 (m, 1);
975 e -= 1;
976 //if (m == 0) // XXX: necessary??
977 // break;
978 }
979
980 m = and_128 (m, MASK71);
981
982 if (s)
983 m = or_128 (m, SIGN72);
984 # else
985 while (s == !! (m & BIT71)) // until C(AQ)0 != C(AQ)1?
986 {
987 m <<= 1;
988 e -= 1;
989 //if (m == 0) // XXX: necessary??
990 // break;
991 }
992
993 m &= MASK71;
994
995 if (s)
996 m |= SIGN72;
997 # endif
998 }
999 #else
1000 # ifdef NEED_128
1001 while (s == isnonzero_128 (and_128 (m, BIT71))) // until C(AQ)0 != C(AQ)1?
1002 {
1003 m = lshift_128 (m, 1);
1004 e -= 1;
1005 //if (m == 0) // XXX: necessary??
1006 // break;
1007 }
1008
1009 m = and_128 (m, MASK71);
1010
1011 if (s)
1012 m = or_128 (m, SIGN72);
1013 # else
1014 while (s == !! (m & BIT71)) // until C(AQ)0 != C(AQ)1?
1015 {
1016 m <<= 1;
1017 e -= 1;
1018 //if (m == 0) // XXX: necessary??
1019 // break;
1020 }
1021
1022 m &= MASK71;
1023
1024 if (s)
1025 m |= SIGN72;
1026 # endif
1027 #endif
1028
1029 if (e < -128)
1030 {
1031 SET_I_EUFL;
1032 if (tstOVFfault ())
1033 dlyDoFault (FAULT_OFL, fst_zero, "fno exp underflow fault");
1034 }
1035
1036 *E = (word8) e & MASK8;
1037 convert_to_word36 (m, A, Q);
1038
1039 // EAQ is normalized, so if A is 0, so is Q, and the check can be elided
1040 if (*A == 0) // set to normalized 0
1041 *E = 0200U; /*-128*/
1042
1043 // Zero: If C(AQ) = floating point 0, then ON; otherwise OFF
1044 SC_I_ZERO (*A == 0 && *Q == 0);
1045
1046 // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
1047 SC_I_NEG ((*A) & SIGN36);
1048 }
1049
1050 #if 0
1051 // XXX eventually replace fno() with fnoEAQ()
1052 void fnoEAQ(word8 *E, word36 *A, word36 *Q)
1053 {
1054 //! The fno instruction normalizes the number in C(EAQ) if C(AQ) ≠ 0 and the overflow indicator is OFF.
1055 //! A normalized floating number is defined as one whose mantissa lies in the interval [0.5,1.0) such that
1056 //! 0.5<= |C(AQ)| <1.0 which, in turn, requires that C(AQ)0 ≠ C(AQ)1.
1057 //! If the overflow indicator is ON, then C(AQ) is shifted one place to the right, C(AQ)0 is inverted to reconstitute the actual sign, and the overflow indicator is set OFF. This action makes the fno instruction useful in correcting overflows that occur with fixed point numbers.
1058 //! Normalization is performed by shifting C(AQ)1,71 one place to the left and reducing C(E) by 1, repeatedly, until the conditions for C(AQ)0 and C(AQ)1 are met. Bits shifted out of AQ1 are lost.
1059 //! If C(AQ) = 0, then C(E) is set to -128 and the zero indicator is set ON.
1060
1061 float72 m = ((word72)*A << 36) | (word72)*Q;
1062 if (TST_I_OFLOW)
1063 {
1064 m >>= 1;
1065 m &= MASK72;
1066
1067 m ^= ((word72)1 << 71);
1068
1069 CLR_I_OFLOW;
1070
1071 // Zero: If C(AQ) = floating point 0, then ON; otherwise OFF
1072 //SC_I_ZERO (*E == -128 && m == 0);
1073 //SC_I_ZERO (*E == 0200U /*-128*/ && m == 0);
1074 if (m == 0)
1075 {
1076 *E = -128;
1077 SET_I_ZERO;
1078 }
1079 // Neg:
1080 CLR_I_NEG;
1081 return; // XXX: ???
1082 }
1083
1084 // only normalize C(EAQ) if C(AQ) ≠ 0 and the overflow indicator is OFF
1085 if (m == 0) // C(AQ) == 0.
1086 {
1087 *A = (m >> 36) & MASK36;
1088 *Q = m & MASK36;
1089 *E = 0200U; /*-128*/
1090
1091 // Zero: If C(AQ) = floating point 0, then ON; otherwise OFF
1092 //SC_I_ZERO(*E == -128 && m == 0);
1093 //SC_I_ZERO(*E == 0200U /*-128*/ && m == 0);
1094 SET_I_ZERO;
1095 // Neg:
1096 CLR_I_NEG;
1097
1098 return;
1099 }
1100 int8 e = (int8)*E;
1101
1102
1103 bool s = m & SIGN72; ///< save sign bit
1104 while ((bool)(m & SIGN72) == (bool)(m & (SIGN72 >> 1))) // until C(AQ)0 ≠ C(AQ)1?
1105 {
1106 m <<= 1;
1107 m &= MASK72;
1108
1109 if (s)
1110 m |= SIGN72;
1111
1112 if ((e - 1) < -128)
1113 SET_I_EUFL;
1114 else // XXX: my interpretation
1115 e -= 1;
1116
1117 if (m == 0) // XXX: necessary??
1118 {
1119 *E = (word8)-128;
1120 break;
1121 }
1122 }
1123
1124 *E = e & 0377;
1125 *A = (m >> 36) & MASK36;
1126 *Q = m & MASK36;
1127
1128 // EAQ is normalized, so if A is 0, so is Q, and the check can be elided
1129 if (*A == 0) // set to normalized 0
1130 *E = (word8)-128;
1131
1132 // Zero: If C(AQ) = floating point 0, then ON; otherwise OFF
1133 SC_I_ZERO (*A == 0);
1134
1135 // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
1136 SC_I_NEG (*A & SIGN36);
1137
1138 }
1139 #endif
1140
1141 /*
1142 * floating negate ...
1143 */
fneg(void)1144 void fneg (void)
1145 {
1146 // This instruction changes the number in C(EAQ) to its normalized negative
1147 // (if C(AQ) ≠ 0). The operation is executed by first forming the twos
1148 // complement of C(AQ), and then normalizing C(EAQ).
1149 //
1150 // Even if originally C(EAQ) were normalized, an exponent overflow can
1151 // still occur, namely when C(E) = +127 and C(AQ) = 100...0 which is the
1152 // twos complement approximation for the decimal value -1.0.
1153
1154 #if 0
1155 float72 m = ((word72)cpu . rA << 36) | (word72)cpu . rQ;
1156
1157 if (m == 0) // (if C(AQ) ≠ 0)
1158 {
1159 SET_I_ZERO; // it's zero
1160 CLR_I_NEG; // it ain't negative
1161 return; //XXX: ????
1162 }
1163
1164 int8 e = (int8)cpu . rE;
1165
1166 word72 mc = 0;
1167 if (m == FLOAT72SIGN)
1168 {
1169 mc = m >> 1;
1170 e += 1;
1171 } else
1172 mc = ~m + 1; // take 2-comp of mantissa
1173
1174
1175 //mc &= FLOAT72MASK;
1176 mc &= ((word72)1 << 72) - 1;
1177 /*
1178 * When signs are the *same* we have an overflow
1179 * (Treat as in addition when we get an overflow)
1180 */
1181 //bool ov = ((m & FLOAT72SIGN) == (mc & FLOAT72SIGN)); // the "weird" number!
1182 bool ov = ((m & ((word72)1 << 71)) == (mc & ((word72)1 << 71))); // the "weird" number!
1183 // if (ov)
1184 // bool ov = ((m & 01000000000LL) == (mc & 01000000000LL)); // the "weird" number.
1185 if (ov && m != 0)
1186 {
1187 mc >>= 1;
1188 //mc &= FLOAT72MASK;
1189 mc &= ((word72)1 << 72) - 1;
1190
1191 if ((e + 1) > 127)
1192 SET_I_EOFL;
1193 else // XXX: this is my interpretation
1194 e += 1;
1195 }
1196
1197 cpu . rE = e & 0377;
1198 cpu . rA = (mc >> 36) & MASK36;
1199 cpu . rQ = mc & MASK36;
1200 #else
1201 CPTUR (cptUseE);
1202 // Form the mantissa from AQ
1203
1204 word72 m = convert_to_word72 (cpu.rA, cpu.rQ);
1205
1206 // If the mantissa is 4000...00 (least negative value, it is negable in
1207 // two's complement arithmetic. Divide it by 2, losing a bit of precision,
1208 // and increment the exponent.
1209 # ifdef NEED_128
1210 if (iseq_128 (m, SIGN72))
1211 # else
1212 if (m == SIGN72)
1213 # endif
1214 {
1215 // Negation of 400..0 / 2 is 200..0; we can get there shifting; we know
1216 // that a zero will be shifted into the sign bit becuase fo the masking
1217 // in 'm='.
1218 # ifdef NEED_128
1219 m = rshift_128 (m, 1);
1220 # else
1221 m >>= 1;
1222 # endif
1223 // Increment the exp, checking for overflow.
1224 if (cpu . rE == 127)
1225 {
1226 SET_I_EOFL;
1227 if (tstOVFfault ())
1228 dlyDoFault (FAULT_OFL, fst_zero, "fneg exp overflow fault");
1229 }
1230 cpu . rE ++;
1231 cpu . rE &= MASK8;
1232 }
1233 else
1234 {
1235 // Do the negation
1236 # ifdef NEED_128
1237 m = negate_128 (m);
1238 # else
1239 m = -m;
1240 # endif
1241 }
1242 convert_to_word36 (m, & cpu.rA, & cpu.rQ);
1243 #endif
1244 fno (& cpu.rE, & cpu.rA, & cpu.rQ); // normalize
1245 #ifdef TESTING
1246 HDBGRegAW ("fneg");
1247 #endif
1248 }
1249
1250 /*!
1251 * Unnormalized Floating Multiply ...
1252 */
ufm(void)1253 void ufm (void)
1254 {
1255 // The ufm instruction is executed as follows:
1256 // C(E) + C(Y)0,7 → C(E)
1257 // ( C(AQ) × C(Y)8,35 )0,71 → C(AQ)
1258
1259 // Zero: If C(AQ) = 0, then ON; otherwise OFF
1260 // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
1261 // Exp Ovr: If exponent is greater than +127, then ON
1262 // Exp Undr: If exponent is less than -128, then ON
1263
1264 CPTUR (cptUseE);
1265 word72 m1 = convert_to_word72 (cpu.rA, cpu.rQ);
1266 int e1 = SIGNEXT8_int (cpu . rE & MASK8);
1267
1268 #ifdef NEED_128
1269 word72 m2 = lshift_128 (construct_128 (0, (uint64_t) getbits36_28 (cpu.CY, 8)), 44u); // 28-bit mantissa (incl sign)
1270 #else
1271 word72 m2 = ((word72) getbits36_28 (cpu.CY, 8)) << 44; ///< 28-bit mantissa (incl sign)
1272 #endif
1273 int e2 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
1274
1275 #ifdef NEED_128
1276 if (iszero_128 (m1) || iszero_128 (m2))
1277 #else
1278 if (m1 == 0 || m2 == 0)
1279 #endif
1280 {
1281 SET_I_ZERO;
1282 CLR_I_NEG;
1283
1284 cpu . rE = 0200U; /*-128*/
1285 cpu . rA = 0;
1286 #ifdef TESTING
1287 HDBGRegAW ("ufm");
1288 #endif
1289 cpu . rQ = 0;
1290
1291 return; // normalized 0
1292 }
1293
1294 int e3 = e1 + e2;
1295
1296 if (e3 > 127)
1297 {
1298 SET_I_EOFL;
1299 if (tstOVFfault ())
1300 dlyDoFault (FAULT_OFL, fst_zero, "ufm exp overflow fault");
1301 }
1302 if (e3 < -128)
1303 {
1304 SET_I_EUFL;
1305 if (tstOVFfault ())
1306 dlyDoFault (FAULT_OFL, fst_zero, "ufm exp underflow fault");
1307 }
1308
1309 // RJ78: This multiplication is executed in the following way:
1310 // C(E) + C(Y)(0-7) -> C(E)
1311 // C(AQ) * C(Y)(8-35) results in a 98-bit product plus sign,
1312 // the leading 71 bits plus sign of which -> C(AQ).
1313
1314 // shift the CY mantissa to get 98 bits precision
1315 #ifdef NEED_128
1316 int128 t = SIGNEXT72_128(m2);
1317 uint128 ut = rshift_128 (cast_128 (t), 44);
1318 int128 m3 = multiply_s128 (SIGNEXT72_128(m1), cast_s128 (ut));
1319 //sim_debug (DBG_TRACEEXT, & cpu_dev, "m3 %016"PRIx64"%016"PRIx64"\n", m3.h, m3.l);
1320 #else
1321 int128 m3 = (SIGNEXT72_128(m1) * (SIGNEXT72_128(m2) >> 44));
1322 //sim_debug (DBG_TRACEEXT, & cpu_dev, "m3 %016"PRIx64"%016"PRIx64"\n", (uint64_t) (m3>>64), (uint64_t) m3);
1323 #endif
1324 // realign to 72bits
1325 #ifdef NEED_128
1326 word72 m3a = and_128 (rshift_128 (cast_128 (m3), 98u - 71u), MASK72);
1327 //sim_debug (DBG_TRACEEXT, & cpu_dev, "m3a %016"PRIx64"%016"PRIx64"\n", m3a.h, m3a.l);
1328 #else
1329 word72 m3a = ((word72) m3 >> (98-71)) & MASK72;
1330 //sim_debug (DBG_TRACEEXT, & cpu_dev, "m3a %016"PRIx64"%016"PRIx64"\n", (uint64_t) (m3a>>64), (uint64_t) m3a);
1331 #endif
1332
1333 // A normalization is performed only in the case of both factor mantissas being 100...0
1334 // which is the twos complement approximation to the decimal value -1.0.
1335 #ifdef NEED_128
1336 if (iseq_128 (m1, SIGN72) && iseq_128 (m2, SIGN72))
1337 #else
1338 if ((m1 == SIGN72) && (m2 == SIGN72))
1339 #endif
1340 {
1341 if (e3 == 127)
1342 {
1343 SET_I_EOFL;
1344 if (tstOVFfault ())
1345 dlyDoFault (FAULT_OFL, fst_zero, "ufm exp overflow fault");
1346 }
1347 #ifdef NEED_128
1348 m3a = rshift_128 (m3a, 1);
1349 #else
1350 m3a >>= 1;
1351 #endif
1352 e3 += 1;
1353 }
1354
1355 convert_to_word36 (m3a, & cpu.rA, & cpu.rQ);
1356 #ifdef TESTING
1357 HDBGRegAW ("ufm");
1358 #endif
1359 cpu . rE = (word8) e3 & MASK8;
1360 sim_debug (DBG_TRACEEXT, & cpu_dev, "fmp A %012"PRIo64" Q %012"PRIo64" E %03o\n", cpu.rA, cpu.rQ, cpu.rE);
1361 SC_I_NEG (cpu.rA & SIGN36);
1362
1363 if (cpu.rA == 0 && cpu.rQ == 0)
1364 {
1365 SET_I_ZERO;
1366 cpu . rE = 0200U; /*-128*/
1367 }
1368 else
1369 {
1370 CLR_I_ZERO;
1371 }
1372 }
1373
1374 /*!
1375 * floating divide ...
1376 */
1377 // CANFAULT
fdvX(bool bInvert)1378 static void fdvX(bool bInvert)
1379 {
1380 //! C(EAQ) / C (Y) → C(EA)
1381 //! C(Y) / C(EAQ) → C(EA) (Inverted)
1382
1383 //! 00...0 → C(Q)
1384
1385 //! The fdv instruction is executed as follows:
1386 //! The dividend mantissa C(AQ) is shifted right and the dividend exponent
1387 //! C(E) increased accordingly until | C(AQ)0,27 | < | C(Y)8,35 |
1388 //! C(E) - C(Y)0,7 → C(E)
1389 //! C(AQ) / C(Y)8,35 → C(A)
1390 //! 00...0 → C(Q)
1391
1392 CPTUR (cptUseE);
1393 #ifdef HEX_MODE
1394 uint shift_amt = isHex() ? 4 : 1;
1395 #endif
1396 word72 m1;
1397 int e1;
1398
1399 word72 m2;
1400 int e2;
1401
1402 bool roundovf = 0;
1403
1404 if (!bInvert)
1405 {
1406 m1 = convert_to_word72 (cpu.rA, cpu.rQ);
1407 e1 = SIGNEXT8_int (cpu . rE & MASK8);
1408
1409 #ifdef NEED_128
1410 m2 = lshift_128 (construct_128 (0, (uint64_t) getbits36_28 (cpu.CY, 8)), 44u); // 28-bit mantissa (incl sign)
1411 #else
1412 m2 = ((word72) getbits36_28 (cpu.CY, 8)) << 44; ///< 28-bit mantissa (incl sign)
1413 #endif
1414 e2 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
1415
1416 } else { // invert
1417
1418 m2 = convert_to_word72 (cpu.rA, cpu.rQ);
1419 e2 = SIGNEXT8_int (cpu . rE & MASK8);
1420
1421 // round divisor per RJ78
1422 // If AQ(28-71) is not equal to 0 and A(0) = 0, then 1 is added to AQ(27).
1423 // 0 -> AQ(28-71) unconditionally. AQ(0-27) is then used as the divisor mantissa.
1424 #ifdef NEED_128
1425 if ((iszero_128 (and_128 (m2, SIGN72))) &&
1426 (isnonzero_128 (and_128 (m2, construct_128 (0, 0377777777777777LL))))) {
1427 m2 = add_128 (m2, construct_128 (0, 0400000000000000LL));
1428 // I surmise that the divisor is taken as unsigned 28 bits in this case
1429 roundovf = 1;
1430 }
1431 m2 = and_128 (m2, lshift_128 (construct_128 (0, 0777777777400), 36));
1432
1433 m1 = lshift_128 (construct_128 (0, getbits36_28 (cpu.CY, 8)), 44); ///< 28-bit mantissa (incl sign)
1434 e1 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
1435 #else
1436 if (!(m2 & SIGN72) && m2 & 0377777777777777LL) {
1437 m2 += 0400000000000000LL;
1438 // I surmise that the divisor is taken as unsigned 28 bits in this case
1439 roundovf = 1;
1440 }
1441 m2 &= (word72)0777777777400 << 36;
1442
1443 m1 = ((word72) getbits36_28 (cpu.CY, 8)) << 44; ///< 28-bit mantissa (incl sign)
1444 e1 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
1445 #endif
1446 }
1447
1448 #ifdef NEED_128
1449 if (iszero_128 (m1))
1450 #else
1451 if (m1 == 0)
1452 #endif
1453 {
1454 SET_I_ZERO;
1455 CLR_I_NEG;
1456
1457 cpu . rE = 0200U; /*-128*/
1458 cpu . rA = 0;
1459 #ifdef TESTING
1460 HDBGRegAW ("fdvX");
1461 #endif
1462 cpu . rQ = 0;
1463
1464 return; // normalized 0
1465 }
1466
1467 // make everything positive, but save sign info for later....
1468 int sign = 1;
1469 #ifdef NEED_128
1470 if (isnonzero_128 (and_128 (m1, SIGN72)))
1471 #else
1472 if (m1 & SIGN72)
1473 #endif
1474 {
1475 SET_I_NEG; // in case of divide fault
1476 #ifdef NEED_128
1477 if (iseq_128 (m1, SIGN72))
1478 {
1479 # ifdef HEX_MODE
1480 m1 = rshift_128 (m1, shift_amt);
1481 # else
1482 m1 = rshift_128 (m1, 1);
1483 # endif
1484 e1 += 1;
1485 } else
1486 m1 = and_128 (negate_128 (m1), MASK72);
1487 #else
1488 if (m1 == SIGN72)
1489 {
1490 # ifdef HEX_MODE
1491 m1 >>= shift_amt;
1492 # else
1493 m1 >>= 1;
1494 # endif
1495 e1 += 1;
1496 } else
1497 m1 = (~m1 + 1) & MASK72;
1498 #endif
1499 sign = -sign;
1500 } else {
1501 CLR_I_NEG; // in case of divide fault
1502 }
1503
1504 #ifdef NEED_128
1505 if ((isnonzero_128 (and_128 (m2, SIGN72))) && !roundovf)
1506 {
1507 if (iseq_128 (m2, SIGN72))
1508 {
1509 # ifdef HEX_MODE
1510 m2 = rshift_128 (m2, shift_amt);
1511 # else
1512 m2 = rshift_128 (m2, 1);
1513 # endif
1514 e2 += 1;
1515 } else
1516 m2 = and_128 (negate_128 (m2), MASK72);
1517 sign = -sign;
1518 }
1519 #else
1520 if ((m2 & SIGN72) && !roundovf)
1521 {
1522 if (m2 == SIGN72)
1523 {
1524 # ifdef HEX_MODE
1525 m2 >>= shift_amt;
1526 # else
1527 m2 >>= 1;
1528 # endif
1529 e2 += 1;
1530 } else
1531 m2 = (~m2 + 1) & MASK72;
1532 sign = -sign;
1533 }
1534 #endif
1535
1536 #ifdef NEED_128
1537 if (iszero_128 (m2))
1538 #else
1539 if (m2 == 0)
1540 #endif
1541 {
1542 // NB: If C(Y)8,35 ==0 then the alignment loop will never exit! That's why it been moved before the alignment
1543
1544 SET_I_ZERO;
1545 // NEG already set
1546
1547 // FDV: If the divisor mantissa C(Y)8,35 is zero after alignment (HWR: why after?), the division does
1548 // not take place. Instead, a divide check fault occurs, C(AQ) contains the dividend magnitude, and
1549 // the negative indicator reflects the dividend sign.
1550 // FDI: If the divisor mantissa C(AQ) is zero, the division does not take place.
1551 // Instead, a divide check fault occurs and all the registers remain unchanged.
1552 if (!bInvert) {
1553 convert_to_word36 (m1, & cpu.rA, & cpu.rQ);
1554 #ifdef TESTING
1555 HDBGRegAW ("fdvX");
1556 #endif
1557 }
1558
1559 doFault(FAULT_DIV, fst_zero, "FDV: divide check fault");
1560 }
1561
1562 #ifdef NEED_128
1563 while (isge_128 (m1, m2)) // DH02 (equivalent but perhaps clearer description):
1564 // dividend exponent C(E) increased accordingly until | C(AQ)0,71 | < | C(Y)8,35 with zero fill |
1565 // We have already taken the absolute value so just shift it
1566 {
1567 # ifdef HEX_MODE
1568 m1 = rshift_128 (m1, shift_amt);
1569 # else
1570 m1 = rshift_128 (m1, 1);
1571 # endif
1572 e1 += 1;
1573 }
1574 #else
1575 while (m1 >= m2) // DH02 (equivalent but perhaps clearer description):
1576 // dividend exponent C(E) increased accordingly until | C(AQ)0,71 | < | C(Y)8,35 with zero fill |
1577 // We have already taken the absolute value so just shift it
1578 {
1579 # ifdef HEX_MODE
1580 m1 >>= shift_amt;
1581 # else
1582 m1 >>= 1;
1583 # endif
1584 e1 += 1;
1585 }
1586 #endif
1587
1588 int e3 = e1 - e2;
1589
1590 if (e3 > 127)
1591 {
1592 SET_I_EOFL;
1593 if (tstOVFfault ())
1594 dlyDoFault (FAULT_OFL, fst_zero, "fdvX exp overflow fault");
1595 }
1596 if (e3 < -128)
1597 {
1598 SET_I_EUFL;
1599 if (tstOVFfault ())
1600 dlyDoFault (FAULT_OFL, fst_zero, "fdvX exp underflow fault");
1601 }
1602
1603 // We need 35 bits quotient + sign. Divisor is at most 28 bits.
1604 // Do a 63(28+35) by 35 fractional divide
1605 // lo 44bits are always zero
1606 #ifdef NEED_128
1607 uint32_t divisor = rshift_128 (m2, 44).l & MASK28;
1608 word72 m3;
1609 if (divisor > MASK16)
1610 m3 = divide_128_32 (rshift_128 (m1, (44u-35u)), divisor, NULL);
1611 else
1612 m3 = divide_128_16 (rshift_128 (m1, (44u-35u)), (uint16_t) divisor, NULL);
1613 #else
1614 word72 m3 = (m1 >> (44-35)) / (m2 >> 44);
1615 #endif
1616
1617 #ifdef NEED_128
1618 m3 = lshift_128 (m3, 36);
1619 if (sign == -1)
1620 m3 = and_128 (negate_128 (m3), MASK72);
1621 #else
1622 m3 <<= 36; // convert back to float
1623 if (sign == -1)
1624 m3 = (~m3 + 1) & MASK72;
1625 #endif
1626
1627 cpu . rE = (word8) e3 & MASK8;
1628 #ifdef NEED_128
1629 cpu.rA = rshift_128 (m3, 36u).l & MASK36;
1630 #else
1631 cpu . rA = (m3 >> 36) & MASK36;
1632 #endif
1633 #ifdef TESTING
1634 HDBGRegAW ("fdvX");
1635 #endif
1636 cpu . rQ = 0;
1637
1638 SC_I_ZERO (cpu . rA == 0);
1639 SC_I_NEG (cpu . rA & SIGN36);
1640
1641 if (cpu . rA == 0) // set to normalized 0
1642 cpu . rE = 0200U; /*-128*/
1643 }
1644
fdv(void)1645 void fdv (void)
1646 {
1647 fdvX(false); // no inversion
1648 }
fdi(void)1649 void fdi (void)
1650 {
1651 fdvX(true);
1652 }
1653
1654 /*!
1655 * single precision floating round ...
1656 */
frd(void)1657 void frd (void)
1658 {
1659 // If C(AQ) != 0, the frd instruction performs a true round to a precision
1660 // of 28 bits and a normalization on C(EAQ).
1661 // A true round is a rounding operation such that the sum of the result of
1662 // applying the operation to two numbers of equal magnitude but opposite
1663 // sign is exactly zero.
1664
1665 // The frd instruction is executed as follows:
1666 // C(AQ) + (11...1)29,71 -> C(AQ)
1667 // If C(AQ)0 = 0, then a carry is added at AQ71
1668 // If overflow occurs, C(AQ) is shifted one place to the right and C(E) is
1669 // increased by 1.
1670 // If overflow does not occur, C(EAQ) is normalized.
1671 // If C(AQ) = 0, C(E) is set to -128 and the zero indicator is set ON.
1672
1673 // I believe AL39 is incorrect; bits 28-71 should be set to 0, not 29-71.
1674 // DH02-01 & Bull 9000 is correct.
1675
1676 // test case 15.5
1677 // rE rA rQ
1678 // 014174000000 00000110 000111110000000000000000000000000000 000000000000000000000000000000000000
1679 // + 1111111 111111111111111111111111111111111111
1680 // = 00000110 000111110000000000000000000001111111 111111111111111111111111111111111111
1681 // If C(AQ)0 = 0, then a carry is added at AQ71
1682 // = 00000110 000111110000000000000000000010000000 000000000000000000000000000000000000
1683 // 0 → C(AQ)29,71
1684 // 00000110 000111110000000000000000000010000000 000000000000000000000000000000000000
1685 // after normalization .....
1686 // 010760000002 00000100 011111000000000000000000001000000000 000000000000000000000000000000000000
1687 // I think this is wrong
1688
1689 // 0 -> C(AQ)28,71
1690 // 00000110 000111110000000000000000000000000000 000000000000000000000000000000000000
1691 // after normalization .....
1692 // 010760000000 00000100 011111000000000000000000000000000000 000000000000000000000000000000000000
1693 // which I think is correct
1694
1695 //
1696 // GE CPB1004F, DH02-01 (DPS8/88) & Bull DPS9000 assembly ... have this ...
1697
1698 // The rounding operation is performed in the following way.
1699 // - a) A constant (all 1s) is added to bits 29-71 of the mantissa.
1700 // - b) If the number being rounded is positive, a carry is inserted into
1701 // the least significant bit position of the adder.
1702 // - c) If the number being rounded is negative, the carry is not inserted.
1703 // - d) Bits 28-71 of C(AQ) are replaced by zeros.
1704 // If the mantissa overflows upon rounding, it is shifted right one place
1705 // and a corresponding correction is made to the exponent.
1706 // If the mantissa does not overflow and is nonzero upon rounding,
1707 // normalization is performed.
1708
1709 // If the resultant mantissa is all zeros, the exponent is forced to -128
1710 // and the zero indicator is set.
1711 // If the exponent resulting from the operation is greater than +127, the
1712 // exponent Overflow indicator is set.
1713 // If the exponent resulting from the operation is less than -128, the
1714 // exponent Underflow indicator is set.
1715 // The definition of normalization is located under the description of the FNO instruction.
1716
1717 // So, Either AL39 is wrong or the DPS8m did it wrong. (Which was fixed in
1718 // later models.) I'll assume AL39 is wrong.
1719
1720 CPTUR (cptUseE);
1721 #ifdef L68
1722 cpu.ou.cycle |= ou_GOS;
1723 #endif
1724
1725 word72 m = convert_to_word72 (cpu.rA, cpu.rQ);
1726 #ifdef NEED_128
1727 if (iszero_128 (m))
1728 #else
1729 if (m == 0)
1730 #endif
1731 {
1732 cpu.rE = 0200U; /*-128*/
1733 SET_I_ZERO;
1734 CLR_I_NEG;
1735 return;
1736 }
1737
1738
1739 #if 1 // according to RJ78
1740 // C(AQ) + (11...1)29,71 → C(AQ)
1741 bool ovf;
1742 word18 flags1 = 0;
1743 //word18 flags2 = 0;
1744 word1 carry = 0;
1745 // If C(AQ)0 = 0, then a carry is added at AQ71
1746 # ifdef NEED_128
1747 if (iszero_128 (and_128 (m, SIGN72)))
1748 # else
1749 if ((m & SIGN72) == 0)
1750 # endif
1751 {
1752 carry = 1;
1753 }
1754 # ifdef NEED_128
1755 m = Add72b (m, construct_128 (0, 0177777777777777LL), carry, I_OFLOW, & flags1, & ovf);
1756 # else
1757 m = Add72b (m, 0177777777777777LL, carry, I_OFLOW, & flags1, & ovf);
1758 # endif
1759 #endif
1760
1761 #if 0 // according to AL39
1762 // C(AQ) + (11...1)29,71 → C(AQ)
1763 bool ovf;
1764 word18 flags1 = 0;
1765 word18 flags2 = 0;
1766 m = Add72b (m, 0177777777777777LL, 0, I_OFLOW, & flags1, & ovf);
1767
1768 // If C(AQ)0 = 0, then a carry is added at AQ71
1769 if ((m & SIGN72) == 0)
1770 {
1771 m = Add72b (m, 1, 0, I_OFLOW, & flags2, & ovf);
1772 }
1773 #endif
1774
1775 // 0 -> C(AQ)28,71 (per. RJ78)
1776 #ifdef NEED_128
1777 m = and_128 (m, lshift_128 (construct_128 (0, 0777777777400), 36));
1778 #else
1779 m &= ((word72)0777777777400 << 36);
1780 #endif
1781
1782 // If overflow occurs, C(AQ) is shifted one place to the right and C(E) is
1783 // increased by 1.
1784 // If overflow does not occur, C(EAQ) is normalized.
1785 // All of this is done by fno, we just need to save the overflow flag
1786
1787 bool savedovf = TST_I_OFLOW;
1788 SC_I_OFLOW(ovf);
1789 convert_to_word36 (m, & cpu.rA, & cpu.rQ);
1790
1791 fno (& cpu.rE, & cpu.rA, & cpu.rQ);
1792 #ifdef TESTING
1793 HDBGRegAW ("frd");
1794 #endif
1795 SC_I_OFLOW(savedovf);
1796 }
1797
fstr(word36 * Y)1798 void fstr (word36 *Y)
1799 {
1800 // The fstr instruction performs a true round and normalization on C(EAQ)
1801 // as it is stored. The definition of true round is located under the
1802 // description of the frd instruction. The definition of normalization is
1803 // located under the description of the fno instruction. Attempted
1804 // repetition with the rpl instruction causes an illegal procedure fault.
1805
1806 #ifdef L68
1807 cpu.ou.cycle |= ou_GOS;
1808 #endif
1809 word36 A = cpu . rA, Q = cpu . rQ;
1810 word8 E = cpu . rE;
1811 //A &= DMASK;
1812 //Q &= DMASK;
1813 //E &= (int) MASK8;
1814
1815 float72 m = convert_to_word72 (A, Q);
1816 #ifdef NEED_128
1817 if (iszero_128 (m))
1818 #else
1819 if (m == 0)
1820 #endif
1821 {
1822 E = (word8)-128;
1823 SET_I_ZERO;
1824 CLR_I_NEG;
1825 *Y = 0;
1826 putbits36_8 (Y, 0, (word8) E & MASK8);
1827 return;
1828 }
1829
1830 // C(AQ) + (11...1)29,71 → C(AQ)
1831 bool ovf;
1832 word18 flags1 = 0;
1833 word1 carry = 0;
1834 // If C(AQ)0 = 0, then a carry is added at AQ71
1835 #ifdef NEED_128
1836 if (iszero_128 (and_128 (m, SIGN72)))
1837 #else
1838 if ((m & SIGN72) == 0)
1839 #endif
1840 {
1841 carry = 1;
1842 }
1843 #ifdef NEED_128
1844 m = Add72b (m, construct_128 (0, 0177777777777777LL), carry, I_OFLOW, & flags1, & ovf);
1845 #else
1846 m = Add72b (m, 0177777777777777LL, carry, I_OFLOW, & flags1, & ovf);
1847 #endif
1848
1849 // 0 -> C(AQ)28,71 (per. RJ78)
1850 #ifdef NEED_128
1851 m = and_128 (m, lshift_128 (construct_128 (0, 0777777777400), 36));
1852 #else
1853 m &= ((word72)0777777777400 << 36);
1854 #endif
1855
1856 // If overflow occurs, C(AQ) is shifted one place to the right and C(E) is
1857 // increased by 1.
1858 // If overflow does not occur, C(EAQ) is normalized.
1859 // All of this is done by fno, we just need to save the overflow flag
1860
1861 bool savedovf = TST_I_OFLOW;
1862 SC_I_OFLOW(ovf);
1863 convert_to_word36 (m, & A, & Q);
1864 fno (& E, & A, & Q);
1865 SC_I_OFLOW(savedovf);
1866
1867 * Y = setbits36_8 (A >> 8, 0, (word8) E);
1868 }
1869
1870 /*!
1871 * single precision Floating Compare ...
1872 */
fcmp(void)1873 void fcmp(void)
1874 {
1875 // C(E) :: C(Y)0,7
1876 // C(AQ)0,27 :: C(Y)8,35
1877
1878 // Zero: If C(EAQ) = C(Y), then ON; otherwise OFF
1879 // Neg: If C(EAQ) < C(Y), then ON; otherwise OFF
1880
1881 // Notes: The fcmp instruction is executed as follows:
1882 // The mantissas are aligned by shifting the mantissa of the operand with
1883 // the algebraically smaller exponent to the right the number of places
1884 // equal to the difference in the two exponents.
1885 // The aligned mantissas are compared and the indicators set accordingly.
1886
1887 CPTUR (cptUseE);
1888 #ifdef NEED_128
1889 word72 m1= lshift_128 (construct_128 (0, cpu.rA & 0777777777400), 36);
1890 #else
1891 word72 m1 = ((word72)cpu.rA & 0777777777400LL) << 36;
1892 #endif
1893 int e1 = SIGNEXT8_int (cpu.rE & MASK8);
1894
1895 // 28-bit mantissa (incl sign)
1896 #ifdef NEED_128
1897 word72 m2 = lshift_128 (construct_128 (0, getbits36_28 (cpu.CY, 8)), 44);
1898 #else
1899 word72 m2 = ((word72) getbits36_28 (cpu.CY, 8)) << 44;
1900 #endif
1901 int e2 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
1902
1903 //which exponent is smaller???
1904
1905 #ifdef L68
1906 cpu.ou.cycle = ou_GOE;
1907 #endif
1908 #ifdef HEX_MODE
1909 uint shift_amt = isHex() ? 4 : 1;
1910 #endif
1911 int shift_count = -1;
1912 word1 notallzeros = 0;
1913
1914 if (e1 == e2)
1915 {
1916 shift_count = 0;
1917 }
1918 else if (e1 < e2)
1919 {
1920 #ifdef L68
1921 cpu.ou.cycle = ou_GOA;
1922 #endif
1923 #ifdef HEX_MODE
1924 shift_count = abs(e2 - e1) * (int) shift_amt;
1925 #else
1926 shift_count = abs(e2 - e1);
1927 #endif
1928 // mantissa negative?
1929 #ifdef NEED_128
1930 bool s = isnonzero_128 (and_128 (m1, SIGN72));
1931 #else
1932 bool s = (m1 & SIGN72) != (word72)0;
1933 #endif
1934 for(int n = 0; n < shift_count; n += 1)
1935 {
1936 #ifdef NEED_128
1937 notallzeros |= m1.l & 1;
1938 m1 = rshift_128 (m1, 1);
1939 #else
1940 notallzeros |= m1 & 1;
1941 m1 >>= 1;
1942 #endif
1943 if (s)
1944 #ifdef NEED_128
1945 m1 = or_128 (m1, SIGN72);
1946 #else
1947 m1 |= SIGN72;
1948 #endif
1949 }
1950 #ifdef NEED_128
1951 # ifdef HEX_MODE
1952 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
1953 m1 = construct_128 (0, 0);
1954 # else
1955 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count > 71)
1956 m1 = construct_128 (0, 0);
1957 # endif
1958 m1 = and_128 (m1, MASK72);
1959 #else // NEED_128
1960 # ifdef HEX_MODE
1961 if (m1 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
1962 m1 = 0;
1963 # else
1964 if (m1 == MASK72 && notallzeros == 1 && shift_count > 71)
1965 m1 = 0;
1966 # endif
1967 m1 &= MASK72;
1968 #endif // NEED_128
1969 }
1970 else
1971 {
1972 // e2 < e1;
1973 #ifdef L68
1974 cpu.ou.cycle = ou_GOA;
1975 #endif
1976 #ifdef HEX_MODE
1977 shift_count = abs(e1 - e2) * (int) shift_amt;
1978 #else
1979 shift_count = abs(e1 - e2);
1980 #endif
1981 // mantissa negative?
1982 #ifdef NEED_128
1983 bool s = isnonzero_128 (and_128 (m2, SIGN72));
1984 #else
1985 bool s = (m2 & SIGN72) != (word72)0;
1986 #endif
1987 for(int n = 0 ; n < shift_count ; n += 1)
1988 {
1989 #ifdef NEED_128
1990 notallzeros |= m2.l & 1;
1991 m2 = rshift_128 (m2, 1);
1992 #else
1993 notallzeros |= m2 & 1;
1994 m2 >>= 1;
1995 #endif
1996 if (s)
1997 #ifdef NEED_128
1998 m2 = or_128 (m2, SIGN72);
1999 #else
2000 m2 |= SIGN72;
2001 #endif
2002 }
2003 #ifdef NEED_128
2004 # ifdef HEX_MODE
2005 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2006 m2 = construct_128 (0, 0);
2007 # else
2008 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count > 71)
2009 m2 = construct_128 (0, 0);
2010 # endif
2011 m2 = and_128 (m2, MASK72);
2012 //e3 = e1;
2013 #else
2014 # ifdef HEX_MODE
2015 if (m2 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2016 m2 = 0;
2017 # else
2018 if (m2 == MASK72 && notallzeros == 1 && shift_count > 71)
2019 m2 = 0;
2020 # endif
2021 m2 &= MASK72;
2022 //e3 = e1;
2023 #endif
2024 }
2025
2026 // need to do algebraic comparisons of mantissae
2027 #ifdef NEED_128
2028 SC_I_ZERO (iseq_128 (m1, m2));
2029 SC_I_NEG (islt_s128 (SIGNEXT72_128(m1), SIGNEXT72_128(m2)));
2030 #else
2031 SC_I_ZERO (m1 == m2);
2032 SC_I_NEG ((int128)SIGNEXT72_128(m1) < (int128)SIGNEXT72_128(m2));
2033 #endif
2034 }
2035
2036 /*!
2037 * single precision Floating Compare magnitude ...
2038 */
fcmg()2039 void fcmg ()
2040 {
2041 // C(E) :: C(Y)0,7
2042 // | C(AQ)0,27 | :: | C(Y)8,35 |
2043 // * Zero: If | C(EAQ)| = | C(Y) |, then ON; otherwise OFF
2044 // * Neg : If | C(EAQ)| < | C(Y) |, then ON; otherwise OFF
2045
2046 // Notes: The fcmp instruction is executed as follows:
2047 // The mantissas are aligned by shifting the mantissa of the operand with
2048 // the algebraically smaller exponent to the right the number of places
2049 // equal to the difference in the two exponents.
2050 // The aligned mantissas are compared and the indicators set accordingly.
2051
2052 // The fcmg instruction is identical to the fcmp instruction except that the
2053 // magnitudes of the mantissas are compared instead of the algebraic values.
2054
2055 // ISOLTS-736 01u asserts that |0.0*2^64|<|1.0| in 28bit precision
2056 // this implies that all shifts are 72 bits long
2057 // RJ78 also comments: If the number of shifts equals or exceeds 72, the
2058 // number with the lower exponent is defined as zero.
2059
2060 CPTUR (cptUseE);
2061 #ifdef L68
2062 cpu.ou.cycle = ou_GOS;
2063 #endif
2064 #ifdef HEX_MODE
2065 uint shift_amt = isHex() ? 4 : 1;
2066 #endif
2067 #if 1
2068 // C(AQ)0,27
2069 # ifdef NEED_128
2070 word72 m1= lshift_128 (construct_128 (0, cpu.rA & 0777777777400), 36);
2071 # else
2072 word72 m1 = ((word72)cpu.rA & 0777777777400LL) << 36;
2073 # endif
2074 int e1 = SIGNEXT8_int (cpu.rE & MASK8);
2075
2076 // C(Y)0,7
2077 // 28-bit mantissa (incl sign)
2078 # ifdef NEED_128
2079 word72 m2 = lshift_128 (construct_128 (0, getbits36_28 (cpu.CY, 8)), 44);
2080 # else
2081 word72 m2 = ((word72) getbits36_28 (cpu.CY, 8)) << 44;
2082 # endif
2083 int e2 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
2084
2085 //int e3 = -1;
2086
2087 //which exponent is smaller???
2088
2089 # ifdef L68
2090 cpu.ou.cycle = ou_GOE;
2091 # endif
2092 int shift_count = -1;
2093 word1 notallzeros = 0;
2094
2095 if (e1 == e2)
2096 {
2097 shift_count = 0;
2098 }
2099 else if (e1 < e2)
2100 {
2101 # ifdef L68
2102 cpu.ou.cycle = ou_GOA;
2103 # endif
2104 # ifdef HEX_MODE
2105 shift_count = abs(e2 - e1) * (int) shift_amt;
2106 # else
2107 shift_count = abs(e2 - e1);
2108 # endif
2109 # ifdef NEED_128
2110 bool s = isnonzero_128 (and_128 (m1, SIGN72));
2111 # else
2112 bool s = (m1 & SIGN72) != (word72)0; ///< save sign bit
2113 # endif
2114 for(int n = 0 ; n < shift_count ; n += 1)
2115 {
2116 # ifdef NEED_128
2117 notallzeros |= m1.l & 1;
2118 m1 = rshift_128 (m1, 1);
2119 # else
2120 notallzeros |= m1 & 1;
2121 m1 >>= 1;
2122 # endif
2123 if (s)
2124 # ifdef NEED_128
2125 m1 = or_128 (m1, SIGN72);
2126 # else
2127 m1 |= SIGN72;
2128 # endif
2129 }
2130
2131 # ifdef NEED_128
2132 # ifdef HEX_MODE
2133 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2134 m1 = construct_128 (0, 0);
2135 # else
2136 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count > 71)
2137 m1 = construct_128 (0, 0);
2138 # endif
2139 m1 = and_128 (m1, MASK72);
2140 # else
2141 # ifdef HEX_MODE
2142 if (m1 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2143 m1 = 0;
2144 # else
2145 if (m1 == MASK72 && notallzeros == 1 && shift_count > 71)
2146 m1 = 0;
2147 # endif
2148 m1 &= MASK72;
2149 # endif
2150 //e3 = e2;
2151 }
2152 else
2153 {
2154 // e2 < e1;
2155 # ifdef L68
2156 cpu.ou.cycle = ou_GOA;
2157 # endif
2158 # ifdef HEX_MODE
2159 shift_count = abs(e1 - e2) * (int) shift_amt;
2160 # else
2161 shift_count = abs(e1 - e2);
2162 # endif
2163 # ifdef NEED_128
2164 bool s = isnonzero_128 (and_128 (m2, SIGN72));
2165 # else
2166 bool s = (m2 & SIGN72) != (word72)0; ///< save sign bit
2167 # endif
2168 for(int n = 0 ; n < shift_count ; n += 1)
2169 {
2170 # ifdef NEED_128
2171 notallzeros |= m2.l & 1;
2172 m2 = rshift_128 (m2, 1);
2173 # else
2174 notallzeros |= m2 & 1;
2175 m2 >>= 1;
2176 # endif
2177 if (s)
2178 # ifdef NEED_128
2179 m2 = or_128 (m2, SIGN72);
2180 # else
2181 m2 |= SIGN72;
2182 # endif
2183 }
2184 # ifdef NEED_128
2185 # ifdef HEX_MODE
2186 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2187 m2 = construct_128 (0, 0);
2188 # else
2189 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count > 71)
2190 m2 = construct_128 (0, 0);
2191 # endif
2192 m2 = and_128 (m2, MASK72);
2193 # else
2194 # ifdef HEX_MODE
2195 if (m2 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2196 m2 = 0;
2197 # else
2198 if (m2 == MASK72 && notallzeros == 1 && shift_count > 71)
2199 m2 = 0;
2200 # endif
2201 m2 &= MASK72;
2202 # endif
2203 //e3 = e1;
2204 }
2205
2206 # ifdef NEED_128
2207 SC_I_ZERO (iseq_128 (m1, m2));
2208 # else
2209 SC_I_ZERO (m1 == m2);
2210 # endif
2211 # ifdef NEED_128
2212 int128 sm1 = SIGNEXT72_128 (m1);
2213 if (islt_s128 (sm1, construct_s128 (0, 0)))
2214 sm1 = negate_s128 (sm1);
2215 int128 sm2 = SIGNEXT72_128 (m2);
2216 if (islt_s128 (sm2, construct_s128 (0, 0)))
2217 sm2 = negate_s128 (sm2);
2218 SC_I_NEG (islt_s128 (sm1, sm2));
2219 # else
2220 int128 sm1 = SIGNEXT72_128 (m1);
2221 if (sm1 < 0)
2222 sm1 = - sm1;
2223 int128 sm2 = SIGNEXT72_128 (m2);
2224 if (sm2 < 0)
2225 sm2 = - sm2;
2226 SC_I_NEG (sm1 < sm2);
2227 # endif
2228 #else
2229 int e1 = SIGNEXT8_int (cpu . rE & MASK8);
2230 int e2 = SIGNEXT8_int (getbits36_8 (cpu.CY, 0));
2231 word36 m1 = cpu . rA & 0777777777400LL;
2232 word36 m2 = ((word36) getbits36_28 (cpu.CY, 8)) << 8; ///< 28-bit mantissa (incl sign)
2233 if (m1 & SIGN36)
2234 m1 = ((~m1) + 1) & MASK36;
2235 if (m2 & SIGN36)
2236 m2 = ((~m2) + 1) & MASK36;
2237 bool m1waszero = m1 == 0;
2238 bool m2waszero = m2 == 0;
2239
2240 if (e1 < e2)
2241 {
2242 int shift_count = abs(e2 - e1);
2243 bool s = m1 & SIGN36; // mantissa negative?
2244 for(int n = 0 ; n < shift_count ; n += 1)
2245 {
2246 m1 >>= 1;
2247 if (s)
2248 m1 |= SIGN36;
2249 }
2250
2251 m1 &= MASK36;
2252 e1 = e2;
2253 }
2254 else if (e2 < e1)
2255 {
2256 int shift_count = abs(e1 - e2);
2257 bool s = m2 & SIGN36; // mantissa negative?
2258 for(int n = 0 ; n < shift_count ; n += 1)
2259 {
2260 m2 >>= 1;
2261 if (s)
2262 m2 |= SIGN36;
2263 }
2264 m2 &= MASK36;
2265 e2 = e1;
2266 }
2267
2268 if (m1 < m2)
2269 {
2270 SET_I_NEG;
2271 CLR_I_ZERO;
2272 return;
2273 }
2274 else if (m1 > m2)
2275 {
2276 CLR_I_NEG;
2277 CLR_I_ZERO;
2278 return;
2279 }
2280 // ISOLTS ps736 test-01u
2281 if (m1 == 0 && ! m2waszero)
2282 SET_I_NEG;
2283 else
2284 CLR_I_NEG;
2285 SET_I_ZERO;
2286 #endif
2287 }
2288
2289 /*
2290 * double-precision arithmetic routines ....
2291 */
2292
2293 #if 0
2294 //! extract mantissa + exponent from a YPair ....
2295 static void YPairToExpMant(word36 Ypair[], word72 *mant, int *exp)
2296 {
2297 //*mant = (word72)bitfieldExtract36(Ypair[0], 0, 28) << 44; // 28-bit mantissa (incl sign)
2298 *mant = ((word72) getbits36_28 (Ypair[0], 8)) << 44; // 28-bit mantissa (incl sign)
2299 *mant |= (((word72) Ypair[1]) & DMASK) << 8;
2300 //*exp = SIGNEXT8_int (bitfieldExtract36(Ypair[0], 28, 8) & 0377U); // 8-bit signed integer (incl sign)
2301 *exp = SIGNEXT8_int (getbits36_8 (Ypair[0], 0) & 0377U); // 8-bit signed integer (incl sign)
2302 }
2303
2304 //! combine mantissa + exponent intoa YPair ....
2305 static void ExpMantToYpair(word72 mant, int exp, word36 *yPair)
2306 {
2307 yPair[0] = ((word36)exp & 0377) << 28;
2308 yPair[0] |= (mant >> 44) & 01777777777LL;
2309 yPair[1] = (mant >> 8) & 0777777777777LL; //400LL;
2310 }
2311 #endif
2312
2313
2314 /*!
2315 * unnormalized floating double-precision add
2316 */
dufa(bool subtract)2317 void dufa (bool subtract)
2318 {
2319 // Except for the precision of the mantissa of the operand from main
2320 // memory, the dufa instruction is identical to the ufa instruction.
2321
2322 // C(EAQ) + C(Y) → C(EAQ)
2323 // The ufa instruction is executed as follows:
2324 // The mantissas are aligned by shifting the mantissa of the operand having
2325 // the algebraically smaller exponent to the right the number of places
2326 // equal to the absolute value of the difference in the two exponents. Bits
2327 // shifted beyond the bit position equivalent to AQ71 are lost.
2328 // The algebraically larger exponent replaces C(E). The sum of the
2329 // mantissas replaces C(AQ).
2330 // If an overflow occurs during addition, then;
2331 // * C(AQ) are shifted one place to the right.
2332 // * C(AQ)0 is inverted to restore the sign.
2333 // * C(E) is increased by one.
2334
2335 // The dufs instruction is identical to the dufa instruction with the
2336 // exception that the twos complement of the mantissa of the operand from
2337 // main memory (op2) is used.
2338
2339 CPTUR (cptUseE);
2340 #ifdef L68
2341 cpu.ou.cycle |= ou_GOS;
2342 #endif
2343 #ifdef HEX_MODE
2344 uint shift_amt = isHex() ? 4 : 1;
2345 #endif
2346
2347 word72 m1 = convert_to_word72 (cpu.rA, cpu.rQ);
2348 int e1 = SIGNEXT8_int (cpu . rE & MASK8);
2349
2350 // 64-bit mantissa (incl sign)
2351 #ifdef NEED_128
2352 word72 m2 = lshift_128 (construct_128 (0, (uint64_t) getbits36_28 (cpu.Ypair[0], 8)), 44u); // 28-bit mantissa (incl sign)
2353 //m2 = or_128 (m2, construct_128 (0, cpu.Ypair[1] << 8));
2354 m2 = or_128 (m2, lshift_128 (construct_128 (0, cpu.Ypair[1]), 8u));
2355 #else
2356 word72 m2 = ((word72) getbits36_28 (cpu.Ypair[0], 8)) << 44;
2357 m2 |= (word72) cpu.Ypair[1] << 8;
2358 #endif
2359
2360 int e2 = SIGNEXT8_int (getbits36_8 (cpu.Ypair[0], 0));
2361
2362 // see ufs
2363 int m2zero = 0;
2364 if (subtract) {
2365
2366 #ifdef NEED_128
2367 if (iszero_128 (m2))
2368 m2zero = 1;
2369 if (iseq_128 (m2, SIGN72)) {
2370 # ifdef HEX_MODE
2371 m2 = rshift_128 (m2, shift_amt);
2372 e2 += 1;
2373 # else
2374 m2 = rshift_128 (m2, 1);
2375 e2 += 1;
2376 # endif
2377 } else
2378 m2 = and_128 (negate_128 (m2), MASK72);
2379 #else
2380 if (m2 == 0)
2381 m2zero = 1;
2382 if (m2 == SIGN72) {
2383 # ifdef HEX_MODE
2384 m2 >>= shift_amt;
2385 e2 += 1;
2386 # else
2387 m2 >>= 1;
2388 e2 += 1;
2389 # endif
2390 } else
2391 m2 = (-m2) & MASK72;
2392 #endif
2393 }
2394
2395 int e3 = -1;
2396
2397 // which exponent is smaller?
2398
2399 #ifdef L68
2400 cpu.ou.cycle |= ou_GOE;
2401 #endif
2402 int shift_count = -1;
2403 word1 notallzeros = 0;
2404
2405 if (e1 == e2)
2406 {
2407 shift_count = 0;
2408 e3 = e1;
2409 }
2410 else if (e1 < e2)
2411 {
2412 #ifdef L68
2413 cpu.ou.cycle |= ou_GOA;
2414 #endif
2415 #ifdef HEX_MODE
2416 shift_count = abs(e2 - e1) * (int) shift_amt;
2417 #else
2418 shift_count = abs(e2 - e1);
2419 #endif
2420 // mantissa negative?
2421 #ifdef NEED_128
2422 bool s = isnonzero_128 (and_128 (m1, SIGN72));
2423 #else
2424 bool s = (m1 & SIGN72) != (word72)0;
2425 #endif
2426 for(int n = 0 ; n < shift_count ; n += 1)
2427 {
2428 #ifdef NEED_128
2429 notallzeros |= m1.l & 1;
2430 m1 = rshift_128 (m1, 1);
2431 #else
2432 notallzeros |= m1 & 1;
2433 m1 >>= 1;
2434 #endif
2435 if (s)
2436 #ifdef NEED_128
2437 m1 = or_128 (m1, SIGN72);
2438 #else
2439 m1 |= SIGN72;
2440 #endif
2441 }
2442 #ifdef NEED_128
2443 # ifdef HEX_MODE
2444 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2445 m1 = construct_128 (0, 0);
2446 # else
2447 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count > 71)
2448 m1 = construct_128 (0, 0);
2449 # endif
2450 m1 = and_128 (m1, MASK72);
2451 #else
2452 # ifdef HEX_MODE
2453 if (m1 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2454 m1 = 0;
2455 # else
2456 if (m1 == MASK72 && notallzeros == 1 && shift_count > 71)
2457 m1 = 0;
2458 # endif
2459 m1 &= MASK72;
2460 #endif
2461 e3 = e2;
2462 }
2463 else
2464 {
2465 // e2 < e1;
2466 #ifdef L68
2467 cpu.ou.cycle |= ou_GOA;
2468 #endif
2469 #ifdef HEX_MODE
2470 shift_count = abs(e1 - e2) * (int) shift_amt;
2471 #else
2472 shift_count = abs(e1 - e2);
2473 #endif
2474 #ifdef NEED_128
2475 bool s = isnonzero_128 (and_128 (m2, SIGN72));
2476 #else
2477 bool s = (m2 & SIGN72) != (word72)0; ///< save sign bit
2478 #endif
2479 for(int n = 0 ; n < shift_count ; n += 1)
2480 {
2481 #ifdef NEED_128
2482 notallzeros |= m2.l & 1;
2483 m2 = rshift_128 (m2, 1);
2484 #else
2485 notallzeros |= m2 & 1;
2486 m2 >>= 1;
2487 #endif
2488 if (s)
2489 #ifdef NEED_128
2490 m2 = or_128 (m2, SIGN72);
2491 #else
2492 m2 |= SIGN72;
2493 #endif
2494 }
2495 #ifdef NEED_128
2496 # ifdef HEX_MODE
2497 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2498 m2 = construct_128 (0, 0);
2499 # else
2500 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count > 71)
2501 m2 = construct_128 (0, 0);
2502 # endif
2503 m2 = and_128 (m2, MASK72);
2504 #else
2505 # ifdef HEX_MODE
2506 if (m2 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
2507 m2 = 0;
2508 # else
2509 if (m2 == MASK72 && notallzeros == 1 && shift_count > 71)
2510 m2 = 0;
2511 # endif
2512 m2 &= MASK72;
2513 #endif
2514 e3 = e1;
2515 }
2516 //sim_printf ("shift_count = %d\n", shift_count);
2517
2518 bool ovf;
2519 word72 m3 = Add72b (m1, m2, 0, I_CARRY, & cpu.cu.IR, & ovf);
2520 if (m2zero)
2521 SET_I_CARRY;
2522
2523 if (ovf)
2524 {
2525 #ifdef HEX_MODE
2526 // word72 signbit = m3 & sign_msk;
2527 // m3 >>= shift_amt;
2528 // m3 = (m3 & MASK71) | signbit;
2529 // m3 ^= SIGN72; // C(AQ)0 is inverted to restore the sign
2530 // e3 += 1;
2531 // save the sign bit
2532 # ifdef NEED_128
2533 bool s = isnonzero_128 (and_128 (m3, SIGN72));
2534 # else
2535 bool s = (m3 & SIGN72) != (word72)0;
2536 # endif
2537 if (isHex ())
2538 {
2539 # ifdef NEED_128
2540 m3 = rshift_128 (m3, shift_amt); // renormalize the mantissa
2541 if (s)
2542 // Sign is set, number should be positive; clear the sign bit and the 3 MSBs
2543 m3 = and_128 (m3, MASK68);
2544 else
2545 // Sign is clr, number should be negative; set the sign bit and the 3 MSBs
2546 m3 = or_128 (m3, HEX_SIGN);
2547 # else
2548 m3 >>= shift_amt; // renormalize the mantissa
2549 if (s)
2550 // Sign is set, number should be positive; clear the sign bit and the 3 MSBs
2551 m3 &= MASK68;
2552 else
2553 // Sign is clr, number should be negative; set the sign bit and the 3 MSBs
2554 m3 |= HEX_SIGN;
2555 # endif
2556 }
2557 else
2558 {
2559 # ifdef NEED_128
2560 word72 signbit = and_128 (m3, SIGN72);
2561 m3 = rshift_128 (m3, 1); // renormalize the mantissa
2562 m3 = or_128 (and_128 (m3, MASK71), signbit);
2563 m3 = xor_128 (m3, SIGN72); // C(AQ)0 is inverted to restore the sign
2564 # else
2565 word72 signbit = m3 & SIGN72;
2566 m3 >>= 1;
2567 m3 = (m3 & MASK71) | signbit;
2568 m3 ^= SIGN72; // C(AQ)0 is inverted to restore the sign
2569 # endif
2570 }
2571 e3 += 1;
2572 #else
2573 # ifdef NEED_128
2574 word72 signbit = and_128 (m3, SIGN72);
2575 m3 = rshift_128 (m3, 1); // renormalize the mantissa
2576 m3 = or_128 (and_128 (m3, MASK71), signbit);
2577 m3 = xor_128 (m3, SIGN72); // C(AQ)0 is inverted to restore the sign
2578 # else
2579 word72 signbit = m3 & SIGN72;
2580 m3 >>= 1;
2581 m3 = (m3 & MASK71) | signbit;
2582 m3 ^= SIGN72; // C(AQ)0 is inverted to restore the sign
2583 # endif
2584 e3 += 1;
2585 #endif
2586 }
2587
2588 convert_to_word36 (m3, & cpu.rA, & cpu.rQ);
2589 #ifdef TESTING
2590 HDBGRegAW ("dufa");
2591 #endif
2592 cpu.rE = e3 & 0377;
2593
2594 SC_I_NEG (cpu.rA & SIGN36); // Do this here instead of in Add72b because
2595 // of ovf handling above
2596 if (cpu.rA == 0 && cpu.rQ == 0)
2597 {
2598 SET_I_ZERO;
2599 cpu . rE = 0200U; /*-128*/
2600 }
2601 else
2602 {
2603 CLR_I_ZERO;
2604 }
2605
2606 // EOFL: If exponent is greater than +127, then ON
2607 if (e3 > 127)
2608 {
2609 SET_I_EOFL;
2610 if (tstOVFfault ())
2611 dlyDoFault (FAULT_OFL, fst_zero, "dufa exp overflow fault");
2612 }
2613
2614 // EUFL: If exponent is less than -128, then ON
2615 if (e3 < -128)
2616 {
2617 SET_I_EUFL;
2618 if (tstOVFfault ())
2619 dlyDoFault (FAULT_OFL, fst_zero, "dufa exp underflow fault");
2620 }
2621 }
2622
2623 #if 0
2624 /*!
2625 * unnormalized floating double-precision subtract
2626 */
2627 void dufs (void)
2628 {
2629 // Except for the precision of the mantissa of the operand from main memory,
2630 // the dufs instruction is identical with the ufs instruction.
2631
2632 // The ufs instruction is identical to the ufa instruction with the
2633 // exception that the twos complement of the mantissa of the operand from
2634 // main memory (op2) is used.
2635
2636 // They're probably a few gotcha's here but we'll see.
2637 // Yup ... when mantissa 1 000 000 .... 000 we can't do 2'c comp.
2638
2639 float72 m2 = 0;
2640 int e2 = -128;
2641
2642 YPairToExpMant(cpu.Ypair, &m2, &e2);
2643
2644 word72 m2c = ~m2 + 1; ///< & 01777777777LL; ///< take 2-comp of mantissa
2645 m2c &= MASK72;
2646
2647 /*!
2648 * When signs are the *same* after complement we have an overflow
2649 * (Treat as in addition when we get an overflow)
2650 */
2651 bool ov = ((m2 & SIGN72) == (m2c & SIGN72)); ///< the "weird" number.
2652
2653 if (ov && m2 != 0)
2654 {
2655 m2c >>= 1;
2656 m2c &= MASK72;
2657
2658 if (e2 == 127)
2659 {
2660 SET_I_EOFL;
2661 if (tstOVFfault ())
2662 doFault (FAULT_OFL, fst_zero, "dufs exp overflow fault");
2663 }
2664 e2 += 1;
2665 }
2666
2667 if (m2c == 0)
2668 {
2669 // cpu.Ypair[0] = 0400000000000LL;
2670 // cpu.Ypair[1] = 0;
2671 ExpMantToYpair(0, -128, cpu.Ypair);
2672 }
2673 else
2674 {
2675 // cpu.Ypair[0] = ((word36)e2 & 0377) << 28;
2676 // cpu.Ypair[0] |= (m2c >> 44) & 01777777777LL;
2677 // cpu.Ypair[1] = (m2c >> 8) & 0777777777400LL;
2678 ExpMantToYpair(m2c, e2, cpu.Ypair);
2679 }
2680
2681 dufa ();
2682
2683 }
2684 #endif
2685
2686 /*!
2687 * double-precision Unnormalized Floating Multiply ...
2688 */
dufm(void)2689 void dufm (void)
2690 {
2691 // Except for the precision of the mantissa of the operand from main memory,
2692 //the dufm instruction is identical to the ufm instruction.
2693
2694 // The ufm instruction is executed as follows:
2695 // C(E) + C(Y)0,7 → C(E)
2696 // ( C(AQ) × C(Y)8,35 )0,71 → C(AQ)
2697
2698 // * Zero: If C(AQ) = 0, then ON; otherwise OFF
2699 // * Neg: If C(AQ)0 = 1, then ON; otherwise OFF
2700 // * Exp Ovr: If exponent is greater than +127, then ON
2701 // * Exp Undr: If exponent is less than -128, then ON
2702
2703 CPTUR (cptUseE);
2704 #ifdef L68
2705 cpu.ou.cycle |= ou_GOS;
2706 #endif
2707 word72 m1 = convert_to_word72 (cpu.rA, cpu.rQ);
2708 int e1 = SIGNEXT8_int (cpu . rE & MASK8);
2709
2710 #ifndef NEED_128
2711 sim_debug (DBG_TRACEEXT, & cpu_dev, "dufm e1 %d %03o m1 %012"PRIo64" %012"PRIo64"\n", e1, e1, (word36) (m1 >> 36) & MASK36, (word36) m1 & MASK36);
2712 #endif
2713 // 64-bit mantissa (incl sign)
2714 #ifdef NEED_128
2715 word72 m2 = lshift_128 (construct_128 (0, (uint64_t) getbits36_28 (cpu.Ypair[0], 8)), 44u); // 28-bit mantissa (incl sign)
2716 //m2 = or_128 (m2, construct_128 (0, cpu.Ypair[1] << 8));
2717 m2 = or_128 (m2, lshift_128 (construct_128 (0, cpu.Ypair[1]), 8u));
2718 #else
2719 word72 m2 = ((word72) getbits36_28 (cpu.Ypair[0], 8)) << 44;
2720 m2 |= (word72) cpu.Ypair[1] << 8;
2721 #endif
2722
2723 // 8-bit signed integer (incl sign)
2724 int e2 = SIGNEXT8_int (getbits36_8 (cpu.Ypair[0], 0));
2725
2726 #ifndef NEED_128
2727 sim_debug (DBG_TRACEEXT, & cpu_dev,
2728 "dufm e2 %d %03o m2 %012"PRIo64" %012"PRIo64"\n", e2, e2, (word36) (m2 >> 36) & MASK36, (word36) m2 & MASK36);
2729 #endif
2730
2731
2732 #ifdef NEED_128
2733 if (iszero_128 (m1) || iszero_128 (m2))
2734 #else
2735 if (m1 == 0 || m2 == 0)
2736 #endif
2737 {
2738 SET_I_ZERO;
2739 CLR_I_NEG;
2740
2741 cpu . rE = 0200U; /*-128*/
2742 cpu . rA = 0;
2743 #ifdef TESTING
2744 HDBGRegAW ("dufm");
2745 #endif
2746 cpu . rQ = 0;
2747
2748 return; // normalized 0
2749 }
2750
2751 int e3 = e1 + e2;
2752
2753 if (e3 > 127)
2754 {
2755 SET_I_EOFL;
2756 if (tstOVFfault ())
2757 dlyDoFault (FAULT_OFL, fst_zero, "dufm exp overflow fault");
2758 }
2759 if (e3 < -128)
2760 {
2761 SET_I_EUFL;
2762 if (tstOVFfault ())
2763 dlyDoFault (FAULT_OFL, fst_zero, "dufm exp underflow fault");
2764 }
2765
2766 // RJ78: This multiplication is executed in the following way:
2767 // C(E) + C(Y)(0-7) -> C(E)
2768 // C(AQ) * C(Y-pair)(8-71) results in a 134-bit product plus sign. This sign plus the
2769 // leading 71 bits are loaded into the AQ.
2770
2771 // do a 128x64 signed multiplication
2772 #if 0
2773 // absolute value and unsigned multiplication
2774 // does not work
2775 uint128 m1a = m1;
2776 uint128 m2a = m2;
2777 int sign = 1;
2778
2779 if (m1 & SIGN72)
2780 {
2781 m1a = (-m1) & MASK72;
2782 sign = -sign;
2783 }
2784 if (m2 & SIGN72)
2785 {
2786 m2a = (-m2) & MASK72;
2787 sign = -sign;
2788 }
2789
2790 // shift the CY mantissa
2791 m2a >>= 8;
2792
2793 uint128 m3l = (m1a & (((uint128)1<<64)-1)) * m2a; // lo partial product
2794 uint128 m3h = (m1a >> 64) * m2a; // hi partial product
2795
2796 // realign to 72bits XXX this is wrong, arithmetic shift is required
2797 m3l >>= 63; // 134-71
2798 m3h <<= 1;
2799 word72 m3a = ((word72) (m3h+m3l)) & MASK72;
2800 if (sign < 0)
2801 m3a = (-m3a) & MASK72;
2802 #endif
2803
2804 #if 1
2805 // fast signed multiplication algorithm without 2's complements
2806 // passes ISOLTS-745 08
2807
2808 # ifdef NEED_128
2809 // shift the CY mantissa
2810 int128 m2s = rshift_s128 (SIGNEXT72_128(m2), 8);
2811
2812 // do a 128x64 signed multiplication
2813 int128 m1l = and_s128 (cast_s128 (m1), construct_128 (0, MASK64));
2814 int128 m1h = rshift_s128 (SIGNEXT72_128(m1), 64);
2815 int128 m3h = multiply_s128 (m1h, m2s); // hi partial product
2816 int128 m3l = multiply_s128 (m1l, m2s); // lo partial product
2817
2818 // realign to 72bits
2819 m3l = rshift_s128 (m3l, 63);
2820 m3h = lshift_s128 (m3h, 1); // m3h is hi by 64, align it for addition. The result is 135 bits so this cannot overflow.
2821 word72 m3a = and_128 (add_128 (cast_128 (m3h), cast_128 (m3l)), MASK72);
2822 # else
2823 // shift the CY mantissa
2824 int128 m2s = SIGNEXT72_128(m2) >> 8;
2825
2826 // do a 128x64 signed multiplication
2827 int128 m1l = m1 & (((uint128)1<<64)-1);
2828 int128 m1h = SIGNEXT72_128(m1) >> 64;
2829 int128 m3h = m1h * m2s; // hi partial product
2830 int128 m3l = m1l * m2s; // lo partial product
2831
2832 // realign to 72bits
2833 m3l >>= 63;
2834 m3h <<= 1; // m3h is hi by 64, align it for addition. The result is 135 bits so this cannot overflow.
2835 word72 m3a = ((word72) (m3h+m3l)) & MASK72;
2836 # endif
2837 #endif
2838
2839 // A normalization is performed only in the case of both factor mantissas being 100...0
2840 // which is the twos complement approximation to the decimal value -1.0.
2841 #ifdef NEED_128
2842 if (iseq_128 (m1, SIGN72) && iseq_128 (m2, SIGN72))
2843 #else
2844 if ((m1 == SIGN72) && (m2 == SIGN72))
2845 #endif
2846 {
2847 if (e3 == 127)
2848 {
2849 SET_I_EOFL;
2850 if (tstOVFfault ())
2851 dlyDoFault (FAULT_OFL, fst_zero, "dufm exp overflow fault");
2852 }
2853 #ifdef NEED_128
2854 m3a = rshift_128 (m3a, 1);
2855 #else
2856 m3a >>= 1;
2857 #endif
2858 e3 += 1;
2859 }
2860
2861 convert_to_word36 (m3a, & cpu.rA, & cpu.rQ);
2862 #ifdef TESTING
2863 HDBGRegAW ("dufm");
2864 #endif
2865 cpu . rE = (word8) e3 & MASK8;
2866
2867 SC_I_NEG (cpu.rA & SIGN36);
2868
2869 if (cpu.rA == 0 && cpu.rQ == 0)
2870 {
2871 SET_I_ZERO;
2872 cpu . rE = 0200U; /*-128*/
2873 }
2874 else
2875 {
2876 CLR_I_ZERO;
2877 }
2878 }
2879
2880 /*!
2881 * floating divide ...
2882 */
2883 // CANFAULT
dfdvX(bool bInvert)2884 static void dfdvX (bool bInvert)
2885 {
2886 // C(EAQ) / C (Y) → C(EA)
2887 // C(Y) / C(EAQ) → C(EA) (Inverted)
2888
2889 // 00...0 → C(Q)
2890
2891 // The dfdv instruction is executed as follows:
2892 // The dividend mantissa C(AQ) is shifted right and the dividend exponent
2893 // C(E) increased accordingly until
2894 // | C(AQ)0,63 | < | C(Y-pair)8,71 |
2895 // C(E) - C(Y-pair)0,7 → C(E)
2896 // C(AQ) / C(Y-pair)8,71 → C(AQ)0,63 00...0 → C(Q)64,71
2897
2898 CPTUR (cptUseE);
2899 #ifdef L68
2900 cpu.ou.cycle |= ou_GOS;
2901 #endif
2902 #ifdef HEX_MODE
2903 uint shift_amt = isHex() ? 4 : 1;
2904 #endif
2905 word72 m1;
2906 int e1;
2907
2908 word72 m2;
2909 int e2;
2910
2911 bool roundovf = 0;
2912
2913 if (!bInvert)
2914 {
2915 m1 = convert_to_word72 (cpu.rA, cpu.rQ);
2916 e1 = SIGNEXT8_int (cpu . rE & MASK8);
2917
2918 // 64-bit mantissa (incl sign)
2919 #ifdef NEED_128
2920 m2 = lshift_128 (construct_128 (0, (uint64_t) getbits36_28 (cpu.Ypair[0], 8)), 44u); // 28-bit mantissa (incl sign)
2921 //m2 = or_128 (m2, construct_128 (0, cpu.Ypair[1] << 8));
2922 m2 = or_128 (m2, lshift_128 (construct_128 (0, cpu.Ypair[1]), 8u));
2923 #else
2924 m2 = ((word72) getbits36_28 (cpu.Ypair[0], 8)) << 44;
2925 m2 |= (word72) cpu.Ypair[1] << 8;
2926 #endif
2927
2928 e2 = SIGNEXT8_int (getbits36_8 (cpu.Ypair[0], 0));
2929 }
2930 else
2931 { // invert
2932 m2 = convert_to_word72 (cpu.rA, cpu.rQ);
2933 e2 = SIGNEXT8_int (cpu . rE & MASK8);
2934
2935 // round divisor per RJ78
2936 // If AQ(64-71) is not = 0 and A(0) = 0, a 1 is added to AQ(63). Zero is moved to
2937 // AQ(64-71), unconditionally. AQ(0-63) is then used as the divisor mantissa.
2938 // ISOLTS-745 10b
2939 #ifdef NEED_128
2940 if ((iszero_128 (and_128 (m2, SIGN72))) && m2.l & 0377)
2941 #else
2942 if (!(m2 & SIGN72) && m2 & 0377)
2943 #endif
2944 {
2945 #ifdef NEED_128
2946 m2 = add_128 (m2, construct_128 (0, 0400));
2947 #else
2948 m2 += 0400;
2949 #endif
2950 // ISOLTS-745 10e asserts that an overflowing addition of 400 to 377777777777 7777777774xx does not shift the quotient (nor divisor)
2951 // I surmise that the divisor is taken as unsigned 64 bits in this case
2952 roundovf = 1;
2953 }
2954 #ifdef NEED_128
2955 putbits72 (& m2, 64, 8, construct_128 (0, 0));
2956 #else
2957 putbits72 (& m2, 64, 8, 0);
2958 #endif
2959
2960 // 64-bit mantissa (incl sign)
2961 #ifdef NEED_128
2962 m1 = lshift_128 (construct_128 (0, (uint64_t) getbits36_28 (cpu.Ypair[0], 8)), 44u); // 28-bit mantissa (incl sign)
2963 //m1 = or_128 (m1, construct_128 (0, cpu.Ypair[1] << 8));
2964 m1 = or_128 (m1, lshift_128 (construct_128 (0, cpu.Ypair[1]), 8u));
2965 #else
2966 m1 = ((word72) getbits36_28 (cpu.Ypair[0], 8)) << 44;
2967 m1 |= (word72) cpu.Ypair[1] << 8;
2968 #endif
2969
2970 e1 = SIGNEXT8_int (getbits36_8 (cpu.Ypair[0], 0));
2971 }
2972
2973 #ifdef NEED_128
2974 if (iszero_128 (m1))
2975 #else
2976 if (m1 == 0)
2977 #endif
2978 {
2979 SET_I_ZERO;
2980 CLR_I_NEG;
2981
2982 cpu.rE = 0200U; /*-128*/
2983 cpu.rA = 0;
2984 #ifdef TESTING
2985 HDBGRegAW ("dfdvX");
2986 #endif
2987 cpu.rQ = 0;
2988
2989 return; // normalized 0
2990 }
2991
2992 // make everything positive, but save sign info for later....
2993 int sign = 1;
2994 #ifdef NEED_128
2995 if (isnonzero_128 (and_128 (m1, SIGN72)))
2996 {
2997 SET_I_NEG; // in case of divide fault
2998 if (iseq_128 (m1, SIGN72))
2999 {
3000 # ifdef HEX_MODE
3001 m1 = rshift_128 (m1, shift_amt);
3002 # else
3003 m1 = rshift_128 (m1, 1);
3004 # endif
3005 e1 += 1;
3006 } else
3007 m1 = and_128 (negate_128 (m1), MASK72);
3008 sign = -sign;
3009 } else {
3010 CLR_I_NEG; // in case of divide fault
3011 }
3012
3013 if ((isnonzero_128 (and_128 (m2, SIGN72))) && !roundovf)
3014 {
3015 if (iseq_128 (m2, SIGN72))
3016 {
3017 # ifdef HEX_MODE
3018 m2 = rshift_128 (m2, shift_amt);
3019 # else
3020 m2 = rshift_128 (m2, 1);
3021 # endif
3022 e2 += 1;
3023 } else
3024 m2 = and_128 (negate_128 (m2), MASK72);
3025 sign = -sign;
3026 }
3027 #else
3028 if (m1 & SIGN72)
3029 {
3030 SET_I_NEG; // in case of divide fault
3031 if (m1 == SIGN72)
3032 {
3033 # ifdef HEX_MODE
3034 m1 >>= shift_amt;
3035 # else
3036 m1 >>= 1;
3037 # endif
3038 e1 += 1;
3039 } else
3040 m1 = (~m1 + 1) & MASK72;
3041 sign = -sign;
3042 } else {
3043 CLR_I_NEG; // in case of divide fault
3044 }
3045
3046 if ((m2 & SIGN72) && !roundovf)
3047 {
3048 if (m2 == SIGN72)
3049 {
3050 # ifdef HEX_MODE
3051 m2 >>= shift_amt;
3052 # else
3053 m2 >>= 1;
3054 # endif
3055 e2 += 1;
3056 } else
3057 m2 = (~m2 + 1) & MASK72;
3058 sign = -sign;
3059 }
3060 #endif
3061
3062 #ifdef NEED_128
3063 if (iszero_128 (m2))
3064 #else
3065 if (m2 == 0)
3066 #endif
3067 {
3068 // NB: If C(Y-pair)8,71 == 0 then the alignment loop will never exit! That's why it been moved before the alignment
3069
3070 SET_I_ZERO;
3071 // NEG already set
3072
3073 // FDV: If the divisor mantissa C(Y-pair)8,71 is zero after alignment (HWR: why after?), the division does
3074 // not take place. Instead, a divide check fault occurs, C(AQ) contains the dividend magnitude, and
3075 // the negative indicator reflects the dividend sign.
3076 // FDI: If the divisor mantissa C(AQ) is zero, the division does not take place.
3077 // Instead, a divide check fault occurs and all the registers remain unchanged.
3078 if (!bInvert) {
3079 convert_to_word36 (m1, & cpu.rA, & cpu.rQ);
3080 #ifdef TESTING
3081 HDBGRegAW ("dfdvX");
3082 #endif
3083 }
3084 doFault (FAULT_DIV, fst_zero, "DFDV: divide check fault");
3085 }
3086
3087 #ifdef L68
3088 cpu.ou.cycle |= ou_GOA;
3089 #endif
3090 #ifdef NEED_128
3091 while (isge_128 (m1, m2))
3092 {
3093 # ifdef HEX_MODE
3094 m1 = rshift_128 (m1, shift_amt);
3095 # else
3096 m1 = rshift_128 (m1, 1);
3097 # endif
3098 e1 += 1;
3099 }
3100 #else
3101 while (m1 >= m2)
3102 {
3103 # ifdef HEX_MODE
3104 m1 >>= shift_amt;
3105 # else
3106 m1 >>= 1;
3107 # endif
3108 e1 += 1;
3109 }
3110 #endif
3111 int e3 = e1 - e2;
3112 if (e3 > 127)
3113 {
3114 SET_I_EOFL;
3115 if (tstOVFfault ())
3116 dlyDoFault (FAULT_OFL, fst_zero, "dfdvX exp overflow fault");
3117 }
3118 if (e3 < -128)
3119 {
3120 SET_I_EUFL;
3121 if (tstOVFfault ())
3122 dlyDoFault (FAULT_OFL, fst_zero, "dfdvX exp underflow fault");
3123 }
3124
3125 #ifdef L68
3126 cpu.ou.cycle |= ou_GD1;
3127 #endif
3128
3129 // We need 63 bits quotient + sign. Divisor is at most 64 bits.
3130 // Do a 127 by 64 fractional divide
3131 // lo 8bits are always zero
3132 #ifdef NEED_128
3133 word72 m3 = divide_128 (lshift_128 (m1, 63-8), rshift_128 (m2, 8), NULL);
3134 #else
3135 word72 m3 = ((uint128)m1 << (63-8)) / ((uint128)m2 >> 8);
3136 #endif
3137 #ifdef L68
3138 cpu.ou.cycle |= ou_GD2;
3139 #endif
3140
3141 #ifdef NEED_128
3142 m3 = lshift_128 (m3, 8); // convert back to float
3143 if (sign == -1)
3144 m3 = and_128 (negate_128 (m3), MASK72);
3145 #else
3146 m3 <<= 8; // convert back to float
3147 if (sign == -1)
3148 m3 = (~m3 + 1) & MASK72;
3149 #endif
3150
3151 convert_to_word36 (m3, & cpu.rA, & cpu.rQ);
3152 #ifdef TESTING
3153 HDBGRegAW ("dfdvX");
3154 #endif
3155 cpu.rE = (word8) e3 & MASK8;
3156
3157 SC_I_ZERO (cpu.rA == 0 && cpu . rQ == 0);
3158 SC_I_NEG (cpu.rA & SIGN36);
3159
3160 if (cpu.rA == 0 && cpu.rQ == 0) // set to normalized 0
3161 cpu.rE = 0200U; /*-128*/
3162 }
3163
3164 // CANFAULT
dfdv(void)3165 void dfdv (void)
3166 {
3167 dfdvX (false); // no inversion
3168 }
3169
3170 // CANFAULT
dfdi(void)3171 void dfdi (void)
3172 {
3173 dfdvX (true);
3174 }
3175
3176
3177 //#define DVF_HWR
3178 //#define DVF_FRACTIONAL
3179 #define DVF_CAC
3180 // CANFAULT
dvf(void)3181 void dvf (void)
3182 {
3183 //#ifdef DBGCAC
3184 //sim_printf ("DVF %"PRId64" %06o:%06o\n", cpu.cycleCnt, PPR.PSR, PPR.IC);
3185 //#endif
3186 // C(AQ) / (Y)
3187 // fractional quotient → C(A)
3188 // fractional remainder → C(Q)
3189
3190 // A 71-bit fractional dividend (including sign) is divided by a 36-bit
3191 // fractional divisor yielding a 36-bit fractional quotient (including
3192 // sign) and a 36-bit fractional remainder (including sign). C(AQ)71 is
3193 // ignored; bit position 35 of the remainder corresponds to bit position
3194 // 70 of the dividend. The remainder sign is equal to the dividend sign
3195 // unless the remainder is zero.
3196 //
3197 // If | dividend | >= | divisor | or if the divisor = 0, division does
3198 // not take place. Instead, a divide check fault occurs, C(AQ) contains
3199 // the dividend magnitude in absolute, and the negative indicator
3200 // reflects the dividend sign.
3201
3202 // HWR code
3203 //HWR--#ifdef DVF_HWR
3204 //HWR-- // m1 divedend
3205 //HWR-- // m2 divisor
3206 //HWR--
3207 //HWR-- word72 m1 = SIGNEXT36_72((cpu . rA << 36) | (cpu . rQ & 0777777777776LLU));
3208 //HWR-- word72 m2 = SIGNEXT36_72(cpu.CY);
3209 //HWR--
3210 //HWR--//sim_debug (DBG_CAC, & cpu_dev, "[%"PRId64"]\n", cpu.cycleCnt);
3211 //HWR--//sim_debug (DBG_CAC, & cpu_dev, "m1 "); print_int128 (m1); sim_printf ("\n");
3212 //HWR--//sim_debug (DBG_CAC, & cpu_dev, "-----------------\n");
3213 //HWR--//sim_debug (DBG_CAC, & cpu_dev, "m2 "); print_int128 (m2); sim_printf ("\n");
3214 //HWR--
3215 //HWR-- if (m2 == 0)
3216 //HWR-- {
3217 //HWR-- // XXX check flags
3218 //HWR-- SET_I_ZERO;
3219 //HWR-- SC_I_NEG (cpu . rA & SIGN36);
3220 //HWR--
3221 //HWR-- cpu . rA = 0;
3222 //HWR-- cpu . rQ = 0;
3223 //HWR--
3224 //HWR-- return;
3225 //HWR-- }
3226 //HWR--
3227 //HWR-- // make everything positive, but save sign info for later....
3228 //HWR-- int sign = 1;
3229 //HWR-- int dividendSign = 1;
3230 //HWR-- if (m1 & SIGN72)
3231 //HWR-- {
3232 //HWR-- m1 = (~m1 + 1);
3233 //HWR-- sign = -sign;
3234 //HWR-- dividendSign = -1;
3235 //HWR-- }
3236 //HWR--
3237 //HWR-- if (m2 & SIGN72)
3238 //HWR-- {
3239 //HWR-- m2 = (~m2 + 1);
3240 //HWR-- sign = -sign;
3241 //HWR-- }
3242 //HWR--
3243 //HWR-- if (m1 >= m2 || m2 == 0)
3244 //HWR-- {
3245 //HWR-- //cpu . rA = m1;
3246 //HWR-- cpu . rA = (m1 >> 36) & MASK36;
3247 //HWR-- cpu . rQ = m1 & 0777777777776LLU;
3248 //HWR--
3249 //HWR-- SET_I_ZERO;
3250 //HWR-- SC_I_NEG (cpu . rA & SIGN36);
3251 //HWR--
3252 //HWR-- doFault(FAULT_DIV, fst_zero, "DVF: divide check fault");
3253 //HWR-- }
3254 //HWR--
3255 //HWR-- uint128 dividend = (uint128)m1 << 63;
3256 //HWR-- uint128 divisor = (uint128)m2;
3257 //HWR--
3258 //HWR-- //uint128 m3 = ((uint128)m1 << 63) / (uint128)m2;
3259 //HWR-- //uint128 m3r = ((uint128)m1 << 63) % (uint128)m2;
3260 //HWR-- int128 m3 = (int128)(dividend / divisor);
3261 //HWR-- int128 m3r = (int128)(dividend % divisor);
3262 //HWR--
3263 //HWR-- if (sign == -1)
3264 //HWR-- m3 = -m3; //(~m3 + 1);
3265 //HWR--
3266 //HWR-- if (dividendSign == -1) // The remainder sign is equal to the dividend sign unless the remainder is zero.
3267 //HWR-- m3r = -m3r; //(~m3r + 1);
3268 //HWR--
3269 //HWR-- cpu . rA = (m3 >> 64) & MASK36;
3270 //HWR-- cpu . rQ = m3r & MASK36; //01777777777LL;
3271 //HWR--#endif
3272
3273 // canonial code
3274 #ifdef DVF_FRACTIONAL
3275 // http://www.ece.ucsb.edu/~parhami/pres_folder/f31-book-arith-pres-pt4.pdf
3276 // slide 10: sequential algorithim
3277
3278 // dividend format
3279 // 0 1 70 71
3280 // s dividend x
3281 // C(AQ)
3282
3283 # ifdef L68
3284 cpu.ou.cycle |= ou_GD1;
3285 # endif
3286 int sign = 1;
3287 bool dividendNegative = (getbits36_1 (cpu . rA, 0) != 0);
3288 bool divisorNegative = (getbits36_1 (cpu.CY, 0) != 0);
3289
3290 // Get the 70 bits of the dividend (72 bits less the sign bit and the
3291 // ignored bit 71.
3292
3293 // dividend format: . d(0) ... d(69)
3294
3295 uint128 zFrac = ((uint128) (cpu . rA & MASK35) << 35) | ((cpu . rQ >> 1) & MASK35);
3296 if (dividendNegative)
3297 {
3298 zFrac = ~zFrac + 1;
3299 sign = - sign;
3300 }
3301 zFrac &= MASK70;
3302 //sim_printf ("zFrac "); print_int128 (zFrac); sim_printf ("\n");
3303
3304 // Get the 35 bits of the divisor (36 bits less the sign bit)
3305
3306 // divisor format: . d(0) .... d(34) 0 0 0 .... 0
3307
3308 # if 1
3309 // divisor goes in the high half
3310 uint128 dFrac = (cpu.CY & MASK35) << 35;
3311 if (divisorNegative)
3312 {
3313 dFrac = ~dFrac + 1;
3314 sign = - sign;
3315 }
3316 dFrac &= MASK35 << 35;
3317 # else
3318 // divisor goes in the low half
3319 uint128 dFrac = cpu.CY & MASK35;
3320 if (divisorNegative)
3321 {
3322 dFrac = ~dFrac + 1;
3323 sign = - sign;
3324 }
3325 dFrac &= MASK35;
3326 # endif
3327
3328 if (dFrac == 0)
3329 {
3330 sim_printf ("DVFa A %012"PRIo64" Q %012"PRIo64" Y %012"PRIo64"\n", cpu.rA, cpu.rQ, cpu.CY);
3331 // case 1: 400000000000 000000000000 000000000000 --> 400000000000 000000000000
3332 // dFrac 000000000000 000000000000
3333
3334 //cpu . rA = (zFrac >> 35) & MASK35;
3335 //cpu . rQ = (zFrac & MASK35) << 1;
3336
3337 //SC_I_ZERO (dFrac == 0);
3338 //SC_I_NEG (cpu . rA & SIGN36);
3339 SC_I_ZERO (cpu.CY == 0);
3340 SC_I_NEG (cpu.rA & SIGN36);
3341 doFault(FAULT_DIV, fst_zero, "DVF: divide check fault");
3342 }
3343
3344 # ifdef L68
3345 cpu.ou.cycle |= ou_GD2;
3346 # endif
3347 uint128 sn = zFrac;
3348 word36 quot = 0;
3349 for (uint i = 0; i < 35; i ++)
3350 {
3351 // 71 bit number
3352 uint128 s2n = sn << 1;
3353 if (s2n > dFrac)
3354 {
3355 s2n -= dFrac;
3356 quot |= (1llu << (34 - i));
3357 }
3358 sn = s2n;
3359 }
3360 word36 remainder = sn;
3361
3362 if (sign == -1)
3363 quot = ~quot + 1;
3364
3365 if (dividendNegative)
3366 remainder = ~remainder + 1;
3367
3368 # ifdef L68
3369 cpu.ou.cycle |= ou_GD2;
3370 # endif
3371 // I am surmising that the "If | dividend | >= | divisor |" is an
3372 // overflow prediction; implement it by checking that the calculated
3373 // quotient will fit in 35 bits.
3374
3375 if (quot & ~MASK35)
3376 {
3377 SC_I_ZERO (cpu.rA == 0);
3378 SC_I_NEG (cpu.rA & SIGN36);
3379
3380 doFault(FAULT_DIV, fst_zero, "DVF: divide check fault");
3381 }
3382 cpu . rA = quot & MASK36;
3383 # ifdef TESTING
3384 HDBGRegAW ("dvf");
3385 # endif
3386 cpu . rQ = remainder & MASK36;
3387
3388 #endif
3389
3390 // MM code
3391 #ifdef DVF_CAC
3392
3393 # if 0
3394 if (cpu.CY == 0)
3395 {
3396 // XXX check flags
3397 SET_I_ZERO;
3398 SC_I_NEG (cpu . rA & SIGN36);
3399
3400 cpu . rA = 0;
3401 cpu . rQ = 0;
3402
3403 return;
3404 }
3405 # endif
3406
3407
3408 // dividend format
3409 // 0 1 70 71
3410 // s dividend x
3411 // C(AQ)
3412
3413 # ifdef L68
3414 cpu.ou.cycle |= ou_GD1;
3415 # endif
3416 int sign = 1;
3417 bool dividendNegative = (getbits36_1 (cpu . rA, 0) != 0);
3418 bool divisorNegative = (getbits36_1 (cpu.CY, 0) != 0);
3419
3420 // Get the 70 bits of the dividend (72 bits less the sign bit and the
3421 // ignored bit 71.
3422
3423 // dividend format: . d(0) ... d(69)
3424
3425 # ifdef NEED_128
3426 uint128 zFrac = lshift_128 (construct_128 (0, cpu.rA & MASK35), 35);
3427 zFrac = or_128 (zFrac, construct_128 (0, (cpu.rQ >> 1) & MASK35));
3428 //sim_debug (DBG_TRACEEXT, & cpu_dev, "zfrac %016"PRIx64" %016"PRIx64"\n", zFrac.h, zFrac.l);
3429 # else
3430 uint128 zFrac = ((uint128) (cpu . rA & MASK35) << 35) | ((cpu . rQ >> 1) & MASK35);
3431 //sim_debug (DBG_TRACEEXT, & cpu_dev, "zfrac %016"PRIx64" %016"PRIx64"\n", (uint64) (zFrac>>64), (uint64) zFrac);
3432 # endif
3433 //zFrac <<= 1; -- Makes Multics unbootable.
3434
3435 if (dividendNegative)
3436 {
3437 # ifdef NEED_128
3438 zFrac = negate_128 (zFrac);
3439 # else
3440 zFrac = ~zFrac + 1;
3441 # endif
3442 sign = - sign;
3443 }
3444 # ifdef NEED_128
3445 zFrac = and_128 (zFrac, MASK70);
3446 //sim_debug (DBG_TRACEEXT, & cpu_dev, "zfrac %016"PRIx64" %016"PRIx64"\n", zFrac.h, zFrac.l);
3447 # else
3448 zFrac &= MASK70;
3449 //sim_debug (DBG_TRACEEXT, & cpu_dev, "zfrac %016"PRIx64" %016"PRIx64"\n", (uint64) (zFrac>>64), (uint64) zFrac);
3450 # endif
3451
3452 //char buf [128] = "";
3453 //print_int128 (zFrac, buf);
3454 //sim_debug (DBG_CAC, & cpu_dev, "zFrac %s\n", buf);
3455
3456 // Get the 35 bits of the divisor (36 bits less the sign bit)
3457
3458 // divisor format: . d(0) .... d(34) 0 0 0 .... 0
3459
3460 // divisor goes in the low half
3461 uint128 dFrac = convert_to_word72 (0, cpu.CY & MASK35);
3462 # ifdef NEED_128
3463 //sim_debug (DBG_TRACEEXT, & cpu_dev, "dfrac %016"PRIx64" %016"PRIx64"\n", dFrac.h, dFrac.l);
3464 # else
3465 //sim_debug (DBG_TRACEEXT, & cpu_dev, "dfrac %016"PRIx64" %016"PRIx64"\n", (uint64) (dFrac>>64), (uint64) dFrac);
3466 # endif
3467 if (divisorNegative)
3468 {
3469 # ifdef NEED_128
3470 dFrac = negate_128 (dFrac);
3471 # else
3472 dFrac = ~dFrac + 1;
3473 # endif
3474 sign = - sign;
3475 }
3476 # ifdef NEED_128
3477 dFrac = and_128 (dFrac, construct_128 (0, MASK35));
3478 //sim_debug (DBG_TRACEEXT, & cpu_dev, "dfrac %016"PRIx64" %016"PRIx64"\n", dFrac.h, dFrac.l);
3479 # else
3480 dFrac &= MASK35;
3481 //sim_debug (DBG_TRACEEXT, & cpu_dev, "dfrac %016"PRIx64" %016"PRIx64"\n", (uint64) (dFrac>>64), (uint64) dFrac);
3482 # endif
3483
3484 //char buf2 [128] = "";
3485 //print_int128 (dFrac, buf2);
3486 //sim_debug (DBG_CAC, & cpu_dev, "dFrac %s\n", buf2);
3487
3488 //if (dFrac == 0 || zFrac >= dFrac)
3489 //if (dFrac == 0 || zFrac >= dFrac << 35)
3490 # ifdef NEED_128
3491 if (iszero_128 (dFrac))
3492 # else
3493 if (dFrac == 0)
3494 # endif
3495 {
3496 // case 1: 400000000000 000000000000 000000000000 --> 400000000000 000000000000
3497 // dFrac 000000000000 000000000000
3498
3499 //cpu . rA = (zFrac >> 35) & MASK35;
3500 //cpu . rQ = (word36) ((zFrac & MASK35) << 1);
3501 // ISOLTS 730 expects the right to be zero and the sign
3502 // bit to be untouched.
3503 cpu.rQ = cpu.rQ & (MASK35 << 1);
3504
3505 //SC_I_ZERO (dFrac == 0);
3506 //SC_I_NEG (cpu . rA & SIGN36);
3507 SC_I_ZERO (cpu.CY == 0);
3508 SC_I_NEG (cpu.rA & SIGN36);
3509 dlyDoFault(FAULT_DIV, fst_zero, "DVF: divide check fault");
3510 return;
3511 }
3512
3513 # ifdef L68
3514 cpu.ou.cycle |= ou_GD2;
3515 # endif
3516 # ifdef NEED_128
3517 uint128 remainder;
3518 uint128 quot = divide_128 (zFrac, dFrac, & remainder);
3519 //sim_debug (DBG_TRACEEXT, & cpu_dev, "remainder %016"PRIx64" %016"PRIx64"\n", remainder.h, remainder.l);
3520 //sim_debug (DBG_TRACEEXT, & cpu_dev, "quot %016"PRIx64" %016"PRIx64"\n", quot.h, quot.l);
3521 # else
3522 uint128 quot = zFrac / dFrac;
3523 uint128 remainder = zFrac % dFrac;
3524 //sim_debug (DBG_TRACEEXT, & cpu_dev, "remainder %016"PRIx64" %016"PRIx64"\n", (uint64) (remainder>>64), (uint64) remainder);
3525 //sim_debug (DBG_TRACEEXT, & cpu_dev, "quot %016"PRIx64" %016"PRIx64"\n", (uint64) (quot>>64), (uint64) quot);
3526 # endif
3527
3528 // I am surmising that the "If | dividend | >= | divisor |" is an
3529 // overflow prediction; implement it by checking that the calculated
3530 // quotient will fit in 35 bits.
3531
3532 # ifdef NEED_128
3533 if (isnonzero_128 (and_128 (quot, construct_128 (MASK36, ~MASK35))))
3534 # else
3535 if (quot & ~MASK35)
3536 # endif
3537 {
3538 //
3539 // this got:
3540 // s/b 373737373737 373737373740 200200
3541 // was 373737373740 373737373740 000200
3542 // ~~
3543 # if 1
3544 bool Aneg = (cpu.rA & SIGN36) != 0; // blood type
3545 bool AQzero = cpu.rA == 0 && cpu.rQ == 0;
3546 if (cpu.rA & SIGN36)
3547 {
3548 cpu.rA = (~cpu.rA) & MASK36;
3549 cpu.rQ = (~cpu.rQ) & MASK36;
3550 cpu.rQ += 1;
3551 if (cpu.rQ & BIT37) // overflow?
3552 {
3553 cpu.rQ &= MASK36;
3554 cpu.rA = (cpu.rA + 1) & MASK36;
3555 }
3556 }
3557 # else
3558 if (cpu.rA & SIGN36)
3559 {
3560 cpu.rA = (cpu.rA + 1) & MASK36;
3561 cpu.rQ = (cpu.rQ + 1) & MASK36;
3562 }
3563 # endif
3564 # ifdef TESTING
3565 HDBGRegAW ("dvf");
3566 # endif
3567 //cpu . rA = (zFrac >> 35) & MASK35;
3568 //cpu . rQ = (word36) ((zFrac & MASK35) << 1);
3569 // ISOLTS 730 expects the right to be zero and the sign
3570 // bit to be untouched.
3571 cpu.rQ = cpu.rQ & (MASK35 << 1);
3572
3573 //SC_I_ZERO (dFrac == 0);
3574 //SC_I_NEG (cpu . rA & SIGN36);
3575 SC_I_ZERO (AQzero);
3576 SC_I_NEG (Aneg);
3577
3578 dlyDoFault(FAULT_DIV, fst_zero, "DVF: divide check fault");
3579 return;
3580 }
3581 //char buf3 [128] = "";
3582 //print_int128 (remainder, buf3);
3583 //sim_debug (DBG_CAC, & cpu_dev, "remainder %s\n", buf3);
3584
3585 if (sign == -1)
3586 # ifdef NEED_128
3587 quot = negate_128 (quot);
3588 # else
3589 quot = ~quot + 1;
3590 # endif
3591
3592 if (dividendNegative)
3593 # ifdef NEED_128
3594 remainder = negate_128 (remainder);
3595 # else
3596 remainder = ~remainder + 1;
3597 # endif
3598
3599 # ifdef NEED_128
3600 cpu.rA = quot.l & MASK36;
3601 cpu.rQ = remainder.l & MASK36;
3602 # else
3603 cpu . rA = quot & MASK36;
3604 cpu . rQ = remainder & MASK36;
3605 # endif
3606 # ifdef TESTING
3607 HDBGRegAW ("dvf");
3608 # endif
3609 #endif
3610
3611 //sim_debug (DBG_CAC, & cpu_dev, "Quotient %"PRId64" (%"PRIo64")\n", cpu . rA, cpu . rA);
3612 //sim_debug (DBG_CAC, & cpu_dev, "Remainder %"PRId64"\n", cpu . rQ);
3613 SC_I_ZERO (cpu . rA == 0 && cpu . rQ == 0);
3614 SC_I_NEG (cpu . rA & SIGN36);
3615 }
3616
3617
3618 /*!
3619 * double precision floating round ...
3620 */
dfrd(void)3621 void dfrd (void)
3622 {
3623 // The dfrd instruction is identical to the frd instruction except that the
3624 // rounding constant used is (11...1)65,71 instead of (11...1)29,71.
3625
3626 // If C(AQ) != 0, the frd instruction performs a true round to a precision
3627 // of 64 bits and a normalization on C(EAQ).
3628 // A true round is a rounding operation such that the sum of the result of
3629 // applying the operation to two numbers of equal magnitude but opposite
3630 // sign is exactly zero.
3631
3632 // The frd instruction is executed as follows:
3633 // C(AQ) + (11...1)65,71 -> C(AQ)
3634 // * If C(AQ)0 = 0, then a carry is added at AQ71
3635 // * If overflow occurs, C(AQ) is shifted one place to the right and C(E)
3636 // is increased by 1.
3637 // * If overflow does not occur, C(EAQ) is normalized.
3638 // * If C(AQ) = 0, C(E) is set to -128 and the zero indicator is set ON.
3639
3640 CPTUR (cptUseE);
3641 float72 m = convert_to_word72 (cpu.rA, cpu.rQ);
3642 #ifdef NEED_128
3643 if (iszero_128 (m))
3644 #else
3645 if (m == 0)
3646 #endif
3647 {
3648 cpu.rE = 0200U; /*-128*/
3649 SET_I_ZERO;
3650 CLR_I_NEG;
3651
3652 return;
3653 }
3654
3655 // C(AQ) + (11...1)65,71 -> C(AQ)
3656 bool ovf;
3657 word18 flags1 = 0;
3658 word1 carry = 0;
3659 // If C(AQ)0 = 0, then a carry is added at AQ71
3660 #ifdef NEED_128
3661 if (iszero_128 (and_128 (m, SIGN72)))
3662 #else
3663 if ((m & SIGN72) == 0)
3664 #endif
3665 {
3666 carry = 1;
3667 }
3668 #ifdef NEED_128
3669 m = Add72b (m, construct_128 (0, 0177), carry, I_OFLOW, & flags1, & ovf);
3670 #else
3671 m = Add72b (m, 0177, carry, I_OFLOW, & flags1, & ovf);
3672 #endif
3673
3674 // 0 -> C(AQ)64,71
3675 #ifdef NEED_128
3676 putbits72 (& m, 64, 8, construct_128 (0, 0)); // 64-71 => 0 per DH02
3677 #else
3678 putbits72 (& m, 64, 8, 0); // 64-71 => 0 per DH02
3679 #endif
3680
3681 // If overflow occurs, C(AQ) is shifted one place to the right and C(E) is
3682 // increased by 1.
3683 // If overflow does not occur, C(EAQ) is normalized.
3684 // All of this is done by fno, we just need to save the overflow flag
3685
3686 bool savedovf = TST_I_OFLOW;
3687 SC_I_OFLOW(ovf);
3688 convert_to_word36 (m, & cpu.rA, & cpu.rQ);
3689
3690 fno (& cpu.rE, & cpu.rA, & cpu.rQ);
3691 #ifdef TESTING
3692 HDBGRegAW ("dfrd");
3693 #endif
3694 SC_I_OFLOW(savedovf);
3695 }
3696
dfstr(word36 * Ypair)3697 void dfstr (word36 *Ypair)
3698 {
3699 //! The dfstr instruction performs a double-precision true round and normalization on C(EAQ) as it is stored.
3700 //! The definition of true round is located under the description of the frd instruction.
3701 //! The definition of normalization is located under the description of the fno instruction.
3702 //! Except for the precision of the stored result, the dfstr instruction is identical to the fstr instruction.
3703
3704 //! The dfrd instruction is identical to the frd instruction except that the rounding constant used is (11...1)65,71 instead of (11...1)29,71.
3705
3706 //! If C(AQ) ≠ 0, the frd instruction performs a true round to a precision of 28 bits and a normalization on C(EAQ).
3707 //! A true round is a rounding operation such that the sum of the result of applying the operation to two numbers of equal magnitude but opposite sign is exactly zero.
3708
3709 //! The frd instruction is executed as follows:
3710 //! C(AQ) + (11...1)29,71 → C(AQ)
3711 //! * If C(AQ)0 = 0, then a carry is added at AQ71
3712 //! * If overflow occurs, C(AQ) is shifted one place to the right and C(E) is increased by 1.
3713 //! * If overflow does not occur, C(EAQ) is normalized.
3714 //! * If C(AQ) = 0, C(E) is set to -128 and the zero indicator is set ON.
3715
3716 //! I believe AL39 is incorrect; bits 64-71 should be set to 0, not 65-71. DH02-01 & Bull 9000 is correct.
3717
3718 CPTUR (cptUseE);
3719 word36 A = cpu . rA, Q = cpu . rQ;
3720 word8 E = cpu . rE;
3721 //A &= DMASK;
3722 //Q &= DMASK;
3723
3724 float72 m = convert_to_word72 (A, Q);
3725 #ifdef NEED_128
3726 if (iszero_128 (m))
3727 #else
3728 if (m == 0)
3729 #endif
3730 {
3731 E = (word8)-128;
3732 SET_I_ZERO;
3733 CLR_I_NEG;
3734
3735 Ypair[0] = ((word36) E & MASK8) << 28;
3736 Ypair[1] = 0;
3737
3738 return;
3739 }
3740
3741
3742 // C(AQ) + (11...1)65,71 → C(AQ)
3743 bool ovf;
3744 word18 flags1 = 0;
3745 word1 carry = 0;
3746 // If C(AQ)0 = 0, then a carry is added at AQ71
3747 #ifdef NEED_128
3748 if (iszero_128 (and_128 (m, SIGN72)))
3749 #else
3750 if ((m & SIGN72) == 0)
3751 #endif
3752 {
3753 carry = 1;
3754 }
3755 #ifdef NEED_128
3756 m = Add72b (m, construct_128 (0, 0177), carry, I_OFLOW, & flags1, & ovf);
3757 #else
3758 m = Add72b (m, 0177, carry, I_OFLOW, & flags1, & ovf);
3759 #endif
3760
3761 // 0 -> C(AQ)65,71 (per. RJ78)
3762 #ifdef NEED_128
3763 putbits72 (& m, 64, 8, construct_128 (0, 0)); // 64-71 => 0 per DH02
3764 #else
3765 putbits72 (& m, 64, 8, 0); // 64-71 => 0 per DH02
3766
3767 #endif
3768
3769 // If overflow occurs, C(AQ) is shifted one place to the right and C(E) is
3770 // increased by 1.
3771 // If overflow does not occur, C(EAQ) is normalized.
3772 // All of this is done by fno, we just need to save the overflow flag
3773
3774 bool savedovf = TST_I_OFLOW;
3775 SC_I_OFLOW(ovf);
3776 convert_to_word36 (m, & A, & Q);
3777
3778 fno (& E, & A, & Q);
3779 SC_I_OFLOW(savedovf);
3780
3781 Ypair[0] = (((word36)E & MASK8) << 28) | ((A & 0777777777400LL) >> 8);
3782 Ypair[1] = ((A & 0377) << 28) | ((Q & 0777777777400LL) >> 8);
3783 }
3784
3785 /*!
3786 * double precision Floating Compare ...
3787 */
dfcmp(void)3788 void dfcmp (void)
3789 {
3790 #if 0
3791 //! C(E) :: C(Y-pair)0,7
3792 //! C(AQ)0,63 :: C(Y-pair)8,71
3793
3794 //! Zero: If C(EAQ) = C(Y), then ON; otherwise OFF
3795 //! Neg: If C(EAQ) < C(Y), then ON; otherwise OFF
3796
3797 //! The dfcmp instruction is identical to the fcmp instruction except for the precision of the mantissas actually compared.
3798
3799 //! Notes: The fcmp instruction is executed as follows:
3800 //! The mantissas are aligned by shifting the mantissa of the operand with the algebraically smaller exponent to the right the number of places equal to the difference in the two exponents.
3801 //! The aligned mantissas are compared and the indicators set accordingly.
3802
3803 int64 m1 = (int64) ((cpu . rA << 28) | ((cpu . rQ & 0777777777400LL) >> 8)); ///< only keep the 1st 64-bits :(
3804 int e1 = SIGNEXT8_int (cpu . rE & MASK8);
3805
3806 //int64 m2 = (int64) (bitfieldExtract36(cpu.Ypair[0], 0, 28) << 36); ///< 64-bit mantissa (incl sign)
3807 int64 m2 = ((int64) (getbits36_28 (cpu.Ypair[0], 8)) << 36); // 64-bit mantissa (incl sign)
3808 m2 |= cpu.Ypair[1];
3809 // CAC int64 m2 = (int64) (bitfieldExtract36(cpu.Ypair[0], 0, 28) << 44); ///< 64-bit mantissa (incl sign)
3810 // CAC m2 |= cpu.Ypair[1] << 8;
3811
3812 //int8 e2 = (int8) (bitfieldExtract36(cpu.Ypair[0], 28, 8) & 0377U); ///< 8-bit signed integer (incl sign)
3813 int e2 = SIGNEXT8_int (getbits36_8 (cpu.Ypair[0], 0));
3814
3815 //which exponent is smaller???
3816
3817 int shift_count = -1;
3818
3819 if (e1 == e2)
3820 {
3821 shift_count = 0;
3822 }
3823 else if (e1 < e2)
3824 {
3825 shift_count = abs(e2 - e1);
3826 m1 >>= shift_count;
3827 }
3828 else
3829 {
3830 shift_count = abs(e1 - e2);
3831 m2 >>= shift_count;
3832 }
3833
3834 // need to do algebraic comparisons of mantissae
3835 SC_I_ZERO (m1 == m2);
3836 SC_I_NEG (m1 < m2);
3837 #else
3838 // C(E) :: C(Y)0,7
3839 // C(AQ)0,63 :: C(Y-pair)8,71
3840 // * Zero: If | C(EAQ)| = | C(Y-pair) |, then ON; otherwise OFF
3841 // * Neg : If | C(EAQ)| < | C(Y-pair) |, then ON; otherwise OFF
3842
3843 // The dfcmp instruction is identical to the fcmp instruction except for
3844 // the precision of the mantissas actually compared.
3845
3846 // Notes: The fcmp instruction is executed as follows:
3847 // The mantissas are aligned by shifting the mantissa of the operand with
3848 // the algebraically smaller exponent to the right the number of places
3849 // equal to the difference in the two exponents.
3850 // The aligned mantissas are compared and the indicators set accordingly.
3851
3852 // C(AQ)0,63
3853 CPTUR (cptUseE);
3854 # ifdef HEX_MODE
3855 uint shift_amt = isHex() ? 4 : 1;
3856 # endif
3857 word72 m1 = convert_to_word72 (cpu.rA, cpu.rQ & 0777777777400LL);
3858 int e1 = SIGNEXT8_int (cpu . rE & MASK8);
3859
3860 // C(Y-pair)8,71
3861 # ifdef NEED_128
3862 word72 m2 = lshift_128 (construct_128 (0, getbits36_28 (cpu.Ypair[0], 8)), (36 + 8));
3863 //m2 = or_128 (m2, construct_128 (0, cpu.Ypair[1] << 8));
3864 m2 = or_128 (m2, lshift_128 (construct_128 (0, cpu.Ypair[1]), 8u));
3865 # else
3866 word72 m2 = (word72) getbits36_28 (cpu.Ypair[0], 8) << (36 + 8);
3867 m2 |= cpu.Ypair[1] << 8;
3868 # endif
3869 int e2 = SIGNEXT8_int (getbits36_8 (cpu.Ypair[0], 0));
3870
3871 //int e3 = -1;
3872
3873 //which exponent is smaller???
3874
3875 int shift_count = -1;
3876 word1 notallzeros = 0;
3877
3878 # ifdef NEED_128
3879 if (e1 == e2)
3880 {
3881 shift_count = 0;
3882 //e3 = e1;
3883 }
3884 else if (e1 < e2)
3885 {
3886 # ifdef HEX_MODE
3887 shift_count = abs(e2 - e1) * (int) shift_amt;
3888 # else
3889 shift_count = abs(e2 - e1);
3890 # endif
3891 bool s = isnonzero_128 (and_128 (m1, SIGN72)); ///< mantissa negative?
3892 for(int n = 0 ; n < shift_count ; n += 1)
3893 {
3894 notallzeros |= m1.l & 1;
3895 m1 = rshift_128 (m1, 1);
3896 if (s)
3897 m1 = or_128 (m1, SIGN72);
3898 }
3899
3900 # ifdef HEX_MODE
3901 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
3902 m1 = construct_128 (0, 0);
3903 # else
3904 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count > 71)
3905 m1 = construct_128 (0, 0);
3906 # endif
3907 m1 = and_128 (m1, MASK72);
3908 //e3 = e2;
3909 }
3910 else
3911 {
3912 // e2 < e1;
3913 # ifdef HEX_MODE
3914 shift_count = abs(e1 - e2) * (int) shift_amt;
3915 # else
3916 shift_count = abs(e1 - e2);
3917 # endif
3918 bool s = isnonzero_128 (and_128 (m2, SIGN72)); ///< mantissa negative?
3919 for(int n = 0 ; n < shift_count ; n += 1)
3920 {
3921 notallzeros |= m2.l & 1;
3922 m2 = rshift_128 (m2, 1);
3923 if (s)
3924 m2 = or_128 (m2, SIGN72);
3925 }
3926 # ifdef HEX_MODE
3927 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
3928 m2 = construct_128 (0, 0);
3929 # else
3930 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count > 71)
3931 m2 = construct_128 (0, 0);
3932 # endif
3933 m2 = and_128 (m2, MASK72);
3934 //e3 = e1;
3935 }
3936
3937 SC_I_ZERO (iseq_128 (m1, m2));
3938 int128 sm1 = SIGNEXT72_128 (m1);
3939 int128 sm2 = SIGNEXT72_128 (m2);
3940 SC_I_NEG (islt_s128 (sm1, sm2));
3941 # else // NEED_128
3942 if (e1 == e2)
3943 {
3944 shift_count = 0;
3945 //e3 = e1;
3946 }
3947 else if (e1 < e2)
3948 {
3949 # ifdef HEX_MODE
3950 shift_count = abs(e2 - e1) * (int) shift_amt;
3951 # else
3952 shift_count = abs(e2 - e1);
3953 # endif
3954 bool s = m1 & SIGN72; ///< mantissa negative?
3955 for(int n = 0 ; n < shift_count ; n += 1)
3956 {
3957 notallzeros |= m1 & 1;
3958 m1 >>= 1;
3959 if (s)
3960 m1 |= SIGN72;
3961 }
3962
3963 # ifdef HEX_MODE
3964 if (m1 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
3965 m1 = 0;
3966 # else
3967 if (m1 == MASK72 && notallzeros == 1 && shift_count > 71)
3968 m1 = 0;
3969 # endif
3970 m1 &= MASK72;
3971 //e3 = e2;
3972 }
3973 else
3974 {
3975 // e2 < e1;
3976 # ifdef HEX_MODE
3977 shift_count = abs(e1 - e2) * (int) shift_amt;
3978 # else
3979 shift_count = abs(e1 - e2);
3980 # endif
3981 bool s = m2 & SIGN72; ///< mantissa negative?
3982 for(int n = 0 ; n < shift_count ; n += 1)
3983 {
3984 notallzeros |= m2 & 1;
3985 m2 >>= 1;
3986 if (s)
3987 m2 |= SIGN72;
3988 }
3989 # ifdef HEX_MODE
3990 if (m2 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
3991 m2 = 0;
3992 # else
3993 if (m2 == MASK72 && notallzeros == 1 && shift_count > 71)
3994 m2 = 0;
3995 # endif
3996 m2 &= MASK72;
3997 //e3 = e1;
3998 }
3999
4000 SC_I_ZERO (m1 == m2);
4001 int128 sm1 = SIGNEXT72_128 (m1);
4002 int128 sm2 = SIGNEXT72_128 (m2);
4003 SC_I_NEG (sm1 < sm2);
4004 # endif // NEED_128
4005 #endif
4006 }
4007
4008 /*!
4009 * double precision Floating Compare magnitude ...
4010 */
dfcmg(void)4011 void dfcmg (void)
4012 {
4013 // C(E) :: C(Y)0,7
4014 // | C(AQ)0,27 | :: | C(Y)8,35 |
4015 // * Zero: If | C(EAQ)| = | C(Y) |, then ON; otherwise OFF
4016 // * Neg : If | C(EAQ)| < | C(Y) |, then ON; otherwise OFF
4017
4018 // Notes: The fcmp instruction is executed as follows:
4019 // The mantissas are aligned by shifting the mantissa of the operand with
4020 // the algebraically smaller exponent to the right the number of places
4021 // equal to the difference in the two exponents.
4022 // The aligned mantissas are compared and the indicators set accordingly.
4023
4024 // The dfcmg instruction is identical to the dfcmp instruction except that
4025 // the magnitudes of the mantissas are compared instead of the algebraic
4026 // values.
4027
4028 CPTUR (cptUseE);
4029 #ifdef HEX_MODE
4030 uint shift_amt = isHex() ? 4 : 1;
4031 #endif
4032 // C(AQ)0,63
4033 word72 m1 = convert_to_word72 (cpu.rA & MASK36, cpu.rQ & 0777777777400LL);
4034 int e1 = SIGNEXT8_int (cpu.rE & MASK8);
4035
4036 // C(Y-pair)8,71
4037 #ifdef NEED_128
4038 //word72 m2 = construct_128 ((uint64_t) getbits36_28 (cpu.Ypair[0], 8) << 8, 0); // 28-bit mantissa (incl sign)
4039 word72 m2 = lshift_128 (construct_128 (0, getbits36_28 (cpu.Ypair[0], 8)), (36 + 8));
4040 //m2 = or_128 (m2, construct_128 (0, cpu.Ypair[1] << 8));
4041 m2 = or_128 (m2, lshift_128 (construct_128 (0, cpu.Ypair[1]), 8u));
4042 #else
4043 word72 m2 = (word72) getbits36_28 (cpu.Ypair[0], 8) << (36 + 8);
4044 m2 |= cpu.Ypair[1] << 8;
4045 #endif
4046 int e2 = SIGNEXT8_int (getbits36_8 (cpu.Ypair[0], 0));
4047
4048 //int e3 = -1;
4049
4050 //which exponent is smaller???
4051 #ifdef L68
4052 cpu.ou.cycle = ou_GOE;
4053 #endif
4054 int shift_count = -1;
4055 word1 notallzeros = 0;
4056
4057 if (e1 == e2)
4058 {
4059 shift_count = 0;
4060 //e3 = e1;
4061 }
4062 else if (e1 < e2)
4063 {
4064 #ifdef L68
4065 cpu.ou.cycle = ou_GOA;
4066 #endif
4067 #ifdef HEX_MODE
4068 shift_count = abs(e2 - e1) * (int) shift_amt;
4069 #else
4070 shift_count = abs(e2 - e1);
4071 #endif
4072 #ifdef NEED_128
4073 bool s = isnonzero_128 (and_128 (m1, SIGN72)); ///< mantissa negative?
4074 for( int n = 0; n < shift_count; n += 1)
4075 {
4076 notallzeros |= m1.l & 1;
4077 m1 = rshift_128 (m1, 1);
4078 if (s)
4079 m1 = or_128 (m1, SIGN72);
4080 }
4081 # ifdef HEX_MODE
4082 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
4083 m1 = construct_128 (0, 0);
4084 # else
4085 if (iseq_128 (m1, MASK72) && notallzeros == 1 && shift_count > 71)
4086 m1 = construct_128 (0, 0);
4087 # endif
4088 m1 = and_128 (m1, MASK72);
4089 //e3 = e2;
4090 #else
4091 bool s = m1 & SIGN72; ///< mantissa negative?
4092 for( int n = 0; n < shift_count; n += 1)
4093 {
4094 notallzeros |= m1 & 1;
4095 m1 >>= 1;
4096 if (s)
4097 m1 |= SIGN72;
4098 }
4099 # ifdef HEX_MODE
4100 if (m1 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
4101 m1 = 0;
4102 # else
4103 if (m1 == MASK72 && notallzeros == 1 && shift_count > 71)
4104 m1 = 0;
4105 # endif
4106 m1 &= MASK72;
4107 //e3 = e2;
4108 #endif
4109 }
4110 else
4111 {
4112 // e2 < e1;
4113 #ifdef HEX_MODE
4114 shift_count = abs(e1 - e2) * (int) shift_amt;
4115 #else
4116 shift_count = abs(e1 - e2);
4117 #endif
4118 #ifdef NEED_128
4119 bool s = isnonzero_128 (and_128 (m2, SIGN72)); ///< mantissa negative?
4120 for(int n = 0; n < shift_count; n += 1)
4121 {
4122 notallzeros |= m2.l & 1;
4123 m2 = rshift_128 (m2, 1);
4124 if (s)
4125 m2 = or_128 (m2, SIGN72);
4126 }
4127 # ifdef HEX_MODE
4128 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count * (int) shift_amt > 71)
4129 m2 = construct_128 (0, 0);
4130 # else
4131 if (iseq_128 (m2, MASK72) && notallzeros == 1 && shift_count > 71)
4132 m2 = construct_128 (0, 0);
4133 # endif
4134 m2 = and_128 (m2, MASK72);
4135 //e3 = e1;
4136 #else
4137 bool s = m2 & SIGN72; ///< mantissa negative?
4138 for(int n = 0; n < shift_count; n += 1)
4139 {
4140 notallzeros |= m2 & 1;
4141 m2 >>= 1;
4142 if (s)
4143 m2 |= SIGN72;
4144 }
4145 # ifdef HEX_MODE
4146 if (m2 == MASK72 && notallzeros == 1 && shift_count * (int) shift_amt > 71)
4147 m2 = 0;
4148 # else
4149 if (m2 == MASK72 && notallzeros == 1 && shift_count > 71)
4150 m2 = 0;
4151 # endif
4152 m2 &= MASK72;
4153 //e3 = e1;
4154 #endif
4155 }
4156
4157 #ifdef NEED_128
4158 SC_I_ZERO (iseq_128 (m1, m2));
4159 int128 sm1 = SIGNEXT72_128 (m1);
4160 if (sm1.h < 0)
4161 sm1 = negate_s128 (sm1);
4162 int128 sm2 = SIGNEXT72_128 (m2);
4163 if (sm2.h < 0)
4164 sm2 = negate_s128 (sm2);
4165
4166 SC_I_NEG (islt_s128 (sm1, sm2));
4167 #else
4168 SC_I_ZERO (m1 == m2);
4169 int128 sm1 = SIGNEXT72_128 (m1);
4170 if (sm1 < 0)
4171 sm1 = - sm1;
4172 int128 sm2 = SIGNEXT72_128 (m2);
4173 if (sm2 < 0)
4174 sm2 = - sm2;
4175
4176 SC_I_NEG (sm1 < sm2);
4177 #endif
4178 }
4179