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