1 /* IEEE.C       (c) Copyright Willem Konynenberg, 2001-2003          */
2 /*              (c) Copyright Roger Bowler and others, 2003-2014     */
3 /*              Hercules Binary (IEEE) Floating Point Instructions   */
4 
5 /*-------------------------------------------------------------------*/
6 /* This module implements ESA/390 Binary Floating-Point (IEEE 754)   */
7 /* instructions as described in SA22-7201-05 ESA/390 Principles of   */
8 /* Operation and SA22-7832-08 z/Architecture Principles of Operation.*/
9 /*-------------------------------------------------------------------*/
10 
11 /*
12  * Hercules System/370, ESA/390, z/Architecture emulator
13  * ieee.c
14  * Binary (IEEE) Floating Point Instructions
15  * Copyright (c) 2001-2009 Willem Konynenberg <wfk@xos.nl>
16  * TCEB, TCDB and TCXB contributed by Per Jessen, 20 September 2001.
17  * THDER,THDR by Roger Bowler, 19 July 2003.
18  * Additional instructions by Roger Bowler, November 2004:
19  *  LXDBR,LXDB,LXEBR,LXEB,LDXBR,LEXBR,CXFBR,CXGBR,CFXBR,CGXBR,
20  *  MXDBR,MXDB,MDEBR,MDEB,MADBR,MADB,MAEBR,MAEB,MSDBR,MSDB,
21  *  MSEBR,MSEB,DIEBR,DIDBR,TBEDR,TBDR.
22  * Licensed under the Q Public License
23  * For details, see html/herclic.html
24  * Based very loosely on float.c by Peter Kuschnerus, (c) 2000-2006.
25  * Converted to use J.R.Hauser's softfloat package - RB, Oct 2013.
26  * Floating-point extension facility - RB, April 2014:
27  *  CELFBR,CDLFBR,CXLFBR,CLFEBR,CLFDBR,CLFXBR,
28  *  CELGBR,CDLGBR,CXLGBR,CLGEBR,CLGDBR,CLGXBR.
29  * Floating-point extension facility - RB, August 2014:
30  *  FIEBRA,FIDBRA,FIXBRA,LDXBRA,LEXBRA,LEDBRA,
31  *  CEFBRA,CDFBRA,CXFBRA,CFEBRA,CFDBRA,CFXBRA,
32  *  CEGBRA,CDGBRA,CXGBRA,CGEBRA,CGDBRA,CGXBRA.
33  */
34 
35 #include "hstdinc.h"
36 
37 #if !defined(_HENGINE_DLL_)
38 #define _HENGINE_DLL_
39 #endif
40 
41 #if !defined(_IEEE_C_)
42 #define _IEEE_C_
43 #endif
44 
45 #include "hercules.h"
46 
47 #if defined(FEATURE_BINARY_FLOATING_POINT)
48 
49 #include "opcode.h"
50 #include "inline.h"
51 
52 /* Definitions of BFP rounding methods */
53 #define RM_DEFAULT_ROUNDING             0
54 #define RM_BIASED_ROUND_TO_NEAREST      1
55 #define RM_PREPARE_SHORTER_PRECISION    3
56 #define RM_ROUND_TO_NEAREST             4
57 #define RM_ROUND_TOWARD_ZERO            5
58 #define RM_ROUND_TOWARD_POS_INF         6
59 #define RM_ROUND_TOWARD_NEG_INF         7
60 
61 /* Macro to generate program check if invalid BFP rounding method */
62 #undef BFPRM_CHECK
63 #if !defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)
64 #define BFPRM_CHECK(x,regs) \
65         {if (!((x)==0 || (x)==1 || ((x)>=4 && (x)<=7))) \
66             {regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION);}}
67 #else /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/
68 #define BFPRM_CHECK(x,regs) \
69         {if (!((x)==0 || (x)==1 || ((x)>=3 && (x)<=7))) \
70             {regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION);}}
71 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/
72 
73 #if !defined(_IEEE_C)
74 /* Architecture independent code goes within this ifdef */
75 #include "milieu.h"
76 #include "softfloat.h"
77 
78 /* Floating point exponent bias values */
79 #define FLOAT32_BIAS    127
80 #define FLOAT64_BIAS    1023
81 #define FLOAT128_BIAS   16383
82 
83 #endif  /* !defined(_IEEE_C) */
84 
85 /* externally defined architecture-dependent functions */
86 #define vfetch4 ARCH_DEP(vfetch4)
87 #define vfetch8 ARCH_DEP(vfetch8)
88 
89 /* locally defined architecture-dependent functions */
90 #define float_exception_masked ARCH_DEP(float_exception_masked)
91 #define float_exception ARCH_DEP(float_exception)
92 #define vfetch_float32 ARCH_DEP(vfetch_float32)
93 #define vfetch_float64 ARCH_DEP(vfetch_float64)
94 
95 #define add_ebfp ARCH_DEP(add_ebfp)
96 #define add_lbfp ARCH_DEP(add_lbfp)
97 #define add_sbfp ARCH_DEP(add_sbfp)
98 #define compare_ebfp ARCH_DEP(compare_ebfp)
99 #define compare_lbfp ARCH_DEP(compare_lbfp)
100 #define compare_sbfp ARCH_DEP(compare_sbfp)
101 #define divide_ebfp ARCH_DEP(divide_ebfp)
102 #define divide_lbfp ARCH_DEP(divide_lbfp)
103 #define divide_sbfp ARCH_DEP(divide_sbfp)
104 #define load_test_ebfp ARCH_DEP(load_test_ebfp)
105 #define load_test_lbfp ARCH_DEP(load_test_lbfp)
106 #define load_test_sbfp ARCH_DEP(load_test_sbfp)
107 #define load_neg_ebfp ARCH_DEP(load_neg_ebfp)
108 #define load_neg_lbfp ARCH_DEP(load_neg_lbfp)
109 #define load_neg_sbfp ARCH_DEP(load_neg_sbfp)
110 #define load_pos_ebfp ARCH_DEP(load_pos_ebfp)
111 #define load_pos_lbfp ARCH_DEP(load_pos_lbfp)
112 #define load_pos_sbfp ARCH_DEP(load_pos_sbfp)
113 #define multiply_ebfp ARCH_DEP(multiply_ebfp)
114 #define multiply_lbfp ARCH_DEP(multiply_lbfp)
115 #define multiply_sbfp ARCH_DEP(multiply_sbfp)
116 #define multiply_add_ebfp ARCH_DEP(multiply_add_ebfp)
117 #define multiply_add_lbfp ARCH_DEP(multiply_add_lbfp)
118 #define multiply_add_sbfp ARCH_DEP(multiply_add_sbfp)
119 #define multiply_subtract_ebfp ARCH_DEP(multiply_subtract_ebfp)
120 #define multiply_subtract_lbfp ARCH_DEP(multiply_subtract_lbfp)
121 #define multiply_subtract_sbfp ARCH_DEP(multiply_subtract_sbfp)
122 #define squareroot_ebfp ARCH_DEP(squareroot_ebfp)
123 #define squareroot_lbfp ARCH_DEP(squareroot_lbfp)
124 #define squareroot_sbfp ARCH_DEP(squareroot_sbfp)
125 #define subtract_ebfp ARCH_DEP(subtract_ebfp)
126 #define subtract_lbfp ARCH_DEP(subtract_lbfp)
127 #define subtract_sbfp ARCH_DEP(subtract_sbfp)
128 #define test_data_class_ebfp ARCH_DEP(test_data_class_ebfp)
129 #define test_data_class_lbfp ARCH_DEP(test_data_class_lbfp)
130 #define test_data_class_sbfp ARCH_DEP(test_data_class_sbfp)
131 #define divint_lbfp ARCH_DEP(divint_lbfp)
132 #define divint_sbfp ARCH_DEP(divint_sbfp)
133 
134 /*
135  * Convert from Softfloat IEEE exception to Pop IEEE exception
136  * with suppression of exceptions according to mask bits:
137  *  - mask bit 0x04 (XxC) suppresses the inexact exception
138  */
float_exception_masked(REGS * regs,int mask)139 static int float_exception_masked(REGS * regs, int mask)
140 {
141     int fpc = 0;
142     int dxc = 0;
143     int exc = 0;
144     int8 flags = float_get_exception_flags();
145 
146     if (flags & float_flag_inexact) {
147         fpc = FPC_FLAG_SFX;
148     }
149 
150     if (flags & float_flag_underflow) {
151         fpc |= FPC_FLAG_SFU;
152     } else if (flags & float_flag_overflow) {
153         fpc |= FPC_FLAG_SFO;
154     } else if (flags & float_flag_divbyzero) {
155         fpc |= FPC_FLAG_SFZ;
156     } else if (flags & float_flag_invalid) {
157         fpc |= FPC_FLAG_SFI;
158     }
159 
160     exc = (fpc & FPC_FLAG) & ((regs->fpc & FPC_MASK) >> 8);
161 
162 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)
163     /* Suppress inexact exception if the XxC mask bit is set */
164     if (mask & 0x04) {
165         exc &= ~FPC_FLAG_SFX;
166     }
167 #else
168     UNREFERENCED(mask);
169 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/
170 
171     if (exc & FPC_FLAG_SFI) {
172         dxc = DXC_IEEE_INVALID_OP;
173     } else if (exc & FPC_FLAG_SFZ) {
174         dxc = DXC_IEEE_DIV_ZERO;
175     } else if (exc & FPC_FLAG_SFO) {
176         dxc = (fpc & FPC_FLAG_SFX) ? DXC_IEEE_OF_INEX_TRUNC : DXC_IEEE_OF_EXACT;
177     } else if (exc & FPC_FLAG_SFU) {
178         dxc = (fpc & FPC_FLAG_SFX) ? DXC_IEEE_UF_INEX_TRUNC : DXC_IEEE_UF_EXACT;
179     } else if (exc & FPC_FLAG_SFX) {
180         dxc = DXC_IEEE_INEXACT_TRUNC;
181     }
182 
183     if (exc) {
184         regs->dxc = dxc;
185         if (dxc == DXC_IEEE_DIV_ZERO || dxc == DXC_IEEE_INVALID_OP) {
186             /* suppress operation */
187             regs->program_interrupt(regs, PGM_DATA_EXCEPTION);
188         }
189         fpc &= ~exc;
190         regs->fpc |= fpc;
191         /*
192          * Other operations need to take appropriate action
193          * to complete the operation.
194          */
195         return PGM_DATA_EXCEPTION;
196     } else {
197         /* Set flags in FPC */
198         regs->fpc |= fpc;
199         /* have caller take default action */
200         return 0;
201     }
202 
203 } /* end function float_exception_masked */
204 
205 /*
206  * Convert from Softfloat IEEE exception to Pop IEEE exception
207  * without suppression of exceptions by mask bits
208  */
float_exception(REGS * regs)209 static inline int float_exception(REGS * regs)
210 {
211     return float_exception_masked(regs, 0);
212 } /* end function float_exception */
213 
214 #if !defined(_IEEE_C)
215 /*
216  * Set softfloat rounding mode according to BFP rounding mode mask
217  */
set_rounding_mode(U32 fpcreg,int mask)218 void set_rounding_mode(U32 fpcreg, int mask)
219 {
220     int brm;
221     int8 flrm;
222 
223     /* If mask is zero, obtain rounding mode from FPC register */
224     if (mask == RM_DEFAULT_ROUNDING)
225         brm = ((fpcreg & FPC_BRM) >> FPC_BRM_SHIFT) + 4;
226     else
227         brm = mask;
228 
229     /* Convert BFP rounding mode to nearest equivalent FE rounding mode */
230     switch (brm) {
231     case RM_ROUND_TO_NEAREST: /* Round to nearest ties to even */
232         flrm = float_round_nearest_even;
233         break;
234     case RM_ROUND_TOWARD_ZERO: /* Round toward zero */
235         flrm = float_round_to_zero;
236         break;
237     case RM_ROUND_TOWARD_POS_INF: /* Round toward +infinity */
238         flrm = float_round_up;
239         break;
240     case RM_ROUND_TOWARD_NEG_INF: /* Round toward -infinity */
241         flrm = float_round_down;
242         break;
243     default:
244         flrm = float_round_nearest_even;
245         break;
246     } /* end switch(brm) */
247 
248     /* Set rounding mode for softfloat */
249     float_set_rounding_mode(flrm);
250 
251 } /* end function set_rounding_mode */
252 #endif  /* !defined(_IEEE_C) */
253 
254 #if !defined(_IEEE_C)
255 /*
256  * Get softfloat operands from registers
257  */
get_float32(float32 * op,U32 * fpr)258 static inline void get_float32(float32 *op, U32 *fpr) {
259     *op = *fpr;
260 }
get_float64(float64 * op,U32 * fpr)261 static inline void get_float64(float64 *op, U32 *fpr) {
262     *op = ((U64)fpr[0] << 32) | fpr[1];
263 }
get_float128(float128 * op,U32 * fpr)264 static inline void get_float128(float128 *op, U32 *fpr) {
265     op->high = ((U64)fpr[0] << 32) | fpr[1];
266     op->low = ((U64)fpr[FPREX] << 32) | fpr[FPREX+1];
267 }
268 #endif  /* !defined(_IEEE_C) */
269 
270 /*
271  * Fetch softfloat operands from memory
272  */
vfetch_float32(float32 * op,VADR addr,int arn,REGS * regs)273 static inline void vfetch_float32(float32 *op, VADR addr, int arn, REGS *regs) {
274     *op = vfetch4(addr, arn, regs);
275 }
vfetch_float64(float64 * op,VADR addr,int arn,REGS * regs)276 static inline void vfetch_float64(float64 *op, VADR addr, int arn, REGS *regs) {
277     *op = vfetch8(addr, arn, regs);
278 }
279 
280 #if !defined(_IEEE_C)
281 /*
282  * Put softfloat operands into registers
283  */
put_float32(float32 * op,U32 * fpr)284 static inline void put_float32(float32 *op, U32 *fpr) {
285     *fpr = *op;
286 }
put_float64(float64 * op,U32 * fpr)287 static inline void put_float64(float64 *op, U32 *fpr) {
288     fpr[0] = (U32)(*op >> 32);
289     fpr[1] = (U32)(*op & 0xFFFFFFFF);
290 }
put_float128(float128 * op,U32 * fpr)291 static inline void put_float128(float128 *op, U32 *fpr) {
292     fpr[0] = (U32)(op->high >> 32);
293     fpr[1] = (U32)(op->high & 0xFFFFFFFF);
294     fpr[FPREX] = (U32)(op->low >> 32);
295     fpr[FPREX+1] = (U32)(op->low & 0xFFFFFFFF);
296 }
297 #define _IEEE_C
298 #endif  /* !defined(_IEEE_C) */
299 
300 /*
301  * Chapter 9. Floating-Point Overview and Support Instructions
302  */
303 
304 #if defined(FEATURE_FPS_EXTENSIONS)
305 #if !defined(_CBH_FUNC)
306 /*
307  * Convert binary floating point to hexadecimal long floating point
308  * save result into long register and return condition code
309  * Roger Bowler, 19 July 2003
310  */
cnvt_bfp_to_hfp(float64 * op,U32 * fpr)311 static int cnvt_bfp_to_hfp (float64 *op, U32 *fpr)
312 {
313     int exp;
314     U64 fract;
315     U32 r0, r1;
316     int cc;
317     int sign;
318 
319     sign = float64_is_neg(*op) ? 1 : 0;
320 
321     if (float64_is_nan(*op)) {
322         r0 = 0x7FFFFFFF;
323         r1 = 0xFFFFFFFF;
324         cc = 3;
325     } else if (float64_is_inf(*op)) {
326         r0 = sign ? 0xFFFFFFFF : 0x7FFFFFFF;
327         r1 = 0xFFFFFFFF;
328         cc = 3;
329     } else if (float64_is_zero(*op)) {
330         r0 = sign ? 0x80000000 : 0;
331         r1 = 0;
332         cc = 0;
333     } else if (float64_is_subnormal(*op)) {
334         r0 = sign ? 0x80000000 : 0;
335         r1 = 0;
336         cc = sign ? 1 : 2;
337     } else {
338         //logmsg("ieee: exp=%d (X\'%3.3x\')\tfract=%16.16"I64_FMT"x\n",
339         //        float64_exp(*op), float64_exp(*op), float64_fract(*op));
340         /* Insert an implied 1. in front of the 52 bit binary
341            fraction and lengthen the result to 56 bits */
342         fract = (U64)(float64_fract(*op) | 0x10000000000000ULL) << 3;
343 
344         /* The binary exponent is equal to the biased exponent - 1023
345            adjusted by 1 to move the point before the 56 bit fraction */
346         exp = float64_exp(*op) - 1023 + 1;
347 
348         //logmsg("ieee: adjusted exp=%d\tfract=%16.16"I64_FMT"x\n", exp, fract);
349         /* Shift the fraction right one bit at a time until
350            the binary exponent becomes a multiple of 4 */
351         while (exp & 3)
352         {
353             exp++;
354             fract >>= 1;
355         }
356         //logmsg("ieee:  shifted exp=%d\tfract=%16.16"I64_FMT"x\n", exp, fract);
357 
358         /* Convert the binary exponent into a hexadecimal exponent
359            by dropping the last two bits (which are now zero) */
360         exp >>= 2;
361 
362         /* If the hexadecimal exponent is less than -64 then return
363            a signed zero result with a non-zero condition code */
364         if (exp < -64)
365         {
366             r0 = sign ? 0x80000000 : 0;
367             r1 = 0;
368             cc = sign ? 1 : 2;
369         }
370         /* If the hexadecimal exponent exceeds +63 then return
371            a signed maximum result with condition code 3 */
372         else if (exp > 63)
373         {
374             r0 = sign ? 0xFFFFFFFF : 0x7FFFFFFF;
375             r1 = 0xFFFFFFFF;
376             cc = 3;
377         }
378         else
379         {
380             /* Convert the hexadecimal exponent to a characteristic
381                by adding 64 */
382             exp += 64;
383 
384             /* Pack the exponent and the fraction into the result */
385             r0 = (sign ? 1<<31 : 0) | (exp << 24) | (fract >> 32);
386             r1 = fract & 0xFFFFFFFF;
387             cc = sign ? 1 : 2;
388         }
389     }
390     /* Store high and low halves of result into fp register array
391        and return condition code */
392     fpr[0] = r0;
393     fpr[1] = r1;
394     return cc;
395 
396 } /* end function cnvt_bfp_to_hfp */
397 
398 /*
399  * Convert hexadecimal long floating point register to
400  * binary floating point and return condition code
401  * Roger Bowler, 28 Nov 2004
402  */
cnvt_hfp_to_bfp(U32 * fpr,int rounding,int bfp_fractbits,int bfp_emax,int bfp_ebias,int * result_sign,int * result_exp,U64 * result_fract)403 static int cnvt_hfp_to_bfp (U32 *fpr, int rounding,
404         int bfp_fractbits, int bfp_emax, int bfp_ebias,
405         int *result_sign, int *result_exp, U64 *result_fract)
406 {
407     BYTE sign;
408     short expo;
409     U64 fract;
410     int roundup = 0;
411     int cc;
412     U64 b;
413 
414     /* Break the source operand into sign, characteristic, fraction */
415     sign = fpr[0] >> 31;
416     expo = (fpr[0] >> 24) & 0x007F;
417     fract = ((U64)(fpr[0] & 0x00FFFFFF) << 32) | fpr[1];
418 
419     /* Determine whether to round up or down */
420     switch (rounding) {
421     case RM_BIASED_ROUND_TO_NEAREST:
422     case RM_ROUND_TO_NEAREST: roundup = 0; break;
423     case RM_DEFAULT_ROUNDING:
424     case RM_ROUND_TOWARD_ZERO: roundup = 0; break;
425     case RM_ROUND_TOWARD_POS_INF: roundup = (sign ? 0 : 1); break;
426     case RM_ROUND_TOWARD_NEG_INF: roundup = sign; break;
427     } /* end switch(rounding) */
428 
429     /* Convert HFP zero to BFP zero and return cond code 0 */
430     if (fract == 0) /* a = -0 or +0 */
431     {
432         *result_sign = sign;
433         *result_exp = 0;
434         *result_fract = 0;
435         return 0;
436     }
437 
438     /* Set the condition code */
439     cc = sign ? 1 : 2;
440 
441     /* Convert the HFP characteristic to a true binary exponent */
442     expo = (expo - 64) * 4;
443 
444     /* Convert true binary exponent to a biased exponent */
445     expo += bfp_ebias;
446 
447     /* Shift the fraction left until leftmost 1 is in bit 8 */
448     while ((fract & 0x0080000000000000ULL) == 0)
449     {
450         fract <<= 1;
451         expo -= 1;
452     }
453 
454     /* Convert 56-bit fraction to 55-bit with implied 1 */
455     expo--;
456     fract &= 0x007FFFFFFFFFFFFFULL;
457 
458     if (expo < -(bfp_fractbits-1)) /* |a| < Dmin */
459     {
460         if (expo == -(bfp_fractbits-1) - 1)
461         {
462             if (rounding == RM_BIASED_ROUND_TO_NEAREST
463                 || rounding == RM_ROUND_TO_NEAREST)
464                 roundup = 1;
465         }
466         if (roundup) { expo = 0; fract = 1; } /* Dmin */
467         else { expo = 0; fract = 0; } /* Zero */
468     }
469     else if (expo < 1) /* Dmin <= |a| < Nmin */
470     {
471         /* Reinstate implied 1 in preparation for denormalization */
472         fract |= 0x0080000000000000ULL;
473 
474         /* Denormalize to get exponent back in range */
475         fract >>= (expo + (bfp_fractbits-1));
476         expo = 0;
477     }
478     else if (expo > (bfp_emax+bfp_ebias)) /* |a| > Nmax */
479     {
480         cc = 3;
481         if (roundup) { /* Inf */
482             expo = (bfp_emax+bfp_ebias) + 1;
483             fract = 0;
484         } else { /* Nmax */
485             expo = (bfp_emax+bfp_ebias);
486             fract = 0x007FFFFFFFFFFFFFULL - (((U64)1<<(1+(55-bfp_fractbits)))-1);
487         } /* Nmax */
488     } /* end Nmax < |a| */
489 
490     /* Set the result sign and exponent */
491     *result_sign = sign;
492     *result_exp = expo;
493 
494     /* Apply rounding before truncating to final fraction length */
495     b = ( (U64)1 ) << ( 55 - bfp_fractbits);
496     if (roundup && (fract & b))
497     {
498         fract += b;
499     }
500 
501     /* Convert 55-bit fraction to result fraction length */
502     *result_fract = fract >> (55-bfp_fractbits);
503 
504     return cc;
505 } /* end function cnvt_hfp_to_bfp */
506 
507 #define _CBH_FUNC
508 #endif /*!defined(_CBH_FUNC)*/
509 
510 /*-------------------------------------------------------------------*/
511 /* B359 THDR  - CONVERT BFP TO HFP (long)                      [RRE] */
512 /* Roger Bowler, 19 July 2003                                        */
513 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_long_to_float_long_reg)514 DEF_INST(convert_bfp_long_to_float_long_reg)
515 {
516     int r1, r2;
517     float64 op2;
518 
519     RRE(inst, regs, r1, r2);
520     //logmsg("THDR r1=%d r2=%d\n", r1, r2);
521     HFPREG2_CHECK(r1, r2, regs);
522 
523     /* Load long BFP operand from R2 register */
524     get_float64(&op2, regs->fpr + FPR2I(r2));
525 
526     /* Convert to HFP register and set condition code */
527     regs->psw.cc =
528         cnvt_bfp_to_hfp (&op2,
529                          regs->fpr + FPR2I(r1));
530 
531 } /* end DEF_INST(convert_bfp_long_to_float_long_reg) */
532 
533 /*-------------------------------------------------------------------*/
534 /* B358 THDER - CONVERT BFP TO HFP (short to long)             [RRE] */
535 /* Roger Bowler, 19 July 2003                                        */
536 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_short_to_float_long_reg)537 DEF_INST(convert_bfp_short_to_float_long_reg)
538 {
539     int r1, r2;
540     float32 op2;
541     float64 lbfp_op2;
542 
543     RRE(inst, regs, r1, r2);
544     //logmsg("THDER r1=%d r2=%d\n", r1, r2);
545     HFPREG2_CHECK(r1, r2, regs);
546 
547     /* Load short BFP operand from R2 register */
548     get_float32(&op2, regs->fpr + FPR2I(r2));
549 
550     /* Lengthen short BFP operand to long BFP */
551     lbfp_op2 = float32_to_float64(op2);
552 
553     /* Convert to HFP register and set condition code */
554     regs->psw.cc =
555         cnvt_bfp_to_hfp (&lbfp_op2,
556                          regs->fpr + FPR2I(r1));
557 
558 } /* end DEF_INST(convert_bfp_short_to_float_long_reg) */
559 
560 /*-------------------------------------------------------------------*/
561 /* B351 TBDR  - CONVERT HFP TO BFP (long)                      [RRF] */
562 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_long_to_bfp_long_reg)563 DEF_INST(convert_float_long_to_bfp_long_reg)
564 {
565     int r1, r2, m3;
566     float64 op1;
567     int sign, exp;
568     U64 fract;
569 
570     RRF_M(inst, regs, r1, r2, m3);
571     //logmsg("TBDR r1=%d r2=%d\n", r1, r2);
572     HFPREG2_CHECK(r1, r2, regs);
573     BFPRM_CHECK(m3,regs);
574 
575     regs->psw.cc =
576         cnvt_hfp_to_bfp (regs->fpr + FPR2I(r2), m3,
577             /*fractbits*/52, /*emax*/1023, /*ebias*/1023,
578             &sign, &exp, &fract);
579     op1 = float64_build(sign, exp, fract);
580 
581     put_float64(&op1, regs->fpr + FPR2I(r1));
582 
583 } /* end DEF_INST(convert_float_long_to_bfp_long_reg) */
584 
585 /*-------------------------------------------------------------------*/
586 /* B350 TBEDR - CONVERT HFP TO BFP (long to short)             [RRF] */
587 /*-------------------------------------------------------------------*/
DEF_INST(convert_float_long_to_bfp_short_reg)588 DEF_INST(convert_float_long_to_bfp_short_reg)
589 {
590     int r1, r2, m3;
591     float32 op1;
592     int sign, exp;
593     U64 fract;
594 
595     RRF_M(inst, regs, r1, r2, m3);
596     //logmsg("TBEDR r1=%d r2=%d\n", r1, r2);
597     HFPREG2_CHECK(r1, r2, regs);
598     BFPRM_CHECK(m3,regs);
599 
600     regs->psw.cc =
601         cnvt_hfp_to_bfp (regs->fpr + FPR2I(r2), m3,
602             /*fractbits*/23, /*emax*/127, /*ebias*/127,
603             &sign, &exp, &fract);
604     op1 = float32_build(sign, exp, (U32)fract);
605 
606     put_float32(&op1, regs->fpr + FPR2I(r1));
607 
608 } /* end DEF_INST(convert_float_long_to_bfp_short_reg) */
609 #endif /*defined(FEATURE_FPS_EXTENSIONS)*/
610 
611 /*
612  * Chapter 19. Binary-Floating-Point Instructions
613  * Most of these instructions were defined as an update to ESA/390.
614  * z/Architecture has added instructions for 64-bit integers.
615  */
616 
617 /*-------------------------------------------------------------------*/
618 /* ADD (extended)                                                    */
619 /*-------------------------------------------------------------------*/
add_ebfp(float128 * op1,float128 * op2,REGS * regs)620 static int add_ebfp(float128 *op1, float128 *op2, REGS *regs)
621 {
622     int code;
623     float128 result;
624 
625     float_clear_exception_flags();
626     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
627     result = float128_add(*op1, *op2);
628     code = float_exception(regs);
629     *op1 = result;
630     regs->psw.cc = float128_is_nan(result) ? 3 :
631                    float128_is_zero(result) ? 0 :
632                    float128_is_neg(result) ? 1 : 2;
633     return code;
634 
635 } /* end function add_ebfp */
636 
637 /*-------------------------------------------------------------------*/
638 /* B34A AXBR  - ADD (extended BFP)                             [RRE] */
639 /*-------------------------------------------------------------------*/
DEF_INST(add_bfp_ext_reg)640 DEF_INST(add_bfp_ext_reg)
641 {
642     int r1, r2;
643     float128 op1, op2;
644     int pgm_check;
645 
646     RRE(inst, regs, r1, r2);
647     //logmsg("AXBR r1=%d r2=%d\n", r1, r2);
648     BFPINST_CHECK(regs);
649     BFPREGPAIR2_CHECK(r1, r2, regs);
650 
651     get_float128(&op1, regs->fpr + FPR2I(r1));
652     get_float128(&op2, regs->fpr + FPR2I(r2));
653 
654     pgm_check = add_ebfp(&op1, &op2, regs);
655 
656     put_float128(&op1, regs->fpr + FPR2I(r1));
657 
658     if (pgm_check) {
659         regs->program_interrupt(regs, pgm_check);
660     }
661 
662 } /* end DEF_INST(add_bfp_ext_reg) */
663 
664 /*-------------------------------------------------------------------*/
665 /* ADD (long)                                                        */
666 /*-------------------------------------------------------------------*/
add_lbfp(float64 * op1,float64 * op2,REGS * regs)667 static int add_lbfp(float64 *op1, float64 *op2, REGS *regs)
668 {
669     int code;
670     float64 result;
671 
672     float_clear_exception_flags();
673     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
674     result = float64_add(*op1, *op2);
675     code = float_exception(regs);
676     *op1 = result;
677     regs->psw.cc = float64_is_nan(result) ? 3 :
678                    float64_is_zero(result) ? 0 :
679                    float64_is_neg(result) ? 1 : 2;
680     return code;
681 
682 } /* end function add_lbfp */
683 
684 /*-------------------------------------------------------------------*/
685 /* B31A ADBR  - ADD (long BFP)                                 [RRE] */
686 /*-------------------------------------------------------------------*/
DEF_INST(add_bfp_long_reg)687 DEF_INST(add_bfp_long_reg)
688 {
689     int r1, r2;
690     float64 op1, op2;
691     int pgm_check;
692 
693     RRE(inst, regs, r1, r2);
694     //logmsg("ADBR r1=%d r2=%d\n", r1, r2);
695     BFPINST_CHECK(regs);
696 
697     get_float64(&op1, regs->fpr + FPR2I(r1));
698     get_float64(&op2, regs->fpr + FPR2I(r2));
699 
700     pgm_check = add_lbfp(&op1, &op2, regs);
701 
702     put_float64(&op1, regs->fpr + FPR2I(r1));
703 
704     if (pgm_check) {
705         regs->program_interrupt(regs, pgm_check);
706     }
707 
708 } /* end DEF_INST(add_bfp_long_reg) */
709 
710 /*-------------------------------------------------------------------*/
711 /* ED1A ADB   - ADD (long BFP)                                 [RXE] */
712 /*-------------------------------------------------------------------*/
DEF_INST(add_bfp_long)713 DEF_INST(add_bfp_long)
714 {
715     int r1, b2;
716     VADR effective_addr2;
717     float64 op1, op2;
718     int pgm_check;
719 
720     RXE(inst, regs, r1, b2, effective_addr2);
721     //logmsg("ADB r1=%d b2=%d\n", r1, b2);
722     BFPINST_CHECK(regs);
723 
724     get_float64(&op1, regs->fpr + FPR2I(r1));
725     vfetch_float64(&op2, effective_addr2, b2, regs);
726 
727     pgm_check = add_lbfp(&op1, &op2, regs);
728 
729     put_float64(&op1, regs->fpr + FPR2I(r1));
730 
731     if (pgm_check) {
732         regs->program_interrupt(regs, pgm_check);
733     }
734 
735 } /* end DEF_INST(add_bfp_long) */
736 
737 /*-------------------------------------------------------------------*/
738 /* ADD (short)                                                       */
739 /*-------------------------------------------------------------------*/
add_sbfp(float32 * op1,float32 * op2,REGS * regs)740 static int add_sbfp(float32 *op1, float32 *op2, REGS *regs)
741 {
742     int code;
743     float32 result;
744 
745     float_clear_exception_flags();
746     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
747     result = float32_add(*op1, *op2);
748     code = float_exception(regs);
749     *op1 = result;
750     regs->psw.cc = float32_is_nan(result) ? 3 :
751                    float32_is_zero(result) ? 0 :
752                    float32_is_neg(result) ? 1 : 2;
753     return code;
754 
755 } /* end function add_sbfp */
756 
757 /*-------------------------------------------------------------------*/
758 /* B30A AEBR  - ADD (short BFP)                                [RRE] */
759 /*-------------------------------------------------------------------*/
DEF_INST(add_bfp_short_reg)760 DEF_INST(add_bfp_short_reg)
761 {
762     int r1, r2;
763     float32 op1, op2;
764     int pgm_check;
765 
766     RRE(inst, regs, r1, r2);
767     //logmsg("AEBR r1=%d r2=%d\n", r1, r2);
768     BFPINST_CHECK(regs);
769 
770     get_float32(&op1, regs->fpr + FPR2I(r1));
771     get_float32(&op2, regs->fpr + FPR2I(r2));
772 
773     pgm_check = add_sbfp(&op1, &op2, regs);
774 
775     put_float32(&op1, regs->fpr + FPR2I(r1));
776 
777     if (pgm_check) {
778         regs->program_interrupt(regs, pgm_check);
779     }
780 
781 } /* end DEF_INST(add_bfp_short_reg) */
782 
783 /*-------------------------------------------------------------------*/
784 /* ED0A AEB   - ADD (short BFP)                                [RXE] */
785 /*-------------------------------------------------------------------*/
DEF_INST(add_bfp_short)786 DEF_INST(add_bfp_short)
787 {
788     int r1, b2;
789     VADR effective_addr2;
790     float32 op1, op2;
791     int pgm_check;
792 
793     RXE(inst, regs, r1, b2, effective_addr2);
794     //logmsg("AEB r1=%d b2=%d\n", r1, b2);
795     BFPINST_CHECK(regs);
796 
797     get_float32(&op1, regs->fpr + FPR2I(r1));
798     vfetch_float32(&op2, effective_addr2, b2, regs);
799 
800     pgm_check = add_sbfp(&op1, &op2, regs);
801 
802     put_float32(&op1, regs->fpr + FPR2I(r1));
803 
804     if (pgm_check) {
805         regs->program_interrupt(regs, pgm_check);
806     }
807 } /* end DEF_INST(add_bfp_short) */
808 
809 /*-------------------------------------------------------------------*/
810 /* COMPARE (extended)                                                */
811 /*-------------------------------------------------------------------*/
compare_ebfp(float128 * op1,float128 * op2,int sig,REGS * regs)812 static int compare_ebfp(float128 *op1, float128 *op2, int sig, REGS *regs)
813 {
814     int code = 0;
815 
816     float_clear_exception_flags();
817     if (float128_is_signaling_nan(*op1) || float128_is_signaling_nan(*op2)
818         || (sig && (float128_is_nan(*op1) || float128_is_nan(*op2)))) {
819         float_raise(float_flag_invalid);
820         code = float_exception(regs);
821         if (code) {
822             return code;
823         }
824     }
825 
826     regs->psw.cc = (float128_is_nan(*op1) || float128_is_nan(*op2)) ? 3 :
827         float128_eq(*op1, *op2) ? 0 :
828         float128_lt_quiet(*op1, *op2) ? 1 : 2;
829 
830     return code;
831 
832 } /* end function compare_ebfp */
833 
834 /*-------------------------------------------------------------------*/
835 /* B349 CXBR  - COMPARE (extended BFP)                         [RRE] */
836 /*-------------------------------------------------------------------*/
DEF_INST(compare_bfp_ext_reg)837 DEF_INST(compare_bfp_ext_reg)
838 {
839     int r1, r2;
840     float128 op1, op2;
841     int pgm_check;
842 
843     RRE(inst, regs, r1, r2);
844     //logmsg("CXBR r1=%d r2=%d\n", r1, r2);
845     BFPINST_CHECK(regs);
846     BFPREGPAIR2_CHECK(r1, r2, regs);
847 
848     get_float128(&op1, regs->fpr + FPR2I(r1));
849     get_float128(&op2, regs->fpr + FPR2I(r2));
850 
851     pgm_check = compare_ebfp(&op1, &op2, 0, regs);
852 
853     if (pgm_check) {
854         regs->program_interrupt(regs, pgm_check);
855     }
856 
857 } /* end DEF_INST(compare_bfp_ext_reg) */
858 
859 /*-------------------------------------------------------------------*/
860 /* COMPARE (long)                                                    */
861 /*-------------------------------------------------------------------*/
compare_lbfp(float64 * op1,float64 * op2,int sig,REGS * regs)862 static int compare_lbfp(float64 *op1, float64 *op2, int sig, REGS *regs)
863 {
864     int code = 0;
865 
866     float_clear_exception_flags();
867     if (float64_is_signaling_nan(*op1) || float64_is_signaling_nan(*op2)
868         || (sig && (float64_is_nan(*op1) || float64_is_nan(*op2)))) {
869         float_raise(float_flag_invalid);
870         code = float_exception(regs);
871         if (code) {
872             return code;
873         }
874     }
875 
876     regs->psw.cc = (float64_is_nan(*op1) || float64_is_nan(*op2)) ? 3 :
877         float64_eq(*op1, *op2) ? 0 :
878         float64_lt_quiet(*op1, *op2) ? 1 : 2;
879 
880     return code;
881 
882 } /* end function compare_lbfp */
883 
884 /*-------------------------------------------------------------------*/
885 /* B319 CDBR  - COMPARE (long BFP)                             [RRE] */
886 /*-------------------------------------------------------------------*/
DEF_INST(compare_bfp_long_reg)887 DEF_INST(compare_bfp_long_reg)
888 {
889     int r1, r2;
890     float64 op1, op2;
891     int pgm_check;
892 
893     RRE(inst, regs, r1, r2);
894     //logmsg("CDBR r1=%d r2=%d\n", r1, r2);
895     BFPINST_CHECK(regs);
896 
897     get_float64(&op1, regs->fpr + FPR2I(r1));
898     get_float64(&op2, regs->fpr + FPR2I(r2));
899 
900     pgm_check = compare_lbfp(&op1, &op2, 0, regs);
901 
902     if (pgm_check) {
903         regs->program_interrupt(regs, pgm_check);
904     }
905 
906 } /* end DEF_INST(compare_bfp_long_reg) */
907 
908 /*-------------------------------------------------------------------*/
909 /* ED19 CDB   - COMPARE (long BFP)                             [RXE] */
910 /*-------------------------------------------------------------------*/
DEF_INST(compare_bfp_long)911 DEF_INST(compare_bfp_long)
912 {
913     int r1, b2;
914     VADR effective_addr2;
915     float64 op1, op2;
916     int pgm_check;
917 
918     RXE(inst, regs, r1, b2, effective_addr2);
919     //logmsg("CDB r1=%d b2=%d\n", r1, b2);
920     BFPINST_CHECK(regs);
921 
922     get_float64(&op1, regs->fpr + FPR2I(r1));
923     vfetch_float64(&op2, effective_addr2, b2, regs);
924 
925     pgm_check = compare_lbfp(&op1, &op2, 0, regs);
926 
927     if (pgm_check) {
928         regs->program_interrupt(regs, pgm_check);
929     }
930 
931 } /* end DEF_INST(compare_bfp_long) */
932 
933 /*-------------------------------------------------------------------*/
934 /* COMPARE (short)                                                   */
935 /*-------------------------------------------------------------------*/
compare_sbfp(float32 * op1,float32 * op2,int sig,REGS * regs)936 static int compare_sbfp(float32 *op1, float32 *op2, int sig, REGS *regs)
937 {
938     int code = 0;
939 
940     float_clear_exception_flags();
941     if (float32_is_signaling_nan(*op1) || float32_is_signaling_nan(*op2)
942         || (sig && (float32_is_nan(*op1) || float32_is_nan(*op2)))) {
943         float_raise(float_flag_invalid);
944         code = float_exception(regs);
945         if (code) {
946             return code;
947         }
948     }
949 
950     regs->psw.cc = (float32_is_nan(*op1) || float32_is_nan(*op2)) ? 3 :
951         float32_eq(*op1, *op2) ? 0 :
952         float32_lt_quiet(*op1, *op2) ? 1 : 2;
953 
954     return code;
955 
956 } /* end function compare_sbfp */
957 
958 /*-------------------------------------------------------------------*/
959 /* B309 CEBR  - COMPARE (short BFP)                            [RRE] */
960 /*-------------------------------------------------------------------*/
DEF_INST(compare_bfp_short_reg)961 DEF_INST(compare_bfp_short_reg)
962 {
963     int r1, r2;
964     float32 op1, op2;
965     int pgm_check;
966 
967     RRE(inst, regs, r1, r2);
968     //logmsg("CEBR r1=%d r2=%d\n", r1, r2);
969     BFPINST_CHECK(regs);
970 
971     get_float32(&op1, regs->fpr + FPR2I(r1));
972     get_float32(&op2, regs->fpr + FPR2I(r2));
973 
974     pgm_check = compare_sbfp(&op1, &op2, 0, regs);
975 
976     if (pgm_check) {
977         regs->program_interrupt(regs, pgm_check);
978     }
979 
980 } /* end DEF_INST(compare_bfp_short_reg) */
981 
982 /*-------------------------------------------------------------------*/
983 /* ED09 CEB   - COMPARE (short BFP)                            [RXE] */
984 /*-------------------------------------------------------------------*/
DEF_INST(compare_bfp_short)985 DEF_INST(compare_bfp_short)
986 {
987     int r1, b2;
988     VADR effective_addr2;
989     float32 op1, op2;
990     int pgm_check;
991 
992     RXE(inst, regs, r1, b2, effective_addr2);
993     //logmsg("CEB r1=%d b2=%d\n", r1, b2);
994     BFPINST_CHECK(regs);
995 
996     get_float32(&op1, regs->fpr + FPR2I(r1));
997     vfetch_float32(&op2, effective_addr2, b2, regs);
998 
999     pgm_check = compare_sbfp(&op1, &op2, 0, regs);
1000 
1001     if (pgm_check) {
1002         regs->program_interrupt(regs, pgm_check);
1003     }
1004 
1005 } /* end DEF_INST(compare_bfp_short) */
1006 
1007 /*-------------------------------------------------------------------*/
1008 /* B348 KXBR  - COMPARE AND SIGNAL (extended BFP)              [RRE] */
1009 /*-------------------------------------------------------------------*/
DEF_INST(compare_and_signal_bfp_ext_reg)1010 DEF_INST(compare_and_signal_bfp_ext_reg)
1011 {
1012     int r1, r2;
1013     float128 op1, op2;
1014     int pgm_check;
1015 
1016     RRE(inst, regs, r1, r2);
1017     //logmsg("KXBR r1=%d r2=%d\n", r1, r2);
1018     BFPINST_CHECK(regs);
1019     BFPREGPAIR2_CHECK(r1, r2, regs);
1020 
1021     get_float128(&op1, regs->fpr + FPR2I(r1));
1022     get_float128(&op2, regs->fpr + FPR2I(r2));
1023 
1024     pgm_check = compare_ebfp(&op1, &op2, 1, regs);
1025 
1026     if (pgm_check) {
1027         regs->program_interrupt(regs, pgm_check);
1028     }
1029 
1030 } /* end DEF_INST(compare_and_signal_bfp_ext_reg) */
1031 
1032 /*-------------------------------------------------------------------*/
1033 /* B318 KDBR  - COMPARE AND SIGNAL (long BFP)                  [RRE] */
1034 /*-------------------------------------------------------------------*/
DEF_INST(compare_and_signal_bfp_long_reg)1035 DEF_INST(compare_and_signal_bfp_long_reg)
1036 {
1037     int r1, r2;
1038     float64 op1, op2;
1039     int pgm_check;
1040 
1041     RRE(inst, regs, r1, r2);
1042     //logmsg("KDBR r1=%d r2=%d\n", r1, r2);
1043     BFPINST_CHECK(regs);
1044 
1045     get_float64(&op1, regs->fpr + FPR2I(r1));
1046     get_float64(&op2, regs->fpr + FPR2I(r2));
1047 
1048     pgm_check = compare_lbfp(&op1, &op2, 1, regs);
1049 
1050     if (pgm_check) {
1051         regs->program_interrupt(regs, pgm_check);
1052     }
1053 
1054 } /* end DEF_INST(compare_and_signal_bfp_long_reg) */
1055 
1056 /*-------------------------------------------------------------------*/
1057 /* ED18 KDB   - COMPARE AND SIGNAL (long BFP)                  [RXE] */
1058 /*-------------------------------------------------------------------*/
DEF_INST(compare_and_signal_bfp_long)1059 DEF_INST(compare_and_signal_bfp_long)
1060 {
1061     int r1, b2;
1062     VADR effective_addr2;
1063     float64 op1, op2;
1064     int pgm_check;
1065 
1066     RXE(inst, regs, r1, b2, effective_addr2);
1067     //logmsg("KDB r1=%d b2=%d\n", r1, b2);
1068     BFPINST_CHECK(regs);
1069 
1070     get_float64(&op1, regs->fpr + FPR2I(r1));
1071     vfetch_float64(&op2, effective_addr2, b2, regs);
1072 
1073     pgm_check = compare_lbfp(&op1, &op2, 1, regs);
1074 
1075     if (pgm_check) {
1076         regs->program_interrupt(regs, pgm_check);
1077     }
1078 
1079 } /* end DEF_INST(compare_and_signal_bfp_long) */
1080 
1081 /*-------------------------------------------------------------------*/
1082 /* B308 KEBR  - COMPARE AND SIGNAL (short BFP)                 [RRE] */
1083 /*-------------------------------------------------------------------*/
DEF_INST(compare_and_signal_bfp_short_reg)1084 DEF_INST(compare_and_signal_bfp_short_reg)
1085 {
1086     int r1, r2;
1087     float32 op1, op2;
1088     int pgm_check;
1089 
1090     RRE(inst, regs, r1, r2);
1091     //logmsg("KEBR r1=%d r2=%d\n", r1, r2);
1092     BFPINST_CHECK(regs);
1093 
1094     get_float32(&op1, regs->fpr + FPR2I(r1));
1095     get_float32(&op2, regs->fpr + FPR2I(r2));
1096 
1097     pgm_check = compare_sbfp(&op1, &op2, 1, regs);
1098 
1099     if (pgm_check) {
1100         regs->program_interrupt(regs, pgm_check);
1101     }
1102 
1103 } /* end DEF_INST(compare_and_signal_bfp_short_reg) */
1104 
1105 /*-------------------------------------------------------------------*/
1106 /* ED08 KEB   - COMPARE AND SIGNAL (short BFP)                 [RXE] */
1107 /*-------------------------------------------------------------------*/
DEF_INST(compare_and_signal_bfp_short)1108 DEF_INST(compare_and_signal_bfp_short)
1109 {
1110     int r1, b2;
1111     VADR effective_addr2;
1112     float32 op1, op2;
1113     int pgm_check;
1114 
1115     RXE(inst, regs, r1, b2, effective_addr2);
1116     //logmsg("KEB r1=%d b2=%d\n", r1, b2);
1117     BFPINST_CHECK(regs);
1118 
1119     get_float32(&op1, regs->fpr + FPR2I(r1));
1120     vfetch_float32(&op2, effective_addr2, b2, regs);
1121 
1122     pgm_check = compare_sbfp(&op1, &op2, 1, regs);
1123 
1124     if (pgm_check) {
1125         regs->program_interrupt(regs, pgm_check);
1126     }
1127 
1128 } /* end DEF_INST(compare_and_signal_bfp_short) */
1129 
1130 /*-------------------------------------------------------------------*/
1131 /* B396 CXFBR - CONVERT FROM FIXED (32 to extended BFP)        [RRE] */
1132 /* B396 CXFBRA - CONVERT FROM FIXED (32 to extended BFP)       [RRF] */
1133 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix32_to_bfp_ext_reg)1134 DEF_INST(convert_fix32_to_bfp_ext_reg)
1135 {
1136     int r1, r2, m3, m4;
1137     float128 op1;
1138     S32 op2;
1139 
1140     RRE_MMA(inst, regs, r1, r2, m3, m4);
1141     //logmsg("CXFBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1142     BFPINST_CHECK(regs);
1143     BFPREGPAIR_CHECK(r1, regs);
1144     BFPRM_CHECK(m3, regs);
1145 
1146     op2 = regs->GR_L(r2);
1147     op1 = int32_to_float128(op2);
1148     put_float128(&op1, regs->fpr + FPR2I(r1));
1149 
1150 } /* end DEF_INST(convert_fix32_to_bfp_ext_reg) */
1151 
1152 /*-------------------------------------------------------------------*/
1153 /* B395 CDFBR - CONVERT FROM FIXED (32 to long BFP)            [RRE] */
1154 /* B395 CDFBRA - CONVERT FROM FIXED (32 to long BFP)           [RRF] */
1155 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix32_to_bfp_long_reg)1156 DEF_INST(convert_fix32_to_bfp_long_reg)
1157 {
1158     int r1, r2, m3, m4;
1159     float64 op1;
1160     S32 op2;
1161 
1162     RRE_MMA(inst, regs, r1, r2, m3, m4);
1163     //logmsg("CDFBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1164     BFPINST_CHECK(regs);
1165     BFPRM_CHECK(m3, regs);
1166 
1167     op2 = regs->GR_L(r2);
1168     op1 = int32_to_float64(op2);
1169     put_float64(&op1, regs->fpr + FPR2I(r1));
1170 
1171 } /* end DEF_INST(convert_fix32_to_bfp_long_reg) */
1172 
1173 /*-------------------------------------------------------------------*/
1174 /* B394 CEFBR - CONVERT FROM FIXED (32 to short BFP)           [RRE] */
1175 /* B394 CEFBRA - CONVERT FROM FIXED (32 to short BFP)          [RRF] */
1176 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix32_to_bfp_short_reg)1177 DEF_INST(convert_fix32_to_bfp_short_reg)
1178 {
1179     int r1, r2, m3, m4;
1180     float32 op1;
1181     S32 op2;
1182     int pgm_check;
1183 
1184     RRE_MMA(inst, regs, r1, r2, m3, m4);
1185     //logmsg("CEFBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1186     BFPINST_CHECK(regs);
1187     BFPRM_CHECK(m3, regs);
1188 
1189     op2 = regs->GR_L(r2);
1190 
1191     float_clear_exception_flags();
1192     set_rounding_mode(regs->fpc, m3);
1193     op1 = int32_to_float32(op2);
1194     pgm_check = float_exception_masked(regs, m4);
1195     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1196 
1197     put_float32(&op1, regs->fpr + FPR2I(r1));
1198 
1199     if (pgm_check) {
1200         regs->program_interrupt(regs, pgm_check);
1201     }
1202 
1203 } /* end DEF_INST(convert_fix32_to_bfp_short_reg) */
1204 
1205 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)
1206 /*-------------------------------------------------------------------*/
1207 /* B392 CXLFBR - CONVERT FROM LOGICAL (32 to extended BFP)     [RRF] */
1208 /*-------------------------------------------------------------------*/
DEF_INST(convert_u32_to_bfp_ext_reg)1209 DEF_INST(convert_u32_to_bfp_ext_reg)
1210 {
1211     int r1, r2, m3, m4;
1212     float128 op1;
1213     U32 op2;
1214 
1215     RRF_MM(inst, regs, r1, r2, m3, m4);
1216     //logmsg("CXLFBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1217     BFPINST_CHECK(regs);
1218     BFPREGPAIR_CHECK(r1, regs);
1219     BFPRM_CHECK(m3,regs);
1220 
1221     op2 = regs->GR_L(r2);
1222     op1 = uint32_to_float128(op2);
1223     put_float128(&op1, regs->fpr + FPR2I(r1));
1224 
1225 } /* end DEF_INST(convert_u32_to_bfp_ext_reg) */
1226 
1227 /*-------------------------------------------------------------------*/
1228 /* B391 CDLFBR - CONVERT FROM LOGICAL (32 to long BFP)         [RRF] */
1229 /*-------------------------------------------------------------------*/
DEF_INST(convert_u32_to_bfp_long_reg)1230 DEF_INST(convert_u32_to_bfp_long_reg)
1231 {
1232     int r1, r2, m3, m4;
1233     float64 op1;
1234     U32 op2;
1235 
1236     RRF_MM(inst, regs, r1, r2, m3, m4);
1237     //logmsg("CDLFBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1238     BFPINST_CHECK(regs);
1239     BFPRM_CHECK(m3,regs);
1240 
1241     op2 = regs->GR_L(r2);
1242     op1 = uint32_to_float64(op2);
1243     put_float64(&op1, regs->fpr + FPR2I(r1));
1244 
1245 } /* end DEF_INST(convert_u32_to_bfp_long_reg) */
1246 
1247 /*-------------------------------------------------------------------*/
1248 /* B390 CELFBR - CONVERT FROM LOGICAL (32 to short BFP)        [RRF] */
1249 /*-------------------------------------------------------------------*/
DEF_INST(convert_u32_to_bfp_short_reg)1250 DEF_INST(convert_u32_to_bfp_short_reg)
1251 {
1252     int r1, r2, m3, m4;
1253     float32 op1;
1254     U32 op2;
1255     int pgm_check;
1256 
1257     RRF_MM(inst, regs, r1, r2, m3, m4);
1258     //logmsg("CELFBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1259     BFPINST_CHECK(regs);
1260     BFPRM_CHECK(m3,regs);
1261 
1262     op2 = regs->GR_L(r2);
1263 
1264     float_clear_exception_flags();
1265     set_rounding_mode(regs->fpc, m3);
1266     op1 = uint32_to_float32(op2);
1267     pgm_check = float_exception_masked(regs, m4);
1268     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1269 
1270     put_float32(&op1, regs->fpr + FPR2I(r1));
1271 
1272     if (pgm_check) {
1273         regs->program_interrupt(regs, pgm_check);
1274     }
1275 
1276 } /* end DEF_INST(convert_u32_to_bfp_short_reg) */
1277 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/
1278 
1279 #if defined(FEATURE_ESAME)
1280 /*-------------------------------------------------------------------*/
1281 /* B3A6 CXGBR - CONVERT FROM FIXED (64 to extended BFP)        [RRE] */
1282 /* B3A6 CXGBRA - CONVERT FROM FIXED (64 to extended BFP)       [RRF] */
1283 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_bfp_ext_reg)1284 DEF_INST(convert_fix64_to_bfp_ext_reg)
1285 {
1286     int r1, r2, m3, m4;
1287     float128 op1;
1288     S64 op2;
1289 
1290     RRF_MMA(inst, regs, r1, r2, m3, m4);
1291     //logmsg("CXGBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1292     BFPINST_CHECK(regs);
1293     BFPREGPAIR_CHECK(r1, regs);
1294     BFPRM_CHECK(m3,regs);
1295 
1296     op2 = regs->GR_G(r2);
1297     op1 = int64_to_float128(op2);
1298     put_float128(&op1, regs->fpr + FPR2I(r1));
1299 
1300 } /* end DEF_INST(convert_fix64_to_bfp_ext_reg) */
1301 #endif /*defined(FEATURE_ESAME)*/
1302 
1303 #if defined(FEATURE_ESAME)
1304 /*-------------------------------------------------------------------*/
1305 /* B3A5 CDGBR - CONVERT FROM FIXED (64 to long BFP)            [RRE] */
1306 /* B3A5 CDGBRA - CONVERT FROM FIXED (64 to long BFP)           [RRF] */
1307 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_bfp_long_reg)1308 DEF_INST(convert_fix64_to_bfp_long_reg)
1309 {
1310     int r1, r2, m3, m4;
1311     float64 op1;
1312     S64 op2;
1313     int pgm_check;
1314 
1315     RRF_MM(inst, regs, r1, r2, m3, m4);
1316     //logmsg("CDGBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1317     BFPINST_CHECK(regs);
1318     BFPRM_CHECK(m3,regs);
1319 
1320     op2 = regs->GR_G(r2);
1321 
1322     float_clear_exception_flags();
1323     set_rounding_mode(regs->fpc, m3);
1324     op1 = int64_to_float64(op2);
1325     pgm_check = float_exception_masked(regs, m4);
1326     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1327 
1328     put_float64(&op1, regs->fpr + FPR2I(r1));
1329 
1330     if (pgm_check) {
1331         regs->program_interrupt(regs, pgm_check);
1332     }
1333 
1334 } /* end DEF_INST(convert_fix64_to_bfp_long_reg) */
1335 #endif /*defined(FEATURE_ESAME)*/
1336 
1337 #if defined(FEATURE_ESAME)
1338 /*-------------------------------------------------------------------*/
1339 /* B3A4 CEGBR - CONVERT FROM FIXED (64 to short BFP)           [RRE] */
1340 /* B3A4 CEGBRA - CONVERT FROM FIXED (64 to short BFP)          [RRF] */
1341 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_bfp_short_reg)1342 DEF_INST(convert_fix64_to_bfp_short_reg)
1343 {
1344     int r1, r2, m3, m4;
1345     float32 op1;
1346     S64 op2;
1347     int pgm_check;
1348 
1349     RRF_MM(inst, regs, r1, r2, m3, m4);
1350     //logmsg("CEGBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1351     BFPINST_CHECK(regs);
1352     BFPRM_CHECK(m3,regs);
1353 
1354     op2 = regs->GR_G(r2);
1355 
1356     float_clear_exception_flags();
1357     set_rounding_mode(regs->fpc, m3);
1358     op1 = int64_to_float32(op2);
1359     pgm_check = float_exception_masked(regs, m4);
1360     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1361 
1362     put_float32(&op1, regs->fpr + FPR2I(r1));
1363 
1364     if (pgm_check) {
1365         regs->program_interrupt(regs, pgm_check);
1366     }
1367 
1368 } /* end DEF_INST(convert_fix64_to_bfp_short_reg) */
1369 #endif /*defined(FEATURE_ESAME)*/
1370 
1371 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)
1372 #if defined(FEATURE_ESAME)
1373 /*-------------------------------------------------------------------*/
1374 /* B3A2 CXLGBR - CONVERT FROM LOGICAL (64 to extended BFP)     [RRF] */
1375 /*-------------------------------------------------------------------*/
DEF_INST(convert_u64_to_bfp_ext_reg)1376 DEF_INST(convert_u64_to_bfp_ext_reg)
1377 {
1378     int r1, r2, m3, m4;
1379     float128 op1;
1380     U64 op2;
1381 
1382     RRF_MM(inst, regs, r1, r2, m3, m4);
1383     //logmsg("CXLGBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1384     BFPINST_CHECK(regs);
1385     BFPREGPAIR_CHECK(r1, regs);
1386     BFPRM_CHECK(m3,regs);
1387 
1388     op2 = regs->GR_G(r2);
1389     op1 = uint64_to_float128(op2);
1390     put_float128(&op1, regs->fpr + FPR2I(r1));
1391 
1392 } /* end DEF_INST(convert_u64_to_bfp_ext_reg) */
1393 
1394 /*-------------------------------------------------------------------*/
1395 /* B3A1 CDLGBR - CONVERT FROM LOGICAL (64 to long BFP)         [RRF] */
1396 /*-------------------------------------------------------------------*/
DEF_INST(convert_u64_to_bfp_long_reg)1397 DEF_INST(convert_u64_to_bfp_long_reg)
1398 {
1399     int r1, r2, m3, m4;
1400     float64 op1;
1401     U64 op2;
1402     int pgm_check;
1403 
1404     RRF_MM(inst, regs, r1, r2, m3, m4);
1405     //logmsg("CDLGBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1406     BFPINST_CHECK(regs);
1407     BFPRM_CHECK(m3,regs);
1408 
1409     op2 = regs->GR_G(r2);
1410 
1411     float_clear_exception_flags();
1412     set_rounding_mode(regs->fpc, m3);
1413     op1 = uint64_to_float64(op2);
1414     pgm_check = float_exception_masked(regs, m4);
1415     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1416 
1417     put_float64(&op1, regs->fpr + FPR2I(r1));
1418 
1419     if (pgm_check) {
1420         regs->program_interrupt(regs, pgm_check);
1421     }
1422 
1423 } /* end DEF_INST(convert_u64_to_bfp_long_reg) */
1424 
1425 /*-------------------------------------------------------------------*/
1426 /* B3A0 CELGBR - CONVERT FROM LOGICAL (64 to short BFP)        [RRF] */
1427 /*-------------------------------------------------------------------*/
DEF_INST(convert_u64_to_bfp_short_reg)1428 DEF_INST(convert_u64_to_bfp_short_reg)
1429 {
1430     int r1, r2, m3, m4;
1431     float32 op1;
1432     U64 op2;
1433     int pgm_check;
1434 
1435     RRF_MM(inst, regs, r1, r2, m3, m4);
1436     //logmsg("CELGBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1437     BFPINST_CHECK(regs);
1438     BFPRM_CHECK(m3,regs);
1439 
1440     op2 = regs->GR_G(r2);
1441 
1442     float_clear_exception_flags();
1443     set_rounding_mode(regs->fpc, m3);
1444     op1 = uint64_to_float32(op2);
1445     pgm_check = float_exception_masked(regs, m4);
1446     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1447 
1448     put_float32(&op1, regs->fpr + FPR2I(r1));
1449 
1450     if (pgm_check) {
1451         regs->program_interrupt(regs, pgm_check);
1452     }
1453 
1454 } /* end DEF_INST(convert_u64_to_bfp_short_reg) */
1455 #endif /*defined(FEATURE_ESAME)*/
1456 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/
1457 
1458 /*-------------------------------------------------------------------*/
1459 /* B39A CFXBR - CONVERT TO FIXED (extended BFP to 32)          [RRF] */
1460 /* B39A CFXBRA - CONVERT TO FIXED (extended BFP to 32)         [RRF] */
1461 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_ext_to_fix32_reg)1462 DEF_INST(convert_bfp_ext_to_fix32_reg)
1463 {
1464     int r1, r2, m3, m4;
1465     S32 op1;
1466     float128 op2;
1467     int pgm_check;
1468 
1469     RRF_MMA(inst, regs, r1, r2, m3, m4);
1470     //logmsg("CFXBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1471     BFPINST_CHECK(regs);
1472     BFPREGPAIR_CHECK(r2, regs);
1473     BFPRM_CHECK(m3,regs);
1474 
1475     get_float128(&op2, regs->fpr + FPR2I(r2));
1476 
1477     float_clear_exception_flags();
1478     set_rounding_mode(regs->fpc, m3);
1479 
1480     op1 = float128_to_int32(op2);
1481     pgm_check = float_exception_masked(regs, m4);
1482 
1483     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1484 
1485     regs->GR_L(r1) = op1;
1486     regs->psw.cc =
1487         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1488         float128_is_zero(op2) ? 0 :
1489         float128_is_neg(op2) ? 1 : 2;
1490 
1491     if (pgm_check) {
1492         regs->program_interrupt(regs, pgm_check);
1493     }
1494 
1495 } /* end DEF_INST(convert_bfp_ext_to_fix32_reg) */
1496 
1497 /*-------------------------------------------------------------------*/
1498 /* B399 CFDBR - CONVERT TO FIXED (long BFP to 32)              [RRF] */
1499 /* B399 CFDBRA - CONVERT TO FIXED (long BFP to 32)             [RRF] */
1500 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_long_to_fix32_reg)1501 DEF_INST(convert_bfp_long_to_fix32_reg)
1502 {
1503     int r1, r2, m3, m4;
1504     S32 op1;
1505     float64 op2;
1506     int pgm_check;
1507 
1508     RRF_MMA(inst, regs, r1, r2, m3, m4);
1509     //logmsg("CFDBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1510     BFPINST_CHECK(regs);
1511     BFPRM_CHECK(m3,regs);
1512 
1513     get_float64(&op2, regs->fpr + FPR2I(r2));
1514 
1515     float_clear_exception_flags();
1516     set_rounding_mode(regs->fpc, m3);
1517 
1518     op1 = float64_to_int32(op2);
1519     pgm_check = float_exception_masked(regs, m4);
1520 
1521     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1522 
1523     regs->GR_L(r1) = op1;
1524     regs->psw.cc =
1525         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1526         float64_is_zero(op2) ? 0 :
1527         float64_is_neg(op2) ? 1 : 2;
1528 
1529     if (pgm_check) {
1530         regs->program_interrupt(regs, pgm_check);
1531     }
1532 
1533 } /* end DEF_INST(convert_bfp_long_to_fix32_reg) */
1534 
1535 /*-------------------------------------------------------------------*/
1536 /* B398 CFEBR - CONVERT TO FIXED (short BFP to 32)             [RRF] */
1537 /* B398 CFEBRA - CONVERT TO FIXED (short BFP to 32)            [RRF] */
1538 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_short_to_fix32_reg)1539 DEF_INST(convert_bfp_short_to_fix32_reg)
1540 {
1541     int r1, r2, m3, m4;
1542     S32 op1;
1543     float32 op2;
1544     int pgm_check;
1545 
1546     RRF_MMA(inst, regs, r1, r2, m3, m4);
1547     //logmsg("CFEBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1548     BFPINST_CHECK(regs);
1549     BFPRM_CHECK(m3,regs);
1550 
1551     get_float32(&op2, regs->fpr + FPR2I(r2));
1552 
1553     float_clear_exception_flags();
1554     set_rounding_mode(regs->fpc, m3);
1555 
1556     op1 = float32_to_int32(op2);
1557     pgm_check = float_exception_masked(regs, m4);
1558 
1559     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1560 
1561     regs->GR_L(r1) = op1;
1562     regs->psw.cc =
1563         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1564         float32_is_zero(op2) ? 0 :
1565         float32_is_neg(op2) ? 1 : 2;
1566 
1567     if (pgm_check) {
1568         regs->program_interrupt(regs, pgm_check);
1569     }
1570 
1571 } /* end DEF_INST(convert_bfp_short_to_fix32_reg) */
1572 
1573 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)
1574 /*-------------------------------------------------------------------*/
1575 /* B39E CLFXBR - CONVERT TO LOGICAL (extended BFP to 32)       [RRF] */
1576 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_ext_to_u32_reg)1577 DEF_INST(convert_bfp_ext_to_u32_reg)
1578 {
1579     int r1, r2, m3, m4;
1580     U32 op1;
1581     float128 op2;
1582     int pgm_check;
1583 
1584     RRF_MM(inst, regs, r1, r2, m3, m4);
1585     //logmsg("CLFXBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1586     BFPINST_CHECK(regs);
1587     BFPREGPAIR_CHECK(r2, regs);
1588     BFPRM_CHECK(m3,regs);
1589 
1590     get_float128(&op2, regs->fpr + FPR2I(r2));
1591 
1592     float_clear_exception_flags();
1593     set_rounding_mode(regs->fpc, m3);
1594 
1595     op1 = float128_to_uint32(op2);
1596     pgm_check = float_exception_masked(regs, m4);
1597 
1598     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1599 
1600     regs->GR_L(r1) = op1;
1601     regs->psw.cc =
1602         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1603         float128_is_zero(op2) ? 0 :
1604         float128_is_neg(op2) ? 1 : 2;
1605 
1606     if (pgm_check) {
1607         regs->program_interrupt(regs, pgm_check);
1608     }
1609 
1610 } /* end DEF_INST(convert_bfp_ext_to_u32_reg) */
1611 
1612 /*-------------------------------------------------------------------*/
1613 /* B39D CLFDBR - CONVERT TO LOGICAL (long BFP to 32)           [RRF] */
1614 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_long_to_u32_reg)1615 DEF_INST(convert_bfp_long_to_u32_reg)
1616 {
1617     int r1, r2, m3, m4;
1618     U32 op1;
1619     float64 op2;
1620     int pgm_check;
1621 
1622     RRF_MM(inst, regs, r1, r2, m3, m4);
1623     //logmsg("CLFDBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1624     BFPINST_CHECK(regs);
1625     BFPRM_CHECK(m3,regs);
1626 
1627     get_float64(&op2, regs->fpr + FPR2I(r2));
1628 
1629     float_clear_exception_flags();
1630     set_rounding_mode(regs->fpc, m3);
1631 
1632     op1 = float64_to_uint32(op2);
1633     pgm_check = float_exception_masked(regs, m4);
1634 
1635     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1636 
1637     regs->GR_L(r1) = op1;
1638     regs->psw.cc =
1639         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1640         float64_is_zero(op2) ? 0 :
1641         float64_is_neg(op2) ? 1 : 2;
1642 
1643     if (pgm_check) {
1644         regs->program_interrupt(regs, pgm_check);
1645     }
1646 
1647 } /* end DEF_INST(convert_bfp_long_to_u32_reg) */
1648 
1649 /*-------------------------------------------------------------------*/
1650 /* B39C CLFEBR - CONVERT TO LOGICAL (short BFP to 32)          [RRF] */
1651 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_short_to_u32_reg)1652 DEF_INST(convert_bfp_short_to_u32_reg)
1653 {
1654     int r1, r2, m3, m4;
1655     U32 op1;
1656     float32 op2;
1657     int pgm_check;
1658 
1659     RRF_MM(inst, regs, r1, r2, m3, m4);
1660     //logmsg("CLFEBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1661     BFPINST_CHECK(regs);
1662     BFPRM_CHECK(m3,regs);
1663 
1664     get_float32(&op2, regs->fpr + FPR2I(r2));
1665 
1666     float_clear_exception_flags();
1667     set_rounding_mode(regs->fpc, m3);
1668 
1669     op1 = float32_to_uint32(op2);
1670     pgm_check = float_exception_masked(regs, m4);
1671 
1672     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1673 
1674     regs->GR_L(r1) = op1;
1675     regs->psw.cc =
1676         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1677         float32_is_zero(op2) ? 0 :
1678         float32_is_neg(op2) ? 1 : 2;
1679 
1680     if (pgm_check) {
1681         regs->program_interrupt(regs, pgm_check);
1682     }
1683 
1684 } /* end DEF_INST(convert_bfp_short_to_u32_reg) */
1685 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/
1686 
1687 #if defined(FEATURE_ESAME)
1688 /*-------------------------------------------------------------------*/
1689 /* B3AA CGXBR - CONVERT TO FIXED (extended BFP to 64)          [RRF] */
1690 /* B3AA CGXBRA - CONVERT TO FIXED (extended BFP to 64)         [RRF] */
1691 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_ext_to_fix64_reg)1692 DEF_INST(convert_bfp_ext_to_fix64_reg)
1693 {
1694     int r1, r2, m3, m4;
1695     S64 op1;
1696     float128 op2;
1697     int pgm_check;
1698 
1699     RRF_MMA(inst, regs, r1, r2, m3, m4);
1700     //logmsg("CGXBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1701     BFPINST_CHECK(regs);
1702     BFPREGPAIR_CHECK(r2, regs);
1703     BFPRM_CHECK(m3,regs);
1704 
1705     get_float128(&op2, regs->fpr + FPR2I(r2));
1706 
1707     float_clear_exception_flags();
1708     set_rounding_mode(regs->fpc, m3);
1709 
1710     op1 = float128_to_int64(op2);
1711     pgm_check = float_exception_masked(regs, m4);
1712 
1713     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1714 
1715     regs->GR_G(r1) = op1;
1716     regs->psw.cc =
1717         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1718         float128_is_zero(op2) ? 0 :
1719         float128_is_neg(op2) ? 1 : 2;
1720 
1721     if (pgm_check) {
1722         regs->program_interrupt(regs, pgm_check);
1723     }
1724 
1725 } /* end DEF_INST(convert_bfp_ext_to_fix64_reg) */
1726 #endif /*defined(FEATURE_ESAME)*/
1727 
1728 #if defined(FEATURE_ESAME)
1729 /*-------------------------------------------------------------------*/
1730 /* B3A9 CGDBR - CONVERT TO FIXED (long BFP to 64)              [RRF] */
1731 /* B3A9 CGDBRA - CONVERT TO FIXED (long BFP to 64)             [RRF] */
1732 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_long_to_fix64_reg)1733 DEF_INST(convert_bfp_long_to_fix64_reg)
1734 {
1735     int r1, r2, m3, m4;
1736     S64 op1;
1737     float64 op2;
1738     int pgm_check;
1739 
1740     RRF_MMA(inst, regs, r1, r2, m3, m4);
1741     //logmsg("CGDBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1742     BFPINST_CHECK(regs);
1743     BFPRM_CHECK(m3,regs);
1744 
1745     get_float64(&op2, regs->fpr + FPR2I(r2));
1746 
1747     float_clear_exception_flags();
1748     set_rounding_mode(regs->fpc, m3);
1749 
1750     op1 = float64_to_int64(op2);
1751     pgm_check = float_exception_masked(regs, m4);
1752 
1753     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1754 
1755     regs->GR_G(r1) = op1;
1756     regs->psw.cc =
1757         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1758         float64_is_zero(op2) ? 0 :
1759         float64_is_neg(op2) ? 1 : 2;
1760 
1761     if (pgm_check) {
1762         regs->program_interrupt(regs, pgm_check);
1763     }
1764 
1765 } /* end DEF_INST(convert_bfp_long_to_fix64_reg) */
1766 #endif /*defined(FEATURE_ESAME)*/
1767 
1768 #if defined(FEATURE_ESAME)
1769 /*-------------------------------------------------------------------*/
1770 /* B3A8 CGEBR - CONVERT TO FIXED (short BFP to 64)             [RRF] */
1771 /* B3A8 CGEBRA - CONVERT TO FIXED (short BFP to 64)            [RRF] */
1772 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_short_to_fix64_reg)1773 DEF_INST(convert_bfp_short_to_fix64_reg)
1774 {
1775     int r1, r2, m3, m4;
1776     S64 op1;
1777     float32 op2;
1778     int pgm_check;
1779 
1780     RRF_MMA(inst, regs, r1, r2, m3, m4);
1781     //logmsg("CGEBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1782     BFPINST_CHECK(regs);
1783     BFPRM_CHECK(m3,regs);
1784 
1785     get_float32(&op2, regs->fpr + FPR2I(r2));
1786 
1787     float_clear_exception_flags();
1788     set_rounding_mode(regs->fpc, m3);
1789 
1790     op1 = float32_to_int64(op2);
1791     pgm_check = float_exception_masked(regs, m4);
1792 
1793     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1794 
1795     regs->GR_G(r1) = op1;
1796     regs->psw.cc =
1797         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1798         float32_is_zero(op2) ? 0 :
1799         float32_is_neg(op2) ? 1 : 2;
1800 
1801     if (pgm_check) {
1802         regs->program_interrupt(regs, pgm_check);
1803     }
1804 
1805 } /* end DEF_INST(convert_bfp_short_to_fix64_reg) */
1806 #endif /*defined(FEATURE_ESAME)*/
1807 
1808 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)
1809 #if defined(FEATURE_ESAME)
1810 /*-------------------------------------------------------------------*/
1811 /* B3AE CLGXBR - CONVERT TO LOGICAL (extended BFP to 64)       [RRF] */
1812 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_ext_to_u64_reg)1813 DEF_INST(convert_bfp_ext_to_u64_reg)
1814 {
1815     int r1, r2, m3, m4;
1816     U64 op1;
1817     float128 op2;
1818     int pgm_check;
1819 
1820     RRF_MM(inst, regs, r1, r2, m3, m4);
1821     //logmsg("CLGXBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1822     BFPINST_CHECK(regs);
1823     BFPREGPAIR_CHECK(r2, regs);
1824     BFPRM_CHECK(m3,regs);
1825 
1826     get_float128(&op2, regs->fpr + FPR2I(r2));
1827 
1828     float_clear_exception_flags();
1829     set_rounding_mode(regs->fpc, m3);
1830 
1831     op1 = float128_to_uint64(op2);
1832     pgm_check = float_exception_masked(regs, m4);
1833 
1834     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1835 
1836     regs->GR_G(r1) = op1;
1837     regs->psw.cc =
1838         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1839         float128_is_zero(op2) ? 0 :
1840         float128_is_neg(op2) ? 1 : 2;
1841 
1842     if (pgm_check) {
1843         regs->program_interrupt(regs, pgm_check);
1844     }
1845 
1846 } /* end DEF_INST(convert_bfp_ext_to_u64_reg) */
1847 
1848 /*-------------------------------------------------------------------*/
1849 /* B3AD CLGDBR - CONVERT TO LOGICAL (long BFP to 64)           [RRF] */
1850 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_long_to_u64_reg)1851 DEF_INST(convert_bfp_long_to_u64_reg)
1852 {
1853     int r1, r2, m3, m4;
1854     U64 op1;
1855     float64 op2;
1856     int pgm_check;
1857 
1858     RRF_MM(inst, regs, r1, r2, m3, m4);
1859     //logmsg("CLGDBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1860     BFPINST_CHECK(regs);
1861     BFPRM_CHECK(m3,regs);
1862 
1863     get_float64(&op2, regs->fpr + FPR2I(r2));
1864 
1865     float_clear_exception_flags();
1866     set_rounding_mode(regs->fpc, m3);
1867 
1868     op1 = float64_to_uint64(op2);
1869     pgm_check = float_exception_masked(regs, m4);
1870 
1871     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1872 
1873     regs->GR_G(r1) = op1;
1874     regs->psw.cc =
1875         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1876         float64_is_zero(op2) ? 0 :
1877         float64_is_neg(op2) ? 1 : 2;
1878 
1879     if (pgm_check) {
1880         regs->program_interrupt(regs, pgm_check);
1881     }
1882 
1883 } /* end DEF_INST(convert_bfp_long_to_u64_reg) */
1884 
1885 /*-------------------------------------------------------------------*/
1886 /* B3AC CLGEBR - CONVERT TO LOGICAL (short BFP to 64)          [RRF] */
1887 /*-------------------------------------------------------------------*/
DEF_INST(convert_bfp_short_to_u64_reg)1888 DEF_INST(convert_bfp_short_to_u64_reg)
1889 {
1890     int r1, r2, m3, m4;
1891     U64 op1;
1892     float32 op2;
1893     int pgm_check;
1894 
1895     RRF_MM(inst, regs, r1, r2, m3, m4);
1896     //logmsg("CLGEBR r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
1897     BFPINST_CHECK(regs);
1898     BFPRM_CHECK(m3,regs);
1899 
1900     get_float32(&op2, regs->fpr + FPR2I(r2));
1901 
1902     float_clear_exception_flags();
1903     set_rounding_mode(regs->fpc, m3);
1904 
1905     op1 = float32_to_uint64(op2);
1906     pgm_check = float_exception_masked(regs, m4);
1907 
1908     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1909 
1910     regs->GR_G(r1) = op1;
1911     regs->psw.cc =
1912         (float_get_exception_flags() & float_flag_invalid) ? 3 :
1913         float32_is_zero(op2) ? 0 :
1914         float32_is_neg(op2) ? 1 : 2;
1915 
1916     if (pgm_check) {
1917         regs->program_interrupt(regs, pgm_check);
1918     }
1919 
1920 } /* end DEF_INST(convert_bfp_short_to_u64_reg) */
1921 #endif /*defined(FEATURE_ESAME)*/
1922 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/
1923 
1924 /*-------------------------------------------------------------------*/
1925 /* DIVIDE (extended)                                                 */
1926 /*-------------------------------------------------------------------*/
divide_ebfp(float128 * op1,float128 * op2,REGS * regs)1927 static int divide_ebfp(float128 *op1, float128 *op2, REGS *regs)
1928 {
1929     int code;
1930     float128 result;
1931 
1932     float_clear_exception_flags();
1933     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1934     result = float128_div(*op1, *op2);
1935     code = float_exception(regs);
1936     *op1 = result;
1937     return code;
1938 
1939 } /* end function divide_ebfp */
1940 
1941 /*-------------------------------------------------------------------*/
1942 /* B34D DXBR  - DIVIDE (extended BFP)                          [RRE] */
1943 /*-------------------------------------------------------------------*/
DEF_INST(divide_bfp_ext_reg)1944 DEF_INST(divide_bfp_ext_reg)
1945 {
1946     int r1, r2;
1947     float128 op1, op2;
1948     int pgm_check;
1949 
1950     RRE(inst, regs, r1, r2);
1951     //logmsg("DXBR r1=%d r2=%d\n", r1, r2);
1952     BFPINST_CHECK(regs);
1953     BFPREGPAIR2_CHECK(r1, r2, regs);
1954 
1955     get_float128(&op1, regs->fpr + FPR2I(r1));
1956     get_float128(&op2, regs->fpr + FPR2I(r2));
1957 
1958     pgm_check = divide_ebfp(&op1, &op2, regs);
1959 
1960     put_float128(&op1, regs->fpr + FPR2I(r1));
1961 
1962     if (pgm_check) {
1963         regs->program_interrupt(regs, pgm_check);
1964     }
1965 
1966 } /* end DEF_INST(divide_bfp_ext_reg) */
1967 
1968 /*-------------------------------------------------------------------*/
1969 /* DIVIDE (long)                                                     */
1970 /*-------------------------------------------------------------------*/
divide_lbfp(float64 * op1,float64 * op2,REGS * regs)1971 static int divide_lbfp(float64 *op1, float64 *op2, REGS *regs)
1972 {
1973     int code;
1974     float64 result;
1975 
1976     float_clear_exception_flags();
1977     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
1978     result = float64_div(*op1, *op2);
1979     code = float_exception(regs);
1980     *op1 = result;
1981     return code;
1982 
1983 } /* end function divide_lbfp */
1984 
1985 /*-------------------------------------------------------------------*/
1986 /* B31D DDBR  - DIVIDE (long BFP)                              [RRE] */
1987 /*-------------------------------------------------------------------*/
DEF_INST(divide_bfp_long_reg)1988 DEF_INST(divide_bfp_long_reg)
1989 {
1990     int r1, r2;
1991     float64 op1, op2;
1992     int pgm_check;
1993 
1994     RRE(inst, regs, r1, r2);
1995     //logmsg("DDBR r1=%d r2=%d\n", r1, r2);
1996     BFPINST_CHECK(regs);
1997 
1998     get_float64(&op1, regs->fpr + FPR2I(r1));
1999     get_float64(&op2, regs->fpr + FPR2I(r2));
2000 
2001     pgm_check = divide_lbfp(&op1, &op2, regs);
2002 
2003     put_float64(&op1, regs->fpr + FPR2I(r1));
2004 
2005     if (pgm_check) {
2006         regs->program_interrupt(regs, pgm_check);
2007     }
2008 
2009 } /* end DEF_INST(divide_bfp_long_reg) */
2010 
2011 /*-------------------------------------------------------------------*/
2012 /* ED1D DDB   - DIVIDE (long BFP)                              [RXE] */
2013 /*-------------------------------------------------------------------*/
DEF_INST(divide_bfp_long)2014 DEF_INST(divide_bfp_long)
2015 {
2016     int r1, b2;
2017     VADR effective_addr2;
2018     float64 op1, op2;
2019     int pgm_check;
2020 
2021     RXE(inst, regs, r1, b2, effective_addr2);
2022     //logmsg("DDB r1=%d b2=%d\n", r1, b2);
2023     BFPINST_CHECK(regs);
2024 
2025     get_float64(&op1, regs->fpr + FPR2I(r1));
2026     vfetch_float64(&op2, effective_addr2, b2, regs);
2027 
2028     pgm_check = divide_lbfp(&op1, &op2, regs);
2029 
2030     put_float64(&op1, regs->fpr + FPR2I(r1));
2031 
2032     if (pgm_check) {
2033         regs->program_interrupt(regs, pgm_check);
2034     }
2035 
2036 } /* end DEF_INST(divide_bfp_long) */
2037 
2038 /*-------------------------------------------------------------------*/
2039 /* DIVIDE (short)                                                    */
2040 /*-------------------------------------------------------------------*/
divide_sbfp(float32 * op1,float32 * op2,REGS * regs)2041 static int divide_sbfp(float32 *op1, float32 *op2, REGS *regs)
2042 {
2043     int code;
2044     float32 result;
2045 
2046     float_clear_exception_flags();
2047     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2048     result = float32_div(*op1, *op2);
2049     code = float_exception(regs);
2050     *op1 = result;
2051     return code;
2052 
2053 } /* end function divide_sbfp */
2054 
2055 /*-------------------------------------------------------------------*/
2056 /* B30D DEBR  - DIVIDE (short BFP)                             [RRE] */
2057 /*-------------------------------------------------------------------*/
DEF_INST(divide_bfp_short_reg)2058 DEF_INST(divide_bfp_short_reg)
2059 {
2060     int r1, r2;
2061     float32 op1, op2;
2062     int pgm_check;
2063 
2064     RRE(inst, regs, r1, r2);
2065     //logmsg("DEBR r1=%d r2=%d\n", r1, r2);
2066     BFPINST_CHECK(regs);
2067 
2068     get_float32(&op1, regs->fpr + FPR2I(r1));
2069     get_float32(&op2, regs->fpr + FPR2I(r2));
2070 
2071     pgm_check = divide_sbfp(&op1, &op2, regs);
2072 
2073     put_float32(&op1, regs->fpr + FPR2I(r1));
2074 
2075     if (pgm_check) {
2076         regs->program_interrupt(regs, pgm_check);
2077     }
2078 
2079 } /* end DEF_INST(divide_bfp_short_reg) */
2080 
2081 /*-------------------------------------------------------------------*/
2082 /* ED0D DEB   - DIVIDE (short BFP)                             [RXE] */
2083 /*-------------------------------------------------------------------*/
DEF_INST(divide_bfp_short)2084 DEF_INST(divide_bfp_short)
2085 {
2086     int r1, b2;
2087     VADR effective_addr2;
2088     float32 op1, op2;
2089     int pgm_check;
2090 
2091     RXE(inst, regs, r1, b2, effective_addr2);
2092     //logmsg("DEB r1=%d b2=%d\n", r1, b2);
2093     BFPINST_CHECK(regs);
2094 
2095     get_float32(&op1, regs->fpr + FPR2I(r1));
2096     vfetch_float32(&op2, effective_addr2, b2, regs);
2097 
2098     pgm_check = divide_sbfp(&op1, &op2, regs);
2099 
2100     put_float32(&op1, regs->fpr + FPR2I(r1));
2101 
2102     if (pgm_check) {
2103         regs->program_interrupt(regs, pgm_check);
2104     }
2105 
2106 } /* end DEF_INST(divide_bfp_short) */
2107 
2108 /*-------------------------------------------------------------------*/
2109 /* B342 LTXBR - LOAD AND TEST (extended BFP)                   [RRE] */
2110 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_bfp_ext_reg)2111 DEF_INST(load_and_test_bfp_ext_reg)
2112 {
2113     int r1, r2;
2114     float128 op1, op2;
2115     int pgm_check = 0;
2116 
2117     RRE(inst, regs, r1, r2);
2118     //logmsg("LTXBR r1=%d r2=%d\n", r1, r2);
2119     BFPINST_CHECK(regs);
2120     BFPREGPAIR2_CHECK(r1, r2, regs);
2121 
2122     get_float128(&op2, regs->fpr + FPR2I(r2));
2123 
2124     float_clear_exception_flags();
2125     if (float128_is_signaling_nan(op2)) {
2126         float_raise(float_flag_invalid);
2127         pgm_check = float_exception(regs);
2128         op1 = float128_snan_to_qnan(op2);
2129     } else {
2130         op1 = op2;
2131     }
2132 
2133     if (pgm_check) {
2134         regs->program_interrupt(regs, pgm_check);
2135     }
2136 
2137     regs->psw.cc = float128_is_nan(op1) ? 3 :
2138                    float128_is_zero(op1) ? 0 :
2139                    float128_is_neg(op1) ? 1 : 2;
2140 
2141     put_float128(&op1, regs->fpr + FPR2I(r1));
2142 
2143 } /* end DEF_INST(load_and_test_bfp_ext_reg) */
2144 
2145 /*-------------------------------------------------------------------*/
2146 /* B312 LTDBR - LOAD AND TEST (long BFP)                       [RRE] */
2147 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_bfp_long_reg)2148 DEF_INST(load_and_test_bfp_long_reg)
2149 {
2150     int r1, r2;
2151     float64 op1, op2;
2152     int pgm_check = 0;
2153 
2154     RRE(inst, regs, r1, r2);
2155     //logmsg("LTDBR r1=%d r2=%d\n", r1, r2);
2156     BFPINST_CHECK(regs);
2157 
2158     get_float64(&op2, regs->fpr + FPR2I(r2));
2159 
2160     float_clear_exception_flags();
2161     if (float64_is_signaling_nan(op2)) {
2162         float_raise(float_flag_invalid);
2163         pgm_check = float_exception(regs);
2164         op1 = float64_snan_to_qnan(op2);
2165     } else {
2166         op1 = op2;
2167     }
2168 
2169     if (pgm_check) {
2170         regs->program_interrupt(regs, pgm_check);
2171     }
2172 
2173     regs->psw.cc = float64_is_nan(op1) ? 3 :
2174                    float64_is_zero(op1) ? 0 :
2175                    float64_is_neg(op1) ? 1 : 2;
2176 
2177     put_float64(&op1, regs->fpr + FPR2I(r1));
2178 
2179 } /* end DEF_INST(load_and_test_bfp_long_reg) */
2180 
2181 /*-------------------------------------------------------------------*/
2182 /* B302 LTEBR - LOAD AND TEST (short BFP)                      [RRE] */
2183 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_bfp_short_reg)2184 DEF_INST(load_and_test_bfp_short_reg)
2185 {
2186     int r1, r2;
2187     float32 op1, op2;
2188     int pgm_check = 0;
2189 
2190     RRE(inst, regs, r1, r2);
2191     //logmsg("LTEBR r1=%d r2=%d\n", r1, r2);
2192     BFPINST_CHECK(regs);
2193 
2194     get_float32(&op2, regs->fpr + FPR2I(r2));
2195 
2196     float_clear_exception_flags();
2197     if (float32_is_signaling_nan(op2)) {
2198         float_raise(float_flag_invalid);
2199         pgm_check = float_exception(regs);
2200         op1 = float32_snan_to_qnan(op2);
2201     } else {
2202         op1 = op2;
2203     }
2204 
2205     if (pgm_check) {
2206         regs->program_interrupt(regs, pgm_check);
2207     }
2208 
2209     regs->psw.cc = float32_is_nan(op1) ? 3 :
2210                    float32_is_zero(op1) ? 0 :
2211                    float32_is_neg(op1) ? 1 : 2;
2212 
2213     put_float32(&op1, regs->fpr + FPR2I(r1));
2214 
2215 } /* end DEF_INST(load_and_test_bfp_short_reg) */
2216 
2217 /*-------------------------------------------------------------------*/
2218 /* B357 FIEBR - LOAD FP INTEGER (short BFP)                    [RRF] */
2219 /* B357 FIEBRA - LOAD FP INTEGER (short BFP)                   [RRF] */
2220 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_bfp_short_reg)2221 DEF_INST(load_fp_int_bfp_short_reg)
2222 {
2223     int r1, r2, m3, m4, pgm_check;
2224     float32 op1, op2;
2225 
2226     RRF_MMA(inst, regs, r1, r2, m3, m4);
2227     //logmsg("FIEBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
2228     BFPINST_CHECK(regs);
2229     BFPRM_CHECK(m3,regs);
2230 
2231     get_float32(&op2, regs->fpr + FPR2I(r2));
2232 
2233     float_clear_exception_flags();
2234     set_rounding_mode(regs->fpc, m3);
2235     op1 = float32_round_to_int(op2);
2236     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2237 
2238     pgm_check = float_exception_masked(regs, m4);
2239 
2240     put_float32(&op1, regs->fpr + FPR2I(r1));
2241 
2242     if (pgm_check) {
2243         regs->program_interrupt(regs, pgm_check);
2244     }
2245 
2246 } /* end DEF_INST(load_fp_int_bfp_short_reg) */
2247 
2248 /*-------------------------------------------------------------------*/
2249 /* B35F FIDBR - LOAD FP INTEGER (long BFP)                     [RRF] */
2250 /* B35F FIDBRA - LOAD FP INTEGER (long BFP)                    [RRF] */
2251 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_bfp_long_reg)2252 DEF_INST(load_fp_int_bfp_long_reg)
2253 {
2254     int r1, r2, m3, m4, pgm_check;
2255     float64 op1, op2;
2256 
2257     RRF_MMA(inst, regs, r1, r2, m3, m4);
2258     //logmsg("FIDBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
2259     BFPINST_CHECK(regs);
2260     BFPRM_CHECK(m3,regs);
2261 
2262     get_float64(&op2, regs->fpr + FPR2I(r2));
2263 
2264     float_clear_exception_flags();
2265     set_rounding_mode(regs->fpc, m3);
2266     op1 = float64_round_to_int(op2);
2267     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2268 
2269     pgm_check = float_exception_masked(regs, m4);
2270 
2271     put_float64(&op1, regs->fpr + FPR2I(r1));
2272 
2273     if (pgm_check) {
2274         regs->program_interrupt(regs, pgm_check);
2275     }
2276 
2277 } /* end DEF_INST(load_fp_int_bfp_long_reg) */
2278 
2279 /*-------------------------------------------------------------------*/
2280 /* B347 FIXBR - LOAD FP INTEGER (extended BFP)                 [RRF] */
2281 /* B347 FIXBRA - LOAD FP INTEGER (extended BFP)                [RRF] */
2282 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_bfp_ext_reg)2283 DEF_INST(load_fp_int_bfp_ext_reg)
2284 {
2285     int r1, r2, m3, m4, pgm_check;
2286     float128 op1, op2;
2287 
2288     RRF_MMA(inst, regs, r1, r2, m3, m4);
2289     //logmsg("FIXBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
2290     BFPINST_CHECK(regs);
2291     BFPREGPAIR2_CHECK(r1, r2, regs);
2292     BFPRM_CHECK(m3,regs);
2293 
2294     get_float128(&op2, regs->fpr + FPR2I(r2));
2295 
2296     float_clear_exception_flags();
2297     set_rounding_mode(regs->fpc, m3);
2298     op1 = float128_round_to_int(op2);
2299     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2300 
2301     pgm_check = float_exception_masked(regs, m4);
2302 
2303     put_float128(&op1, regs->fpr + FPR2I(r1));
2304 
2305     if (pgm_check) {
2306         regs->program_interrupt(regs, pgm_check);
2307     }
2308 
2309 } /* end DEF_INST(load_fp_int_bfp_ext_reg) */
2310 
2311 /*-------------------------------------------------------------------*/
2312 /* B29D LFPC  - LOAD FPC                                         [S] */
2313 /* This instruction is in module esame.c                             */
2314 /*-------------------------------------------------------------------*/
2315 
2316 /*-------------------------------------------------------------------*/
2317 /* B304 LDEBR - LOAD LENGTHENED (short to long BFP)            [RRE] */
2318 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_bfp_short_to_long_reg)2319 DEF_INST(load_lengthened_bfp_short_to_long_reg)
2320 {
2321     int r1, r2;
2322     float64 op1;
2323     float32 op2;
2324     int pgm_check;
2325 
2326     RRE(inst, regs, r1, r2);
2327     //logmsg("LDEBR r1=%d r2=%d\n", r1, r2);
2328     BFPINST_CHECK(regs);
2329 
2330     float_clear_exception_flags();
2331     get_float32(&op2, regs->fpr + FPR2I(r2));
2332 
2333     op1 = float32_to_float64(op2);
2334     pgm_check = float_exception(regs);
2335 
2336     put_float64(&op1, regs->fpr + FPR2I(r1));
2337 
2338     if (pgm_check) {
2339         regs->program_interrupt(regs, pgm_check);
2340     }
2341 
2342 } /* end DEF_INST(load_lengthened_bfp_short_to_long_reg) */
2343 
2344 /*-------------------------------------------------------------------*/
2345 /* ED04 LDEB  - LOAD LENGTHENED (short to long BFP)            [RXE] */
2346 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_bfp_short_to_long)2347 DEF_INST(load_lengthened_bfp_short_to_long)
2348 {
2349     int r1, b2;
2350     VADR effective_addr2;
2351     float64 op1;
2352     float32 op2;
2353     int pgm_check;
2354 
2355     RXE(inst, regs, r1, b2, effective_addr2);
2356     //logmsg("LDEB r1=%d b2=%d\n", r1, b2);
2357     BFPINST_CHECK(regs);
2358 
2359     float_clear_exception_flags();
2360     vfetch_float32(&op2, effective_addr2, b2, regs);
2361 
2362     op1 = float32_to_float64(op2);
2363     pgm_check = float_exception(regs);
2364 
2365     put_float64(&op1, regs->fpr + FPR2I(r1));
2366 
2367     if (pgm_check) {
2368         regs->program_interrupt(regs, pgm_check);
2369     }
2370 
2371 } /* end DEF_INST(load_lengthened_bfp_short_to_long) */
2372 
2373 /*-------------------------------------------------------------------*/
2374 /* B305 LXDBR - LOAD LENGTHENED (long to extended BFP)         [RRE] */
2375 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_bfp_long_to_ext_reg)2376 DEF_INST(load_lengthened_bfp_long_to_ext_reg)
2377 {
2378     int r1, r2;
2379     float128 op1;
2380     float64 op2;
2381     int pgm_check;
2382 
2383     RRE(inst, regs, r1, r2);
2384     //logmsg("LXDBR r1=%d r2=%d\n", r1, r2);
2385     BFPINST_CHECK(regs);
2386     BFPREGPAIR_CHECK(r1, regs);
2387 
2388     float_clear_exception_flags();
2389     get_float64(&op2, regs->fpr + FPR2I(r2));
2390 
2391     op1 = float64_to_float128(op2);
2392     pgm_check = float_exception(regs);
2393 
2394     put_float128(&op1, regs->fpr + FPR2I(r1));
2395 
2396     if (pgm_check) {
2397         regs->program_interrupt(regs, pgm_check);
2398     }
2399 
2400 } /* end DEF_INST(load_lengthened_bfp_long_to_ext_reg) */
2401 
2402 /*-------------------------------------------------------------------*/
2403 /* ED05 LXDB  - LOAD LENGTHENED (long to extended BFP)         [RXE] */
2404 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_bfp_long_to_ext)2405 DEF_INST(load_lengthened_bfp_long_to_ext)
2406 {
2407     int r1, b2;
2408     VADR effective_addr2;
2409     float128 op1;
2410     float64 op2;
2411     int pgm_check;
2412 
2413     RXE(inst, regs, r1, b2, effective_addr2);
2414     //logmsg("LXDB r1=%d b2=%d\n", r1, b2);
2415     BFPINST_CHECK(regs);
2416     BFPREGPAIR_CHECK(r1, regs);
2417 
2418     float_clear_exception_flags();
2419     vfetch_float64(&op2, effective_addr2, b2, regs);
2420 
2421     op1 = float64_to_float128(op2);
2422     pgm_check = float_exception(regs);
2423 
2424     put_float128(&op1, regs->fpr + FPR2I(r1));
2425 
2426     if (pgm_check) {
2427         regs->program_interrupt(regs, pgm_check);
2428     }
2429 
2430 } /* end DEF_INST(load_lengthened_bfp_long_to_ext) */
2431 
2432 /*-------------------------------------------------------------------*/
2433 /* B306 LXEBR - LOAD LENGTHENED (short to extended BFP)        [RRE] */
2434 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_bfp_short_to_ext_reg)2435 DEF_INST(load_lengthened_bfp_short_to_ext_reg)
2436 {
2437     int r1, r2;
2438     float128 op1;
2439     float32 op2;
2440     int pgm_check;
2441 
2442     RRE(inst, regs, r1, r2);
2443     //logmsg("LXEBR r1=%d r2=%d\n", r1, r2);
2444     BFPINST_CHECK(regs);
2445     BFPREGPAIR_CHECK(r1, regs);
2446 
2447     float_clear_exception_flags();
2448     get_float32(&op2, regs->fpr + FPR2I(r2));
2449 
2450     op1 = float32_to_float128(op2);
2451     pgm_check = float_exception(regs);
2452 
2453     put_float128(&op1, regs->fpr + FPR2I(r1));
2454 
2455     if (pgm_check) {
2456         regs->program_interrupt(regs, pgm_check);
2457     }
2458 
2459 } /* end DEF_INST(load_lengthened_bfp_short_to_ext_reg) */
2460 
2461 /*-------------------------------------------------------------------*/
2462 /* ED06 LXEB  - LOAD LENGTHENED (short to extended BFP)        [RXE] */
2463 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_bfp_short_to_ext)2464 DEF_INST(load_lengthened_bfp_short_to_ext)
2465 {
2466     int r1, b2;
2467     VADR effective_addr2;
2468     float128 op1;
2469     float32 op2;
2470     int pgm_check;
2471 
2472     RXE(inst, regs, r1, b2, effective_addr2);
2473     //logmsg("LXEB r1=%d b2=%d\n", r1, b2);
2474     BFPINST_CHECK(regs);
2475     BFPREGPAIR_CHECK(r1, regs);
2476 
2477     float_clear_exception_flags();
2478     vfetch_float32(&op2, effective_addr2, b2, regs);
2479 
2480     op1 = float32_to_float128(op2);
2481     pgm_check = float_exception(regs);
2482 
2483     put_float128(&op1, regs->fpr + FPR2I(r1));
2484 
2485     if (pgm_check) {
2486         regs->program_interrupt(regs, pgm_check);
2487     }
2488 
2489 } /* end DEF_INST(load_lengthened_bfp_short_to_ext) */
2490 
2491 /*-------------------------------------------------------------------*/
2492 /* B341 LNXBR - LOAD NEGATIVE (extended BFP)                   [RRE] */
2493 /*-------------------------------------------------------------------*/
DEF_INST(load_negative_bfp_ext_reg)2494 DEF_INST(load_negative_bfp_ext_reg)
2495 {
2496     int r1, r2;
2497     float128 op1, op2;
2498 
2499     RRE(inst, regs, r1, r2);
2500     //logmsg("LNXBR r1=%d r2=%d\n", r1, r2);
2501     BFPINST_CHECK(regs);
2502     BFPREGPAIR2_CHECK(r1, r2, regs);
2503 
2504     get_float128(&op2, regs->fpr + FPR2I(r2));
2505 
2506     op1 = float128_neg(op2);
2507 
2508     regs->psw.cc = float128_is_nan(op1) ? 3 :
2509                    float128_is_zero(op1) ? 0 : 1;
2510 
2511     put_float128(&op1, regs->fpr + FPR2I(r1));
2512 
2513 } /* end DEF_INST(load_negative_bfp_ext_reg) */
2514 
2515 /*-------------------------------------------------------------------*/
2516 /* B311 LNDBR - LOAD NEGATIVE (long BFP)                       [RRE] */
2517 /*-------------------------------------------------------------------*/
DEF_INST(load_negative_bfp_long_reg)2518 DEF_INST(load_negative_bfp_long_reg)
2519 {
2520     int r1, r2;
2521     float64 op1, op2;
2522 
2523     RRE(inst, regs, r1, r2);
2524     //logmsg("LNDBR r1=%d r2=%d\n", r1, r2);
2525     BFPINST_CHECK(regs);
2526 
2527     get_float64(&op2, regs->fpr + FPR2I(r2));
2528 
2529     op1 = float64_neg(op2);
2530 
2531     regs->psw.cc = float64_is_nan(op1) ? 3 :
2532                    float64_is_zero(op1) ? 0 : 1;
2533 
2534     put_float64(&op1, regs->fpr + FPR2I(r1));
2535 
2536 } /* end DEF_INST(load_negative_bfp_long_reg) */
2537 
2538 /*-------------------------------------------------------------------*/
2539 /* B301 LNEBR - LOAD NEGATIVE (short BFP)                      [RRE] */
2540 /*-------------------------------------------------------------------*/
DEF_INST(load_negative_bfp_short_reg)2541 DEF_INST(load_negative_bfp_short_reg)
2542 {
2543     int r1, r2;
2544     float32 op1, op2;
2545 
2546     RRE(inst, regs, r1, r2);
2547     //logmsg("LNEBR r1=%d r2=%d\n", r1, r2);
2548     BFPINST_CHECK(regs);
2549 
2550     get_float32(&op2, regs->fpr + FPR2I(r2));
2551 
2552     op1 = float32_neg(op2);
2553 
2554     regs->psw.cc = float32_is_nan(op1) ? 3 :
2555                    float32_is_zero(op1) ? 0 : 1;
2556 
2557     put_float32(&op1, regs->fpr + FPR2I(r1));
2558 
2559 } /* end DEF_INST(load_negative_bfp_short_reg) */
2560 
2561 /*-------------------------------------------------------------------*/
2562 /* B343 LCXBR - LOAD COMPLEMENT (extended BFP)                 [RRE] */
2563 /*-------------------------------------------------------------------*/
DEF_INST(load_complement_bfp_ext_reg)2564 DEF_INST(load_complement_bfp_ext_reg)
2565 {
2566     int r1, r2;
2567     float128 op1, op2;
2568 
2569     RRE(inst, regs, r1, r2);
2570     //logmsg("LCXBR r1=%d r2=%d\n", r1, r2);
2571     BFPINST_CHECK(regs);
2572     BFPREGPAIR2_CHECK(r1, r2, regs);
2573 
2574     get_float128(&op2, regs->fpr + FPR2I(r2));
2575 
2576     op1 = float128_is_neg(op2) ? float128_pos(op2) : float128_neg(op2);
2577 
2578     regs->psw.cc = float128_is_nan(op1) ? 3 :
2579                    float128_is_zero(op1) ? 0 :
2580                    float128_is_neg(op1) ? 1 : 2;
2581 
2582     put_float128(&op1, regs->fpr + FPR2I(r1));
2583 
2584 } /* end DEF_INST(load_complement_bfp_ext_reg) */
2585 
2586 /*-------------------------------------------------------------------*/
2587 /* B313 LCDBR - LOAD COMPLEMENT (long BFP)                     [RRE] */
2588 /*-------------------------------------------------------------------*/
DEF_INST(load_complement_bfp_long_reg)2589 DEF_INST(load_complement_bfp_long_reg)
2590 {
2591     int r1, r2;
2592     float64 op1, op2;
2593 
2594     RRE(inst, regs, r1, r2);
2595     //logmsg("LCDBR r1=%d r2=%d\n", r1, r2);
2596     BFPINST_CHECK(regs);
2597 
2598     get_float64(&op2, regs->fpr + FPR2I(r2));
2599 
2600     op1 = float64_is_neg(op2) ? float64_pos(op2) : float64_neg(op2);
2601 
2602     regs->psw.cc = float64_is_nan(op1) ? 3 :
2603                    float64_is_zero(op1) ? 0 :
2604                    float64_is_neg(op1) ? 1 : 2;
2605 
2606     put_float64(&op1, regs->fpr + FPR2I(r1));
2607 
2608 } /* end DEF_INST(load_complement_bfp_long_reg) */
2609 
2610 /*-------------------------------------------------------------------*/
2611 /* B303 LCEBR - LOAD COMPLEMENT (short BFP)                    [RRE] */
2612 /*-------------------------------------------------------------------*/
DEF_INST(load_complement_bfp_short_reg)2613 DEF_INST(load_complement_bfp_short_reg)
2614 {
2615     int r1, r2;
2616     float32 op1, op2;
2617 
2618     RRE(inst, regs, r1, r2);
2619     //logmsg("LCEBR r1=%d r2=%d\n", r1, r2);
2620     BFPINST_CHECK(regs);
2621 
2622     get_float32(&op2, regs->fpr + FPR2I(r2));
2623 
2624     op1 = float32_is_neg(op2) ? float32_pos(op2) : float32_neg(op2);
2625 
2626     regs->psw.cc = float32_is_nan(op1) ? 3 :
2627                    float32_is_zero(op1) ? 0 :
2628                    float32_is_neg(op1) ? 1 : 2;
2629 
2630     put_float32(&op1, regs->fpr + FPR2I(r1));
2631 
2632 } /* end DEF_INST(load_complement_bfp_short_reg) */
2633 
2634 /*-------------------------------------------------------------------*/
2635 /* B340 LPXBR - LOAD POSITIVE (extended BFP)                   [RRE] */
2636 /*-------------------------------------------------------------------*/
DEF_INST(load_positive_bfp_ext_reg)2637 DEF_INST(load_positive_bfp_ext_reg)
2638 {
2639     int r1, r2;
2640     float128 op1, op2;
2641 
2642     RRE(inst, regs, r1, r2);
2643     //logmsg("LPXBR r1=%d r2=%d\n", r1, r2);
2644     BFPINST_CHECK(regs);
2645     BFPREGPAIR2_CHECK(r1, r2, regs);
2646 
2647     get_float128(&op2, regs->fpr + FPR2I(r2));
2648 
2649     op1 = float128_pos(op2);
2650 
2651     regs->psw.cc = float128_is_nan(op1) ? 3 :
2652                    float128_is_zero(op1) ? 0 : 2;
2653 
2654     put_float128(&op1, regs->fpr + FPR2I(r1));
2655 
2656 } /* end DEF_INST(load_positive_bfp_ext_reg) */
2657 
2658 /*-------------------------------------------------------------------*/
2659 /* B310 LPDBR - LOAD POSITIVE (long BFP)                       [RRE] */
2660 /*-------------------------------------------------------------------*/
DEF_INST(load_positive_bfp_long_reg)2661 DEF_INST(load_positive_bfp_long_reg)
2662 {
2663     int r1, r2;
2664     float64 op1, op2;
2665 
2666     RRE(inst, regs, r1, r2);
2667     //logmsg("LPDBR r1=%d r2=%d\n", r1, r2);
2668     BFPINST_CHECK(regs);
2669 
2670     get_float64(&op2, regs->fpr + FPR2I(r2));
2671 
2672     op1 = float64_pos(op2);
2673 
2674     regs->psw.cc = float64_is_nan(op1) ? 3 :
2675                    float64_is_zero(op1) ? 0 : 2;
2676 
2677     put_float64(&op1, regs->fpr + FPR2I(r1));
2678 
2679 } /* end DEF_INST(load_positive_bfp_long_reg) */
2680 
2681 /*-------------------------------------------------------------------*/
2682 /* B300 LPEBR - LOAD POSITIVE (short BFP)                      [RRE] */
2683 /*-------------------------------------------------------------------*/
DEF_INST(load_positive_bfp_short_reg)2684 DEF_INST(load_positive_bfp_short_reg)
2685 {
2686     int r1, r2;
2687     float32 op1, op2;
2688 
2689     RRE(inst, regs, r1, r2);
2690     //logmsg("LPEBR r1=%d r2=%d\n", r1, r2);
2691     BFPINST_CHECK(regs);
2692 
2693     get_float32(&op2, regs->fpr + FPR2I(r2));
2694 
2695     op1 = float32_pos(op2);
2696 
2697     regs->psw.cc = float32_is_nan(op1) ? 3 :
2698                    float32_is_zero(op1) ? 0 : 2;
2699 
2700     put_float32(&op1, regs->fpr + FPR2I(r1));
2701 
2702 } /* end DEF_INST(load_positive_bfp_short_reg) */
2703 
2704 /*-------------------------------------------------------------------*/
2705 /* B344 LEDBR - LOAD ROUNDED (long to short BFP)               [RRE] */
2706 /* B344 LEDBRA - LOAD ROUNDED (long to short BFP)              [RRF] */
2707 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_bfp_long_to_short_reg)2708 DEF_INST(load_rounded_bfp_long_to_short_reg)
2709 {
2710     int r1, r2, m3, m4;
2711     float32 op1;
2712     float64 op2;
2713     int pgm_check;
2714 
2715     RRE_MMA(inst, regs, r1, r2, m3, m4);
2716     //logmsg("LEDBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
2717     BFPINST_CHECK(regs);
2718     BFPRM_CHECK(m3, regs);
2719 
2720     get_float64(&op2, regs->fpr + FPR2I(r2));
2721 
2722     float_clear_exception_flags();
2723     set_rounding_mode(regs->fpc, m3);
2724     op1 = float64_to_float32(op2);
2725     pgm_check = float_exception_masked(regs, m4);
2726     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2727 
2728     put_float32(&op1, regs->fpr + FPR2I(r1));
2729 
2730     if (pgm_check && (regs->fpc & (FPC_DXC_O | FPC_DXC_U))) {
2731         op2 = float32_to_float64(op1);
2732         put_float64(&op2, regs->fpr + FPR2I(r1));
2733     }
2734 
2735     if (pgm_check) {
2736         regs->program_interrupt(regs, pgm_check);
2737     }
2738 
2739 } /* end DEF_INST(load_rounded_bfp_long_to_short_reg) */
2740 
2741 /*-------------------------------------------------------------------*/
2742 /* B345 LDXBR - LOAD ROUNDED (extended to long BFP)            [RRE] */
2743 /* B345 LDXBRA - LOAD ROUNDED (extended to long BFP)           [RRF] */
2744 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_bfp_ext_to_long_reg)2745 DEF_INST(load_rounded_bfp_ext_to_long_reg)
2746 {
2747     int r1, r2, m3, m4;
2748     float64 op1;
2749     float128 op2;
2750     int pgm_check;
2751 
2752     RRE_MMA(inst, regs, r1, r2, m3, m4);
2753     //logmsg("LDXBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
2754     BFPINST_CHECK(regs);
2755     BFPREGPAIR2_CHECK(r1, r2, regs);
2756     BFPRM_CHECK(m3, regs);
2757 
2758     get_float128(&op2, regs->fpr + FPR2I(r2));
2759 
2760     float_clear_exception_flags();
2761     set_rounding_mode(regs->fpc, m3);
2762     op1 = float128_to_float64(op2);
2763     pgm_check = float_exception_masked(regs, m4);
2764     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2765 
2766     put_float64(&op1, regs->fpr + FPR2I(r1));
2767 
2768     if (pgm_check && (regs->fpc & (FPC_DXC_O | FPC_DXC_U))) {
2769         op2 = float64_to_float128(op1);
2770         put_float128(&op2, regs->fpr + FPR2I(r1));
2771     }
2772 
2773     if (pgm_check) {
2774         regs->program_interrupt(regs, pgm_check);
2775     }
2776 
2777 } /* end DEF_INST(load_rounded_bfp_ext_to_long_reg) */
2778 
2779 /*-------------------------------------------------------------------*/
2780 /* B346 LEXBR - LOAD ROUNDED (extended to short BFP)           [RRE] */
2781 /* B346 LEXBRA - LOAD ROUNDED (extended to short BFP)          [RRF] */
2782 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_bfp_ext_to_short_reg)2783 DEF_INST(load_rounded_bfp_ext_to_short_reg)
2784 {
2785     int r1, r2, m3, m4;
2786     float32 op1;
2787     float128 op2;
2788     int pgm_check;
2789 
2790     RRE_MMA(inst, regs, r1, r2, m3, m4);
2791     //logmsg("LEXBR(A) r1=%d r2=%d m3=%d m4=%d\n", r1, r2, m3, m4);
2792     BFPINST_CHECK(regs);
2793     BFPREGPAIR2_CHECK(r1, r2, regs);
2794     BFPRM_CHECK(m3, regs);
2795 
2796     get_float128(&op2, regs->fpr + FPR2I(r2));
2797 
2798     float_clear_exception_flags();
2799     set_rounding_mode(regs->fpc, m3);
2800     op1 = float128_to_float32(op2);
2801     pgm_check = float_exception_masked(regs, m4);
2802     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2803 
2804     put_float32(&op1, regs->fpr + FPR2I(r1));
2805 
2806     if (pgm_check && (regs->fpc & (FPC_DXC_O | FPC_DXC_U))) {
2807         op2 = float32_to_float128(op1);
2808         put_float128(&op2, regs->fpr + FPR2I(r1));
2809     }
2810 
2811     if (pgm_check) {
2812         regs->program_interrupt(regs, pgm_check);
2813     }
2814 
2815 } /* end DEF_INST(load_rounded_bfp_ext_to_short_reg) */
2816 
2817 /*-------------------------------------------------------------------*/
2818 /* MULTIPLY (extended)                                               */
2819 /*-------------------------------------------------------------------*/
multiply_ebfp(float128 * op1,float128 * op2,REGS * regs)2820 static int multiply_ebfp(float128 *op1, float128 *op2, REGS *regs)
2821 {
2822     int code;
2823     float128 result;
2824 
2825     float_clear_exception_flags();
2826     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2827     result = float128_mul(*op1, *op2);
2828     code = float_exception(regs);
2829     *op1 = result;
2830     return code;
2831 
2832 } /* end function multiply_ebfp */
2833 
2834 /*-------------------------------------------------------------------*/
2835 /* B34C MXBR  - MULTIPLY (extended BFP)                        [RRE] */
2836 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_ext_reg)2837 DEF_INST(multiply_bfp_ext_reg)
2838 {
2839     int r1, r2;
2840     float128 op1, op2;
2841     int pgm_check;
2842 
2843     RRE(inst, regs, r1, r2);
2844     //logmsg("MXBR r1=%d r2=%d\n", r1, r2);
2845     BFPINST_CHECK(regs);
2846     BFPREGPAIR2_CHECK(r1, r2, regs);
2847 
2848     get_float128(&op1, regs->fpr + FPR2I(r1));
2849     get_float128(&op2, regs->fpr + FPR2I(r2));
2850 
2851     pgm_check = multiply_ebfp(&op1, &op2, regs);
2852 
2853     put_float128(&op1, regs->fpr + FPR2I(r1));
2854 
2855     if (pgm_check) {
2856         regs->program_interrupt(regs, pgm_check);
2857     }
2858 
2859 } /* end DEF_INST(multiply_bfp_ext_reg) */
2860 
2861 /*-------------------------------------------------------------------*/
2862 /* B307 MXDBR - MULTIPLY (long to extended BFP)                [RRE] */
2863 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_long_to_ext_reg)2864 DEF_INST(multiply_bfp_long_to_ext_reg)
2865 {
2866     int r1, r2;
2867     float64 op1, op2;
2868     float128 eb1, eb2;
2869     int pgm_check;
2870 
2871     RRE(inst, regs, r1, r2);
2872     //logmsg("MXDBR r1=%d r2=%d\n", r1, r2);
2873     BFPINST_CHECK(regs);
2874     BFPREGPAIR_CHECK(r1, regs);
2875 
2876     get_float64(&op1, regs->fpr + FPR2I(r1));
2877     get_float64(&op2, regs->fpr + FPR2I(r2));
2878 
2879     eb1 = float64_to_float128(op1);
2880     eb2 = float64_to_float128(op2);
2881 
2882     pgm_check = multiply_ebfp(&eb1, &eb2, regs);
2883 
2884     put_float128(&eb1, regs->fpr + FPR2I(r1));
2885 
2886     if (pgm_check) {
2887         regs->program_interrupt(regs, pgm_check);
2888     }
2889 
2890 } /* end DEF_INST(multiply_bfp_long_to_ext_reg) */
2891 
2892 /*-------------------------------------------------------------------*/
2893 /* ED07 MXDB  - MULTIPLY (long to extended BFP)                [RXE] */
2894 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_long_to_ext)2895 DEF_INST(multiply_bfp_long_to_ext)
2896 {
2897     int r1, b2;
2898     VADR effective_addr2;
2899     float64 op1, op2;
2900     float128 eb1, eb2;
2901     int pgm_check;
2902 
2903     RXE(inst, regs, r1, b2, effective_addr2);
2904     //logmsg("MXDB r1=%d b2=%d\n", r1, b2);
2905     BFPINST_CHECK(regs);
2906     BFPREGPAIR_CHECK(r1, regs);
2907 
2908     get_float64(&op1, regs->fpr + FPR2I(r1));
2909     vfetch_float64(&op2, effective_addr2, b2, regs);
2910 
2911     eb1 = float64_to_float128(op1);
2912     eb2 = float64_to_float128(op2);
2913 
2914     pgm_check = multiply_ebfp(&eb1, &eb2, regs);
2915 
2916     put_float128(&eb1, regs->fpr + FPR2I(r1));
2917 
2918     if (pgm_check) {
2919         regs->program_interrupt(regs, pgm_check);
2920     }
2921 
2922 } /* end DEF_INST(multiply_bfp_long_to_ext) */
2923 
2924 /*-------------------------------------------------------------------*/
2925 /* MULTIPLY (long)                                                   */
2926 /*-------------------------------------------------------------------*/
multiply_lbfp(float64 * op1,float64 * op2,REGS * regs)2927 static int multiply_lbfp(float64 *op1, float64 *op2, REGS *regs)
2928 {
2929     int code;
2930     float64 result;
2931 
2932     float_clear_exception_flags();
2933     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
2934     result = float64_mul(*op1, *op2);
2935     code = float_exception(regs);
2936     *op1 = result;
2937     return code;
2938 
2939 } /* end function multiply_lbfp */
2940 
2941 /*-------------------------------------------------------------------*/
2942 /* B31C MDBR  - MULTIPLY (long BFP)                            [RRE] */
2943 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_long_reg)2944 DEF_INST(multiply_bfp_long_reg)
2945 {
2946     int r1, r2;
2947     float64 op1, op2;
2948     int pgm_check;
2949 
2950     RRE(inst, regs, r1, r2);
2951     //logmsg("MDBR r1=%d r2=%d\n", r1, r2);
2952     BFPINST_CHECK(regs);
2953 
2954     get_float64(&op1, regs->fpr + FPR2I(r1));
2955     get_float64(&op2, regs->fpr + FPR2I(r2));
2956 
2957     pgm_check = multiply_lbfp(&op1, &op2, regs);
2958 
2959     put_float64(&op1, regs->fpr + FPR2I(r1));
2960 
2961     if (pgm_check) {
2962         regs->program_interrupt(regs, pgm_check);
2963     }
2964 
2965 } /* end DEF_INST(multiply_bfp_long_reg) */
2966 
2967 /*-------------------------------------------------------------------*/
2968 /* ED1C MDB   - MULTIPLY (long BFP)                            [RXE] */
2969 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_long)2970 DEF_INST(multiply_bfp_long)
2971 {
2972     int r1, b2;
2973     VADR effective_addr2;
2974     float64 op1, op2;
2975     int pgm_check;
2976 
2977     RXE(inst, regs, r1, b2, effective_addr2);
2978     //logmsg("MDB r1=%d b2=%d\n", r1, b2);
2979     BFPINST_CHECK(regs);
2980 
2981     get_float64(&op1, regs->fpr + FPR2I(r1));
2982     vfetch_float64(&op2, effective_addr2, b2, regs);
2983 
2984     pgm_check = multiply_lbfp(&op1, &op2, regs);
2985 
2986     put_float64(&op1, regs->fpr + FPR2I(r1));
2987 
2988     if (pgm_check) {
2989         regs->program_interrupt(regs, pgm_check);
2990     }
2991 
2992 } /* end DEF_INST(multiply_bfp_long) */
2993 
2994 /*-------------------------------------------------------------------*/
2995 /* B30C MDEBR - MULTIPLY (short to long BFP)                   [RRE] */
2996 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_short_to_long_reg)2997 DEF_INST(multiply_bfp_short_to_long_reg)
2998 {
2999     int r1, r2;
3000     float32 op1, op2;
3001     float64 lb1, lb2;
3002     int pgm_check;
3003 
3004     RRE(inst, regs, r1, r2);
3005     //logmsg("MDEBR r1=%d r2=%d\n", r1, r2);
3006     BFPINST_CHECK(regs);
3007 
3008     get_float32(&op1, regs->fpr + FPR2I(r1));
3009     get_float32(&op2, regs->fpr + FPR2I(r2));
3010 
3011     lb1 = float32_to_float64(op1);
3012     lb2 = float32_to_float64(op2);
3013 
3014     pgm_check = multiply_lbfp(&lb1, &lb2, regs);
3015 
3016     put_float64(&lb1, regs->fpr + FPR2I(r1));
3017 
3018     if (pgm_check) {
3019         regs->program_interrupt(regs, pgm_check);
3020     }
3021 
3022 } /* end DEF_INST(multiply_bfp_short_to_long_reg) */
3023 
3024 /*-------------------------------------------------------------------*/
3025 /* ED0C MDEB  - MULTIPLY (short to long BFP)                   [RXE] */
3026 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_short_to_long)3027 DEF_INST(multiply_bfp_short_to_long)
3028 {
3029     int r1, b2;
3030     VADR effective_addr2;
3031     float32 op1, op2;
3032     float64 lb1, lb2;
3033     int pgm_check;
3034 
3035     RXE(inst, regs, r1, b2, effective_addr2);
3036     //logmsg("MDEB r1=%d b2=%d\n", r1, b2);
3037     BFPINST_CHECK(regs);
3038 
3039     get_float32(&op1, regs->fpr + FPR2I(r1));
3040     vfetch_float32(&op2, effective_addr2, b2, regs);
3041 
3042     lb1 = float32_to_float64(op1);
3043     lb2 = float32_to_float64(op2);
3044 
3045     pgm_check = multiply_lbfp(&lb1, &lb2, regs);
3046 
3047     put_float64(&lb1, regs->fpr + FPR2I(r1));
3048 
3049     if (pgm_check) {
3050         regs->program_interrupt(regs, pgm_check);
3051     }
3052 
3053 } /* end DEF_INST(multiply_bfp_short_to_long) */
3054 
3055 /*-------------------------------------------------------------------*/
3056 /* MULTIPLY (short)                                                  */
3057 /*-------------------------------------------------------------------*/
multiply_sbfp(float32 * op1,float32 * op2,REGS * regs)3058 static int multiply_sbfp(float32 *op1, float32 *op2, REGS *regs)
3059 {
3060     int code;
3061     float32 result;
3062 
3063     float_clear_exception_flags();
3064     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3065     result = float32_mul(*op1, *op2);
3066     code = float_exception(regs);
3067     *op1 = result;
3068     return code;
3069 
3070 } /* end function multiply_sbfp */
3071 
3072 /*-------------------------------------------------------------------*/
3073 /* B317 MEEBR - MULTIPLY (short BFP)                           [RRE] */
3074 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_short_reg)3075 DEF_INST(multiply_bfp_short_reg)
3076 {
3077     int r1, r2;
3078     float32 op1, op2;
3079     int pgm_check;
3080 
3081     RRE(inst, regs, r1, r2);
3082     //logmsg("MEEBR r1=%d r2=%d\n", r1, r2);
3083     BFPINST_CHECK(regs);
3084 
3085     get_float32(&op1, regs->fpr + FPR2I(r1));
3086     get_float32(&op2, regs->fpr + FPR2I(r2));
3087 
3088     pgm_check = multiply_sbfp(&op1, &op2, regs);
3089 
3090     put_float32(&op1, regs->fpr + FPR2I(r1));
3091 
3092     if (pgm_check) {
3093         regs->program_interrupt(regs, pgm_check);
3094     }
3095 
3096 } /* end DEF_INST(multiply_bfp_short_reg) */
3097 
3098 /*-------------------------------------------------------------------*/
3099 /* ED17 MEEB  - MULTIPLY (short BFP)                           [RXE] */
3100 /*-------------------------------------------------------------------*/
DEF_INST(multiply_bfp_short)3101 DEF_INST(multiply_bfp_short)
3102 {
3103     int r1, b2;
3104     VADR effective_addr2;
3105     float32 op1, op2;
3106     int pgm_check;
3107 
3108     RXE(inst, regs, r1, b2, effective_addr2);
3109     //logmsg("MEEB r1=%d b2=%d\n", r1, b2);
3110     BFPINST_CHECK(regs);
3111 
3112     get_float32(&op1, regs->fpr + FPR2I(r1));
3113     vfetch_float32(&op2, effective_addr2, b2, regs);
3114 
3115     pgm_check = multiply_sbfp(&op1, &op2, regs);
3116 
3117     put_float32(&op1, regs->fpr + FPR2I(r1));
3118 
3119     if (pgm_check) {
3120         regs->program_interrupt(regs, pgm_check);
3121     }
3122 
3123 } /* end DEF_INST(multiply_bfp_short) */
3124 
3125 /*-------------------------------------------------------------------*/
3126 /* MULTIPLY AND ADD (long)                                           */
3127 /*-------------------------------------------------------------------*/
multiply_add_lbfp(float64 * op1,float64 * op2,float64 * op3,REGS * regs)3128 static int multiply_add_lbfp(float64 *op1, float64 *op2, float64 *op3,
3129                 REGS *regs)
3130 {
3131     int code;
3132     float64 product, result;
3133 
3134     float_clear_exception_flags();
3135     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3136     product = float64_mul(*op2, *op3);
3137     result = float64_add(product, *op1);
3138     code = float_exception(regs);
3139     *op1 = result;
3140     return code;
3141 
3142 } /* end function multiply_add_lbfp */
3143 
3144 /*-------------------------------------------------------------------*/
3145 /* B31E MADBR - MULTIPLY AND ADD (long BFP)                    [RRF] */
3146 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_bfp_long_reg)3147 DEF_INST(multiply_add_bfp_long_reg)
3148 {
3149     int r1, r2, r3;
3150     float64 op1, op2, op3;
3151     int pgm_check;
3152 
3153     RRF_R(inst, regs, r1, r2, r3);
3154     //logmsg("MADBR r1=%d r3=%d r2=%d\n", r1, r3, r2);
3155     BFPINST_CHECK(regs);
3156 
3157     get_float64(&op1, regs->fpr + FPR2I(r1));
3158     get_float64(&op2, regs->fpr + FPR2I(r2));
3159     get_float64(&op3, regs->fpr + FPR2I(r3));
3160 
3161     pgm_check = multiply_add_lbfp(&op1, &op2, &op3, regs);
3162 
3163     put_float64(&op1, regs->fpr + FPR2I(r1));
3164 
3165     if (pgm_check) {
3166         regs->program_interrupt(regs, pgm_check);
3167     }
3168 
3169 } /* end DEF_INST(multiply_add_bfp_long_reg) */
3170 
3171 /*-------------------------------------------------------------------*/
3172 /* ED1E MADB  - MULTIPLY AND ADD (long BFP)                    [RXF] */
3173 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_bfp_long)3174 DEF_INST(multiply_add_bfp_long)
3175 {
3176     int r1, r3, b2;
3177     VADR effective_addr2;
3178     float64 op1, op2, op3;
3179     int pgm_check;
3180 
3181     RXF(inst, regs, r1, r3, b2, effective_addr2);
3182     //logmsg("MADB r1=%d r3=%d b2=%d\n", r1, r3, b2);
3183     BFPINST_CHECK(regs);
3184 
3185     get_float64(&op1, regs->fpr + FPR2I(r1));
3186     vfetch_float64(&op2, effective_addr2, b2, regs);
3187     get_float64(&op3, regs->fpr + FPR2I(r3));
3188 
3189     pgm_check = multiply_add_lbfp(&op1, &op2, &op3, regs);
3190 
3191     put_float64(&op1, regs->fpr + FPR2I(r1));
3192 
3193     if (pgm_check) {
3194         regs->program_interrupt(regs, pgm_check);
3195     }
3196 
3197 } /* end DEF_INST(multiply_add_bfp_long) */
3198 
3199 /*-------------------------------------------------------------------*/
3200 /* MULTIPLY AND ADD (short)                                          */
3201 /*-------------------------------------------------------------------*/
multiply_add_sbfp(float32 * op1,float32 * op2,float32 * op3,REGS * regs)3202 static int multiply_add_sbfp(float32 *op1, float32 *op2, float32 *op3,
3203                 REGS *regs)
3204 {
3205     int code;
3206     float32 product, result;
3207 
3208     float_clear_exception_flags();
3209     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3210     product = float32_mul(*op2, *op3);
3211     result = float32_add(product, *op1);
3212     code = float_exception(regs);
3213     *op1 = result;
3214     return code;
3215 
3216 } /* end function multiply_add_sbfp */
3217 
3218 /*-------------------------------------------------------------------*/
3219 /* B30E MAEBR - MULTIPLY AND ADD (short BFP)                   [RRF] */
3220 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_bfp_short_reg)3221 DEF_INST(multiply_add_bfp_short_reg)
3222 {
3223     int r1, r2, r3;
3224     float32 op1, op2, op3;
3225     int pgm_check;
3226 
3227     RRF_R(inst, regs, r1, r2, r3);
3228     //logmsg("MAEBR r1=%d r3=%d r2=%d\n", r1, r3, r2);
3229     BFPINST_CHECK(regs);
3230 
3231     get_float32(&op1, regs->fpr + FPR2I(r1));
3232     get_float32(&op2, regs->fpr + FPR2I(r2));
3233     get_float32(&op3, regs->fpr + FPR2I(r3));
3234 
3235     pgm_check = multiply_add_sbfp(&op1, &op2, &op3, regs);
3236 
3237     put_float32(&op1, regs->fpr + FPR2I(r1));
3238 
3239     if (pgm_check) {
3240         regs->program_interrupt(regs, pgm_check);
3241     }
3242 
3243 } /* end DEF_INST(multiply_add_bfp_short_reg) */
3244 
3245 /*-------------------------------------------------------------------*/
3246 /* ED0E MAEB  - MULTIPLY AND ADD (short BFP)                   [RXF] */
3247 /*-------------------------------------------------------------------*/
DEF_INST(multiply_add_bfp_short)3248 DEF_INST(multiply_add_bfp_short)
3249 {
3250     int r1, r3, b2;
3251     VADR effective_addr2;
3252     float32 op1, op2, op3;
3253     int pgm_check;
3254 
3255     RXF(inst, regs, r1, r3, b2, effective_addr2);
3256     //logmsg("MAEB r1=%d r3=%d b2=%d\n", r1, r3, b2);
3257     BFPINST_CHECK(regs);
3258 
3259     get_float32(&op1, regs->fpr + FPR2I(r1));
3260     vfetch_float32(&op2, effective_addr2, b2, regs);
3261     get_float32(&op3, regs->fpr + FPR2I(r3));
3262 
3263     pgm_check = multiply_add_sbfp(&op1, &op2, &op3, regs);
3264 
3265     put_float32(&op1, regs->fpr + FPR2I(r1));
3266 
3267     if (pgm_check) {
3268         regs->program_interrupt(regs, pgm_check);
3269     }
3270 
3271 } /* end DEF_INST(multiply_add_bfp_short) */
3272 
3273 /*-------------------------------------------------------------------*/
3274 /* MULTIPLY AND SUBTRACT (long)                                      */
3275 /*-------------------------------------------------------------------*/
multiply_subtract_lbfp(float64 * op1,float64 * op2,float64 * op3,REGS * regs)3276 static int multiply_subtract_lbfp(float64 *op1, float64 *op2,
3277                 float64 *op3, REGS *regs)
3278 {
3279     int code;
3280     float64 product, result;
3281 
3282     float_clear_exception_flags();
3283     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3284     product = float64_mul(*op2, *op3);
3285     result = float64_sub(product, *op1);
3286     code = float_exception(regs);
3287     *op1 = result;
3288     return code;
3289 
3290 } /* end function multiply_subtract_lbfp */
3291 
3292 /*-------------------------------------------------------------------*/
3293 /* B31F MSDBR - MULTIPLY AND SUBTRACT (long BFP)               [RRF] */
3294 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_bfp_long_reg)3295 DEF_INST(multiply_subtract_bfp_long_reg)
3296 {
3297     int r1, r2, r3;
3298     float64 op1, op2, op3;
3299     int pgm_check;
3300 
3301     RRF_R(inst, regs, r1, r2, r3);
3302     //logmsg("MSDBR r1=%d r3=%d r2=%d\n", r1, r3, r2);
3303     BFPINST_CHECK(regs);
3304 
3305     get_float64(&op1, regs->fpr + FPR2I(r1));
3306     get_float64(&op2, regs->fpr + FPR2I(r2));
3307     get_float64(&op3, regs->fpr + FPR2I(r3));
3308 
3309     pgm_check = multiply_subtract_lbfp(&op1, &op2, &op3, regs);
3310 
3311     put_float64(&op1, regs->fpr + FPR2I(r1));
3312 
3313     if (pgm_check) {
3314         regs->program_interrupt(regs, pgm_check);
3315     }
3316 
3317 } /* end DEF_INST(multiply_subtract_bfp_long_reg) */
3318 
3319 /*-------------------------------------------------------------------*/
3320 /* ED1F MSDB  - MULTIPLY AND SUBTRACT (long BFP)               [RXF] */
3321 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_bfp_long)3322 DEF_INST(multiply_subtract_bfp_long)
3323 {
3324     int r1, r3, b2;
3325     VADR effective_addr2;
3326     float64 op1, op2, op3;
3327     int pgm_check;
3328 
3329     RXF(inst, regs, r1, r3, b2, effective_addr2);
3330     //logmsg("MSDB r1=%d r3=%d b2=%d\n", r1, r3, b2);
3331     BFPINST_CHECK(regs);
3332 
3333     get_float64(&op1, regs->fpr + FPR2I(r1));
3334     vfetch_float64(&op2, effective_addr2, b2, regs);
3335     get_float64(&op3, regs->fpr + FPR2I(r3));
3336 
3337     pgm_check = multiply_subtract_lbfp(&op1, &op2, &op3, regs);
3338 
3339     put_float64(&op1, regs->fpr + FPR2I(r1));
3340 
3341     if (pgm_check) {
3342         regs->program_interrupt(regs, pgm_check);
3343     }
3344 
3345 } /* end DEF_INST(multiply_subtract_bfp_long) */
3346 
3347 /*-------------------------------------------------------------------*/
3348 /* MULTIPLY AND SUBTRACT (short)                                     */
3349 /*-------------------------------------------------------------------*/
multiply_subtract_sbfp(float32 * op1,float32 * op2,float32 * op3,REGS * regs)3350 static int multiply_subtract_sbfp(float32 *op1, float32 *op2,
3351                 float32 *op3, REGS *regs)
3352 {
3353     int code;
3354     float32 product, result;
3355 
3356     float_clear_exception_flags();
3357     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3358     product = float32_mul(*op2, *op3);
3359     result = float32_sub(product, *op1);
3360     code = float_exception(regs);
3361     *op1 = result;
3362     return code;
3363 
3364 } /* end function multiply_subtract_sbfp */
3365 
3366 /*-------------------------------------------------------------------*/
3367 /* B30F MSEBR - MULTIPLY AND SUBTRACT (short BFP)              [RRF] */
3368 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_bfp_short_reg)3369 DEF_INST(multiply_subtract_bfp_short_reg)
3370 {
3371     int r1, r2, r3;
3372     float32 op1, op2, op3;
3373     int pgm_check;
3374 
3375     RRF_R(inst, regs, r1, r2, r3);
3376     //logmsg("MSEBR r1=%d r3=%d r2=%d\n", r1, r3, r2);
3377     BFPINST_CHECK(regs);
3378 
3379     get_float32(&op1, regs->fpr + FPR2I(r1));
3380     get_float32(&op2, regs->fpr + FPR2I(r2));
3381     get_float32(&op3, regs->fpr + FPR2I(r3));
3382 
3383     pgm_check = multiply_subtract_sbfp(&op1, &op2, &op3, regs);
3384 
3385     put_float32(&op1, regs->fpr + FPR2I(r1));
3386 
3387     if (pgm_check) {
3388         regs->program_interrupt(regs, pgm_check);
3389     }
3390 
3391 } /* end DEF_INST(multiply_subtract_bfp_short_reg) */
3392 
3393 /*-------------------------------------------------------------------*/
3394 /* ED0F MSEB  - MULTIPLY AND SUBTRACT (short BFP)              [RXF] */
3395 /*-------------------------------------------------------------------*/
DEF_INST(multiply_subtract_bfp_short)3396 DEF_INST(multiply_subtract_bfp_short)
3397 {
3398     int r1, r3, b2;
3399     VADR effective_addr2;
3400     float32 op1, op2, op3;
3401     int pgm_check;
3402 
3403     RXF(inst, regs, r1, r3, b2, effective_addr2);
3404     //logmsg("MSEB r1=%d r3=%d b2=%d\n", r1, r3, b2);
3405     BFPINST_CHECK(regs);
3406 
3407     get_float32(&op1, regs->fpr + FPR2I(r1));
3408     vfetch_float32(&op2, effective_addr2, b2, regs);
3409     get_float32(&op3, regs->fpr + FPR2I(r3));
3410 
3411     pgm_check = multiply_subtract_sbfp(&op1, &op2, &op3, regs);
3412 
3413     put_float32(&op1, regs->fpr + FPR2I(r1));
3414 
3415     if (pgm_check) {
3416         regs->program_interrupt(regs, pgm_check);
3417     }
3418 
3419 } /* end DEF_INST(multiply_subtract_bfp_short) */
3420 
3421 /*-------------------------------------------------------------------*/
3422 /* B384 SFPC  - SET FPC                                        [RRE] */
3423 /* This instruction is in module esame.c                             */
3424 /*-------------------------------------------------------------------*/
3425 
3426 /*-------------------------------------------------------------------*/
3427 /* B299 SRNM  - SET BFP ROUNDING MODE (2-BIT)                    [S] */
3428 /* B2B8 SRNMB - SET BFP ROUNDING MODE (3-BIT)                    [S] */
3429 /* These instructions are in module esame.c                          */
3430 /*-------------------------------------------------------------------*/
3431 
3432 /*-------------------------------------------------------------------*/
3433 /* SQUARE ROOT (extended)                                            */
3434 /*-------------------------------------------------------------------*/
squareroot_ebfp(float128 * op,REGS * regs)3435 static int squareroot_ebfp(float128 *op, REGS *regs)
3436 {
3437     int code;
3438     float128 result;
3439 
3440     float_clear_exception_flags();
3441     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3442     result = float128_sqrt(*op);
3443     code = float_exception(regs);
3444     *op = result;
3445     return code;
3446 
3447 } /* end function squareroot_ebfp */
3448 
3449 /*-------------------------------------------------------------------*/
3450 /* B316 SQXBR - SQUARE ROOT (extended BFP)                     [RRE] */
3451 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_bfp_ext_reg)3452 DEF_INST(squareroot_bfp_ext_reg)
3453 {
3454     int r1, r2;
3455     float128 op;
3456     int pgm_check;
3457 
3458     RRE(inst, regs, r1, r2);
3459     //logmsg("SQXBR r1=%d r2=%d\n", r1, r2);
3460     BFPINST_CHECK(regs);
3461     BFPREGPAIR2_CHECK(r1, r2, regs);
3462 
3463     get_float128(&op, regs->fpr + FPR2I(r2));
3464 
3465     pgm_check = squareroot_ebfp(&op, regs);
3466 
3467     put_float128(&op, regs->fpr + FPR2I(r1));
3468 
3469     if (pgm_check) {
3470         regs->program_interrupt(regs, pgm_check);
3471     }
3472 
3473 } /* end DEF_INST(squareroot_bfp_ext_reg) */
3474 
3475 /*-------------------------------------------------------------------*/
3476 /* SQUARE ROOT (long)                                                */
3477 /*-------------------------------------------------------------------*/
squareroot_lbfp(float64 * op,REGS * regs)3478 static int squareroot_lbfp(float64 *op, REGS *regs)
3479 {
3480     int code;
3481     float64 result;
3482 
3483     float_clear_exception_flags();
3484     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3485     result = float64_sqrt(*op);
3486     code = float_exception(regs);
3487     *op = result;
3488     return code;
3489 
3490 } /* end function squareroot_lbfp */
3491 
3492 /*-------------------------------------------------------------------*/
3493 /* B315 SQDBR - SQUARE ROOT (long BFP)                         [RRE] */
3494 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_bfp_long_reg)3495 DEF_INST(squareroot_bfp_long_reg)
3496 {
3497     int r1, r2;
3498     float64 op;
3499     int pgm_check;
3500 
3501     RRE(inst, regs, r1, r2);
3502     //logmsg("SQDBR r1=%d r2=%d\n", r1, r2);
3503     BFPINST_CHECK(regs);
3504 
3505     get_float64(&op, regs->fpr + FPR2I(r2));
3506 
3507     pgm_check = squareroot_lbfp(&op, regs);
3508 
3509     put_float64(&op, regs->fpr + FPR2I(r1));
3510 
3511     if (pgm_check) {
3512         regs->program_interrupt(regs, pgm_check);
3513     }
3514 
3515 } /* end DEF_INST(squareroot_bfp_long_reg) */
3516 
3517 /*-------------------------------------------------------------------*/
3518 /* ED15 SQDB  - SQUARE ROOT (long BFP)                         [RXE] */
3519 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_bfp_long)3520 DEF_INST(squareroot_bfp_long)
3521 {
3522     int r1, b2;
3523     VADR effective_addr2;
3524     float64 op;
3525     int pgm_check;
3526 
3527     RXE(inst, regs, r1, b2, effective_addr2);
3528     //logmsg("SQDB r1=%d b2=%d\n", r1, b2);
3529     BFPINST_CHECK(regs);
3530 
3531     vfetch_float64(&op, effective_addr2, b2, regs);
3532 
3533     pgm_check = squareroot_lbfp(&op, regs);
3534 
3535     put_float64(&op, regs->fpr + FPR2I(r1));
3536 
3537     if (pgm_check) {
3538         regs->program_interrupt(regs, pgm_check);
3539     }
3540 
3541 } /* end DEF_INST(squareroot_bfp_long) */
3542 
3543 /*-------------------------------------------------------------------*/
3544 /* SQUARE ROOT (short)                                               */
3545 /*-------------------------------------------------------------------*/
squareroot_sbfp(float32 * op,REGS * regs)3546 static int squareroot_sbfp(float32 *op, REGS *regs)
3547 {
3548     int code;
3549     float32 result;
3550 
3551     float_clear_exception_flags();
3552     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3553     result = float32_sqrt(*op);
3554     code = float_exception(regs);
3555     *op = result;
3556     return code;
3557 
3558 } /* end function squareroot_sbfp */
3559 
3560 /*-------------------------------------------------------------------*/
3561 /* B314 SQEBR - SQUARE ROOT (short BFP)                        [RRE] */
3562 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_bfp_short_reg)3563 DEF_INST(squareroot_bfp_short_reg)
3564 {
3565     int r1, r2;
3566     float32 op;
3567     int pgm_check;
3568 
3569     RRE(inst, regs, r1, r2);
3570     //logmsg("SQEBR r1=%d r2=%d\n", r1, r2);
3571     BFPINST_CHECK(regs);
3572 
3573     get_float32(&op, regs->fpr + FPR2I(r2));
3574 
3575     pgm_check = squareroot_sbfp(&op, regs);
3576 
3577     put_float32(&op, regs->fpr + FPR2I(r1));
3578 
3579     if (pgm_check) {
3580         regs->program_interrupt(regs, pgm_check);
3581     }
3582 
3583 } /* end DEF_INST(squareroot_bfp_short_reg) */
3584 
3585 /*-------------------------------------------------------------------*/
3586 /* ED14 SQEB  - SQUARE ROOT (short BFP)                        [RXE] */
3587 /*-------------------------------------------------------------------*/
DEF_INST(squareroot_bfp_short)3588 DEF_INST(squareroot_bfp_short)
3589 {
3590     int r1, b2;
3591     VADR effective_addr2;
3592     float32 op;
3593     int pgm_check;
3594 
3595     RXE(inst, regs, r1, b2, effective_addr2);
3596     //logmsg("SQEB r1=%d b2=%d\n", r1, b2);
3597     BFPINST_CHECK(regs);
3598 
3599     vfetch_float32(&op, effective_addr2, b2, regs);
3600 
3601     pgm_check = squareroot_sbfp(&op, regs);
3602 
3603     put_float32(&op, regs->fpr + FPR2I(r1));
3604 
3605     if (pgm_check) {
3606         regs->program_interrupt(regs, pgm_check);
3607     }
3608 
3609 } /* end DEF_INST(squareroot_bfp_short) */
3610 
3611 /*-------------------------------------------------------------------*/
3612 /* B29C STFPC - STORE FPC                                        [S] */
3613 /* This instruction is in module esame.c                             */
3614 /*-------------------------------------------------------------------*/
3615 
3616 /*-------------------------------------------------------------------*/
3617 /* SUBTRACT (extended)                                               */
3618 /*-------------------------------------------------------------------*/
subtract_ebfp(float128 * op1,float128 * op2,REGS * regs)3619 static int subtract_ebfp(float128 *op1, float128 *op2, REGS *regs)
3620 {
3621     int code;
3622     float128 result;
3623 
3624     float_clear_exception_flags();
3625     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3626     result = float128_sub(*op1, *op2);
3627     code = float_exception(regs);
3628     *op1 = result;
3629     regs->psw.cc = float128_is_nan(result) ? 3 :
3630                    float128_is_zero(result) ? 0 :
3631                    float128_is_neg(result) ? 1 : 2;
3632     return code;
3633 
3634 } /* end function subtract_ebfp */
3635 
3636 /*-------------------------------------------------------------------*/
3637 /* B34B SXBR  - SUBTRACT (extended BFP)                        [RRE] */
3638 /*-------------------------------------------------------------------*/
DEF_INST(subtract_bfp_ext_reg)3639 DEF_INST(subtract_bfp_ext_reg)
3640 {
3641     int r1, r2;
3642     float128 op1, op2;
3643     int pgm_check;
3644 
3645     RRE(inst, regs, r1, r2);
3646     //logmsg("SXBR r1=%d r2=%d\n", r1, r2);
3647     BFPINST_CHECK(regs);
3648     BFPREGPAIR2_CHECK(r1, r2, regs);
3649 
3650     get_float128(&op1, regs->fpr + FPR2I(r1));
3651     get_float128(&op2, regs->fpr + FPR2I(r2));
3652 
3653     pgm_check = subtract_ebfp(&op1, &op2, regs);
3654 
3655     put_float128(&op1, regs->fpr + FPR2I(r1));
3656 
3657     if (pgm_check) {
3658         regs->program_interrupt(regs, pgm_check);
3659     }
3660 
3661 } /* end DEF_INST(subtract_bfp_ext_reg) */
3662 
3663 /*-------------------------------------------------------------------*/
3664 /* SUBTRACT (long)                                                   */
3665 /*-------------------------------------------------------------------*/
subtract_lbfp(float64 * op1,float64 * op2,REGS * regs)3666 static int subtract_lbfp(float64 *op1, float64 *op2, REGS *regs)
3667 {
3668     int code;
3669     float64 result;
3670 
3671     float_clear_exception_flags();
3672     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3673     result = float64_sub(*op1, *op2);
3674     code = float_exception(regs);
3675     *op1 = result;
3676     regs->psw.cc = float64_is_nan(result) ? 3 :
3677                    float64_is_zero(result) ? 0 :
3678                    float64_is_neg(result) ? 1 : 2;
3679     return code;
3680 
3681 } /* end function subtract_lbfp */
3682 
3683 /*-------------------------------------------------------------------*/
3684 /* B31B SDBR  - SUBTRACT (long BFP)                            [RRE] */
3685 /*-------------------------------------------------------------------*/
DEF_INST(subtract_bfp_long_reg)3686 DEF_INST(subtract_bfp_long_reg)
3687 {
3688     int r1, r2;
3689     float64 op1, op2;
3690     int pgm_check;
3691 
3692     RRE(inst, regs, r1, r2);
3693     //logmsg("SDBR r1=%d r2=%d\n", r1, r2);
3694     BFPINST_CHECK(regs);
3695 
3696     get_float64(&op1, regs->fpr + FPR2I(r1));
3697     get_float64(&op2, regs->fpr + FPR2I(r2));
3698 
3699     pgm_check = subtract_lbfp(&op1, &op2, regs);
3700 
3701     put_float64(&op1, regs->fpr + FPR2I(r1));
3702 
3703     if (pgm_check) {
3704         regs->program_interrupt(regs, pgm_check);
3705     }
3706 
3707 } /* end DEF_INST(subtract_bfp_long_reg) */
3708 
3709 /*-------------------------------------------------------------------*/
3710 /* ED1B SDB   - SUBTRACT (long BFP)                            [RXE] */
3711 /*-------------------------------------------------------------------*/
DEF_INST(subtract_bfp_long)3712 DEF_INST(subtract_bfp_long)
3713 {
3714     int r1, b2;
3715     VADR effective_addr2;
3716     float64 op1, op2;
3717     int pgm_check;
3718 
3719     RXE(inst, regs, r1, b2, effective_addr2);
3720     //logmsg("SDB r1=%d b2=%d\n", r1, b2);
3721     BFPINST_CHECK(regs);
3722 
3723     get_float64(&op1, regs->fpr + FPR2I(r1));
3724     vfetch_float64(&op2, effective_addr2, b2, regs);
3725 
3726     pgm_check = subtract_lbfp(&op1, &op2, regs);
3727 
3728     put_float64(&op1, regs->fpr + FPR2I(r1));
3729 
3730     if (pgm_check) {
3731         regs->program_interrupt(regs, pgm_check);
3732     }
3733 
3734 } /* end DEF_INST(subtract_bfp_long) */
3735 
3736 /*-------------------------------------------------------------------*/
3737 /* SUBTRACT (short)                                                  */
3738 /*-------------------------------------------------------------------*/
subtract_sbfp(float32 * op1,float32 * op2,REGS * regs)3739 static int subtract_sbfp(float32 *op1, float32 *op2, REGS *regs)
3740 {
3741     int code;
3742     float32 result;
3743 
3744     float_clear_exception_flags();
3745     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
3746     result = float32_sub(*op1, *op2);
3747     code = float_exception(regs);
3748     *op1 = result;
3749     regs->psw.cc = float32_is_nan(result) ? 3 :
3750                    float32_is_zero(result) ? 0 :
3751                    float32_is_neg(result) ? 1 : 2;
3752     return code;
3753 
3754 } /* end function subtract_sbfp */
3755 
3756 /*-------------------------------------------------------------------*/
3757 /* B30B SEBR  - SUBTRACT (short BFP)                           [RRE] */
3758 /*-------------------------------------------------------------------*/
DEF_INST(subtract_bfp_short_reg)3759 DEF_INST(subtract_bfp_short_reg)
3760 {
3761     int r1, r2;
3762     float32 op1, op2;
3763     int pgm_check;
3764 
3765     RRE(inst, regs, r1, r2);
3766     //logmsg("SEBR r1=%d r2=%d\n", r1, r2);
3767     BFPINST_CHECK(regs);
3768 
3769     get_float32(&op1, regs->fpr + FPR2I(r1));
3770     get_float32(&op2, regs->fpr + FPR2I(r2));
3771 
3772     pgm_check = subtract_sbfp(&op1, &op2, regs);
3773 
3774     put_float32(&op1, regs->fpr + FPR2I(r1));
3775 
3776     if (pgm_check) {
3777         regs->program_interrupt(regs, pgm_check);
3778     }
3779 
3780 } /* end DEF_INST(subtract_bfp_short_reg) */
3781 
3782 /*-------------------------------------------------------------------*/
3783 /* ED0B SEB   - SUBTRACT (short BFP)                           [RXE] */
3784 /*-------------------------------------------------------------------*/
DEF_INST(subtract_bfp_short)3785 DEF_INST(subtract_bfp_short)
3786 {
3787     int r1, b2;
3788     VADR effective_addr2;
3789     float32 op1, op2;
3790     int pgm_check;
3791 
3792     RXE(inst, regs, r1, b2, effective_addr2);
3793     //logmsg("SEB r1=%d b2=%d\n", r1, b2);
3794     BFPINST_CHECK(regs);
3795 
3796     get_float32(&op1, regs->fpr + FPR2I(r1));
3797     vfetch_float32(&op2, effective_addr2, b2, regs);
3798 
3799     pgm_check = subtract_sbfp(&op1, &op2, regs);
3800 
3801     put_float32(&op1, regs->fpr + FPR2I(r1));
3802 
3803     if (pgm_check) {
3804         regs->program_interrupt(regs, pgm_check);
3805     }
3806 
3807 } /* end DEF_INST(subtract_bfp_short) */
3808 
3809 /*-------------------------------------------------------------------*/
3810 /* ED10 TCEB  - TEST DATA CLASS (short BFP)                    [RXE] */
3811 /* Per Jessen, Willem Konynenberg, 20 September 2001                 */
3812 /*-------------------------------------------------------------------*/
DEF_INST(test_data_class_bfp_short)3813 DEF_INST(test_data_class_bfp_short)
3814 {
3815     int r1, b2;
3816     VADR effective_addr2;
3817     float32 op1;
3818     int bit;
3819 
3820     RXE(inst, regs, r1, b2, effective_addr2);
3821     //logmsg("TCEB r1=%d b2=%d\n", r1, b2);
3822     BFPINST_CHECK(regs);
3823 
3824     get_float32(&op1, regs->fpr + FPR2I(r1));
3825 
3826     if (float32_is_signaling_nan(op1))
3827         bit=30;
3828     else if (float32_is_nan(op1))
3829         bit=28;
3830     else if (float32_is_inf(op1))
3831         bit=26;
3832     else if (float32_is_subnormal(op1))
3833         bit=24;
3834     else if (float32_is_zero(op1))
3835         bit=20;
3836     else
3837         bit=22;
3838 
3839     if (float32_is_neg(op1))
3840         bit++;
3841 
3842     bit=31-bit;
3843     regs->psw.cc = (effective_addr2>>bit) & 1;
3844 
3845 } /* end DEF_INST(test_data_class_bfp_short) */
3846 
3847 /*-------------------------------------------------------------------*/
3848 /* ED11 TCDB  - TEST DATA CLASS (long BFP)                     [RXE] */
3849 /* Per Jessen, Willem Konynenberg, 20 September 2001                 */
3850 /*-------------------------------------------------------------------*/
DEF_INST(test_data_class_bfp_long)3851 DEF_INST(test_data_class_bfp_long)
3852 {
3853     int r1, b2;
3854     VADR effective_addr2;
3855     float64 op1;
3856     int bit;
3857 
3858     RXE(inst, regs, r1, b2, effective_addr2);
3859     //logmsg("TCDB r1=%d b2=%d\n", r1, b2);
3860     BFPINST_CHECK(regs);
3861 
3862     get_float64(&op1, regs->fpr + FPR2I(r1));
3863 
3864     if (float64_is_signaling_nan(op1))
3865         bit=30;
3866     else if (float64_is_nan(op1))
3867         bit=28;
3868     else if (float64_is_inf(op1))
3869         bit=26;
3870     else if (float64_is_subnormal(op1))
3871         bit=24;
3872     else if (float64_is_zero(op1))
3873         bit=20;
3874     else
3875         bit=22;
3876 
3877     if (float64_is_neg(op1))
3878         bit++;
3879 
3880     bit=31-bit;
3881     regs->psw.cc = (effective_addr2>>bit) & 1;
3882 
3883 } /* end DEF_INST(test_data_class_bfp_long) */
3884 
3885 /*-------------------------------------------------------------------*/
3886 /* ED12 TCXB  - TEST DATA CLASS (extended BFP)                 [RXE] */
3887 /* Per Jessen, Willem Konynenberg, 20 September 2001                 */
3888 /*-------------------------------------------------------------------*/
DEF_INST(test_data_class_bfp_ext)3889 DEF_INST(test_data_class_bfp_ext)
3890 {
3891     int r1, b2;
3892     VADR effective_addr2;
3893     float128 op1;
3894     int bit;
3895 
3896     RXE(inst, regs, r1, b2, effective_addr2);
3897     //logmsg("TCXB r1=%d b2=%d\n", r1, b2);
3898     BFPINST_CHECK(regs);
3899     BFPREGPAIR_CHECK(r1, regs);
3900 
3901     get_float128(&op1, regs->fpr + FPR2I(r1));
3902 
3903     if (float128_is_signaling_nan(op1))
3904         bit=30;
3905     else if (float128_is_nan(op1))
3906         bit=28;
3907     else if (float128_is_inf(op1))
3908         bit=26;
3909     else if (float128_is_subnormal(op1))
3910         bit=24;
3911     else if (float128_is_zero(op1))
3912         bit=20;
3913     else
3914         bit=22;
3915 
3916     if (float128_is_neg(op1))
3917         bit++;
3918 
3919     bit=31-bit;
3920     regs->psw.cc = (effective_addr2>>bit) & 1;
3921 
3922 } /* end DEF_INST(test_data_class_bfp_ext) */
3923 
3924 /*-------------------------------------------------------------------*/
3925 /* DIVIDE TO INTEGER (long)                                          */
3926 /*-------------------------------------------------------------------*/
divint_lbfp(float64 * op1,float64 * op2,float64 * op3,int mode,REGS * regs)3927 static int divint_lbfp(float64 *op1, float64 *op2,
3928                         float64 *op3, int mode, REGS *regs)
3929 {
3930     int code;
3931     int cc;
3932     int flags;
3933     int divsign, dvrsign;
3934     float128 xop1, xop2, xop3, xtemp;
3935     float128 xmaxint64 = {0x4034000000000000ULL, 0ULL}; // 2**53
3936     float128 xfract64 = {0xFFFFFFFFFFFFFFFFULL, 0xF000000000000000ULL}; // sign+exp+52 bits
3937 
3938     divsign = float64_is_neg(*op1) ? 1 : 0;
3939     dvrsign = float64_is_neg(*op2) ? 1 : 0;
3940 
3941     float_clear_exception_flags();
3942 
3943     if (float64_is_signaling_nan(*op1)) {
3944         float_raise(float_flag_invalid);
3945         code = float_exception(regs);
3946         *op1 = float64_snan_to_qnan(*op1);
3947         *op3 = float64_snan_to_qnan(*op1);
3948         regs->psw.cc = 1;
3949         return code;
3950     }
3951 
3952     if (float64_is_signaling_nan(*op2)) {
3953         float_raise(float_flag_invalid);
3954         code = float_exception(regs);
3955         *op1 = float64_snan_to_qnan(*op2);
3956         *op3 = float64_snan_to_qnan(*op2);
3957         regs->psw.cc = 1;
3958         return code;
3959     }
3960 
3961     if (float64_is_nan(*op1)) {
3962         *op3 = *op1;
3963         regs->psw.cc = 1;
3964         return 0;
3965     }
3966 
3967     if (float64_is_nan(*op2)) {
3968         *op1 = *op2;
3969         *op3 = *op2;
3970         regs->psw.cc = 1;
3971         return 0;
3972     }
3973 
3974     if (float64_is_inf(*op1) || float64_is_zero(*op2)) {
3975         float_raise(float_flag_invalid);
3976         code = float_exception(regs);
3977         *op1 = float64_default_nan;
3978         *op3 = float64_default_nan;
3979         regs->psw.cc = 1;
3980         return code;
3981     }
3982 
3983     if (float64_is_inf(*op2)) {
3984         *op3 = (divsign != dvrsign) ? 0x8000000000000000ULL : 0ULL;
3985         regs->psw.cc = 0;
3986         return 0;
3987     }
3988 
3989     xop1 = float64_to_float128(*op1);
3990     xop2 = float64_to_float128(*op2);
3991 
3992     set_rounding_mode(regs->fpc, RM_ROUND_TOWARD_ZERO);
3993     xtemp = float128_div(xop1, xop2);
3994 
3995     flags = float_get_exception_flags();
3996     if ((flags & float_flag_inexact)
3997         && (float128_le(xmaxint64, float128_pos(xtemp)))) {
3998         /* If quotient exceeds 2**53, truncate it to form a partial
3999            quotient consisting of an implied 1 with 52 fraction bits,
4000            and set the condition code to 2 */
4001         xop3.high = xtemp.high & xfract64.high;
4002         xop3.low = xtemp.low & xfract64.low;
4003         cc = 2;
4004     } else {
4005         /* Otherwise round it to an integer according to the specified
4006            rounding mode, and set the condition code to 0 */
4007         set_rounding_mode(regs->fpc, mode);
4008         float_clear_exception_flags();
4009         xop3 = float128_round_to_int(xtemp);
4010         cc = 0;
4011     }
4012 
4013     set_rounding_mode(regs->fpc, RM_ROUND_TOWARD_ZERO);
4014     float_clear_exception_flags();
4015     xtemp = float128_mul(xop2, xop3);
4016     float_clear_exception_flags();
4017     xop1 = float128_sub(xop1, xtemp);
4018     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
4019     float_clear_exception_flags();
4020 
4021     code = float_exception(regs);
4022 
4023     if (float128_exp(xop3) > FLOAT128_BIAS + FLOAT64_BIAS) {
4024         /* If quotient exponent exceeds maximum for float64, reduce
4025            the exponent by 1536 and increase condition code by 1 */
4026         xop3 = float128_build(float128_is_neg(xop3) ? 1 : 0,
4027                         float128_exp(xop3) - 1536,
4028                         float128_fract_high(xop3),
4029                         float128_fract_low(xop3));
4030         cc += 1;
4031     }
4032 
4033     *op1 = float128_to_float64(xop1);
4034     *op3 = float128_to_float64(xop3);
4035 
4036     /* A zero remainder is negative if the dividend is negative */
4037     if (float64_is_zero(*op1)) {
4038         *op1 = divsign ? 0x8000000000000000ULL : 0ULL;
4039     }
4040 
4041     /* A zero quotient is negative if dividend and divisor have different signs */
4042     if (float64_is_zero(*op3)) {
4043         *op3 = (divsign != dvrsign) ? 0x8000000000000000ULL : 0ULL;
4044     }
4045 
4046     regs->psw.cc = cc;
4047     return code;
4048 
4049 } /* end function divint_lbfp */
4050 
4051 /*-------------------------------------------------------------------*/
4052 /* B35B DIDBR - DIVIDE TO INTEGER (long BFP)                   [RRF] */
4053 /*-------------------------------------------------------------------*/
DEF_INST(divide_integer_bfp_long_reg)4054 DEF_INST(divide_integer_bfp_long_reg)
4055 {
4056     int r1, r2, r3, m4;
4057     float64 op1, op2, op3;
4058     int pgm_check;
4059 
4060     RRF_RM(inst, regs, r1, r2, r3, m4);
4061     //logmsg("DIDBR r1=%d r3=%d r2=%d m4=%d\n", r1, r3, r2, m4);
4062     BFPINST_CHECK(regs);
4063     if (r1 == r2 || r2 == r3 || r1 == r3) {
4064         regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION);
4065     }
4066     BFPRM_CHECK(m4,regs);
4067 
4068     get_float64(&op1, regs->fpr + FPR2I(r1));
4069     get_float64(&op2, regs->fpr + FPR2I(r2));
4070 
4071     pgm_check = divint_lbfp(&op1, &op2, &op3, m4, regs);
4072 
4073     put_float64(&op1, regs->fpr + FPR2I(r1));
4074     put_float64(&op3, regs->fpr + FPR2I(r3));
4075 
4076     if (pgm_check) {
4077         regs->program_interrupt(regs, pgm_check);
4078     }
4079 
4080 } /* end DEF_INST(divide_integer_bfp_long_reg) */
4081 
4082 /*-------------------------------------------------------------------*/
4083 /* DIVIDE TO INTEGER (short)                                         */
4084 /*-------------------------------------------------------------------*/
divint_sbfp(float32 * op1,float32 * op2,float32 * op3,int mode,REGS * regs)4085 static int divint_sbfp(float32 *op1, float32 *op2,
4086                         float32 *op3, int mode, REGS *regs)
4087 {
4088     int code;
4089     int cc;
4090     int flags;
4091     int divsign, dvrsign;
4092     float128 xop1, xop2, xop3, xtemp;
4093     float128 xmaxint32 = {0x4017000000000000ULL, 0ULL}; // 2**24
4094     float128 xfract32 = {0xFFFFFFFFFE000000ULL, 0ULL}; // sign+exp+23 bits
4095 
4096     divsign = float32_is_neg(*op1) ? 1 : 0;
4097     dvrsign = float32_is_neg(*op2) ? 1 : 0;
4098 
4099     float_clear_exception_flags();
4100 
4101     if (float32_is_signaling_nan(*op1)) {
4102         float_raise(float_flag_invalid);
4103         code = float_exception(regs);
4104         *op1 = float32_snan_to_qnan(*op1);
4105         *op3 = float32_snan_to_qnan(*op1);
4106         regs->psw.cc = 1;
4107         return code;
4108     }
4109 
4110     if (float32_is_signaling_nan(*op2)) {
4111         float_raise(float_flag_invalid);
4112         code = float_exception(regs);
4113         *op1 = float32_snan_to_qnan(*op2);
4114         *op3 = float32_snan_to_qnan(*op2);
4115         regs->psw.cc = 1;
4116         return code;
4117     }
4118 
4119     if (float32_is_nan(*op1)) {
4120         *op3 = *op1;
4121         regs->psw.cc = 1;
4122         return 0;
4123     }
4124 
4125     if (float32_is_nan(*op2)) {
4126         *op1 = *op2;
4127         *op3 = *op2;
4128         regs->psw.cc = 1;
4129         return 0;
4130     }
4131 
4132     if (float32_is_inf(*op1) || float32_is_zero(*op2)) {
4133         float_raise(float_flag_invalid);
4134         code = float_exception(regs);
4135         *op1 = float32_default_nan;
4136         *op3 = float32_default_nan;
4137         regs->psw.cc = 1;
4138         return code;
4139     }
4140 
4141     if (float32_is_inf(*op2)) {
4142         *op3 = (divsign != dvrsign) ? 0x80000000 : 0;
4143         regs->psw.cc = 0;
4144         return 0;
4145     }
4146 
4147     xop1 = float32_to_float128(*op1);
4148     xop2 = float32_to_float128(*op2);
4149 
4150     set_rounding_mode(regs->fpc, RM_ROUND_TOWARD_ZERO);
4151     xtemp = float128_div(xop1, xop2);
4152     //logmsg("DIEBR div flags=%2.2X\n", float_get_exception_flags());
4153 
4154     flags = float_get_exception_flags();
4155     if ((flags & float_flag_inexact)
4156         && (float128_le(xmaxint32, float128_pos(xtemp)))) {
4157         /* If quotient exceeds 2**24, truncate it to form a partial
4158            quotient consisting of an implied 1 with 23 fraction bits,
4159            and set the condition code to 2 */
4160         xop3.high = xtemp.high & xfract32.high;
4161         xop3.low = 0;
4162         cc = 2;
4163     } else {
4164         /* Otherwise round it to an integer according to the specified
4165            rounding mode, and set the condition code to 0 */
4166         set_rounding_mode(regs->fpc, mode);
4167         float_clear_exception_flags();
4168         xop3 = float128_round_to_int(xtemp);
4169         //logmsg("DIEBR rou flags=%2.2X\n", float_get_exception_flags());
4170         cc = 0;
4171     }
4172 
4173     set_rounding_mode(regs->fpc, RM_ROUND_TOWARD_ZERO);
4174     float_clear_exception_flags();
4175     xtemp = float128_mul(xop2, xop3);
4176     //logmsg("DIEBR mul flags=%2.2X\n", float_get_exception_flags());
4177     float_clear_exception_flags();
4178     xop1 = float128_sub(xop1, xtemp);
4179     //logmsg("DIEBR sub flags=%2.2X\n", float_get_exception_flags());
4180     set_rounding_mode(regs->fpc, RM_DEFAULT_ROUNDING);
4181     float_clear_exception_flags();
4182 
4183     code = float_exception(regs);
4184 
4185     if (float128_exp(xop3) > FLOAT128_BIAS + FLOAT32_BIAS) {
4186         /* If quotient exponent exceeds maximum for float32, reduce
4187            the exponent by 192 and increase condition code by 1 */
4188         xop3 = float128_build(float128_is_neg(xop3) ? 1 : 0,
4189                         float128_exp(xop3) - 192,
4190                         float128_fract_high(xop3),
4191                         float128_fract_low(xop3));
4192         cc += 1;
4193     }
4194 
4195     *op1 = float128_to_float32(xop1);
4196     *op3 = float128_to_float32(xop3);
4197 
4198     /* A zero remainder is negative if the dividend is negative */
4199     if (float32_is_zero(*op1)) {
4200         *op1 = divsign ? 0x80000000 : 0;
4201     }
4202 
4203     /* A zero quotient is negative if dividend and divisor have different signs */
4204     if (float32_is_zero(*op3)) {
4205         *op3 = (divsign != dvrsign) ? 0x80000000 : 0;
4206     }
4207 
4208     regs->psw.cc = cc;
4209     return code;
4210 
4211 } /* end function divint_sbfp */
4212 
4213 /*-------------------------------------------------------------------*/
4214 /* B353 DIEBR - DIVIDE TO INTEGER (short BFP)                  [RRF] */
4215 /*-------------------------------------------------------------------*/
DEF_INST(divide_integer_bfp_short_reg)4216 DEF_INST(divide_integer_bfp_short_reg)
4217 {
4218     int r1, r2, r3, m4;
4219     float32 op1, op2, op3;
4220     int pgm_check;
4221 
4222     RRF_RM(inst, regs, r1, r2, r3, m4);
4223     //logmsg("DIEBR r1=%d r3=%d r2=%d m4=%d\n", r1, r3, r2, m4);
4224     BFPINST_CHECK(regs);
4225     if (r1 == r2 || r2 == r3 || r1 == r3) {
4226         regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION);
4227     }
4228     BFPRM_CHECK(m4,regs);
4229 
4230     get_float32(&op1, regs->fpr + FPR2I(r1));
4231     get_float32(&op2, regs->fpr + FPR2I(r2));
4232 
4233     pgm_check = divint_sbfp(&op1, &op2, &op3, m4, regs);
4234 
4235     put_float32(&op1, regs->fpr + FPR2I(r1));
4236     put_float32(&op3, regs->fpr + FPR2I(r3));
4237 
4238     if (pgm_check) {
4239         regs->program_interrupt(regs, pgm_check);
4240     }
4241 
4242 } /* end DEF_INST(divide_integer_bfp_short_reg) */
4243 
4244 #endif  /* FEATURE_BINARY_FLOATING_POINT */
4245 
4246 #if !defined(_GEN_ARCH)
4247 
4248 #if defined(_ARCHMODE2)
4249  #define  _GEN_ARCH _ARCHMODE2
4250  #include "ieee.c"
4251 #endif
4252 
4253 #if defined(_ARCHMODE3)
4254  #undef   _GEN_ARCH
4255  #define  _GEN_ARCH _ARCHMODE3
4256  #include "ieee.c"
4257 #endif
4258 
4259 #endif  /*!defined(_GEN_ARCH) */
4260 
4261 /* end of ieee.c */
4262