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